How to test spring batch job - java

I'm trying to test a job but I can't get to the bottom of it, basically my step consists of a single reader and a composite Processor and a Composite writer, all this because I have to read from a single .CSV and write on MongoDB and Mysql,
here is my Job Configuration class:
#Configuration
#EnableBatchProcessing
public class BatchConfiguration {
#Autowired
public JobBuilderFactory jobBuilderFactory;
#Autowired
public StepBuilderFactory stepBuilderFactory;
#Autowired
public MarketDataMySqlRepository marketDataMySqlRepository;
#Value("${file.input}")
private String fileInput;
#Bean
public TaskExecutor taskExecutor(){
SimpleAsyncTaskExecutor taskExecutor=new SimpleAsyncTaskExecutor("customerInfoThreads-");
return taskExecutor;
}
#Bean
public FlatFileItemReader<MarketDataDto> reader() {
return new FlatFileItemReaderBuilder<MarketDataDto>().name("ItemReader")
.resource(new PathResource(fileInput)).delimited()
.names("time","id", "price", "quantity", "isbuyermaker")
.fieldSetMapper(new BeanWrapperFieldSetMapper<MarketDataDto>() {
{
setTargetType(MarketDataDto.class);
}
}).build();
}
#Bean
public MongoItemWriter<MarketDataMongo> writer(MongoTemplate mongoTemplate) {
return new MongoItemWriterBuilder<MarketDataMongo>().template(mongoTemplate).collection("marketdata")
.build();
}
#Bean
public RepositoryItemWriter<MarketDataMySql> writer1() {
RepositoryItemWriter<MarketDataMySql> writer = new RepositoryItemWriter<>();
writer.setRepository(marketDataMySqlRepository);
writer.setMethodName("save");
return writer;
}
#Bean
public CompositeItemWriter CompositeItemWriter(MongoTemplate mongoTemplate){
CompositeItemWriter writer = new CompositeItemWriter();
writer.setDelegates(Arrays.asList(writer(mongoTemplate),writer1()));
return writer;
}
#Bean
public UserItemProcessorMongo MongoProcessor() {
return new UserItemProcessorMongo();
}
#Bean
public UserItemProcessorMySql MySqlProcessor() {return new UserItemProcessorMySql();}
#Bean
public CompositeItemProcessor compositeProcessor() throws Exception {
List<ItemProcessor<MarketDataDto,MarketDataMongo>> itemProcessors = new ArrayList<>(1);
List<ItemProcessor<MarketDataDto,MarketDataMySql>> itemProcessors1 = new ArrayList<>(1);
itemProcessors1.add(MySqlProcessor());
itemProcessors.add(MongoProcessor());
CompositeItemProcessor processor = new CompositeItemProcessor();
processor.setDelegates(itemProcessors);
processor.setDelegates(itemProcessors1);
//processor.afterPropertiesSet();
return processor;
}
#Bean
public Step step1(FlatFileItemReader<MarketDataDto> itemReader, MongoItemWriter<MarketDataMongo> itemWriter, MongoTemplate mongoTemplate)
throws Exception {
return this.stepBuilderFactory.get("step1").chunk(200000).reader(itemReader)
.processor(compositeProcessor()).writer(CompositeItemWriter(mongoTemplate)).build();
}
#Bean
public Job updateUserJob(JobCompletionNotificationListener listener, Step step1)
throws Exception {
return this.jobBuilderFactory.get("updateMarketJob").incrementer(new RunIdIncrementer())
.listener(listener).start(step1).build();
}
}
And this is my TestClass :
#RunWith(SpringRunner.class)
#SpringBatchTest
#ContextConfiguration(classes= {BatchConfiguration.class, BatchAutoConfiguration.class})
public class BatchConfigurationTest {
#Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
#Autowired
private JobRepositoryTestUtils jobRepositoryTestUtils;
#Autowired
private MarketDataMySqlRepository marketDataMySqlRepository;
#Test
public void readerTest() throws Exception {
JobParameters jobParameters = this.jobLauncherTestUtils.getUniqueJobParameters();
JobExecution jobExecution = this.jobLauncherTestUtils.launchJob(jobParameters);
Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
}
}
When i try to launch my test i riceive this Exception :
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:248)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jobRepositoryTestUtils': Unsatisfied dependency expressed through method 'setDataSource' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:767)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:719)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:132)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:141)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:90)
... 27 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1801)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1357)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:759)
... 46 more

Spring Batch automatically creates tables in db, do you have a database launched and linked to your project ?
If not, use the application.properties file to bind your project to the database, Exemple for Postgres database, with db name dbName :
spring.datasource.platform=postgres
spring.datasource.jdbc-url=jdbc:postgresql://host:port/dbName
spring.datasource.username=postgres
spring.datasource.password=postgres

I answer to myself, maybe it can be useful to someone, I created a configuration class for my Datasource with a configuration bean inside:
public class DataSourceConfig {
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1");
dataSource.setUsername("sa");
dataSource.setPassword("sa");
return dataSource;
}}
although i solved this problem now i have others lol, i hope it will be useful to someone :-)

