Why is my app's spring boot app interfering with another spring boot app from Adobe's s3mock test framework - spring

The context is I am using s3mock-junit5 for mocking s3 using groovy's Spock framework
testImplementation group: 'com.adobe.testing', name: 's3mock-junit5', version: '2.4.10'
I had to write a groovy's custom Extension because s3mock does work with junit4 and 5 out of the box but not with Spock.
package com.myapp.test.utils
...
class S3MockTestExtension extends S3MockStarter implements IAnnotationDrivenExtension<S3MockTest> {
Eventually the s3mock library runs a spring boot app (to mock the s3 behavior)
final ConfigurableApplicationContext ctx =
new SpringApplicationBuilder(S3MockApplication.class)
.properties(translateLegacyProperties(defaults))
.properties(translateLegacyProperties(properties))
.bannerMode(bannerMode)
.run(args);
The problem I have is that it tries to create beans that my app uses (the data source and amazon's SdkClient):
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class
at app//org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at app//org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653)
... 97 more
Caused by: org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class
Why does it do that? The library spring boot Application class has a #ComponentScan annotation, but the base package is way different from my app's package.
package com.adobe.testing.s3mock;
...
#Configuration
#EnableAutoConfiguration(exclude = {SecurityAutoConfiguration.class},
excludeName = {"org.springframework.boot.actuate.autoconfigure.security.servlet."
+ "ManagementWebSecurityAutoConfiguration"})
#ComponentScan
public class S3MockApplication {

Related

jackson-databind Java7SupportImpl problem on jdk11 and aws-sdk

I'm migrating a spring boot app from jdk8 to jdk11, along with spring boot to 2.7.7.
I am getting this runtime error post a successful compile.
jackson-databind resolved to the one sourced by spring boot, which is only 1 minor version about the one sourced by aws-sdk.
From the doc on Java7SupportImpl, understand that this impl dynamically loaded and jdk7 dependent, but not sure if it's partially
or fully implemented on loading as it's missing a method.
Have I missed any dependency?
Is any other dependency conflict creating this condition?
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.amazonaws.auth.AWSCredentialsProvider]: Factory method 'awsCredentialsProvider' threw exception; nested exception is java.lang.AbstractMethodError: Receiver class com.fasterxml.jackson.databind.ext.Java7SupportImpl does not define or inherit an implementation of the resolved method 'abstract com.fasterxml.jackson.databind.JsonDeserializer getDeserializerForJavaNioFilePath(java.lang.Class)' of abstract class com.fasterxml.jackson.databind.ext.Java7Support.
at app//org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at app//org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653)
... 61 more
Caused by: java.lang.AbstractMethodError: Receiver class com.fasterxml.jackson.databind.ext.Java7SupportImpl does not define or inherit an implementation of the resolved method 'abstract com.fasterxml.jackson.databind.JsonDeserializer getDeserializerForJavaNioFilePath(java.lang.Class)' of abstract class com.fasterxml.jackson.databind.ext.Java7Support.

#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 {}

Spring/tomcat Cannot load driver class: com.mysql.jdbc.driver

Lately I have been trying to learn spring boot. I have the following relevant files:
an #Configuration class: I use this to generate the entitymanagerfactory
an #Entity class: I use this to map to a mysql table instance
an #Repository crudrepository interface: this is built in to spring
an #Controller class: this is used to test auto-wiring (when I can inject, I will move this to the service layer)
an #SpringBootApplication class: this runs my application
an application.properties file
a pom.xml: this is used for maven and includes mysql jar
an entity class mapped to a mysql table and a UserRepository class(annotated with #Repository). I am trying to inject the crudrepository class via #Autowire annotation, but spring is having difficulty creating the datasource for it because it cannot find the mysql driver. What confuses me is that I have the mysql dependency in maven and I am deploying this on a glassfish 4 server, but Spring is trying to use apache tomcat to connect to the database. Below is my stack trace, code snippets, and mysql-connector:
Relevant Stack Trace (inner exception)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.tomcat.jdbc.pool.DataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException: Cannot load driver class: com.mysql.jdbc.driver
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
... 62 common frames omitted
Caused by: java.lang.IllegalStateException: Cannot load driver class: com.mysql.jdbc.driver
notice how this is trying to use org.apache.tomcat to create datasource, even though I am using a glassfish server. Does this matter?
Source Code: the first relevant exception occurs when spring tries to inject the datasource bean that is a parameter to this method and can't create it
#Configuration
#EnableAutoConfiguration
public class AppConfigUtil {
#Autowired
#Bean
public EntityManagerFactory entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
bean.setPackagesToScan("com.connor");
bean.setDataSource(dataSource);
return bean.getObject();
}
Maven (pom.xml) for mysql jar:
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
application.properties: this is the entirety of my application.properties file spring uses to generate datasource
spring.datasource.url=jdbc:mysql://localhost:3307/craigslist
spring.datasource.username=dbadmin
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.driver
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
hibernate.format_sql=true
Here is picture of my maven dependencies: the mysql jar is present:
downloaded maven dependencies: including mysql jar
Any ideas on how to fix this?
Assuming you are using Spring boot.
Here are some things you can do to make it work (You might have done some of these, I added anything I can think of just to make sure):
Remove your AppConfigUtil class because Spring boot will "magically" find the datasource for you if your application.properties is configured right.
Add #SpringBootApplication to your ConnerApplication.java class
Add spring-boot-starter-data-jpa dependency in your pom
Some side notes:
#Autowire is not intended to be marked with #Bean annotation. #Autowire CAN be used to autowire bean which is annotated with #Bean.
EDIT :
I realized that OP wants to deploy it on Glassfish. In that case, you will need to tweak Spring to produce a deployable war file and configure your application container (glassfish) to include a jdbc driver. All of it is doable but requires a lot of efforts.
I suggested that you go with embedded tomcat approach if you use Spring-boot for new project. It is basically battle-ready. You can hardly go wrong with this.
You don't need declare in pom.xml
spring.datasource.driver-class-name=com.mysql.jdbc.driver
You can read my configuration in a simple app using Spring Boot here
Beside, if you're using Spring Boot you don't need use codes "Source Code: the first relevant exception occurs when spring tries to inject the datasource bean that is a parameter to this method and can't create it..."

Disabling Transaction Management in Spring JMS listener

I have a spring boot application as a Spring JMS listener. i have configured multiple datasource manager one for Oracle and another one for DB2 .
whenever i am starting app ,jms listener container is looking for a transaction manager bean and giving below error as it find two bean.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.jms.JmsAnnotationDrivenConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.transaction.PlatformTransactionManager org.springframework.boot.autoconfigure.jms.JmsAnnotationDrivenConfiguration.transactionManager; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined: expected single matching bean but found 2: db2TransactionManager,oracleTransactionManager
i dont want to maintain JMS transaction. how could i achieve it or how can we disable jms transaction feature?
below are the annotation i have added on my main spring boot class. also i am using Spring Data repository
#SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class})
#ComponentScan(basePackages = "com.deere.oracledataupdate.*")
//#EnableJpaRepositories(basePackages ="com.deere.oracledataupdate.dao.springdata")
#EntityScan(basePackages = "com.deere.oracledataupdate.*")
#PropertySource({ "classpath:application-${IafConfigSuffix}.properties" })
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Looking to the current Spring Boot code we have (JmsAnnotationDrivenConfiguration):
#Autowired(required = false)
private JtaTransactionManager transactionManager;
So, right now it requires only the bean which is exactly JtaTransactionManager by type. I guess both yours are DataSourceTransactionManager.
I'm sure that was correct fix to worry only about the XA tx-manager for auto-config.
Seems for me you can fix your issue with something like #Primary on one of your tx-manager beans.
But... Do you need a JMS Annotation support in your application at all?
Maybe it would be just enough to exclude JmsAnnotationDrivenConfiguration as well?
If need it anyway, I see only one way to fix it: disable JmsAnnotationDrivenConfiguration and configure #EnableJms manually, bypassing the tx-manager issue and just don't configure it for the DefaultJmsListenerContainerFactory as you request.
See JmsAnnotationDrivenConfiguration source code for more information.

Mockito Spring 3.1 Integration

I have been using #Configuration support in Spring to create my Mockito Mocks for use in JUnit tests
#Configuration
public class MockAppContextHelper {
#Bean
public IntegrationServerServiceWrapper integrationServerServiceWrapperTest() {
return mock(IntegrationServerServiceWrapper.class);
}
}
This used to work fine in Spring 3.0.2.
In Spring 3.1 I get the following error:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'integrationServerServiceWrapperTest' defined in class path resource [com/kn/bpa/task/service/impl/MockAppContextHelper.class]: No matching factory method found: factory bean 'mockAppContextHelper'; factory method 'integrationServerServiceWrapperTest()'. Check that a method with the specified name exists and that it is non-static.
Any ideas?
Thanks for your support
Consider adding a reproduction project per the instructions at https://github.com/SpringSource/spring-framework-issues#readme that demonstrates the configuration in question working in 3.0.2 and failing against 3.1.x

Resources