I started making a bot. And would like to take advantage of spirng data JPA to make it easier. In the context of the spring, I'm not strong. I'm using a 3rd party bot library and it ran the bot like this:
public class VkBot extends LongPollBot {
#Override
public void onMessageEvent(MessageEvent messageEvent) {
//code
}
#Override
public void onMessageNew(MessageNewEvent messageNewEvent) {
//code
}
public static void main(String[] args) throws VkApiException {
new BotsLongPoll(new VkBot()).run;
/*BotsLongPoll is a class of library*/
}
}
Now I have rewritten it so that it works like this:
#SpringBootApplication
public class VkBot extends LongPollBot {
PersonRepository personRepository;
#Autowired
public PersonRepository getPersonRepository() {
return personRepository;
}
#Override
public void onMessageEvent(MessageEvent messageEvent) {
//code
}
#Override
public void onMessageNew(MessageNewEvent messageNewEvent) {
personRepository.save(person)
//code
}
public static void main(String[] args) throws VkApiException {
AnnotationConfigApplicationContext annotationConfigApplicationContext =
new AnnotationConfigApplicationContext(JPAConfiguration.class);
BotsLongPoll botsLongPollBean = annotationConfigApplicationContext.getBean(BotsLongPoll.class);
botsLongPollBean.run();
}
Config:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories ("ru.voronavk.repositories")
#EnableAutoConfiguration
#EntityScan("ru.voronavk.entities")
#ComponentScan("ru.voronavk")
public class JPAConfiguration {
#Bean
VkBot vkBot(){
return new VkBot();
}
#Bean
BotsLongPoll botsLongPoll(){
return new BotsLongPoll(vkBot());
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUsername("equipment");
dataSource.setPassword("password");
dataSource.setUrl("jdbc:postgresql://127.0.0.1:5432/botsdb");
return dataSource;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan("ru.voronavk.ru.voronavk.entities");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
#Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
return new PersistenceExceptionTranslationPostProcessor();
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
return properties;
}
}
PersonRepository:
#Repository
public interface PersonRepository extends JpaRepository<Person, Long> {
}
I get an error
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'personRepository' defined in ru.voronavk.repositories.PersonRepository defined in #EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class ru.voronavk.entities.Person
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804) ~[spring-beans-5.3.20.jar:5.3.20]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.20.jar:5.3.20]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.20.jar:5.3.20]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.20.jar:5.3.20]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.20.jar:5.3.20]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.20.jar:5.3.20]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.20.jar:5.3.20]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:934) ~[spring-beans-5.3.20.jar:5.3.20]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.20.jar:5.3.20]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.20.jar:5.3.20]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:734) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) ~[spring-boot-2.7.0.jar:2.7.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1295) ~[spring-boot-2.7.0.jar:2.7.0]
at ru.voronavk.VkBot.main(VkBot.java:302) ~[classes/:na]
Caused by: java.lang.IllegalArgumentException: Not a managed type: class ru.voronavk.entities.Person
at org.hibernate.metamodel.internal.MetamodelImpl.managedType(MetamodelImpl.java:582) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.hibernate.metamodel.internal.MetamodelImpl.managedType(MetamodelImpl.java:85) ~[hibernate-core-5.6.10.Final.jar:5.6.10.Final]
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:75) ~[spring-data-jpa-2.7.0.jar:2.7.0]
at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:66) ~[spring-data-jpa-2.7.0.jar:2.7.0]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:233) ~[spring-data-jpa-2.7.0.jar:2.7.0]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:182) ~[spring-data-jpa-2.7.0.jar:2.7.0]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:165) ~[spring-data-jpa-2.7.0.jar:2.7.0]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:76) ~[spring-data-jpa-2.7.0.jar:2.7.0]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:324) ~[spring-data-commons-2.7.0.jar:2.7.0]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:322) ~[spring-data-commons-2.7.0.jar:2.7.0]
at org.springframework.data.util.Lazy.getNullable(Lazy.java:230) ~[spring-data-commons-2.7.0.jar:2.7.0]
at org.springframework.data.util.Lazy.get(Lazy.java:114) ~[spring-data-commons-2.7.0.jar:2.7.0]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:328) ~[spring-data-commons-2.7.0.jar:2.7.0]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:144) ~[spring-data-jpa-2.7.0.jar:2.7.0]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) ~[spring-beans-5.3.20.jar:5.3.20]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) ~[spring-beans-5.3.20.jar:5.3.20]
... 15 common frames omitted
Process finished with exit code 1
Tried also:
SpringBootApplication.run(BotsLongPoll.class)
Gave an NullPointer, bacause personRepository was null.
In which direction should I read?
Autowired annotation doesn't work like this. It's not an injection
#Autowired
public PersonRepository getPersonRepository() {
return personRepository;
}
You should read about different types of injection in Spring such as constructor, field, and setter injection, f.e. here
You should remove all these annotations from your JPAConfiguration, spring boot with data jpa starter does all what you need
#EnableTransactionManagement
#EnableJpaRepositories ("ru.voronavk.repositories")
#EnableAutoConfiguration
#EntityScan("ru.voronavk.entities")
#ComponentScan("ru.voronavk")
Also with spring boot you don't need to create infrastructure beans like DataSource. All settings can be written in application.properties or other config files. About data jpa you can read here
Rewrite or create class with #SpringBootApplication annotation in root package of your project. It should look like this:
#SpringBootApplication
public class VkBotConsoleApp implements CommandLineRunner {
#Autowired
private BotsLongPoll botsLongPoll;
public static void main(String[] args) {
SpringApplication.run(VkBotConsoleApp.class, args);
}
#Override
public void run(String... args) {
botsLongPoll.run();
}
}
Related
I am working on a Spring Batch application. Untill now I was able to unit test something like service methods and something like this (as done in every Spring Boot application).
Now I am trying to follow this tutorial in order to test an entire job from my unit test class (basically I want to execute a test method that perform a Job): https://www.baeldung.com/spring-batch-testing-job
This is my JUnit test class, in this case works fine and I correctly can test my services method using the #SpringBootTest annotation:
#SpringBootTest
#SpringBatchTest
class UpdateInfoBatchApplicationTests {
#Autowired
private NotaryService notaryService;
#Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
#Autowired
private JobRepositoryTestUtils jobRepositoryTestUtils;
#After
public void cleanUp() {
jobRepositoryTestUtils.removeJobExecutions();
}
#Autowired
#Qualifier("launcher")
private JobLauncher jobLauncher;
#Autowired
#Qualifier("updateNotaryDistrictsJob")
private Job updateNotaryDistrictsJob;
#Autowired
#Qualifier("updateNotaryListInfoJob")
private Job updateNotaryListInfoJob;
private JobParameters defaultJobParameters() {
JobParametersBuilder paramsBuilder = new JobParametersBuilder();
//paramsBuilder.addString("file.input", TEST_INPUT);
//paramsBuilder.addString("file.output", TEST_OUTPUT);
return paramsBuilder.toJobParameters();
}
#Test
public void givenReferenceOutput_whenJobExecuted_thenSuccess() throws Exception {
// when
JobExecution jobExecution = jobLauncherTestUtils.launchJob(defaultJobParameters());
JobInstance actualJobInstance = jobExecution.getJobInstance();
ExitStatus actualJobExitStatus = jobExecution.getExitStatus();
Assert.assertEquals(actualJobInstance.getJobName(), "updateNotaryDistrictsJob");
// then
//assertThat(actualJobInstance.getJobName(), is("updateNotaryDistrictsJob"));
//assertThat(actualJobExitStatus.getExitCode(), is("COMPLETED"));
//AssertFile.assertFileEquals(expectedResult, actualResult);
}
#Test
void contextLoads() {
System.out.println("TEST - contextLoads()");
}
#Test
void getNotaryList() throws Exception {
List<Notary> notaryList = this.notaryService.getNotaryList();
System.out.println("notaryList size: " + notaryList);
Assert.assertEquals("Notary List must be 5069", 5069, notaryList.size());
}
#Test
void getNotaryDetails() throws Exception {
NotaryDetails notaryDetails = this.notaryService.getNotaryDetails("089cy5Ra9zE%253D");
System.out.println("notaryDetails: " + notaryDetails);
Assert.assertEquals("Notary ID must be 089cy5Ra9zE%253D", "089cy5Ra9zE%253D", notaryDetails.getIdNotary());
}
#Test
void getNotaryDistrictsList() throws Exception {
List<NotaryDistrict> notaryDistrictsList = this.notaryService.getNotaryDistrictsList();
System.out.println("notaryDistrictsList: " + notaryDistrictsList);
Assert.assertEquals("Notary districts list lenght must be 91", 91, notaryDistrictsList.size());
//ArrayList<NotaryDistrict> notaryDistrictsListArrayList = new ArrayList<NotaryDistrict>(notaryDistrictsList);
notaryDistrictsList.remove(0);
Assert.assertEquals("Notary districts list lenght must now be 90", 90, notaryDistrictsList.size());
}
#Test
void getNotaryDistrictDetails() throws Exception {
NotaryDistrictDetails notaryDistrictDetails = this.notaryService.getNotaryDistrictDetails("CG7drXn9fvA%253D");
System.out.println("notaryDistrictDetails: " + notaryDistrictDetails.toString());
Assert.assertEquals("Distretto must be: SCIACCA", "SCIACCA", notaryDistrictDetails.getDistretto());
}
}
As you can see in the previous code I first inject my two Job objects defined:
#Autowired
#Qualifier("launcher")
private JobLauncher jobLauncher;
#Autowired
#Qualifier("updateNotaryDistrictsJob")
private Job updateNotaryDistrictsJob;
These Job are defined as bean into the class that configures my Spring Batch jobs and steps, basically I have these 2 beans:
#Bean("updateNotaryDistrictsJob")
public Job updateNotaryDistrictsListInfoJob(){
return jobs.get("updateNotaryDistrictsListInfoJob")
.incrementer(new RunIdIncrementer())
.start(readNotaryDistrictsListStep())
.build();
}
and
#Bean("updateNotaryListInfoJob")
public Job updateNotaryListInfoJob(){
return jobs.get("updateNotaryListInfoJob")
.incrementer(new RunIdIncrementer())
.start(readNotaryListStep())
.build();
}
Then in the previous test class there is this test method that should test the entire flow of the previous updateNotaryDistrictsJob job:
#Test
public void givenReferenceOutput_whenJobExecuted_thenSuccess() throws Exception {
// when
JobExecution jobExecution = jobLauncherTestUtils.launchJob(defaultJobParameters());
JobInstance actualJobInstance = jobExecution.getJobInstance();
ExitStatus actualJobExitStatus = jobExecution.getExitStatus();
Assert.assertEquals(actualJobInstance.getJobName(), "updateNotaryDistrictsJob");
}
The problem is that doing in this way when I run this test method I am obtaining this exception in my stack trace:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jobLauncherTestUtils': Unsatisfied dependency expressed through method 'setJob' parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.batch.core.Job' available: expected single matching bean but found 2: updateNotaryDistrictsJob,updateNotaryListInfoJob
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:768) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:720) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1413) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.9.jar:5.3.9]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.9.jar:5.3.9]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-2.5.3.jar:2.5.3]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434) ~[spring-boot-2.5.3.jar:2.5.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:338) ~[spring-boot-2.5.3.jar:2.5.3]
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:123) ~[spring-boot-test-2.5.3.jar:2.5.3]
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99) ~[spring-test-5.3.9.jar:5.3.9]
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) ~[spring-test-5.3.9.jar:5.3.9]
... 69 common frames omitted
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.batch.core.Job' available: expected single matching bean but found 2: updateNotaryDistrictsJob,updateNotaryListInfoJob
at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:220) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1358) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300) ~[spring-beans-5.3.9.jar:5.3.9]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:760) ~[spring-beans-5.3.9.jar:5.3.9]
... 88 common frames omitted
It seems that it can't recognize what of my two Job beans must be used.
Why? What is wrong? What am I missing? How can I try to fix this issue?
The JobLauncherTestUtils that is provided by #SpringBatchTest expects that there is only a single bean of type Job in the test context. This is also documented in the java doc of the annotation.
If you use #SpringBootTest and full component scanning such that more than one job bean is picked up, #SpringBatchTest does not work out of the box.
The easiest solution is probably to remove #SpringBatchTest and to start the jobs with the jobLauncher. Alternatively, you can split your tests across multiple test classes and use test contexts that only contain a single job bean, respectively.
First of all, this is not a duplicate issue. Because I have configured correctly please see my code and tell me what is here wrong. Then Here I am trying Spring Boot Multi Data Source Configuration.
Error I facing:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'workerEntityManagerFactory' defined in class path resource [com/sample/engine/config/WorkerDBConfiguration.class]: Unsatisfied dependency expressed through method 'workerEntityManagerFactory' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:798)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:539)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1108)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:152)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:132)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:92)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:172)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5135)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
... 38 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1695)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1253)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1207)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:885)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:789)
My Configuration Class
Primary Data Configuration:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
entityManagerFactoryRef = "customerApiEntityManagerFactory",
transactionManagerRef = "customerTransactionManager",
basePackages = {
"com.sample.engine.agent.customerdb.dao"
}
)
public class CustomerDBConfiguration {
#Value("${customer.datasource.jndi-name}")
private String customerDB;
#Bean(name = "customerDataSource")
#Primary
public DataSource customerDataSource() {
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
DataSource dataSource = dataSourceLookup.getDataSource(customerDB);
return dataSource;
}
#Primary
#Bean(name = "customerEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean customerEntityManagerFactory(EntityManagerFactoryBuilder builder
) {
return builder
.dataSource(customerDataSource())
.packages("com.sample.engine.agent.customer.model")
.persistenceUnit("db1")
.build();
}
#Primary
#Bean(name = "customerTransactionManager")
public PlatformTransactionManager customerTransactionManager(#Qualifier("customerEntityManagerFactory") EntityManagerFactory customerEntityManagerFactory) {
return new JpaTransactionManager(customerEntityManagerFactory);
}
}
SeconDary Data Configuration
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
entityManagerFactoryRef = "workerEntityManagerFactory",
transactionManagerRef = "workerTransactionManager",
basePackages = {
"com.sample.engine.agent.worker.dao"
}
)
public class WorkerDBConfiguration {
#Value("${worker.datasource.jndi-name}")
private String workerDB;
#Bean(name = "workerDataSource")
public DataSource workerDataSource() {
JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
DataSource dataSource = dataSourceLookup.getDataSource(workerDB);
return dataSource;
}
#Bean(name = "workerEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean
workerEntityManagerFactory(EntityManagerFactoryBuilder workerBuilder) {//, #Qualifier("workerDataSource") DataSource dataSource
return workerBuilder
.dataSource(ceapiDataSource())
.packages("com.sample.engine.agent.worker.model")
.persistenceUnit("db2")
.build();
}
#Bean(name = "workerTransactionManager")
public PlatformTransactionManager workerTransactionManager(#Qualifier("workerEntityManagerFactory") EntityManagerFactoryworkerEntityManagerFactory) {
return new JpaTransactionManager(workerEntityManagerFactory);
}
}
Main Class
#SpringBootApplication
#EnableMongoRepositories
#ComponentScan
#EnableAutoConfiguration(exclude = {HibernateJpaAutoConfiguration.class, JpaRepositoriesAutoConfiguration.class})
public class AgentManagerWeb extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(AgentManagerWeb.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(AgentManagerWeb.class);
}
}
Application.Properties
saasapi.datasource.jndi-name=java:comp/env/jdbc/saasapi
ceapi.datasource.jndi-name=java:comp/env/jdbc/ceapi
We have an application that we are migrating from Spring Boot 1 and Hibernate 3.6.8 to latest Spring Boot 2 and Hibernate 5.2.17.
Everything seems to be ok, except that there are some methods that we are calling and are not getting a transaction injected. Like this service:
#Service
public class BreakFixProcessorBO extends BaseProcessorBO {
#Transactional
public void process(String xml){
[...]
It's called from this other class:
#Service
public class BreakFixAmerInternalConsumer extends BaseConsumer {
private BreakFixProcessorBO breakFixProcessorBO;
#Autowired
public BreakFixAmerInternalConsumer(BreakFixProcessorBO breakFixProcessorBO) {
this.breakFixProcessorBO = breakFixProcessorBO;
}
#Override
protected void proccess(String messageBody) {
breakFixProcessorBO.process(messageBody);
}
Many other code call repositories use #Transactional, and many services also use #Transactional, and many of them work correctly. Except that some of them aren't, and we can't find any difference.
I have been reading a lot of documentation on how transactions work on proxied classes. And it seems that when the class implements an interface behaviour changes a bit.
So I tried to create an interface just with the method:
public interface BreakFixProcessorBO_TransactionTest {
void process(String xml);
}
And have the service implement it:
#Service
public class BreakFixProcessorBO extends BaseProcessorBO implements BreakFixProcessorBO_TransactionTest {
Does not matter what we do. We are having the following exception on some specific services:
Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.internal.SessionImpl.checkTransactionNeeded(SessionImpl.java:3505) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1427) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1423) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
at org.springframework.orm.hibernate5.SessionFactoryUtils.flush(SessionFactoryUtils.java:147) ~[spring-orm-5.0.7.RELEASE.jar!/:5.0.7.RELEASE]
at org.springframework.orm.hibernate5.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:95) ~[spring-orm-5.0.7.RELEASE.jar!/:5.0.7.RELEASE]
at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:96) ~[spring-tx-5.0.7.RELEASE.jar!/:5.0.7.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:922) ~[spring-tx-5.0.7.RELEASE.jar!/:5.0.7.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:730) ~[spring-tx-5.0.7.RELEASE.jar!/:5.0.7.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714) ~[spring-tx-5.0.7.RELEASE.jar!/:5.0.7.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:532) ~[spring-tx-5.0.7.RELEASE.jar!/:5.0.7.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:304) ~[spring-tx-5.0.7.RELEASE.jar!/:5.0.7.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.0.7.RELEASE.jar!/:5.0.7.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.7.RELEASE.jar!/:5.0.7.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.0.7.RELEASE.jar!/:5.0.7.RELEASE]
at d.s.a.bizo.processor.BreakFixProcessorBO$$EnhancerBySpringCGLIB$$e171e8a9.process(<generated>) ~[classes/:na]
at d.s.a.consumer.BreakFixAmerInternalConsumer.proccess(BreakFixAmerInternalConsumer.java:25) ~[classes/:na]
at d.s.a.consumer.BaseConsumer.onMessage(BaseConsumer.java:16) ~[classes/:na]
at d.s.a.consumer.BreakFixAmerInternalConsumer.onMessage(BreakFixAmerInternalConsumer.java:31) ~[classes/:na]
at sun.reflect.GeneratedMethodAccessor218.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_162]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_162]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:181) ~[spring-messaging-5.0.7.RELEASE.jar!/:5.0.7.RELEASE]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:114) ~[spring-messaging-5.0.7.RELEASE.jar!/:5.0.7.RELEASE]
at org.springframework.amqp.rabbit.listener.adapter.HandlerAdapter.invoke(HandlerAdapter.java:51) ~[spring-rabbit-2.0.4.RELEASE.jar!/:2.0.4.RELEASE]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:182) ~[spring-rabbit-2.0.4.RELEASE.jar!/:2.0.4.RELEASE]
... 10 common frames omitted
It seems that Spring AOP is proxying successfully the instance... but no transaction is created.
I tried Propagation.REQUIRES_NEW, and it behaves the same.
Our PlatformTransactionManager is defined together with our datasource:
#Configuration
#EnableTransactionManagement(proxyTargetClass = true)
#EnableAspectJAutoProxy(proxyTargetClass = true)
#RefreshScope
public class DBConfiguration extends DatabaseConfiguration implements EnvironmentAware {
#Primary
#Bean
public LocalSessionFactoryBean sessionFactory() {
final LocalSessionFactoryBean annotationSessionFactoryBean = new LocalSessionFactoryBean();
annotationSessionFactoryBean.setDataSource(dataSource());
annotationSessionFactoryBean.setPackagesToScan("d.s.a");
annotationSessionFactoryBean.setHibernateProperties(hibernateProperties());
return annotationSessionFactoryBean;
}
#Primary
#Bean
public DataSource dataSource() {
return createDataSource(propertyResolver);
}
#Primary
#Bean
public PlatformTransactionManager transactionManager() {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory().getObject());
return txManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
And our application uses most auto-configuration available:
#SpringBootApplication
#EnableAutoConfiguration(
exclude = {
JmsAutoConfiguration.class,
CamelAutoConfiguration.class
})
#ImportResource({"classpath:/META-INF/spring/applicationContext.xml"})
#ComponentScan(basePackages = "d.s.a")
public class OurApplication extends SpringBootServletInitializer implements WebApplicationInitializer {
public static void main(String[] args) {
if(System.getProperty("debug") != null) { //-Ddebug=true should be a feature
args = Arrays.copyOf(args, args.length+1);
args[args.length-1] = "--debug";
}
SpringApplication.run(OurApplication.class, args);
}
}
The applicationContext.xml is just some old task runner definitions we haven't migrated yet.
What are we missing, or is it a Spring bug?
Have you tried
#Override
#Transactional
protected void proccess(String messageBody) {
breakFixProcessorBO.process(messageBody);
}
I am trying to integrate spring Boot with Hibernate 5 using Java configs.
It has been some time since I have used Hibernate.
I am getting the below mentioned exception. Can someone please suggest how to resolve this ?
Following is my java config file followed by the exception stack trace.
package com.example;
import com.example.dao.CustomerDao;
import com.example.model.Customer;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.util.Properties;
#SpringBootApplication
#EnableTransactionManagement
public class SpringHibernateDemoApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(SpringHibernateDemoApplication.class, args);
}
#Bean
public DataSource dataSource() throws ClassNotFoundException {
//SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
// dataSource.setDriverClass((Class<? extends Driver>)Class.forName("com.mysql.jdbc.Driver"));
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/customerDB");
dataSource.setUsername("root");
dataSource.setPassword("welcome");
return dataSource;
}
#Bean
public LocalSessionFactoryBean sessionFactory() throws ClassNotFoundException {
Properties properties = new Properties();
properties.put("hibernate.dialect","org.hibernate.dialect.MySQLDialect");
properties.put("hibernate.show_sql", "true");
properties.put("hibernate.hbm2ddl.auto","create");
// properties.put("hibernate.connection.provider_class","org.hibernate.connection.DatasourceConnectionProvider");
LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
localSessionFactoryBean.setDataSource(dataSource());
localSessionFactoryBean.setPackagesToScan("com.example.model");
localSessionFactoryBean.setHibernateProperties(properties);
/*SessionFactory sessionFactory = new LocalSessionFactoryBuilder(dataSource()).
addAnnotatedClass(Customer.class).setProperties(properties).buildSessionFactory();*/
return localSessionFactoryBean;
}
#Bean(name = "hibernateTemplate")
public HibernateTemplate hibernateTemplate() throws ClassNotFoundException {
return new HibernateTemplate(sessionFactory().getObject());
}
#Bean
public CustomerDao customerDao() {
return new CustomerDao();
}
#Override
public void run(String... args) throws Exception {
Customer customer = new Customer();
customer.setFistName("amar");
customer.setLastName("dev");
customer.setEmail("amar#gmail.com");
customerDao().saveCustomer(customer);
}
}
The exception.
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:809) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:790) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:777) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at com.example.SpringHibernateDemoApplication.main(SpringHibernateDemoApplication.java:23) [main/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_74]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_74]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_74]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_74]
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) [idea_rt.jar:na]
Caused by: java.lang.IllegalStateException: Already value [org.springframework.orm.jpa.EntityManagerHolder#10753c9] for key [org.hibernate.internal.SessionFactoryImpl#ba5d30] bound to thread [main]
at org.springframework.transaction.support.TransactionSynchronizationManager.bindResource(TransactionSynchronizationManager.java:190) ~[spring-tx-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.orm.hibernate5.SpringSessionContext.currentSession(SpringSessionContext.java:127) ~[spring-orm-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:454) ~[hibernate-core-5.2.0.Final.jar:5.2.0.Final]
at org.springframework.orm.hibernate5.HibernateTemplate.doExecute(HibernateTemplate.java:326) ~[spring-orm-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.orm.hibernate5.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:309) ~[spring-orm-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.orm.hibernate5.HibernateTemplate.save(HibernateTemplate.java:616) ~[spring-orm-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at com.example.dao.CustomerDao.saveCustomer(CustomerDao.java:11) ~[main/:na]
at com.example.dao.CustomerDao$$FastClassBySpringCGLIB$$fb200467.invoke(<generated>) ~[main/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) ~[spring-tx-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) ~[spring-tx-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655) ~[spring-aop-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at com.example.dao.CustomerDao$$EnhancerBySpringCGLIB$$22cf791b.saveCustomer(<generated>) ~[main/:na]
at com.example.SpringHibernateDemoApplication.run(SpringHibernateDemoApplication.java:71) [main/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:806) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
The problem is you aren't defining a HibernateTransactionManager next to that Spring Boot detects hibernate and JPA and automatically configures it. Both technologies try to start a transaction and that fails. Instead work with the framework, Spring Boot already auto configures a DataSource and EntityManagerFactory (the JPA variant of a SessionFactory) for you.
Missing HibernateTransactionManager
If you really want to use plain Hibernate add a transaction manager.
#Bean
public HibernateTransactionManager transactionManager(SessionFactory sf) {
return new HibernateTransactionManager(sf);
}
Use Spring Boot to configure DataSource
I would however urge you to use the framework.
Create a file called application.properties in src/main/resources and put the following properties in it.
spring.datasource.url=jdbc:mysql://localhost:3306/customerDB
spring.datasource.username=root
spring.datasource.password=welcome
Now you can remove the DataSource and you can rewrite your sessionFactory method to take a DataSource as method argument.
#Bean
public LocalSessionFactoryBean sessionFactory(DataSource ds) throws ClassNotFoundException {
LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
localSessionFactoryBean.setDataSource(dataSource());
... // Other settings here
return localSessionFactoryBean;
}
Use JPA instead of plain Hibernate
However instead of doing this I suggest removing everything and add the following to your configuration (the application.properties).
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create
spring.jpa.database-platform=org.hibernate.dialect.MySQL57InnoDBDialect
Now in your SpringHibernateDemoApplication you can remove everything but your CustomerDao (unless that is annotated with #Repository you could remove that as well). Spring Boot already detects and enables transactions so you can also remove the #EnableTransactionManagement.
#SpringBootApplication
public class SpringHibernateDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringHibernateDemoApplication.class, args);
}
#Bean
public CustomerDao customerDao() {
return new CustomerDao();
}
#Bean
public CommandLineRunner runner(CustomerDao dao) {
return new CommandLineRunner() {
#Override
public void run(String... args) throws Exception {
Customer customer = new Customer();
customer.setFistName("amar");
customer.setLastName("dev");
customer.setEmail("amar#gmail.com");
dao.saveCustomer(customer);
}
};
}
}
The only thing for you to do is to replace the use of HibernateTemplate (which isn't recommended in the first place!) with the use of an EntityManager. See the JPA Section of the reference guide.
#Repository
public class CustomerDao {
#PersistenceContext
private EntityManager em;
public void saveCustomer(Customer customer) {
em.persist(customer);
}
}
Use Spring Data JPA
However if you want to really reduce your code I suggest adding the spring-boot-starter-data-jpa. This will add Spring Data JPA and allows you to remove your current CustomerDao and simply replace it with an interface. (Code below assumes Customer has an id of type Long.).
public interface CustomerDao extends JpaRepository<Customer, Long> {}
Now replace the saveCustomer with save in the CommandLineRunner. (I added the COmmandLineRunner as an inner bean to be able to inject the CustomerDao into the method as an argument).
#SpringBootApplication
public class SpringHibernateDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringHibernateDemoApplication.class, args);
}
#Bean
public CommandLineRunner runner(CustomerDao dao) {
return new CommandLineRunner() {
#Override
public void run(String... args) throws Exception {
Customer customer = new Customer();
customer.setFistName("amar");
customer.setLastName("dev");
customer.setEmail("amar#gmail.com");
dao.save(customer);
}
};
}
}
I strongly suggest a read of the Spring Boot reference guide and learn what it is and what it does. I would also suggest learning new and accepted technologies like JPA and how Spring projects like Spring Data JPA can help you with those.
The root issue you have is basically the usage of LocalSessionFactoryBean with spring-data which already defines a EntityManagerFactory instance; one would probably have no reason to use it directly but HibernateTemplate might appear as a good reason; if you really need to use HibernateTemplate than create it like below such that to avoid the creation of an additional EntityManagerFactory instance:
#Bean
public HibernateTemplate hibernateTemplate(EntityManagerFactory entityManagerFactory) {
return new HibernateTemplate(entityManagerFactory.unwrap(SessionFactory.class));
}
PS: this solution is incomplete because I don't know how to further integrate the correctly created HibernateTemplate (which works with reads but not writes) with the existing transaction manager
This question already has answers here:
java.lang.ClassNotFoundException: org.aspectj.util.PartialOrder$PartialComparable
(4 answers)
Closed 4 years ago.
i created an app based on spring boot and spring boot data , so i want to use
HSQLDB in memory
This is my Application Class :
package boot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication()
public class Application {
public static void main(String[] args) {
SpringApplication.run(Config.class);
}
}
and this is Config class :
#Configuration
#EnableAutoConfiguration
#EnableJpaRepositories
#ComponentScan(basePackages = {"controller", "dao", "service"})
#EnableTransactionManagement
class Config {
#Bean(name = "dataSource")
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
return builder.setType(EmbeddedDatabaseType.HSQL).build();
}
#Bean(name = "entityManager")
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setDatabase(Database.HSQL);
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan(getClass().getPackage().getName());
factory.setDataSource(dataSource());
return factory;
}
#Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager();
}
}
as you khnow in the these three packages "controller", "dao", "service" there are
some #Autowired
when i run the Application, i got this error :
Error creating bean with name 'taskController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private service.TaskManager controller.TaskController.taskManager; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'taskManagerImpl' defined in file [D:\JavaSe\restAng\target\classes\service\impl\TaskManagerImpl.class]: Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/aspectj/util/PartialOrder$PartialComparable
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
this is my TaskController
#RestController
public class TaskController {
#Autowired
private TaskManager taskManager;
#RequestMapping(value = "/tasks", method = RequestMethod.GET, headers = "Accept=application/json")
public List<Task> getAllTasks() {
return taskManager.getAll();
}
}
What's wrong with it ?
You are missing aspectjweaver. You need to add it to your dependencies.
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>