Related

SPRING-BATCH ERROR: No context holder available for step scope

This is my simple job configuration:
#Configuration
public class Testjob {
#Autowired
private StepBuilderFactory stepBuilderFactory;
#Autowired
private JobBuilderFactory jobBuilderFactory;
#Bean
#org.springframework.batch.core.configuration.annotation.StepScope
public Step step1() {
return stepBuilderFactory.get("step1")
.tasklet((stepContribution, chunkContext) -> {
System.out.println("Hello World !");
return RepeatStatus.FINISHED;
}).build();
}
#Bean
#DependsOn("step1")
public Job job1() {
return jobBuilderFactory.get("job1")
.start(step1())
.build();
}
#Bean
public StepScope stepScope() {
StepScope stepScope = new StepScope();
stepScope.setAutoProxy(true);
return stepScope;
}
}
As you can see I have configured the stepScope bean as instructed over here and and also added the following line to my application.properties:
spring.main.allow-bean-definition-overriding=true
This is the error I am getting. Where am I going wrong ?
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.step1': Scope 'step' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No context holder available for step scope
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:368) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:192) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at com.sun.proxy.$Proxy359.getName(Unknown Source) ~[na:na]
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:115) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:410) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:319) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:147) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at com.sun.proxy.$Proxy360.run(Unknown Source) ~[na:na]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.execute(JobLauncherCommandLineRunner.java:192) ~[spring-boot-autoconfigure-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.executeLocalJobs(JobLauncherCommandLineRunner.java:166) ~[spring-boot-autoconfigure-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.launchJobFromProperties(JobLauncherCommandLineRunner.java:153) ~[spring-boot-autoconfigure-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.run(JobLauncherCommandLineRunner.java:148) ~[spring-boot-autoconfigure-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:784) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:768) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:322) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at com.foo.BatchApplication.main(BatchApplication.java:17) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.2.6.RELEASE.jar:2.2.6.RELEASE]
Caused by: java.lang.IllegalStateException: No context holder available for step scope
at org.springframework.batch.core.scope.StepScope.getContext(StepScope.java:167) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.core.scope.StepScope.get(StepScope.java:99) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:356) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
... 37 common frames omitted
Please note my project has 2 datasources configured, along with Spring MVC Web:
Datasource 1, for JPA/Hiberate:
#Configuration
#EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactory",
basePackages = {"com.foo.repositories"})
public class JpaConfig {
#Autowired
private Environment env;
#Bean
#Primary
#ConfigurationProperties("spring.datasource")
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#Primary
#DependsOn({"dataSourceProperties"})
public DataSource hikariDataSource(DataSourceProperties dataSourceProperties) {
return dataSourceProperties.initializeDataSourceBuilder().build();
}
#Bean("entityManagerFactory")
#DependsOn({"hikariDataSource"})
public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean(EntityManagerFactoryBuilder
entityManagerFactoryBuilder, #Qualifier("hikariDataSource") DataSource dataSource) {
Map<String, Object> properties = new HashMap<>();
properties.put("hibernate.dialect", env.getProperty("spring.hib.properties.hibernate.dialect"));
properties.put("hibernate.temp.use_jdbc_metadata_defaults", env.getProperty(
"spring.hib.properties.hibernate.temp.use_jdbc_metadata_defaults"));
return entityManagerFactoryBuilder.dataSource(dataSource)
.persistenceUnit("TestPersistenceUnit")
.properties(properties)
.packages("com.foo.entities")
.build();
}
DataSource 2, for Spring Batch JDBC Job Repository:
#Configuration
public class BatchFrameworkConfig {
#Autowired
private Environment env;
#Bean("batch_datasource_properties")
#ConfigurationProperties("spring.batch.datasource")
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
#Bean("batch_datasource")
#DependsOn({"batch_datasource_properties"})
public DataSource batchFrameworkDatasource(DataSourceProperties dataSourceProperties) {
return dataSourceProperties.initializeDataSourceBuilder().build();
}
#Bean
#DependsOn({"batch_datasource"})
public BatchConfigurer defaultBatchConfigurer(#Qualifier("batch_datasource") DataSource dataSource) {
return new DefaultBatchConfigurer(dataSource);
}
}
I am unable to find the mysterious XML mentioned over here.
What is going wrong ?
Thanks.
My mistake.
#StepScope should be declared like the following:
#Configuration
#EnableBatchProcessing
public class Testjob {
#Autowired
private StepBuilderFactory stepBuilderFactory;
#Autowired
private JobBuilderFactory jobBuilderFactory;
#Bean
#StepScope
public Tasklet helloWorldTasklet() {
return (stepContribution, chunkContext) -> {
System.out.println("Hello World !");
return RepeatStatus.FINISHED;
};
}
#Bean
public Step step1() {
return stepBuilderFactory.get("step1")
.tasklet(helloWorldTasklet())
.build();
}
#Bean
public Job job1() {
return jobBuilderFactory.get("job1")
.start(step1())
.build();
}
}
Notice that the helloWorldTasklet bean is declared as #StepScope and not my #Step.
Using Java configuration, you don't need to register yourself the StepScope (this is for XML), add the annotation #EnableBatchProcessing on your configuration. In your case, you don't need to add #StepScope and #DependsOn.
#Configuration
#EnableBatchProcessing
public class Testjob {
#Autowired
private StepBuilderFactory stepBuilderFactory;
#Autowired
private JobBuilderFactory jobBuilderFactory;
#Bean
public Step step1() {
return stepBuilderFactory.get("step1")
.tasklet((stepContribution, chunkContext) -> {
System.out.println("Hello World !");
return RepeatStatus.FINISHED;
}).build();
}
#Bean
public Job job1() {
return jobBuilderFactory.get("job1")
.start(step1())
.build();
}
}
Use #JobScope and #StepScope on bean used in your step or job when you need a new instance for each job or step.

Integration tests with JUnit5 and Mockito in spring boot

I have a problem with controller test in spring boot. I can't find anywhere example how should looks spring controller integration test with junit5 and mockito. I have written something like this:
#ExtendWith(SpringExtension.class)
#WebMvcTest(UserController.class)
class UserControllerTest {
#MockBean
private UserService userService;
#Autowired
private MockMvc mockMvc;
private User user;
#BeforeEach
void init(){
user = getUserData();
}
private User getUserData(){
User u = new User();
u.setId(0);
return u;
}
#Test
void shouldReturnDefaultMessage() throws Exception {
int id = 0;
when(userService.findById(id)).thenReturn(Optional.ofNullable(user));
this.mockMvc.perform(get("/user/" + id))
.andDo(print())
.andExpect(status()
.isOk())
.andExpect(jsonPath("$.id", is(String.valueOf(id))));
}
}
UserController.class:
#RestController
#RequestMapping(value = "/user")
public class UserController {
private final UserService userService;
private final ConverterContext converterContext;
public UserController(UserService userService,
ConverterContext converterContext) {
this.userService = userService;
this.converterContext = converterContext;
}
#RequestMapping(value = "", method = RequestMethod.GET)
public ResponseEntity get(#RequestParam(value = "username", required = false) #ExistAccountWithUsername String username) {
if(!username.isEmpty()){
return getUsersByUsername(username);
}
return getAllUsers();
}
private ResponseEntity getUsersByUsername(String username){
Optional<User> user = userService.findByUsername(username);
ShowUserDto showUserDto = convert(user.get());
return new ResponseEntity<>(showUserDto, HttpStatus.OK);
}
private ResponseEntity getAllUsers(){
List<User> users = userService.findAll();
List<ShowUserDto> showUserDtos = users.stream()
.map(this::convert)
.collect(Collectors.toList());
return new ResponseEntity<>(showUserDtos, HttpStatus.OK);
}
#RequestMapping(value = "/{id}", method = RequestMethod.GET)
public ResponseEntity getById(#PathVariable(value = "id") int id) {
Optional<User> user = userService.findById(id);
if (user.isPresent()) {
ShowUserDto userDto = convert(user.get());
return new ResponseEntity<>(userDto, HttpStatus.OK);
} else {
return new ResponseEntity<>(new ResourceNotFoundMessage("user", "id", id), HttpStatus.NOT_FOUND);
}
}
private ShowUserDto convert(User user) {
return converterContext.getConverter(ConverterShowUserDto.class).convert(user);
}
}
And i get error:
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:108)
at org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.postProcessFields(MockitoTestExecutionListener.java:99)
at org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.injectFields(MockitoTestExecutionListener.java:79)
at org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.prepareTestInstance(MockitoTestExecutionListener.java:54)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:246)
at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:97)
at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$null$2(ClassTestDescriptor.java:204)
at org.junit.jupiter.engine.descriptor.JupiterTestDescriptor.executeAndMaskThrowable(JupiterTestDescriptor.java:145)
at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$invokeTestInstancePostProcessors$3(ClassTestDescriptor.java:204)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312)
at java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:743)
at java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:742)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.invokeTestInstancePostProcessors(ClassTestDescriptor.java:203)
at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.instantiateAndPostProcessTestInstance(ClassTestDescriptor.java:189)
at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$testInstanceProvider$1(ClassTestDescriptor.java:181)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:80)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:60)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$null$2(HierarchicalTestExecutor.java:92)
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
at java.util.Iterator.forEachRemaining(Iterator.java:116)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$execute$3(HierarchicalTestExecutor.java:92)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:77)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$null$2(HierarchicalTestExecutor.java:92)
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
at java.util.Iterator.forEachRemaining(Iterator.java:116)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$execute$3(HierarchicalTestExecutor.java:92)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:77)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:51)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:74)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userController' defined in file [D:\zzz\target\classes\pl\xxx\zzz\controller\user\UserController.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'pl.xxx.zzz.converter.ConverterContext' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:732)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:197)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1276)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1133)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:503)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:760)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:395)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:327)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:139)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:117)
... 61 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'pl.xxx.zzz.converter.ConverterContext' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1509)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1065)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:818)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:724)
... 79 more
When I ran your code as it is, this is the error I got
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
'in.phani.springboot.camel.controller.UserService' available: expected
at least 1 bean which qualifies as autowire candidate. Dependency
annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
Which means spring is searching for UserService bean. i.e. your mock is not being taken.
Use #MockBean instead of #Mock.
#MockBean
private UserService userService;
That should solve the problem. On a high level the basic difference is
#Mock is a class from Mockito. It is just a mock, it doesn't do anything as such.
#MockBean It allows to add Mockito mocks in a Spring ApplicationContext. (this is exactly what is missing in your case)

