Cannot construct instance of `reactor.core.publisher.Mono` Spring Cloud OpenFeign and Spring boot 2 - spring-boot

Goal: migration from Spring Boot 1.x (webMvc) to version 2 (webFlux) and Spring Cloud Edgware SR2 to FinchleyM8 (awaiting release version).
Problem: Feign -> OpenFeign. OpenFeign under the hood uses RxJava but WebFlux - Reactor3. At the current moment when I using Mono as returned type, I have got an error:
Caused by: org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class reactor.core.publisher.Mono]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of reactor.core.publisher.Mono (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
Code example:
#FeignClient(name = "thirdpartyresource", url = "${third.party.resource.url}")
public interface ThirdPartyResource {
#PostMapping(value = "/validate", consumes = APPLICATION_FORM_URLENCODED_VALUE)
Mono<ValidationResultDto> validate(MultiValueMap multiValueMap); // WORKS BAD
// Single<ValidationResultDto> validate(MultiValueMap multiValueMap); WORKS WELL
}
Question:
Do I need to create my own converter Single to Mono or it's some problems of spring-cloud-starter-openfeign and all should work OOTB?

The reactor.core.publisher.Mono belongs to the spring-boot-starter-webflux jar.
Get the latest version of it from the mvn repository.
Then add it to your pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.5.3</version>
</dependency>
Also do remove spring-boot-starter-web from your pom.xml, just in case if you have it.
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>-->
This fixed the issue!

You can use those methods to adapt:
For Single<T> rxJavaSingle
Mono.from(RxReactiveStreams.toPublisher(rxJavaSingle))
For Completable rxJavaCompletable
Mono.from(RxReactiveStreams.toPublisher(rxJavaCompletable))

Related

Hystrix - behaviour of #HystrixCommand annotation

I have inherited a Java SpringBoot application (currently SpringBoot 2.7) that uses Hystrix for fault tolerance. I am aware that this has been deprecated, and we plan to more to Resilience4J
The Hystrix dependencies are
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.10.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
<version>2.2.10.RELEASE</version>
<scope>compile</scope>
</dependency>
The main class in the application is annotated with:
#EnableCircuitBreaker
#EnableHystrixDashboard
#EnableHystrix
The following properties are specified:
hystrix.threadpool.default.coreSize=30
hystrix.threadpool.default.maxQueueSize=300
hystrix.threadpool.default.queueSizeRejectionThreshold=300
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=30000
hystrix.command.default.circuitBreaker.errorThresholdPercentage=50
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=5000
hystrix.command.default.circuitBreaker.requestVolumeThreshold=60
hystrix.shareSecurityContext=true
I have gone through the usage of Hystrix within the application to understand exactly what the application is gaining from using Hystrix. I see that there are two different usages of the annotation HystrixCommand within the application.
In some cases, there are methods that are annotated as follows:
#HystrixCommand(fallbackMethod = "executeFallback")
public ResponseClass methodName (inputs...) {
private ResponseClass executeFallback(inputs...) {
LOGGER.error("Something went wrong...");
return new ResponseClass();
}
I have simplified the code, but my understanding is if the circuit is open, then it will result in the fallback method (named "executeFallback" above) being executed until the circuit is closed again.
But there are also many instances within the application of methods that are simply annotated with #HystrixCommand but there is no fallback method specified. These methods are also trying to access some data source, that could potentially be unavailable.
For example:
#HystrixCommand
public ResponseClass methodName (inputs...) {
My question is: what does an application gain from annotating methods with #HystrixCommand if no fallback method is specified?

Is Zonky embedded database supported for Spring boot 3.0 version?

I am trying to migrate my application from spring boot 2.7.2 to 3.0.0 version.
On running integration test case, I am getting below error :
java.lang.NullPointerException: Cannot invoke "org.hibernate.metamodel.mapping.JdbcMapping.getJdbcValueBinder()" because "jdbcMapping" is null
Hibernate ORM core version is 6.1.5.Final.
Could someone please guide if they have used zonky libraries with spring boot 3.0 ?
I have added below dependencies in pom.xml :
<dependency>
<groupId>io.zonky.test</groupId>
<artifactId>embedded-database-spring-test</artifactId>
<version>2.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zonky.test</groupId>
<artifactId>embedded-postgres</artifactId>
<version>2.0.2</version>
<scope>test</scope>
</dependency>
In case the test class uses a spring context that already contains a data source bean, the data source bean will be automatically replaced with a testing data source. The newly created data source bean will be injected into all related components, and you can also inject it into a test class.

Spring-boot bean name conflict between two dependent retrofit clients

My maven springboot app has a dependency on two Retrofit clients whose code I have no control over. Both of these clients have a #Configuration class called ClientConfig. When I try to run my application, I get this error:
ConflictingBeanDefinitionException: Annotation-specified bean name 'clientConfig' for bean class [a.b.c.client.config.ClientConfig] conflicts with existing, non-compatible bean definition of same name and class [a.b.c.config.ClientConfig]
How can I fix this? Is there any way I can override the bean names for these classes? This is my maven configuration:
<dependency>
<groupId>a.b</groupId>
<artifactId>lib1-client</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>a.b</groupId>
<artifactId>lib2-client</artifactId>
<version>1.2.55</version>
</dependency>
Only thing I could think of is to exclude them from component scan:
#SpringBootApplication
#ComponentScan(excludeFilters = {"a.b.lib1-client",...})

Prevent XXE (External Entity Processing) Attack with JAXB + Spring RESTful Web Services

I know that we can prevent the XXE attack by setting the property IS_SUPPORTING_EXTERNAL_ENTITIES in the abstract class XMLInputFactory to false in JAXB.
I have also seen this stackoverflow answer.
My question here is,
How do I create a instance of XMLInputFactory and set this IS_SUPPORTING_EXTERNAL_ENTITIES property to false when the spring application loads up. And that particular XMLInputFactory instance should only be used for all the JAXB conversion for all the classes that uses javax.xml.bind.annotation package.
Spring uses RequestMappingHandlerAdapter which is an AbstractHandlerMethodAdapter that supports HandlerMethods with the signature -- method argument and return types, defined in #RequestMapping.
There are 7 seven HttpMessageConverters and one of them is Jaxb2RootElementHttpMessageConverter
Jaxb2RootElementHttpMessageConverter is from the spring-web package.
From 3.2.8 version of spring-web onwards Jaxb2RootElementHttpMessageConverter sets the processExternalEntities to false which in turn sets the XMLInputFactory property IS_SUPPORTING_EXTERNAL_ENTITIES to false.
Refer : Jaxb2RootElementHttpMessageConverter from Spring
Answer use
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.2.8.RELEASE</version>
</dependency>

Conflict between Spring data MongoDb and Elasticsearch

I started a project in which I use both Mongo, Elasticsearch and spring boot.
With either technologies by itself, the project works just fine. However with both together, they conflict. I saw this particular article that seemed to be similar to my issue.
https://jira.spring.io/browse/DATAES-57
So I tried it out and it the problem is still there.
I put these on the Main class
#EnableAutoConfiguration(exclude = MongoRepositoriesAutoConfiguration.class)
#EnableMongoRepositories(basePackages = "com.searchizi.mongo.repository")
#EnableElasticsearchRepositories(basePackages = "com.searchizi.elasticsearch.repository")
#ComponentScan
public class Application implements CommandLineRunner { … }
A shortened form the the exception trace is this
The class SearchiziUser is in the com.searchizi.mongo.model package. It is not on the Elasticsearch scan path.
Caused by: java.lang.IllegalArgumentException: Unable to identify index name. SearchiziUser is not a Document. Make sure the document class is annotated with #Document(indexName="foo")
at org.springframework.util.Assert.isTrue(Assert.java:65)
at org.springframework.data.elasticsearch.core.ElasticsearchTemplate.getPersistentEntityFor(ElasticsearchTemplate.java:869)
at org.springframework.data.elasticsearch.core.ElasticsearchTemplate.createIndexIfNotCreated(ElasticsearchTemplate.java:684)
at org.springframework.data.elasticsearch.core.ElasticsearchTemplate.createIndex(ElasticsearchTemplate.java:135)
at org.springframework.data.elasticsearch.repository.support.AbstractElasticsearchRepository.createIndex(AbstractElasticsearchRepository.java:80)
at org.springframework.data.elasticsearch.repository.support.AbstractElasticsearchRepository.<init>(AbstractElasticsearchRepository.java:72)
at org.springframework.data.elasticsearch.repository.support.SimpleElasticsearchRepository.<init>(SimpleElasticsearchRepository.java:36)
The scanning for each repository type should be separated but apparently it is not. Any idea what to do?
This is clearly a bug in Spring Data Elasticsearch as it seems to scan for domain types in packages it actually shouldn't. I filed DATAES-?? for you. Also, I filed a ticket so that Spring Data Elasticsearch supports the new multi-store configuration improvements so that you shouldn't have to explicitly configure separate packages.
On a side note, excluding the auto-configuration is not necessary if you set up #EnableMongoRepositories as it will automatically disable Spring Boot's auto-configuration.
I faced this exception and I resolved by change version of elasticsearch and mongodb lib versions
<!-- Spring data mongodb -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.7.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>1.10.0.RELEASE</version>
</dependency>
<!-- mongodb java driver -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
</dependency>
<!-- ELASTICSEARCH -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>1.2.0.RELEASE</version>
</dependency>

Resources