0

I am trying to run a spring-bot micro-service using netflix-eureka and webflux and I have the following problem:

When I try to launch a request using webClient on one of my other micro-service it fails but it works with rest template.

My pom.xml :

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.2</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.my.company.invoise</groupId>
<artifactId>invoice</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>invoice</name>
<description>Demo project for Spring Boot</description>
<properties>
    <java.version>11</java.version>
    <spring-cloud.version>2020.0.0</spring-cloud.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-hibernate5</artifactId>
    </dependency>
    <dependency>
        <groupId>com.mycompany.invoise</groupId>
        <artifactId>core</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

My run file (InvoiceApplication.java) :

@SpringBootApplication
@EntityScan("com.mycompany.invoise.core.entity.invoice")
 public class InvoiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(InvoiceApplication.class, args);
    }

   @Bean
   public Hibernate5Module dataTypeHibernateModule(){
       Hibernate5Module module = new Hibernate5Module();
       module.disable(Hibernate5Module.Feature.USE_TRANSIENT_ANNOTATION);
       module.enable(Hibernate5Module.Feature.SERIALIZE_IDENTIFIER_FOR_LAZY_NOT_LOADED_OBJECTS);
       return module;
   }

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

    @Bean
    @LoadBalanced
    public WebClient.Builder getWebClientBuilder(){
        return WebClient.builder();
    }
}

My API (InvoiceRessource.java) :

@RestController
@RequestMapping("/invoice")
public class InvoiceResource {

    @Autowired
    private IInvoiceService invoiceService ;

    @Autowired
    private RestTemplate restTemplate ;

    @Autowired
    private WebClient.Builder wBuilder ;

    public IInvoiceService getInvoiceService() {
        return invoiceService;
    }

    public void setInvoiceService(IInvoiceService invoiceService) {
        this.invoiceService = invoiceService;
    }

    @PostMapping("")
    public Invoice create(@RequestBody Invoice invoice){
        invoiceService.createInvoice(invoice);
        return invoice ;
    }

    @GetMapping("")
    public ParallelFlux<Invoice> list(){
        System.out.println("You just called list method");
        Iterable<Invoice> invoices = invoiceService.getInvoiceList();
        List<Mono<Invoice>> invoiceMonos = new ArrayList<>();
        final WebClient webClient = wBuilder.baseUrl("http://customer-service").build();

        invoices.forEach(invoice ->
        //{
            invoiceMonos.add(webClient.get()
                    .uri("/customer/" + invoice.getIdCustomer())
                    .retrieve()
                    .bodyToMono(Customer.class)
                    .map(customer -> {
                        invoice.setCustomer(customer);
                        return invoice ;
                    }))
//            invoice.setCustomer(restTemplate.getForObject(
//                    "http://customer-service/customer/" + invoice.getIdCustomer(),
//                    Customer.class
    //            ));}
   //               This version works !
        );

        Flux<Invoice> invoiceFlux = Flux.concat(invoiceMonos);

        return invoiceFlux.parallel().runOn(Schedulers.boundedElastic());
        //return invoices ;
    }



    @GetMapping("/{id}")
    public @ResponseBody  Invoice displayInvoice(@PathVariable("id") String number){
        System.out.println("displayInvoice had been called");
        Invoice invoice = invoiceService.getInvoiceByNumber(number);
        Customer customer = restTemplate.getForObject(
                "http://customer-service/customer/" + invoice.getIdCustomer(),
                Customer.class);
        customer.setAddress(restTemplate.getForObject(
                "http://customer-service/address/" + customer.getAddress().getId(),
                Address.class));
        invoice.setCustomer(customer);
        return invoice ;
    }

    public RestTemplate getRestTemplate() {
        return restTemplate;
    }

    public void setRestTemplate(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public WebClient.Builder getwBuilder() {
        return wBuilder;
    }

    public void setwBuilder(WebClient.Builder wBuilder) {
        this.wBuilder = wBuilder;
    }
}

Entity File (Customer.java):

@Entity
public class Customer {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false,length = 50)
private String name;

@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL,orphanRemoval = true,optional = false)
@JoinColumn(name="ID_ADDRESS")
private Address address;