Spring boot multiple datasource configuration

I am trying to configure multiple data sources in spring boot app. But I am getting following error when application is about to boot.
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mySQLReplicationStatusService': Unsatisfied dependency expressed through field 'jdbcTemplate'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.jdbc.core.JdbcTemplate' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=msMysqlJdbcTemplate)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.jdbc.core.JdbcTemplate' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=msMysqlJdbcTemplate)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:283)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
Here is my configuration class looks like:
package com.example;
#Configuration
public class MultipleDBConfig {
#Bean(name = "masterMysqlDb")
#Primary
#ConfigurationProperties(prefix = "spring.ds_master_mysql")
public DataSource masterMysqlDataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "msMysqlJdbcTemplate")
public JdbcTemplate masterJdbcTemplate(#Qualifier("masterMysqlDb") DataSource masterMysqlDb) {
return new JdbcTemplate(masterMysqlDb);
}
#Bean(name = "slaveMysqlDb")
#ConfigurationProperties(prefix = "spring.ds_slave_mysql")
public DataSource slaveMysqlDataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "slaveMysqlJdbcTemplate")
public JdbcTemplate slaveJdbcTemplate(#Qualifier("slaveMysqlDb") DataSource dsSlaveMySQL) {
return new JdbcTemplate(dsSlaveMySQL);
}
}
Here is my service class:
package com.example.replication.service;
#Service
public class MySQLReplicationStatusService {
#Autowired
#Qualifier("msMysqlJdbcTemplate")
private JdbcTemplate jdbcTemplate;
#Autowired
#Qualifier("slaveMysqlJdbcTemplate")
private JdbcTemplate slaveJdbcTemplate;
public void checkReplicationStatus(String dbName, String tableName){
System.out.println("In checkReplicationStatus");
Connection conn_master = null;
Statement stmt_master = null;
StringBuilder sbSql_master = null;
ResultSet rs_master = null;
Connection conn_slave = null;
Statement stmt_slave = null;
StringBuilder sbSql_slave = null;
ResultSet rs_slave = null;
try{
conn_master = jdbcTemplate.getDataSource().getConnection();
stmt_master = conn_master.createStatement();
sbSql_master = new StringBuilder();
sbSql_master.append("SELECT COLUMN_NAME");
sbSql_master.append("FROM information_schema.COLUMNS");
sbSql_master.append("WHERE (TABLE_SCHEMA = " + dbName + ")");
sbSql_master.append("AND (TABLE_NAME = " + tableName + ")");
sbSql_master.append("AND (COLUMN_KEY = 'PRI') ");
rs_master = stmt_master.executeQuery(sbSql_master.toString());
/*conn_slave = slaveJdbcTemplate.getDataSource().getConnection();
stmt_slave = conn_slave.createStatement();
sbSql_slave = new StringBuilder();
sbSql_slave.append("SELECT * FROM ").append(dbName).append(".").append(tableName);
rs_slave = stmt_slave.executeQuery(sbSql_slave.toString());*/
if(rs_master != null){
while(!rs_master.isLast()){
rs_master.next();
Object obj = rs_master.getObject(1);
Object obj2 = rs_master.getObject(2);
String key = null;
String val = null;
if(obj != null){
key = obj.toString();
System.out.println("Key = " + key);
}
if(obj2 != null){
val = obj2.toString();
System.out.println("Value = " + val);
}
}
}
}
catch(SQLException e){
e.printStackTrace();
}
}
}
Here is component class:
#Component
public class MySQLReplicationStatusCheck {
final static Logger logger = Logger.getLogger(MySQLReplicationStatusCheck.class);
#Autowired
private MySQLReplicationStatusService mysqlReplicationStatusService = null;
#Value("${master.db_name}")
private String databaseName;
#Value("${master.table_name}")
private String tableName;
public void replicationEvent(){
logger.info("Inside replicationEvent method");
System.out.println("Inside replicationEvent method");
mysqlReplicationStatusService.checkReplicationStatus(databaseName, tableName);
}
}
Here is my application.properties:
logging.config=./conf/log4j.xml
spring.ds_master_mysql.url = jdbc:mysql://<host>:3306
spring.ds_master_mysql.username = username
spring.ds_master_mysql.password = password
spring.ds_master_mysql.driverClassName=com.mysql.jdbc.Driver
master.db_name=fdmsus_demo
master.table_name=vitalstats
Here is Spring boot class:
package com.example;
#SpringBootApplication
public class FdmsMysqlReplicationApplication {
public static void main(String[] args) {
SpringApplication.run(FdmsMysqlReplicationApplication.class, args);
}
}
However I am not able to figure out where is I am missing something. Can anyone please help me get this done.
Thanks.
I think issue is with declaring driver class name in application.properties
logging.config=./conf/log4j.xml
spring.ds_master_mysql.url = jdbc:mysql://<host>:3306
spring.ds_master_mysql.username = username
spring.ds_master_mysql.password = password
spring.ds_master_mysql.driverClassName=com.mysql.jdbc.Driver
master.db_name=fdmsus_demo
master.table_name=vitalstats
Use below application.properties:
logging.config=./conf/log4j.xml
spring.ds_master_mysql.url = jdbc:mysql://<host>:3306
spring.ds_master_mysql.username = username
spring.ds_master_mysql.password = password
spring.ds_master_mysql.driver-class-name=com.mysql.jdbc.Driver
master.db_name=fdmsus_demo
master.table_name=vitalstats
SpringBoot configuration multiple datasource:
application.properties
#spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.generate-ddl=true
spring.jpa.database=default
logging.level.org.springframework = info
spring.jpa.show-sql=true
spring.jpa.open-in-view=true
spring.jpa.hibernate.ddl-auto=create-drop
# Connection properties of Data Source A
spring.datasource.a.url=jdbc:mysql://localhost:3306/demo1?serverTimezone=UTC
spring.datasource.a.jdbcUrl=${spring.datasource.a.url}
spring.datasource.a.username = root
spring.datasource.a.password =
spring.datasource.a.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.a.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
# Connection properties of Data Source B
spring.datasource.b.url=jdbc:mysql://localhost:3306/demo2?serverTimezone=UTC
spring.datasource.b.jdbcUrl=${spring.datasource.b.url}
spring.datasource.b.username = root
spring.datasource.b.password =
spring.datasource.b.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.b.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
ConfigA.java
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = {"api.a.repo"})
public class ConfigA {
#Autowired
private Environment env;
#Primary
#Bean(name = "dataSourceA")
#ConfigurationProperties(prefix = "spring.datasource.a")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
#Primary
#Bean(name = "entityManagerFactoryA")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder,
#Qualifier("dataSourceA") DataSource dataSource) {
Map<String, Object> properties = new HashMap<>();
properties.put("hibernate.show-sql", env.getProperty("spring.datasource.a.jpa.show-sql"));
properties.put("spring.jpa.hibernate.ddl-auto", env.getProperty("spring.datasource.a.hibernate.dialect"));
properties.put("hibernate.dialect", env.getProperty("spring.datasource.a.hibernate.dialect"));
return builder
.dataSource(dataSource)
.properties(properties)
.packages("api.a.model")
.persistenceUnit("datasourceA")
.build();
}
#Primary
#Bean(name = "transactionManagerA")
public PlatformTransactionManager transactionManager(#Qualifier("entityManagerFactoryA") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
ConfigB.java
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = {"api.b.repo"})
public class ConfigB {
#Autowired
private Environment env;
#Bean(name = "dataSourceB")
#ConfigurationProperties(prefix = "spring.datasource.b")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "entityManagerFactoryB")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder,
#Qualifier("dataSourceB") DataSource dataSource) {
Map<String, Object> properties = new HashMap<>();
properties.put("hibernate.show-sql", env.getProperty("spring.datasource.b.jpa.show-sql"));
properties.put("spring.jpa.hibernate.ddl-auto", env.getProperty("spring.datasource.b.hibernate.dialect"));
properties.put("hibernate.dialect", env.getProperty("spring.datasource.b.hibernate.dialect"));
return builder
.dataSource(dataSource)
.packages("api.b.model")
.persistenceUnit("datasourceB")
.build();
}
#Bean(name = "transactionManagerB")
public PlatformTransactionManager transactionManager(#Qualifier("entityManagerFactoryB") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
visit : https://github.com/johanmoncada/OpenWork
I faced the same issue a few days back and solved it. I'm using spring boot version 3.0.1 and java version 19. Here is the source code
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
**for oracle db**
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<scope>runtime</scope>
</dependency>
**for postgresql db**
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
application.properties
#first DB MYSQL
first.db.datasource.jdbc-url: jdbc:mysql://localhost:3306/test_db
first.db.datasource.username:
first.db.datasource.password:
first.db.datasource.driverClassName: com.mysql.jdbc.Driver
#second DB mysql ...
second.db.datasource.jdbc-url: jdbc:mysql://localhost:3308/test_db_2
second.db.datasource.username:
second.db.datasource.password:
second.db.datasource.driverClassName: com.mysql.jdbc.Driver
Config Class for the first datasource
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef = "firstDBEntityManagerFactory",
transactionManagerRef = "firstDBTransactionManager",
basePackages = {"com.*.*.repository"})
public class FirstDbConfig {
#Primary
#Bean(name = "firstDBDataSource")
#ConfigurationProperties(prefix = "first.db.datasource")
public DataSource firstDataSource() {
return DataSourceBuilder.create().build();
}
#Primary
#Bean(name = "firstDBEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder,
#Qualifier("firstDBDataSource") DataSource dataSource) {
return builder.dataSource(dataSource).packages("com.*.*.entity")
.persistenceUnit("db1").build();
}
#Primary
#Bean(name = "firstDBTransactionManager")
public PlatformTransactionManager firstDBTransactionManager(#Qualifier("firstDBEntityManagerFactory") EntityManagerFactory firstDBEntityManagerFactory) {
return new JpaTransactionManager(firstDBEntityManagerFactory);
}
}
Config Class for the second datasource
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef = "secondDBEntityManagerFactory",
transactionManagerRef = "secondDBTransactionManager",
basePackages = {"com.*.*.seconddb.repository"})
public class SecondDbConfig {
#Bean(name = "secondDBDataSource")
#ConfigurationProperties(prefix = "second.db.datasource")
public DataSource secondDataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "secondDBEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean secondDBEntityManagerFactory(EntityManagerFactoryBuilder builder, #Qualifier("secondDBDataSource") DataSource dataSource) {
return builder.dataSource(dataSource)
.packages("com.*.*.seconddb.entity")
.persistenceUnit("db2")
.build();
}
#Bean(name = "secondDBTransactionManager")
public PlatformTransactionManager secondDBTransactionManager(#Qualifier("secondDBEntityManagerFactory") EntityManagerFactory secondDBEntityManagerFactory) {
return new JpaTransactionManager(secondDBEntityManagerFactory);
}
}

