Is Zonky embedded database supported for Spring boot 3.0 version? - spring-boot

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.

Related

Using Spring-Actuator in combination with ObjectDB

I am implementing a program in Spring-Boot using ObjectDB. To actually use ObjectDB I have followed this approach https://www.objectdb.com/forum/2523 which is working perfectly.
However, as soon as I want to use Spring-Actuator then I am getting the following errors:
Error creating bean with name 'org.springframework.boot.actuate.autoconfigure.metrics.orm.jpa.HibernateMetricsAutoConfiguration': Injection of autowired dependencies failed; nested exception is com.objectdb.o.UserException: Unsupported unwrap(org.hibernate.SessionFactory.class) for EntityManagerFactory
Any ideas on how to solve this error?
I am using the exact same code as in the link. I have added Spring-Actuator in the pom like this:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
The failure is occurring because Spring Boot is trying to unwrap the JPA EntityManagerFactory to get Hibernate's SessionFactory. It's attempting to do this as you have Hibernate on the classpath (it's a dependency of spring-boot-starter-data-jpa). According to the JPA specification, unwrap should throw a PersistenceException "if the provider does not support the call". Spring Boot catches PersistenceException in case unwrap isn't supported. Unfortunately, ObjectDB is throwing com.objectdb.o.UserException which isn't spec compliant. I'd recommend raising this as an ObjectDB bug.
You can avoid the problem by excluding Hibernate from the classpath. This will stop Spring Boot from attempting to unwrap Hibernate's SessionFactory, preventing the ObjectDB bug from occurring. You can do so by adding an exclusion to the spring-boot-starter-data-jpa dependency in your pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</exclusion>
</exclusions>
</dependency>

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

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))

Spring Boot : Cannot load driver class: org.hsqldb.jdbcDriver

I have a simple Spring Boot application (generated through Spring Roo).
The database is configured as following :
spring.datasource.driver-class-name=org.hsqldb.jdbcDriver
spring.datasource.url=jdbc\:hsqldb\:mem\:PetClinic
spring.jpa.hibernate.naming.strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.messages.encoding=ISO-8859-1
spring.messages.fallback-to-system-locale=false
spring.thymeleaf.mode=html
Here are the how I declared the HSQLDB dependency :
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>provided</scope>
</dependency>
When I start the application, I get the error :
Caused by: java.lang.IllegalStateException: Cannot load driver class: org.hsqldb.jdbcDriver
at org.springframework.util.Assert.state(Assert.java:392) ~[spring-core-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.determineDriverClassName(DataSourceProperties.java:214) ~[spring-boot-autoconfigure-1.4.1.RELEASE.jar:1.4.1.RELEASE]
The Spring-boot-autoconfigure module tries to load the class with the ClassUtils utility class that loads the current context classes.
I wonder if this method works fine since I use a Tomcat container which is responsible to load the Maven dependencies ?
Why even with the JAR in the libs directory Spring is not able to find it ?
Remove <scope>provided</scope> from your pom.xml
Remove both spring.datasource.driver-class-name and spring.datasource.url properties from your application properties
Because:
when spring.datasource.url is provided the driver class name is redundant as Spring Boot will automatically attempt to load the correct driver.
since you want to use an embedded database you don't need to provide spring.datasource.url at all. Just need to have an embedded database JAR on the classpath (like HSQLDB)
Relevant docs snippet:
Spring Boot can auto-configure embedded H2, HSQL and Derby databases.
You don’t need to provide any connection URLs, simply include a build
dependency to the embedded database that you want to use.
Please read the Working with SQL databases section in of Spring Boot documentation. Everything I said is mentioned there, so you can get more detail.
I see the scope you gave is provided, <scope>provided</scope>, I don't think Tomcat provides the hsqldb.jar with it out of the box.
So try removing the provided scope.

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>

Spring MVC: Adding JAXB to the classpath so that it automatically serializes XML

According to Spring MVC documentation, <mvc:annotation-driven/> configures support for JSON if Jackson is in the classpath, and support for XML if JAXB is present in the classpath. Simply by adding a Jackson dependency to my pom.xml, I get JSON support to work! (see: Ajax Simplification in Spring 3.0)
However, after trying to access the same service with accept header "application/xml", I get a 406 Not Acceptable response. What's the simplest way to get JAXB in the classpath? What is necessary to enable support for XML MarshallingHttpMessageConverter?
Update
Taking a look at AnnotationDrivenBeanDefinitionParser, I can see what defines if "jaxb2Present". I set a breakpoint around line 179 to see if the Jaxb2RootElementHttpMessageConverter is indeed being registered like the MappingJacksonHttpMessageConverter is. It isn't...
What's the simplest way to add JAXB to the classpath to make it automatically serialize my XML requests?
It should work. Make sure that the object being returned has #XmlRootElement annotation as required by JAXB.
If you're using Java 6, JAXB is already on the classpath. If you're using Java 5, you'll need to add a reference implementation yourself.
If you're using Maven, you can add to your pom.xml:
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2</version>
</dependency>

Resources