Search code examples
javaservermicronautmicronaut-client

Micronaut java httpclient creation with the existing server


I have a Micronaut application running with the below configuration:

micronaut:
  server:
    cors:
       enabled: true 
    port: 8080

Now I have an enhancement where I want to call a 3rd party URL and get the response in my application (one of the module in my application). I used the below code snippet:

    EmbeddedServer server = ApplicationContext.run(EmbeddedServer.class);
    HttpClient client = server .getApplicationContext() .createBean(HttpClient.class, server.getURL());
    HttpRequest req = HttpRequest.GET(urlHost);
    HttpResponse<String> response = client.toBlocking().exchange(req, String.class);

But this is not working. I get port already in use. I did not find much help in google because Micronaut's HttpClient is usually used in Micronaut Test which is not in my case. Is this possible to use it in my application? If so how? Thanks in Advance.


Solution

  • It is because you are starting another server by ApplicationContext.run(EmbeddedServer.class).

    You don't need it. It is enough to inject HttpClient into your class by constructor:

    @Singleton 
    public class MyClient {
    
        private final RxHttpClient client;
    
        public MyClient(@Client("https://some.third-party.com") RxHttpClient client) {  
            this.client = client;
        }
    
        HttpResponse<String> getSomething(Integer id) {
            URI uri = UriBuilder.of("/some-objects").path(id).build();
            return client.toBlocking().exchange(HttpRequest.GET(uri), String.class);
        }
    }
    

    If you have third-party server URL in application configuration under some-service.url path for example, then you can use @Client("${some-service.url}")


    Another option is to define declarative client for the third-party server and then inject it in your classes where needed.

    First define client interface for your third-party service:

    @Client("some-service")
    public interface SomeServiceClient {
    
        @Get("/api/some-objects/{id}")
        String getSomeObject(@QueryValue("id") Integer id);
    }
    

    Add client configuration for that service in application configuration (application.yaml):

    micronaut:
      http:
        services:
          some-service:
            url: "https://some.third-party.com"
            read-timeout: 1m
    

    And then you can inject the SomeServiceClient where you need it:

    @Singleton 
    public class SomeServiceConsumer {
    
        private final SomeServiceClient client;
    
        public SomeServiceConsumer(SomeServiceClient client) {  
            this.client = client;
        }
    
        void doWithSomething(Integer id) {
            String object = client.getSomeObject(id);
            ... // processing of object here
        }
    }
    

    You can find more information in a Micronaut documentation https://guides.micronaut.io/latest/micronaut-http-client-gradle-java.html