Spring 5+Glassfish 4.1+ hibernate 5 : AbstractMethodError: oracle.jdbc.driver.T4CConnection.getSchema

we are upgrading an application and I'm really stuck for days on the error below when trying to deploy the application on glassfish 4.1.1
Environment :
Java 8
DB1: Oracle 11g DB (ojdbc6.jar)
DB2: Informix DB
Hibernate Core : 5.2.8.Final
Hibernate Search : 5.7.0.Final
Spring 5.0.0
Atomikos 4.0.4 (for transaction management)
Hibernate Search failed with the following error :
ERROR o.s.web.context.ContextLoader - Context initialization failed
org.hibernate.search.exception.SearchException: HSEARCH000222: The SearchFactory was not initialized
But when I look at the server instance log, the root cause is in the stack trace below :
[2017-03-04T16:47:44.366-0500] [glassfish 4.1] [SEVERE] [jdbc.ex_connection_holder]
[javax.enterprise.resource.resourceadapter.com.sun.gjc.spi] [tid: _ThreadID=56 _ThreadName=admin-listener(4)] [timeMillis: 1488664064366] [levelValue: 1000] [[
RAR9008 : Exception while invoking method on Connection object. Exception : {0}
javax.resource.ResourceException: java.lang.reflect.InvocationTargetException
at com.sun.gjc.util.MethodExecutor.invokeMethod(MethodExecutor.java:244)
at com.sun.gjc.spi.jdbc40.ConnectionHolder40.getSchema(ConnectionHolder40.java:609)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.hibernate.engine.jdbc.env.internal.DefaultSchemaNameResolver$SchemaNameResolverJava17Delegate.resolveSchemaName(DefaultSchemaNameResolver.java:72)
at org.hibernate.engine.jdbc.env.internal.DefaultSchemaNameResolver.resolveSchemaName(DefaultSchemaNameResolver.java:59)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl.determineCurrentSchemaName(JdbcEnvironmentImpl.java:274)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl.<init>(JdbcEnvironmentImpl.java:210)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:114)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:234)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:208)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:189)
at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:217)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:189)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874)
at org.hibernate.jpa.HibernatePersistenceProvider.createContainerEntityManagerFactory(HibernatePersistenceProvider.java:135)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:353)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:370)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:359)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1081)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:856)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:443)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:325)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
at org.apache.catalina.core.StandardContext.contextListenerStart(StandardContext.java:5394)
at com.sun.enterprise.web.WebModule.contextListenerStart(WebModule.java:743)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:5963)
at com.sun.enterprise.web.WebModule.start(WebModule.java:691)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:1041)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:1024)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:747)
at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:2286)
at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:1932)
at com.sun.enterprise.web.WebApplication.start(WebApplication.java:139)
at org.glassfish.internal.data.EngineRef.start(EngineRef.java:122)
at org.glassfish.internal.data.ModuleInfo.start(ModuleInfo.java:291)
at org.glassfish.internal.data.ApplicationInfo.start(ApplicationInfo.java:352)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.sun.gjc.util.MethodExecutor.invokeMethod(MethodExecutor.java:238)
... 130 more
Caused by: java.lang.AbstractMethodError: oracle.jdbc.driver.T4CConnection.getSchema()Ljava/lang/String;
... 135 more
]]
These are all classes of my configuration :
#Configuration
#Import({AtomikosJtaConfig.class, Db1DatabaseConfig.class, Db2DatabaseConfig.class})
public class DatabaseConfig {
}
#Configuration
#ComponentScan
#EnableTransactionManagement
public class AtomikosJtaConfig {
private static final Logger log = LoggerFactory.getLogger(AtomikosJtaConfig.class.getSimpleName());
#Bean(name = "atomikosUserTransaction")
public UserTransaction atomikosUserTransaction() {
UserTransactionImp userTransactionImp = new UserTransactionImp();
try {
userTransactionImp.setTransactionTimeout(240);
} catch (SystemException e) {
log.debug(" Failed to set atomikos user transaction timeout. Caught {} ", e);
throw new AtomikosConfigException(" Failed to set atomikos user transaction timeout. Caught {} ", e);
}
return userTransactionImp;
}
#Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close")
public TransactionManager atomikosTransactionManager() {
UserTransactionManager userTransactionManager = new UserTransactionManager();
userTransactionManager.setForceShutdown(true);
userTransactionManager.setStartupTransactionService(false);
return userTransactionManager;
}
#Bean(name = "transactionManager")
#DependsOn({ "atomikosUserTransaction", "atomikosTransactionManager" })
public PlatformTransactionManager transactionManager() {
return new JtaTransactionManager(atomikosUserTransaction(), atomikosTransactionManager());
}
}
#Configuration
#DependsOn("transactionManager")
#EnableJpaRepositories(
entityManagerFactoryRef = "db1EntityManagerFactory"
)
#ComponentScan("xx.xxx.xxx.db1")
public class Db1DatabaseConfig extends BaseDatabaseConfig {
#Primary
#Bean(name = "db1DataSource")
public DataSource db1DataSource() {
JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
dsLookup.setResourceRef(true);
return dsLookup.getDataSource("jdbc/db1DB");
}
#Primary
#Bean(name = "db1EntityManagerFactory")
public LocalContainerEntityManagerFactoryBean db1EntityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setPackagesToScan("xx.xxx.xxx.db1.entity");
entityManagerFactory.setPersistenceUnitName("db1PU");
entityManagerFactory.setJtaDataSource(db1DataSource());
entityManagerFactory.setPersistenceProvider(new HibernatePersistenceProvider());
entityManagerFactory.setJpaVendorAdapter(db1JpaVendorAdapter());
entityManagerFactory.setJpaDialect(new HibernateJpaDialect());
entityManagerFactory.setJpaPropertyMap(jpaPropertiesMap());
entityManagerFactory.setJpaProperties(jpaAdditionalProperties());
return entityManagerFactory;
}
#Bean("fullTextEntityManager")
public FullTextEntityManager fullTextEntityManager() throws InterruptedException {
return Search.getFullTextEntityManager(db1EntityManagerFactory().getObject().createEntityManager());
}
#Bean
public PersistenceAnnotationBeanPostProcessor persistenceAnnotationBeanPostProcessor() {
return new PersistenceAnnotationBeanPostProcessor();
}
#Bean
public PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
#Configuration
#DependsOn("transactionManager")
#EnableJpaRepositories(
entityManagerFactoryRef = "db2EntityManagerFactory"
)
#ComponentScan("xx.xxx.xxx.db2")
public class Db2DatabaseConfig extends BaseDatabaseConfig {
#Primary
#Bean(name = "db2DataSource")
public DataSource db2DataSource() {
JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
dsLookup.setResourceRef(true);
return dsLookup.getDataSource("jdbc/db2DB");
}
#Bean(name = "db2EntityManagerFactory")
public LocalContainerEntityManagerFactoryBean db2EntityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setPackagesToScan("xx.xxxdb2.entity");
entityManagerFactory.setPersistenceUnitName("db2PU");
entityManagerFactory.setJtaDataSource(db2DataSource());
entityManagerFactory.setPersistenceProvider(new HibernatePersistenceProvider());
entityManagerFactory.setJpaVendorAdapter(db2JpaVendorAdapter());
entityManagerFactory.setJpaDialect(new HibernateJpaDialect());
entityManagerFactory.setJpaPropertyMap(jpaPropertiesMap());
return entityManagerFactory;
}
#Bean
public PersistenceAnnotationBeanPostProcessor persistenceAnnotationBeanPostProcessor() {
return new PersistenceAnnotationBeanPostProcessor();
}
#Bean
public PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
public abstract class BaseDatabaseConfig {
protected Map<String, Object> jpaPropertiesMap() {
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.transaction.jta.platform","com.atomikos.icatch.jta.hibernate4.AtomikosPlatform");
properties.put("javax.persistence.transactionType","JTA");
properties.put("hibernate.search.autoregister_listeners","false");
properties.put("hibernate.connection.handling_mode","DELAYED_ACQUISITION_AND_RELEASE_AFTER_TRANSACTION");
properties.put("hibernate.connection.release_mode","on_close");
properties.put("hibernate.cache.use_second_level_cache","false");
return properties;
}
protected JpaVendorAdapter db2JpaVendorAdapter() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setDatabase(Database.INFORMIX);
hibernateJpaVendorAdapter.setShowSql(false);
hibernateJpaVendorAdapter.setGenerateDdl(false);
return hibernateJpaVendorAdapter;
}
protected JpaVendorAdapter db1JpaVendorAdapter() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.Oracle10gDialect");
hibernateJpaVendorAdapter.setShowSql(false);
hibernateJpaVendorAdapter.setGenerateDdl(false);
return hibernateJpaVendorAdapter;
}
JNDI resources (jdbc/db1DB and jdbc/db2DB) have been created successfully in Glassfish and are bind to connection pools (poolDB1 and poolDB2). Ping queries work. Oracle driver (ojdbc6.jar) and informix have been dropped in glassfish/domains/zzzz/lib and not package in the application (mark as provided im pom.xml)
I don't see what's wrong in my configuration.
Any help will be greatly appreciated.

