Spring Boot disable creation of JpaProperties configuration in WAR deployment - spring

I'm trying to setup a Spring Boot application that uses EclipseLink instead of Hibernate. The project has a similar structure to this example project:
https://github.com/spring-projects/spring-data-examples/blob/master/jpa/eclipselink/src/main/java/example/springdata/jpa/eclipselink/Application.java
The main difference is that our application needs to be packaged as a WAR... so the main Application.java extends SpringBootServletInitializer instead of the JpaBaseConfiguration shown in the example (we have another bean with #Configuration that extends JpaBaseConfiguration).
When the app starts it encounters a ClassNotFoundException for the a naming strategy that comes form Hibernate:
Error creating bean with name 'spring.jpa-org.springframework.boot.autoconfigure.orm.jpa.JpaProperties': Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/hibernate/boot/model/naming/ImplicitNamingStrategy
It seems that this only happens when the application extends from SpringBootServletInitializer.
Turning on debug shows this:
JpaBaseConfiguration.JpaWebConfiguration:
Did not match:
- #ConditionalOnProperty (spring.jpa.open-in-view=true) found different value in property 'open-in-view' (OnPropertyCondition)
Matched:
- #ConditionalOnClass found required class 'org.springframework.web.servlet.config.annotation.WebMvcConfigurer'; #ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- found ConfigurableWebEnvironment (OnWebApplicationCondition)
Is there any way to exclude the JpaWebConfiguration, but still have the application extend from SpringBootServletInitializer?
UPDATE: After debugging this further I don't believe the JpaWebConfiguration is the issue as that is in the unmatched section of the debug, but something is still causing the creation of a JpaProperties bean and hitting the ClassNotFoundException.

Related

#EnableAutoConfiguration(exclude =...) on tests failed in Spring Boot 2.6.0

I tried to upgrade my data-mongo example project to Spring Boot 2.6.0. There is a test designed to run against Testcontainers, I also included the embedded mongo dep for other tests, so I have to exclude the AutoConfiguration for embedded mongo to make sure this test working on Docker/testcontainers.
The following configuration worked well with Spring Boot 2.5.6.
#DataMongoTest
#ContextConfiguration(initializers = {MongodbContainerInitializer.class})
#EnableAutoConfiguration(exclude = EmbeddedMongoAutoConfiguration.class)
#Slf4j
#ActiveProfiles("test")
public class PostRepositoryTest {}
But after upgrading to Spring Boot 2.6.0 and running the application, I got the exception like this.
[ main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: o
rg.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'embeddedMongoServer' defined in class path resource [org/springframework/boot/autoconfig
ure/mongo/embedded/EmbeddedMongoAutoConfiguration.class]: Unsatisfied dependency expressed through method 'embeddedMongoServer' parameter 0; nested exception is org.springframework.bea
ns.factory.BeanCreationException: Error creating bean with name 'embeddedMongoConfiguration' defined in class path resource [org/springframework/boot/autoconfigure/mongo/embedded/Embed
dedMongoAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [de.flap
doodle.embed.mongo.config.MongodConfig]: Factory method 'embeddedMongoConfiguration' threw exception; nested exception is java.lang.IllegalStateException: Set the spring.mongodb.embedd
ed.version property or define your own MongodConfig bean to use embedded MongoDB
Obviously, #EnableAutoConfiguration(exclude =...) did not affect the context in tests when upgrading to Spring Boot 2.6.0.
Update: Temporarily resolved it, see my answer below.
Just add:
#TestPropertySource(properties = "spring.mongodb.embedded.version=3.5.5")
annotation before your Unit Test and it will start working.
#Henning's answer has a good explanation of why you need this.
As of Spring Boot 2.6, the property spring.mongodb.embedded.version must be set to use the auto-configured embedded MongoDB. It's mentioned in the release notes: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.6-Release-Notes#embedded-mongo
This is also what the error message you posted, advises to do: Set the spring.mongodb.embedd ed.version property or define your own MongodConfig bean to use embedded MongoDB
The annotation #DataMongoTest is meta-annotated with #ImportAutoConfiguration and #AutoConfigureDataMongo, and is designed to trigger auto-configuration of MongoDB unless explicitly disabled as you do in the working configuration examples.
In your first configuration example, the annotation #EnableAutoConfiguration(exclude = EmbeddedMongoAutoConfiguration.class) does not override this effect of #DataMongoTest.
With Spring Boot 2.5.6, the auto-configured MongodConfig bean is most likely also part of the application context but not effectively used. But this depends on the rest of the code and in particular on the MongodbContainerInitializer.
Use #ImportAutoConfiguration(exclude = ...) or #DataMongoTest(excludeAutoConfiguration = ...) on test classes to overcome this barrier when upgrading to Spring Boot 2.6.0.
#DataMongoTest
#ImportAutoConfiguration(exclude = EmbeddedMongoAutoConfiguration.class)
//other config are ommitted
public class PostRepositoryTest {}
//or
#DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class)
public class PostRepositoryTest {}

The bean 'methodSecurityInterceptor', defined in class path resource [org/activiti/spring/boot/MethodSecurityConfig.class], could not be registered

***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'methodSecurityInterceptor', defined in class path resource [org/activiti/spring/boot/MethodSecurityConfig.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.class] and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
I use the SpringBoot 2.2.12 and SpringSecurity 5.2.8 and activiti 7.1.0.M4 then get the error.
I think it may coursed by activiti conflict with SpringSecurity.
I think. If there is a conflict between the two framework bean naming definitions.You can try to customize one of them

CacheAutoConfiguration is not working due to CacheAspectSupport not found

I'm using springboot 2.1.1.
I enabled cache with #EnableCaching
A CacheManager is created and can be injected in my classes.
Once I add a library https://github.com/MarcGiffing/bucket4j-spring-boot-starter
I've got an error when starting the application :
java.lang.IllegalStateException: No CacheResolver specified, and no bean of type CacheManager found. Register a CacheManager bean or remove the #EnableCaching annotation from your configuration.
at org.springframework.cache.interceptor.CacheAspectSupport.afterSingletonsInstantiated(CacheAspectSupport.java:227)
After a lot of debugging, I can't find why and how the library is breaking the CacheManager.
It seems like the CacheAutoConfiguration spring class is not used :
CacheAutoConfiguration:
Did not match:
- #ConditionalOnBean (types: org.springframework.cache.interceptor.CacheAspectSupport; SearchStrategy: all) did not find any beans of type org.springframework.cache.interceptor.CacheAspectSupport (OnBeanCondition)
Matched:
- #ConditionalOnClass found required class 'org.springframework.cache.CacheManager' (OnClassCondition)
But I added a breakpoint in ProxyCachingConfiguration#L63 and an instance of CacheInterceptor (CacheAspectSupport impl) is created.
I can inject it in one of my Configuration class. So the bean CacheAspectSupport seems to exist in the application context.
So why the CacheAutoConfiguration says the bean is missing ?
Thanks
I found out why.
My Configuration class holding the #EnableCaching annotation was loaded too late when the library was added.
I added a #AutoConfigureBefore(CacheAutoConfiguration.class) and It is now working.

Spring Boot MessageSourceAutoConfiguration

I have a problem or possibly I found a bug in Spring Boot. I am not sure at the moment.
I have a project with the following dependencies
spring-boot-starter-thymeleaf
spring-boot-starter-web
spring-boot-starter-actuator
spring-boot-starter-mail
spring-cloud-starter-bus-amqp
spring-cloud-starter-config
spring-cloud-starter-eureka
I want to use a messageSource in my Thymeleaf templates and so I set the following in my application.yml:
spring:
messages:
basename: de/mycompany/messages/message
and placed a message.properties and a message_de.properties in the above package. But the replacing did not work.
So I debugged MessageSourceAutoConfiguration and found, that the #Conditional(ResourceBundleCondition.class) did work. It found my Resources and returned true.
So I let print the debug report and found, that it says
MessageSourceAutoConfiguration
- Bundle found for spring.messages.basename: de/mycompany/messages/message (MessageSourceAutoConfiguration.ResourceBundleCondition)
- #ConditionalOnMissingBean (types: org.springframework.context.MessageSource; SearchStrategy: all) found the following [messageSource] (OnBeanCondition)
So there is another messageSource Bean already defined, but i wondered where it did come from. So i investigated further and found the following log output:
AnnotationConfigEmbeddedWebApplicationContext : Unable to locate MessageSource with name 'messageSource': using default [org.springframework.context.support.DelegatingMessageSource#60df7989]
In fact it comes from the class AbstractApplicationContext in method initMessageSource (around line 622).
There it checks for a bean with name "messageSource" and if it doesn't find one, it creates the above mentioned DelegatingMessageSource.
Am I missing something? Do I have to do something to get the MessageSourceAutoConfiguration happen before this AbstractApplicationContext stuff? Or is this really a bug?
For myself I fixed it by simply creating the messageSource myself as a #Bean, but using the AutoConfiguration would be far smarter :)
Greetings Christian
Turns out this is a bug, hopefully it gets resolved soon, tracked here:
https://github.com/spring-cloud/spring-cloud-commons/issues/29

conflicts with existing, non-compatible bean definition of same name and class after proguard obfuscation

after Proguard obfuscation i get the following error :
Unexpected exception parsing XML document from ServletContext resource
[/WEB-INF/applicationContext.xml]; nested exception is
java.lang.IllegalStateException: Annotation-specified bean name 'a'
for bean class [com.company.project.b.a.a.a] conflicts with existing,
non-compatible bean definition of same name and class
[com.company.project.a.a]
i'm using annotation based spring configuration , how can i avoid having two classes with the same name using Proguard because Spring doesn't allow two beans to have the same name.
I'm not sure if this is what you want, but you can specify bean name in #Component (and stereotypes #Repository, #Service and #Controller) value:
#Component("myBeanName")
public class MyBean {
}
I had the same problem and nothing else was helping out. Sometimes the problem occurs if you have moved your classes around and it refers to old classes, even if they don't exist.
In this case, just do this :
mvn eclipse:clean
mvn eclipse:eclipse
This worked well for me.
Another cause; you may have different versions of Spring in your classpath, for example, spring 2.x with spring 3.x. In such condition, beans seem to be loaded twice. If you use maven, check if a module does not import an old version of Spring (mvn dependency:tree) and remove it by excluding the involved spring artifact (exclusions).

Resources