I am working on a project which wants to use spring-boot-data-jpa. The local (IDE) database can be H2. However, for all servers (dev/test/prod), we are forced to use DB/2 (unfortunately!).
We can't seem to get it things working with DB/2. We get an error like this:
java.lang.IllegalStateException: Failed to load ApplicationContext....
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type [...Repository] found for
dependency: expected at least 1 bean which qualifies as autowire candidate for this
dependency. Dependency annotations: {}
when running the unit tests (JUnit). Note, the blank {} annotation. Which on the face of it seems like an "obvious" issue. The repository bean can not be loaded or found on the classpath. However, when we run this with H2 configuration, it works just fine.
So, the next logical conclusion seems to be the repositories configuration (data source, etc.) is not set up correctly. However, we can use the same configuration values in a non spring boot application and it works fine!
So then I was thinking it could be something with the either the differing classloaders or cglib proxies not using the "real" implementation class. SO questions like these:
However, the correct answers for those questions do not resolve the issue. So here is my post/question.
How do figure out the root cause of this issue? I have tried to walk through the code (spring and our code) in the debugger but can't narrow down a cause.
So then I tried this, I took the sample spring boot jpa and modified it to use specific properties for DB/2 and I can get the same failure. So it seems like my configuration must be wrong or there is a bug in the spring code. I have looked at the configuration with someone else and we don't see the problem. We tried this configuration in another (non-spring boot app) and it works.
Here is a patch file that shows the differences between the original jpa sample and the modified one with the configuration changes. Note, we removed the DB2 server details. Hopefully, this makes the issue reproducible for anyone and then can assist in figuring out the cause.
TIA,
Scott
edit 1 --- add configuration details here directly instead of a patch file ---
Java Configuration
@Configuration
@ComponentScan
@EnableAutoConfiguration
@PropertySource("classpath:application.properties")
public class SampleDataJpaApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(SampleDataJpaApplication.class, args);
}
}
Properties File
spring.jpa.hibernate.naming_strategy: org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.hibernate.dialect: org.hibernate.dialect.DB2Dialect
#spring.jpa.database-platform: DB2Platform
spring.jpa.show-sql: true
spring.jpa.generate-ddl: true
spring.datasource.driverClassName: om.ibm.db2.jcc.DB2Driver
spring.datasource.url: jdbc:db2:someDB2-db:5000
spring.datasource.username: fakeuser
spring.datasource.password: fakepassword
spring.datasource.schema:schema-name
Unit Test Configuration
@RunWith(SpringJUnit4ClassRunner.class)
@PropertySource("classpath:application.properties")
@ContextConfiguration(classes = SampleDataJpaApplication.class, loader = AnnotationConfigContextLoader.class)
public class CityRepositoryIntegrationTests {
//....
}
This should be nearly identical to the patch file just changing the user/password/jdbc URL to hide the specifics of the environment.
As far as I can see, the JUnit setup is not correct. To let Boot work correctly you have two choices:
Use @SpringApplicationConfiguration
instead of @ContextConfiguration
Boot configures the ApplicationContext
bootstrap process quite a bit, eg to enable the default configuration files being picked up. Using the custom annotation will automatically activate that stuff for the JUnit executions as well.
Configure @ContextConfiguration
with the appropriate listeners yourself
In your case you at least need the ConfigFileApplicationContextInitializer
in addition to all the default ones registered.
As the second option is rather cumbersome, I highly recommend to go with option one and see where that leads you.
Oliver,
I can't seem to find the annotation @SpringApplicationConfiguration
using the spring-boot-starter-test JAR as defined in the how-to. I'm using spring boot 0.5.0.M6. Below are the dependencies in my Maven POM. Anything I'm missing here?
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
EDIT : After looking through the Spring Boot sample projects I found a different approach to getting Junit and Spring test to play nicely with each other. If you can define your class like the following things should work identical to what Oliver has mentioned in his reply for option 1. Notice the "loader" argument needs to be present to correctly configure listeners and backing beans correctly.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MyDataApplication.class, loader = SpringApplicationContextLoader.class)
public class MyServiceTest {
I have similar problem with integration tests in Spring Boot and I can confirm @user3166395 solution.
This configuration works for me:
import org.springframework.boot.test.SpringApplicationContextLoader;
import org.springframework.test.context.ContextConfiguration;
...
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MyDataApplication.class, loader = SpringApplicationContextLoader.class)
public class MyServiceTest {
@Autowired
CityRepository cityRepository;
}
This requires test dependency to:
org.springframework.boot:spring-boot-starter-test:0.5.0.M7
I cant achieve working test with SpringApplicationConfiguration
Hey guys a little late to the party but to be clear about your error (since I copied it, I had the same):
spring.datasource.driverClassName: **om**.ibm.db2.jcc.DB2Driver
should be
spring.datasource.driverClassName: **com**.ibm.db2.jcc.DB2Driver
This worked for me so far.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.