Error while creating EmbeddedDataSource to testing purpose using profiles in Spring JPA/Hibernate

I am trying to test my simple app (Spring JPA/Hibernate) using JUnit and embeddedDataSource (yes i am aware that this should be done by integral tests). When i introduced spring profiles to my project and trying to create embedded dataSource in tests i got this exception :
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactoryBean' defined in class path resource [app/config/JdbcConfig.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1076)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:851)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:128)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:108)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:251)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
... 29 more
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:951)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:881)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:338)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:373)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:362)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
... 44 more
Caused by: org.hibernate.exception.SQLGrammarException: Unable to build DatabaseInformation
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97)
at org.hibernate.tool.schema.internal.Helper.buildDatabaseInformation(Helper.java:134)
at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigration(SchemaMigratorImpl.java:96)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:176)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:65)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:307)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:490)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:878)
... 50 more
Caused by: org.h2.jdbc.JdbcSQLException: Table "PG_CLASS" not found; SQL statement:
select relname from pg_class where relkind='S' [42102-192]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:179)
at org.h2.message.DbException.get(DbException.java:155)
at org.h2.command.Parser.readTableOrView(Parser.java:5388)
at org.h2.command.Parser.readTableFilter(Parser.java:1257)
at org.h2.command.Parser.parseSelectSimpleFromPart(Parser.java:1896)
at org.h2.command.Parser.parseSelectSimple(Parser.java:2044)
at org.h2.command.Parser.parseSelectSub(Parser.java:1890)
at org.h2.command.Parser.parseSelectUnion(Parser.java:1711)
at org.h2.command.Parser.parseSelect(Parser.java:1699)
at org.h2.command.Parser.parsePrepared(Parser.java:445)
at org.h2.command.Parser.parse(Parser.java:317)
at org.h2.command.Parser.parse(Parser.java:289)
at org.h2.command.Parser.prepareCommand(Parser.java:254)
at org.h2.engine.Session.prepareLocal(Session.java:560)
at org.h2.engine.Session.prepareCommand(Session.java:501)
at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1202)
at org.h2.jdbc.JdbcStatement.executeQuery(JdbcStatement.java:73)
at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:42)
at org.hibernate.tool.schema.internal.exec.ImprovedDatabaseInformationImpl.initializeSequences(ImprovedDatabaseInformationImpl.java:64)
at org.hibernate.tool.schema.internal.exec.ImprovedDatabaseInformationImpl.<init>(ImprovedDatabaseInformationImpl.java:58)
at org.hibernate.tool.schema.internal.Helper.buildDatabaseInformation(Helper.java:126)
... 56 more
My config:
#Configuration
#PropertySource("classpath:db.properties")
#EnableTransactionManagement
public class JdbcConfig
{
#Resource
public Environment env;
#Bean
#Profile("prod")
public DataSource dataSource()
{
System.out.println(env);
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName(env.getProperty("dataSource.driverClassName"));
ds.setUrl(env.getProperty("dataSource.Url"));
ds.setUsername(env.getProperty("dataSource.username"));
ds.setPassword(env.getProperty("dataSource.password"));
return ds;
}
#Bean
#Profile("test")
public DataSource embeddedDataSource()
{
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.build();
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(DataSource ds, JpaVendorAdapter jpaVendorAdapter)
{
LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
emfb.setDataSource(ds);
emfb.setJpaVendorAdapter(jpaVendorAdapter);
emfb.setPackagesToScan("app.model");
return emfb;
}
#Bean
public JpaVendorAdapter jpaVendorAdapter()
{
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabase(Database.POSTGRESQL);
adapter.setShowSql(true);
adapter.setGenerateDdl(true);
adapter.setDatabasePlatform(env.getProperty("dataSource.dialect"));
return adapter;
}
#Bean
public BeanPostProcessor beanPostProcessor()
{
return new PersistenceExceptionTranslationPostProcessor();
}
#Bean
public JpaTransactionManager jpaTransactionManager(EntityManagerFactory em)
{
return new JpaTransactionManager(em);
}
}
Missing bean to #PropertyContext is in other config file. And my tests looks like this:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = RootConfig.class)
#ActiveProfiles("test")
public class UserRepositoryTest
{
#Inject
UserDAO dao;
#Test
public void injectionDAOTest()
{
assertThat(dao,not(nullValue()));
}
}
As you can see property - generateDdl in hibernate is set, but it still doesn't work. What is the source of this error?
Problem solved. I didn't configure proper database type in jpaVendorAdapter

Categories