Search code examples
javaspring-bootgraphqlwebclient

using webclient to call the grapql mutation API in spring boot


I am stuck while calling the graphQL mutation API in spring boot. Let me explain my scenario, I have two microservice one is the AuditConsumeService which consume the message from the activeMQ, and the other is GraphQL layer which simply takes the data from the consume service and put it inside the database. Everything well when i try to push data using graphql playground or postman. How do I push data from AuditConsumeService. In the AuditConsumeService I am trying to send mutation API as a string. the method which is responsible to send that to graphQL layer is

public Mono<String> sendLogsToGraphQL(String logs){
        return webClient
                .post()
                .uri("http://localhost:8080/logs/createEventLog")
                .bodyValue(logs)
                .retrieve()
                .bodyToMono(String.class);
    }  

NOTE: I try to pass data as Object as well but no use. The String logs will be given to it from activeMQ. The data which I am sending is;

{
    "hasError": false,
    "message": "Hello There",
    "sender": "Ali Ahmad",
    "payload": {
        "type": "String",
        "title": "Topoic",
        "description": "This is the demo description of the activemqq"
    },
    "serviceInfo":{
        "version": "v1",
        "date": "2021-05-18T08:44:17.8237608+05:00",
        "serverStatus": "UP",
        "serviceName": "IdentityService"
    }
}

The mutation will be like;

mutation($eventLog:EventLogInput){
  createEventLog(eventLog: $eventLog){
    hasError
    message
    payload{
      title,
      description
    }
  }
}

The $eventLog has json body as;

{
  "eventLog": {
    "hasError": false,
    "message": "Hello There",
    "sender": "Ali Ahmad",
    "payload": {
        "type": "String",
        "title": "Topoic",
        "description": "This is the demo description of the activemqq"
    },
    "serviceInfo":{
        "version": "v1",
        "date": "2021-05-18T08:44:17.8237608+05:00",
        "serverStatus": "UP",
        "serviceName": "IdentityService"
    }
}
}

EDIT The follow the below answer, by updating the consumerservice as;

@Component
public class Consumer {
    @Autowired
    private AuditService auditService;

    private final String MUTATION_QUERY = "mutation($eventLog: EventLogInput){\n" +
            "createEventLog(eventLog: $eventLog){\n" +
            "hasError\n" +
            "}\n" +
            "}";

    @JmsListener(destination = "Audit.queue")
    public void consumeLogs(String logs) {
        Gson gson = new Gson();
        Object jsonObject = gson.fromJson(logs, Object.class);
        Map<String, Object> graphQlBody = new HashMap<>();
        graphQlBody.put("query", MUTATION_QUERY);
        graphQlBody.put("variables", "{eventLog: " + jsonObject+ "}");
        auditService.sendLogsToGraphQL(graphQlBody);
    }
}

Now In the `sendLogsToGraphQL' will becomes.

public void sendLogsToGraphQL(Map<String, String> logs) {
        log.info("Logs: {} ", logs);
        Mono<String> stringMono = webClient
                .post()
                .uri("http://localhost:8080/graphql")
                .bodyValue(BodyInserters.fromValue(logs))
                .retrieve()
                .bodyToMono(String.class);
        log.info("StringMono: {}", stringMono);
        return stringMono;
    }

The data is not sending to the graphql layer with the specified url.


Solution

  • You have to send the query and body as variables in post request like shown here

    graphQlBody = { "query" : mutation_query, "variables" : { "eventLog" : event_log_json } }
    

    And then in webClient you can send body as multiple ways

    public Mono<String> sendLogsToGraphQL(Map<String,Object> body){
        return webClient
                .post()
                .uri("http://localhost:8080/logs/createEventLog")
                .bodyValue(BodyInserters.fromValue(body))
                .retrieve()
                .bodyToMono(String.class);
    }  
    

    Here i just showed using Map<String,Object> for forming graphQL request body, but you can also create corresponding POJO classes with the properties of query and variables