public Customer(String name) {
    this.name = name;
}

public Customer() {
}

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public Address getAddress() {
    return address;
}

public void setAddress(Address address) {
    this.address = address;
}

}

Logs (Debug mode activated):

2021-01-23 23:07:22.886 DEBUG 2244 --- [p-nio-80-exec-9] o.s.web.servlet.DispatcherServlet        : 

GET "/home", parameters={}
2021-01-23 23:07:22.886 DEBUG 2244 --- [p-nio-80-exec-9] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.my.company.invoise.invoice.controller.InvoiceControllerWeb#displayWhom(Model)
You just called displayWhom
2021-01-23 23:07:22.886 DEBUG 2244 --- [p-nio-80-exec-9] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, application/xhtml+xml, image/webp, application/xml;q=0.9, */*;q=0.8]
2021-01-23 23:07:22.886 DEBUG 2244 --- [p-nio-80-exec-9] o.s.web.servlet.DispatcherServlet        : Completed 200 OK
2021-01-23 23:07:22.933 DEBUG 2244 --- [-nio-80-exec-10] o.s.web.servlet.DispatcherServlet        : GET "/js/script.js", parameters={}
2021-01-23 23:07:22.933 DEBUG 2244 --- [-nio-80-exec-10] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler [class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/]]
2021-01-23 23:07:22.933 DEBUG 2244 --- [-nio-80-exec-10] o.s.web.servlet.DispatcherServlet        : Completed 304 NOT_MODIFIED
2021-01-23 23:07:22.964 DEBUG 2244 --- [p-nio-80-exec-1] o.s.web.servlet.DispatcherServlet        : GET "/invoice", parameters={}
2021-01-23 23:07:22.964 DEBUG 2244 --- [p-nio-80-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.my.company.invoise.invoice.api.InvoiceResource#list()
You just called list method
Hibernate: 
    select
        invoice0_.invoice_number as invoice_1_0_,
        invoice0_.id_customer as id_custo2_0_,
        invoice0_.order_number as order_nu3_0_ 
    from
        invoice invoice0_
2021-01-23 23:07:22.980 DEBUG 2244 --- [p-nio-80-exec-1] o.s.w.r.f.client.ExchangeFunctions       : [1150dd84] HTTP GET http://MSI:8090/customer/1
2021-01-23 23:07:22.980 DEBUG 2244 --- [p-nio-80-exec-1] o.s.w.c.request.async.WebAsyncManager    : Started async request
2021-01-23 23:07:22.980 DEBUG 2244 --- [p-nio-80-exec-1] o.s.web.servlet.DispatcherServlet        : Exiting but response remains open for further handling
2021-01-23 23:07:28.012 DEBUG 2244 --- [oundedElastic-2] o.s.w.c.request.async.WebAsyncManager    : Async error, dispatch to /invoice
2021-01-23 23:07:28.012 DEBUG 2244 --- [p-nio-80-exec-2] o.s.web.servlet.DispatcherServlet        : "ASYNC" dispatch for GET "/invoice", parameters={}
2021-01-23 23:07:28.012 DEBUG 2244 --- [p-nio-80-exec-2] s.w.s.m.m.a.RequestMappingHandlerAdapter : Resume with async result [org.springframework.web.reactive.function.client.WebClientRequestException: failed to resolve 'MSI'  (truncated)...]
2021-01-23 23:07:28.012 DEBUG 2244 --- [p-nio-80-exec-2] o.s.web.servlet.DispatcherServlet        : Unresolved failure from "ASYNC" dispatch: org.springframework.web.reactive.function.client.WebClientRequestException: failed to resolve 'MSI' after 2 queries ; nested exception is java.net.UnknownHostException: failed to resolve 'MSI' after 2 queries 
2021-01-23 23:07:28.027 ERROR 2244 --- [p-nio-80-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] threw exception

io.netty.resolver.dns.DnsNameResolverTimeoutException: [/192.168.0.254:53] query via UDP timed out after 5000 milliseconds (no stack trace available)

2021-01-23 23:07:28.027 ERROR 2244 --- [p-nio-80-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.reactive.function.client.WebClientRequestException: failed to resolve 'MSI' after 2 queries ; nested exception is java.net.UnknownHostException: failed to resolve 'MSI' after 2 queries ] with root cause

io.netty.resolver.dns.DnsNameResolverTimeoutException: [/192.168.0.254:53] query via UDP timed out after 5000 milliseconds (no stack trace available)

2021-01-23 23:07:28.027 DEBUG 2244 --- [p-nio-80-exec-2] o.s.web.servlet.DispatcherServlet        : "ERROR" dispatch for GET "/error", parameters={}
2021-01-23 23:07:28.027 DEBUG 2244 --- [p-nio-80-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error(HttpServletRequest)
2021-01-23 23:07:28.027 DEBUG 2244 --- [p-nio-80-exec-2] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json]
2021-01-23 23:07:28.027 DEBUG 2244 --- [p-nio-80-exec-2] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Writing [{timestamp=Sat Jan 23 23:07:28 CET 2021, status=500, error=Internal Server Error, message=, path=/in (truncated)...]
2021-01-23 23:07:28.027 DEBUG 2244 --- [p-nio-80-exec-2] o.s.web.servlet.DispatcherServlet        : Exiting from "ERROR" dispatch, status 500
2021-01-23 23:07:45.856 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : HTTP GET http://localhost:8761/eureka/apps/delta
2021-01-23 23:07:45.856 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Accept=[application/json, application/*+json]
2021-01-23 23:07:45.856 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Response 200 OK
2021-01-23 23:07:45.856 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Reading to [org.springframework.cloud.netflix.eureka.http.EurekaApplications]
2021-01-23 23:07:45.856 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : HTTP PUT http://localhost:8761/eureka/apps/INVOICE-SERVICE/MSI:invoice-service:80?status=UP&lastDirtyTimestamp=1611439605837
2021-01-23 23:07:45.856 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : Accept=[application/json, application/*+json]
2021-01-23 23:07:45.872 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : Response 200 OK
2021-01-23 23:08:15.869 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : HTTP GET http://localhost:8761/eureka/apps/delta
2021-01-23 23:08:15.869 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Accept=[application/json, application/*+json]
2021-01-23 23:08:15.869 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Response 200 OK
2021-01-23 23:08:15.869 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Reading to [org.springframework.cloud.netflix.eureka.http.EurekaApplications]
2021-01-23 23:08:15.869 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : HTTP PUT http://localhost:8761/eureka/apps/INVOICE-SERVICE/MSI:invoice-service:80?status=UP&lastDirtyTimestamp=1611439605837
2021-01-23 23:08:15.869 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : Accept=[application/json, application/*+json]
2021-01-23 23:08:15.869 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : Response 200 OK
2021-01-23 23:08:45.885 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : HTTP GET http://localhost:8761/eureka/apps/delta
2021-01-23 23:08:45.885 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : HTTP PUT http://localhost:8761/eureka/apps/INVOICE-SERVICE/MSI:invoice-service:80?status=UP&lastDirtyTimestamp=1611439605837
2021-01-23 23:08:45.885 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Accept=[application/json, application/*+json]
2021-01-23 23:08:45.885 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : Accept=[application/json, application/*+json]
2021-01-23 23:08:45.885 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Response 200 OK
2021-01-23 23:08:45.885 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Reading to [org.springframework.cloud.netflix.eureka.http.EurekaApplications]
2021-01-23 23:08:45.885 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : Response 200 OK
2021-01-23 23:09:15.908 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : HTTP PUT http://localhost:8761/eureka/apps/INVOICE-SERVICE/MSI:invoice-service:80?status=UP&lastDirtyTimestamp=1611439605837
2021-01-23 23:09:15.908 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : HTTP GET http://localhost:8761/eureka/apps/delta
2021-01-23 23:09:15.908 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : Accept=[application/json, application/*+json]
2021-01-23 23:09:15.908 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Accept=[application/json, application/*+json]
2021-01-23 23:09:15.908 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Response 200 OK
2021-01-23 23:09:15.908 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : Response 200 OK
2021-01-23 23:09:15.908 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Reading to [org.springframework.cloud.netflix.eureka.http.EurekaApplications]
2021-01-23 23:09:45.915 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : HTTP GET http://localhost:8761/eureka/apps/delta
2021-01-23 23:09:45.915 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : HTTP PUT http://localhost:8761/eureka/apps/INVOICE-SERVICE/MSI:invoice-service:80?status=UP&lastDirtyTimestamp=1611439605837
2021-01-23 23:09:45.915 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Accept=[application/json, application/*+json]
2021-01-23 23:09:45.915 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : Accept=[application/json, application/*+json]
2021-01-23 23:09:45.915 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : Response 200 OK
2021-01-23 23:09:45.915 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Response 200 OK
2021-01-23 23:09:45.915 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Reading to [org.springframework.cloud.netflix.eureka.http.EurekaApplications]
2021-01-23 23:10:15.925 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : HTTP PUT http://localhost:8761/eureka/apps/INVOICE-SERVICE/MSI:invoice-service:80?status=UP&lastDirtyTimestamp=1611439605837
2021-01-23 23:10:15.925 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : Accept=[application/json, application/*+json]
2021-01-23 23:10:15.925 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : Response 200 OK
2021-01-23 23:10:15.925 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : HTTP GET http://localhost:8761/eureka/apps/delta
2021-01-23 23:10:15.925 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Accept=[application/json, application/*+json]
2021-01-23 23:10:15.925 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Response 200 OK
2021-01-23 23:10:15.925 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Reading to [org.springframework.cloud.netflix.eureka.http.EurekaApplications]
2021-01-23 23:10:45.944 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : HTTP GET http://localhost:8761/eureka/apps/delta
2021-01-23 23:10:45.944 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : HTTP PUT http://localhost:8761/eureka/apps/INVOICE-SERVICE/MSI:invoice-service:80?status=UP&lastDirtyTimestamp=1611439605837
2021-01-23 23:10:45.944 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Accept=[application/json, application/*+json]
2021-01-23 23:10:45.944 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : Accept=[application/json, application/*+json]
2021-01-23 23:10:45.944 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Response 200 OK
2021-01-23 23:10:45.944 DEBUG 2244 --- [freshExecutor-0] o.s.web.client.RestTemplate              : Reading to [org.springframework.cloud.netflix.eureka.http.EurekaApplications]
2021-01-23 23:10:45.944 DEBUG 2244 --- [tbeatExecutor-0] o.s.web.client.RestTemplate              : Response 200 OK

Funny think is this url : "http://MSI:8090/customer/1" is correct and send me back a correct json for customer :

{"id":1,"name":"John Doe","address":{"id":1}}
Infinite Learner
  • 196
  • 1
  • 1
  • 8
  • Can you be more specific with the error that you're getting? – Welsh Jan 23 '21 at 23:51
  • The underlying Netty library that WebClient uses has a bug when dealing with some types of networks, proxies and so on... I myself ended up dropping WebClient to avoid those issues. It was unable to just use the machines proxy config, and setting it up manually was a no-go for me. WebClient Netty is making the transition from Rest Template to it terrible and full of bugs. – BBacon Apr 15 '21 at 15:51

1 Answers1

1

Not sure if this is going to help but I had a similar issue. I was using below:

@SpringBootApplication
public class Application implements CommandLineRunner {
    

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);

    }

    @Override
    public void run(String... args) throws Exception {

        WebClient webClient = WebClient.builder().baseUrl("http://myserver:8080")
                .defaultHeaders(header -> header.setBasicAuth("admin", "admin")).build();

        Mono<String> flux = webClient.get()
            .uri("/alfresco/api/-default-/public/alfresco/versions/1/nodes/f37b52a8-de40-414b-b64d-a958137e89e2")
            .retrieve()
            .bodyToMono(String.class);

        System.out.println(flux.block());
        
    }
}

But when I changed to my server's FQDN (fully qualified distinguished name) it resolved the issue like below:

.baseUrl("http://myserver.mycompany.com:8080

Ajay Kumar
  • 2,906
  • 3
  • 23
  • 46