skip to Main Content

I am using spring webclient to make a Facebook graph api request with url containing {comment_count}

But, getting this exception

java.lang.IllegalArgumentException: Not enough variable values available to expand reactive spring

Code Snippet :

import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;

import reactor.core.publisher.Mono;

@Component
public class Stackoverflow {

    WebClient client = WebClient.create();

    public Mono<Post> fetchPost(String url) {
        // Url contains "comments{comment_count}"
        return client.get().uri(url).retrieve()
                .bodyToMono(Post.class);
    }
}

I know the solution with resttemplate, But i need to use spring webclient.

2

Answers


  1. You can create your URL using UriComponentsBuilder as follows

     webClient.get().uri(getFacebookGraphURI(3)).retrieve().bodyToMono(Object.class);
    
    private URI getFacebookGraphURI(int comments){
       return UriComponentsBuilder.fromHttpUrl("https://graph.facebook.com")
            .pathSegment("v3.2", "PAGE_ID", "posts").queryParam("fields", "comments{comment_count}")
            .queryParam("access_token", "acacaaac").build(comments);
    
      }
    

    OR

    int commentsCount = 3; webClient.get().uri(UriComponentsBuilder.fromHttpUrl(“https://graph.facebook.com“)
    .pathSegment(“v3.2”, “PAGE_ID”, “posts”).queryParam(“fields”, “comments{comment_count}”)
    .queryParam(“access_token”, “acacaaac”).build().toString(),commentsCount).retrieve().bodyToMono(Object.class);

    Login or Signup to reply.
  2. The solution I use is to disable the encoding in DefaultUriBuilderFactory

    val urlBuilderFactory = DefaultUriBuilderFactory("https://foo.bar.com").apply {
        encodingMode = EncodingMode.NONE
    }
    
    val wc = wcb
        .clone()
        .uriBuilderFactory(urlBuilderFactory)
        .build()
    

    It’s in Kotlin, in Java you just have to use DefaultUriBuilderFactory#setEncodingMode(EncodingMode) with NONE as parameter.

    Due to this change of behavior, you have to encode your query params yourself. To do so, I use the

    val query = URLEncoder.encode(query_as_string, StandardCharsets.UTF_8.toString())
    

    And I can perform call like this:

    wc.get()
        .uri { it
            .path(graphqlEndpoints)
            .queryParam("variables", query)
            .build()
        }
        .retrieve()
        .bodyToFlux<String>()
        // ...
    

    For Java (as per comment by Anurag below) it will be something like this:

    var uriBuilderFactory = new DefaultUriBuilderFactory(baseUrl);   
    uriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE);
    
    var wc = WebClient.builder()
        .baseUrl(baseUrl) 
        .uriBuilderFactory(uriBuilderFactory)
        // ... other options
        .build(); 
    
    wc.get()
         .uri(uriBuilder -> uriBuilder
             .path(path)
             // value still needs to be URL-encoded as needed (e.g., if value is a JSON
             .queryParam("param", value))
             .build())
         .retrieve()
         .bodyToMono(...);
    

    As noted above, you will still need to URL-encode the parameter value. With this approach, you are merely avoiding "double URL encoding" by replacing the urlBuilderFactory.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search