Spring 3.2.6-RELEASE and JUnit 4.11
I've being trying to write integration tests with spring 3.2.6-RELEASE and for some reason my bean can't be injected into the test class.
When I remove the extends AbstractSpringService part the code works fine. But it would be a shame to loose all the reusable code in my AbstractSpringService.
The code also works when I remove the persistance part of the configuration file leaving only this:
<context:property-placeholder location="classpath*:*.properties"/>
<context:annotation-config/>
<context:component-scan base-package="br.eti.danielcamargo.hsnpersonal.model" />
Any idea of what is going on here?
Here is the service to test:
import br.eti.danielcamargo.hsnpersonal.domain.entities.Programa;
import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Service;
#Service
public class ProgramaService extends AbstractSpringService<Programa> {
#PersistenceContext
private EntityManager em;
#PostConstruct
private void setup() {
System.out.println("Creating programaService");
}
public ProgramaService() {
super(Programa.class);
}
#Override
public EntityManager getEntityManager() {
return em;
}
}
It's parent:
import br.eti.danielcamargo.commons.business.AbstractService;
import br.eti.danielcamargo.commons.business.BusinessException;
import br.eti.danielcamargo.commons.domain.AbstractEntity;
import org.springframework.transaction.annotation.Transactional;
public abstract class AbstractSpringService<ENTITY extends AbstractEntity> extends AbstractService<ENTITY> {
public AbstractSpringService(Class<ENTITY> entityClass) {
super(entityClass);
}
#Override
#Transactional
public ENTITY save(ENTITY entity) throws BusinessException {
return super.save(entity);
}
#Override
#Transactional
public void remove(ENTITY entity) {
super.remove(entity);
}
}
And grandparent:
import br.eti.danielcamargo.commons.domain.AbstractEntity;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaQuery;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
public abstract class AbstractService<ENTITY extends AbstractEntity> implements
Serializable {
private static final long serialVersionUID = 1L;
private static final Validator validator;
static {
validator = Validation.buildDefaultValidatorFactory().getValidator();
}
public abstract EntityManager getEntityManager();
private final Class<ENTITY> entityClass;
public AbstractService(Class<ENTITY> entityClass) {
this.entityClass = entityClass;
}
public void validate(ENTITY entity) throws BusinessException {
Set<ConstraintViolation<ENTITY>> constraintViolations = validator
.validate(entity);
if (!constraintViolations.isEmpty()) {
List<ValidationOccurrence> ocorrencias = new ArrayList<ValidationOccurrence>();
for (ConstraintViolation<ENTITY> constraintViolation : constraintViolations) {
ocorrencias.add(new ValidationOccurrence(true, constraintViolation
.getRootBeanClass().getSimpleName()
+ "."
+ constraintViolation.getPropertyPath(),
constraintViolation.getMessage(), constraintViolation
.getInvalidValue()));
}
throw new BusinessException(ocorrencias);
}
}
public ENTITY save(ENTITY entity) throws BusinessException {
validate(entity);
entity = getEntityManager().merge(entity);
afterSave(entity);
return entity;
}
public void afterSave(ENTITY entity) {
}
public ENTITY get(Long id) {
TypedQuery<ENTITY> query = null;
try {
query = getEntityManager().createNamedQuery(
"get" + entityClass.getSimpleName(), entityClass);
} catch (IllegalArgumentException e) {
return getEntityManager().find(entityClass, id);
}
try {
query.setParameter("id", id);
} catch (IllegalArgumentException e) {
query.setParameter(1, id);
}
query.setMaxResults(1);
List<ENTITY> result = query.getResultList();
return result.isEmpty() ? null : result.get(0);
}
public List<ENTITY> getAll() {
TypedQuery<ENTITY> query = null;
try {
query = getEntityManager().createNamedQuery(
"getAll" + entityClass.getSimpleName(), entityClass);
} catch (IllegalArgumentException e) {
CriteriaQuery<ENTITY> cq = getEntityManager().getCriteriaBuilder()
.createQuery(entityClass);
cq.select(cq.from(entityClass));
query = getEntityManager().createQuery(cq);
}
List<ENTITY> result = query.getResultList();
return result;
}
public void remove(ENTITY entity) {
entity = getEntityManager().find(entityClass, entity.getId());
getEntityManager().remove(entity);
}
}
Here is the test:
import javax.annotation.PostConstruct;
import junit.framework.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("/testContext.xml")
public class ProgramaServiceTest {
#Autowired
private ProgramaService programaService;
#PostConstruct
private void setup() {
System.out.println("Creating programa test");
}
#Test
public void test() {
Assert.assertNotNull(programaService);
}
}
And here is the configuration file:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<context:property-placeholder location="classpath*:*.properties"/>
<context:annotation-config/>
<context:component-scan base-package="br.eti.danielcamargo.hsnpersonal.model" />
<!-- PERSISTENCE -->
<bean id="appDS" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<!-- Connection properties -->
<property name="driverClass" value="${database.driverClassName}" />
<property name="jdbcUrl" value="${database.url}" />
<property name="user" value="${database.username}" />
<property name="password" value="${database.password}" />
<!-- Pool properties -->
<property name="minPoolSize" value="1" />
<property name="maxPoolSize" value="2" />
<property name="maxStatements" value="50" />
<property name="idleConnectionTestPeriod" value="3000" />
<property name="loginTimeout" value="300" />
</bean>
<bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="defaultDataSource" ref="appDS" />
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="persistenceUnitName" value="${database.persistentUnitName}" />
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.import_files">${database.imports}</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
Here is the exception:
[HSN-PERSONAL] [INFO]: [23:17:34,208] [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - [Loading XML bean definitions from class path resource [testContext.xml]]
[HSN-PERSONAL] [INFO]: [23:17:34,414] [org.springframework.context.support.GenericApplicationContext] - [Refreshing org.springframework.context.support.GenericApplicationContext#41942912: startup date [Mon Feb 03 23:17:34 BRST 2014]; root of context hierarchy]
[HSN-PERSONAL] [INFO]: [23:17:34,527] [org.springframework.context.support.PropertySourcesPlaceholderConfigurer] - [Loading properties file from file [D:\development\projects\hsn-personal\target\test-classes\database.properties]]
[HSN-PERSONAL] [INFO]: [23:17:34,534] [org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor] - [JSR-330 'javax.inject.Inject' annotation found and supported for autowiring]
[HSN-PERSONAL] [INFO]: [23:17:34,603] [com.mchange.v2.log.MLog] - [MLog clients using log4j logging.]
[HSN-PERSONAL] [INFO]: [23:17:34,705] [com.mchange.v2.c3p0.C3P0Registry] - [Initializing c3p0-0.9.2.1 [built 20-March-2013 10:47:27 +0000; debug? true; trace: 10]]
[HSN-PERSONAL] [INFO]: [23:17:34,845] [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean] - [Building JPA container EntityManagerFactory for persistence unit 'hsnpu']
[HSN-PERSONAL] [INFO]: [23:17:34,992] [org.hibernate.annotations.common.Version] - [HCANN000001: Hibernate Commons Annotations {4.0.2.Final}]
[HSN-PERSONAL] [INFO]: [23:17:34,998] [org.hibernate.Version] - [HHH000412: Hibernate Core {4.2.2.Final}]
[HSN-PERSONAL] [INFO]: [23:17:35,000] [org.hibernate.cfg.Environment] - [HHH000206: hibernate.properties not found]
[HSN-PERSONAL] [INFO]: [23:17:35,002] [org.hibernate.cfg.Environment] - [HHH000021: Bytecode provider name : javassist]
[HSN-PERSONAL] [INFO]: [23:17:35,023] [org.hibernate.ejb.Ejb3Configuration] - [HHH000204: Processing PersistenceUnitInfo [
name: hsnpu
...]]
[HSN-PERSONAL] [INFO]: [23:17:35,170] [org.hibernate.service.jdbc.connections.internal.ConnectionProviderInitiator] - [HHH000130: Instantiating explicit connection provider: org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider]
[HSN-PERSONAL] [INFO]: [23:17:35,236] [com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource] - [Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1hge5zz8z1xhw46nud6z0y|5c07481f, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> org.postgresql.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1hge5zz8z1xhw46nud6z0y|5c07481f, idleConnectionTestPeriod -> 3000, initialPoolSize -> 3, jdbcUrl -> jdbc:postgresql://127.0.0.1:5432/hsn, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 2, maxStatements -> 50, maxStatementsPerConnection -> 0, minPoolSize -> 1, numHelperThreads -> 3, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]]
[HSN-PERSONAL] [INFO]: [23:17:35,503] [org.hibernate.dialect.Dialect] - [HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect]
[HSN-PERSONAL] [INFO]: [23:17:35,512] [org.hibernate.engine.jdbc.internal.LobCreatorBuilder] - [HHH000424: Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.InvocationTargetException]
[HSN-PERSONAL] [INFO]: [23:17:35,697] [org.hibernate.engine.transaction.internal.TransactionFactoryInitiator] - [HHH000268: Transaction strategy: org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory]
[HSN-PERSONAL] [INFO]: [23:17:35,702] [org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory] - [HHH000397: Using ASTQueryTranslatorFactory]
[HSN-PERSONAL] [INFO]: [23:17:35,743] [org.hibernate.validator.internal.util.Version] - [HV000001: Hibernate Validator 4.3.1.Final]
[HSN-PERSONAL] [INFO]: [23:17:36,066] [org.hibernate.tool.hbm2ddl.SchemaExport] - [HHH000227: Running hbm2ddl schema export]
[HSN-PERSONAL] [INFO]: [23:17:39,131] [org.hibernate.tool.hbm2ddl.SchemaExport] - [HHH000230: Schema export complete]
[HSN-PERSONAL] [INFO]: [23:17:39,197] [org.springframework.beans.factory.support.DefaultListableBeanFactory] - [Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#5839cb0: defining beans [org.springframework.context.support.PropertySourcesPlaceholderConfigurer#0,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,programaService,appDS,persistenceUnitManager,entityManagerFactory,transactionManager,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy]
Creating programaService
[HSN-PERSONAL] [ERROR]: [23:17:39,251] [org.springframework.test.context.TestContextManager] - [Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener#619130e2] to prepare test instance [br.eti.danielcamargo.hsnpersonal.model.services.ProgramaServiceTest#3207779]]
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'br.eti.danielcamargo.hsnpersonal.model.services.ProgramaServiceTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private br.eti.danielcamargo.hsnpersonal.model.services.ProgramaService br.eti.danielcamargo.hsnpersonal.model.services.ProgramaServiceTest.programaService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [br.eti.danielcamargo.hsnpersonal.model.services.ProgramaService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1146)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:376)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:110)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:312)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:284)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:264)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:153)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:124)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:200)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:153)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private br.eti.danielcamargo.hsnpersonal.model.services.ProgramaService br.eti.danielcamargo.hsnpersonal.model.services.ProgramaServiceTest.programaService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [br.eti.danielcamargo.hsnpersonal.model.services.ProgramaService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:517)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286)
... 26 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [br.eti.danielcamargo.hsnpersonal.model.services.ProgramaService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:988)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:858)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:489)
... 28 more
[HSN-PERSONAL] [INFO]: [23:17:39,262] [org.springframework.context.support.GenericApplicationContext] - [Closing org.springframework.context.support.GenericApplicationContext#41942912: startup date [Mon Feb 03 23:17:34 BRST 2014]; root of context hierarchy]
[HSN-PERSONAL] [INFO]: [23:17:39,263] [org.springframework.beans.factory.support.DefaultListableBeanFactory] - [Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#5839cb0: defining beans [org.springframework.context.support.PropertySourcesPlaceholderConfigurer#0,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,programaService,appDS,persistenceUnitManager,entityManagerFactory,transactionManager,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy]
[HSN-PERSONAL] [INFO]: [23:17:39,269] [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean] - [Closing JPA EntityManagerFactory for persistence unit 'hsnpu']
The problem was solved by adding
<aop:aspectj-autoproxy proxy-target-class="true" />
to the configuration file. Documentation for proxy-target-class says:
"Are class-based (CGLIB) proxies to be created? By default, standard Java interface-based proxies are created."
I suspect when Spring created this bean, it is of the parent class type, not subclass. Hence when you requested to autowire the subclass, it couldn't cast it / couldn't tell this parent class has one.
It should work if you autowire using the parent class:
#Autowired private AbstractSpringService programaService;
If you do need to use the subclass' members you can cast it.
If you have multiple beans implementing the abstract, you can select a particular one by using #Qualifier
#Autowired #Qualifier("foo") private AbstractSpringService programaService;
And in your service class
#Service("foo")
public class Blah extends AbstractSpringService {
...
Other solution maybe to avoid using #Service and declare the bean in xml.
I hope there's a more elegant solution than these
Related
I'm new to spring. I.m learning spring from javapoint. After learning some basics of spring from javapoint and spring docs, I moved towards learning hibernate with spring, but in very first try (example), I stucked with the expception: NoClassDefFoundExpetion: javax/persistence/PersistenceContext. To resolve this exception, I've googled and looked for similar kind of situations (and their solutions) on this and this, but nothing helps me.
Here is the full stacktrace: of my exception
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.context.annotation.internalPersistenceAnnotationProcessor': Instantiation of bean failed; nested exception is java.lang.NoClassDefFoundError: javax/persistence/PersistenceContext
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1105)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1050)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
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:202)
at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:207)
at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:697)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:526)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
at test.Test.main(Test.java:15)
Caused by: java.lang.NoClassDefFoundError: javax/persistence/PersistenceContext
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.<clinit>(PersistenceAnnotationBeanPostProcessor.java:172)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:142)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:89)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1098)
... 12 more
I'm using eclipse-neon IDE, spring-framework 4.3.2 RELEASE, Hibernate-5.2.2 Final and Oracle 10G(database).There is a STUDENT table in my database having 4-5 entries. Also I've written thespring code using simple (console base) java project and NOT using any build tool. Here is my complete code and libraries list which I'm currently using:
Student.java
public class Student {
private Integer rollNo;
private String name;
/**
* #param rollNo
* #param name
*/
public Student(Integer rollNo, String name) {
super();
this.rollNo = rollNo;
this.name = name;
}
//Getter and setter ....
StudentDAO.java
public class StudentDAO {
private HibernateTemplate hibernateTemplate;
public StudentDAO(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
public void setHibernateTemplate(HibernateTemplate template) {
this.hibernateTemplate = template;
}
public void saveStudent(Student student) {
hibernateTemplate.save(student);
}
public List<Student> readAll() {
return hibernateTemplate.loadAll(Student.class);
}
}
I'm using java annotation based configuration, So my AppConfig.java is:
#Configuration
public class AppConfig {
#Bean
public DriverManagerDataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource("jdbc:oracle:thin:#localhost:1521/xe", "user", "password");
dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
return dataSource;
}
#Bean
public LocalSessionFactoryBean sessionFactoryBean() {
LocalSessionFactoryBean bean = new LocalSessionFactoryBean();
bean.setDataSource(dataSource());
bean.setMappingResources("xml/student.hbm.xml");
Properties prop = new Properties();
prop.setProperty("hibernate.dialect", "org.hibernate.dialect.Oracle9Dialect");
prop.setProperty("hibernate.hbm2ddl.auto", "update");
prop.setProperty("hibernate.show_sql", "true");
bean.setHibernateProperties(prop);
return bean;
}
#Bean
public HibernateTemplate hibernateTemplate() {
HibernateTemplate template = new HibernateTemplate((SessionFactory) sessionFactoryBean());
return template;
}
#Bean
public StudentDAO DAO() {
return new StudentDAO(hibernateTemplate());
}
}
Student.hbm.xml XML file:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="bean.Student" table="student">
<rollNo name="rollNo">
<generator class="assigned"></generator>
</rollNo>
<property name="name"></property>
</class>
</hibernate-mapping>
and here is my Main-Method Class
public class Test {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
StudentDAO dao = context.getBean(StudentDAO.class);
List<Student> list = dao.readAll();
for(Student s: list)
System.out.println(s);
}
}
here is the list of liberaries (with jar file) which I've included in my project:
SPRING
HIBERNATE
Commons logging and ORALCE 10G Driver
And some other too
How to solve the above mentioned exception, which library I've to add/remove or what else I can try to resolve the issue.
Regret for long question
Example Reference
This example is based on source code, available at javapoint
I made slightly changes in my example. Instead of AppConfig.java, I used ApplicationContext.xml. Here is code for file
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url" value="jdbc:oracle:thin:#localhost:1521:xe"></property>
<property name="username" value="sachin"></property>
<property name="password" value="sachin476"></property>
</bean>
<bean id="mysessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="mappingResources">
<list>
<value>student.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect
</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="template" class="org.springframework.orm.hibernate5.HibernateTemplate">
<property name="sessionFactory" ref="mysessionFactory"></property>
</bean>
<bean id="d" class="bean.dao.StudentDao">
<property name="template" ref="template"></property>
</bean>
</beans>
and added two more jar files:
>commons-dbcp2-2.1.1.jar
>commons-pool2-2.4.2.jar
for BasicDataSource class.
Now It gives me Exception:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mysessionFactory' defined in class path resource [xml/ApplicationContext.xml]: Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: org/hibernate/SessionFactory
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
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.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:757)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at test.Test.main(Test.java:15)
Caused by: java.lang.NoClassDefFoundError: org/hibernate/SessionFactory
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetPublicMethods(Class.java:2902)
at java.lang.Class.getMethods(Class.java:1615)
at org.springframework.beans.ExtendedBeanInfoFactory.supports(ExtendedBeanInfoFactory.java:54)
at org.springframework.beans.ExtendedBeanInfoFactory.getBeanInfo(ExtendedBeanInfoFactory.java:46)
at org.springframework.beans.CachedIntrospectionResults.<init>(CachedIntrospectionResults.java:270)
at org.springframework.beans.CachedIntrospectionResults.forClass(CachedIntrospectionResults.java:189)
at org.springframework.beans.BeanWrapperImpl.getCachedIntrospectionResults(BeanWrapperImpl.java:173)
at org.springframework.beans.BeanWrapperImpl.getLocalPropertyHandler(BeanWrapperImpl.java:226)
at org.springframework.beans.BeanWrapperImpl.getLocalPropertyHandler(BeanWrapperImpl.java:63)
at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyHandler(AbstractNestablePropertyAccessor.java:725)
at org.springframework.beans.AbstractNestablePropertyAccessor.isWritableProperty(AbstractNestablePropertyAccessor.java:557)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1483)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1226)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
... 11 more
But I peeped into hibernate-core-5.2.2-Final.jar, that had definition for SessionFectory.class in org.hibernate package i.e there was class entry named org.hibernate.SessionFactory.class. Now I'm wondering why it gives such exceptions
UPDATE
After lots of try and search on google, I found that hibernate 5 doesn't support oracle10g drivers. so I've updated ojdbc14.jar to ojdbc6.jar, and it works for me
As mentioned here Upgrade your hibernate jpa-jar since the jpa supported version for hibernate4.3+ is 2.1.
Whoever answers correct will be rewarded
My Implementation is as follows:
NextShipmentDaoImpl.java
public class NextShipmentDaoImpl implements NextShipmentDao{
private DataSource dataSource;
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
LoginController.java
#Controller
public class LoginController {
#Autowired
private NextShipmentDao nextShipmentDao;
public void setNextShipmentDao(NextShipmentDao nextShipmentDao) {
this.nextShipmentDao = nextShipmentDao;
}
While Creating the required above bean like this:
<bean id="nextShipmentDao" class="com.ibrahim.dao.NextShipmentDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
ApplicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/board" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<bean id="nextShipmentDao" class="com.ibrahim.dao.NextShipmentDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<security:http auto-config="true" >
<security:intercept-url pattern="/index*" access="ROLE_USER" />
<security:form-login login-page="/login.htm" default-target-url="/index.htm"
authentication-failure-url="/loginerror.htm" />
<security:logout logout-success-url="/logout.htm" />
</security:http>
<context:component-scan base-package="com.ibrahim.controller,com.ibrahim.domain,com.ibrahim.dao" />
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
Everything works fine. But when I try to create a bean This shows the error
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loginController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.ibrahim.dao.NextShipmentDao com.ibrahim.controller.LoginController.nextShipmentDao; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'nextShipmentDao' defined in ServletContext resource [/WEB-INF/board-dao.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.ibrahim.dao.NextShipmentDaoImpl]: Constructor threw exception; nested exception is java.lang.IllegalArgumentException: Property 'dataSource' is required
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1116)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:628)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4728)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5166)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1399)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.ibrahim.dao.NextShipmentDao com.ibrahim.controller.LoginController.nextShipmentDao; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'nextShipmentDao' defined in ServletContext resource [/WEB-INF/board-dao.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.ibrahim.dao.NextShipmentDaoImpl]: Constructor threw exception; nested exception is java.lang.IllegalArgumentException: Property 'dataSource' is required
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:514)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285)
... 22 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'nextShipmentDao' defined in ServletContext resource [/WEB-INF/board-dao.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.ibrahim.dao.NextShipmentDaoImpl]: Constructor threw exception; nested exception is java.lang.IllegalArgumentException: Property 'dataSource' is required
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1007)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:953)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:487)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:912)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:855)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486)
... 24 more
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.ibrahim.dao.NextShipmentDaoImpl]: Constructor threw exception; nested exception is java.lang.IllegalArgumentException: Property 'dataSource' is required
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:163)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1000)
... 35 more
Caused by: java.lang.IllegalArgumentException: Property 'dataSource' is required
at org.springframework.jdbc.support.JdbcAccessor.afterPropertiesSet(JdbcAccessor.java:134)
at org.springframework.jdbc.core.JdbcTemplate.<init>(JdbcTemplate.java:165)
at com.ibrahim.dao.NextShipmentDaoImpl.<init>(NextShipmentDaoImpl.java:28)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:148)
... 37 more
May 07, 2015 12:21:48 PM org.apache.catalina.core.StandardContext startInternal
SEVERE: Error listenerStart
May 07, 2015 12:21:48 PM org.apache.catalina.core.StandardContext startInternal
SEVERE: Context [/13.1SecuringUrlAcces] startup failed due to previous errors
May 07, 2015 12:21:48 PM org.apache.catalina.core.ApplicationContext log
INFO: Closing Spring root WebApplicationContext
May 07, 2015 12:21:48 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-nio-8080"]
May 07, 2015 12:21:48 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-nio-8009"]
May 07, 2015 12:21:48 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 12402 ms
Here's My NextShipmentDaoImpl.java
public class NextShipmentDaoImpl implements NextShipmentDao{
private DataSource dataSource;
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
JdbcTemplate jdbcTemplate= new JdbcTemplate(dataSource);
#Override
public List<NextShipment> display() {
String sql = "SELECT * FROM NEXTSHIPMENT";
List<NextShipment> shipments = new ArrayList<NextShipment>();
List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql);
for (Map row : rows) {
NextShipment shipment = new NextShipment();
shipment.setOid((String) row.get("OID"));
shipment.setAddress((String) row.get("ADDRESS"));
shipment.setPack_Date((Date) row.get("PACK_DATE"));
shipment.setIsAvailable((Boolean) row.get("ISAVAILABLE"));
shipment.setAssignShipper((String) row.get("ASSIGNSHIPPER"));
shipment.setInTransit((Boolean) row.get("InTransit"));
shipments.add(shipment);
}
return shipments;
}
}
The times of the XML-based configuration are over.
I strongly recommend you to use Annotated Configuration
Something like this:
#Configuration
#EnableWebMvc
#EnableTransactionManagement
#ComponentScan(basePackages = "com.myapp.*")
public class AppConfiguration extends WebMvcConfigurerAdapter {
#Bean
public DataSource myDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("<full.driver.class.name>");
dataSource.setUrl("url");
dataSource.setUsername("dit");
dataSource.setPassword("pass");
return dataSource;
}
[...] other Beans like TransactionManager....
}
The stacktrace says :
you correctly autowire nextShipmentDAO in loginController
but dataSource property is null is the NextShipmentDAOImpl bean
and the exception occurs in JdbcTemplate initialization
The NextShipmentDAOImpl gives the cause : you correctly inject the datasource, but initialize the JdbcTemplate at construction time. So here is what happens :
jvm creates a NextShipmentDaoImpl object
jvm initializes all fields of the object including jdbcTemplate
spring sets the datasource field ... too late !
[It had been noted in comments by #M.Deinum, but I did not give it enough attention]
You shall never use an injected field at creation time, because at that moment it has not been injected. You should instead use an initialization method called by spring after all properties have been set :
public class NextShipmentDaoImpl implements NextShipmentDao{
private DataSource dataSource;
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
JdbcTemplate jdbcTemplate;
void init(void) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
and declare the bean that way :
<bean id="nextShipmentDao" class="com.ibrahim.dao.NextShipmentDaoImpl"
init-method="init">
<property name="dataSource" ref="dataSource"></property>
</bean>
NextShipmentDaoImpl.java looks like this
public class NextShipmentDaoImpl implements NextShipmentDao{
private DataSource dataSource;
JdbcTemplate jdbcTemplate;
public NextShipmentDaoImpl(DataSource dataSource) {
this.dataSource = dataSource;
}
In the above lines of code I had declared JdbcTemplate inside its implementation function itself. Where it is used.
And the relevant bean I had declared is:
<bean id="nextShipmentDao" class="com.ibrahim.dao.NextShipmentDaoImpl">
<constructor-arg ref="dataSource"></constructor-arg>
</bean>
LoginController remains the same:
#Controller
public class LoginController {
#Autowired
private NextShipmentDao nextShipmentDao;
public void setNextShipmentDao(NextShipmentDao nextShipmentDao) {
this.nextShipmentDao = nextShipmentDao;
}
I had shifted my spring and spring security jars from 3.2.4 to 3.2.7
Problem got solved in this manner.
I am using Spring-batch Spring-batch-admin and Spring-boot
I defined repository and created basic entities
However when I do save(..) I check my database table and nothing is persisted. also not errors being thrown except of some debug logs:
2015-01-12 12:21:12.652 DEBUG 13692 --- [nio-8080-exec-1] stomAnnotationTransactionAttributeSource : Adding transactional method 'save' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
2015-01-12 12:21:12.653 DEBUG 13692 --- [nio-8080-exec-1] o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'transactionManager'
2015-01-12 12:21:12.678 DEBUG 13692 --- [nio-8080-exec-1] o.s.j.d.DataSourceTransactionManager : Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
2015-01-12 12:21:12.683 DEBUG 13692 --- [nio-8080-exec-1] o.s.j.d.DataSourceTransactionManager : Acquired Connection [jdbc:mysql://localhost:3306/spring_batch_test, UserName=root#localhost, MySQL Connector Java] for JDBC transaction
2015-01-12 12:21:12.693 DEBUG 13692 --- [nio-8080-exec-1] o.s.j.d.DataSourceTransactionManager : Switching JDBC Connection [jdbc:mysql://localhost:3306/spring_batch_test, UserName=root#localhost, MySQL Connector Java] to manual commit
2015-01-12 12:21:12.816 DEBUG 13692 --- [nio-8080-exec-1] ataPostProcessor$ThreadBoundTargetSource : Initializing lazy target object
Gradle build:
buildscript {
repositories {
maven { url 'http://artifactory/artifactory/libs-release-local' }
mavenCentral()
maven { url 'http://repo.spring.io/milestone/' }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.0.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
apply plugin: 'war'
war {
baseName = 'notification-processor-service'
version = '1.0.0-SNAPSHOT'
}
jar {
baseName = 'notification-processor-service'
version = '1.0.0-SNAPSHOT'
}
ext {
springIntegrationKafkaVersion = '1.0.0.M2'
}
repositories {
maven { url 'http://artifactory/artifactory/libs-release-local' }
maven { url 'http://artifactory/artifactory/resin-hessian' }
mavenCentral()
maven {
url 'https://repository.apache.org/content/groups/public'
}
maven { url 'http://repo.spring.io/milestone/' }
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile("com.caucho:resin-hessian:4.0.23")
compile("mysql:mysql-connector-java")
compile('org.springframework.boot:spring-boot-starter-web:1.2.0.RELEASE')
compile("org.springframework.boot:spring-boot-starter-batch:1.2.0.RELEASE")
compile("org.springframework.boot:spring-boot-starter-actuator")
compile("javax.inject:javax.inject:1")
compile('org.springframework.batch:spring-batch-admin-manager:1.3.0.RELEASE') {
exclude module: 'slf4j-log4j12'
}
testCompile('org.springframework.boot:spring-boot-starter-test:1.2.0.RELEASE')
}
task wrapper(type: Wrapper) {
gradleVersion = '1.11'
}
Application.class:
package com.mycompany.notification.processor.service.main;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.orm.jpa.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* Created by Ext_IdanF on 25/12/2014.
*/
#ComponentScan({"com.mycompany.notification.processor.service"})
#EnableAutoConfiguration
#Configuration
#EntityScan({"com.mycompany.notification.processor.service.entities"})
#ImportResource({
"classpath:integration-context.xml", "classpath:launch-context.xml", "classpath:applicationContext-NotificationProcessorService.xml"
})
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = {"com.mycompany.notification.processor.service.dao"})
//#Import({ ServletConfiguration.class, WebappConfiguration.class })
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
System.out.printf("hello man");
}
}
Spring batch configurations:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--<context:property-placeholder location="classpath:batch-mysql.properties,
file:///d:/etc/mycompany/services/pushExecuterService/pushExecuterServices.properties"
ignore-unresolvable="true"
/>
-->
<bean id="jobBuilderFactory" class="org.springframework.batch.core.configuration.annotation.JobBuilderFactory">
<constructor-arg ref="jobRepository"/>
</bean>
<bean id="stepBuilderFactory" class="org.springframework.batch.core.configuration.annotation.StepBuilderFactory">
<constructor-arg index="0" ref="jobRepository"/>
<constructor-arg index="1" ref="transactionManager"/>
</bean>
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"
p:dataSource-ref="dataSource" p:transactionManager-ref="transactionManager"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${batch.jdbc.driver}"/>
<property name="url" value="${batch.jdbc.url}"/>
<property name="username" value="${batch.jdbc.user}"/>
<property name="password" value="${batch.jdbc.password}"/>
</bean>
<bean id="jobOperator"
class="org.springframework.batch.core.launch.support.SimpleJobOperator"
p:jobLauncher-ref="jobLauncher" p:jobExplorer-ref="jobExplorer"
p:jobRepository-ref="jobRepository" p:jobRegistry-ref="jobRegistry"/>
<bean id="jobExplorer"
class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean"
p:dataSource-ref="dataSource"/>
<bean id="jobRegistry"
class="org.springframework.batch.core.configuration.support.MapJobRegistry"/>
<bean class="org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor">
<property name="jobRegistry" ref="jobRegistry"/>
</bean>
<bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository"/>
</bean>
</beans>
this is batch-mysql.properties:
# GENERAL:
batch.jdbc.testWhileIdle=true
batch.business.schema.script=classpath:/business-schema.sql
# Set to False to stop the database from being wiped and re-created.
batch.data.source.init=false
batch.schema=spring_batch_test
# MySQL:
batch.jdbc.driver=com.mysql.jdbc.Driver
batch.jdbc.url=jdbc:mysql://localhost:3306/spring_batch_test
batch.jdbc.user=root
batch.jdbc.password=root
batch.jdbc.validationQuery=SELECT 1
batch.schema.script=classpath:/org/springframework/batch/core/schema-mysql.sql
batch.drop.script=classpath*:/org/springframework/batch/core/schema-drop-mysql.sql
batch.database.incrementer.class=org.springframework.jdbc.support.incrementer.MySQLMaxValueIncrementr
and application.propteties
#LOGS PROPS
logging.level.com.mycompany.notification.processor.service: DEBUG
logging.level.org.springframework : DEBUG
logging.level.org.springframework.integration : INFO
#SPRING BATCH
spring.batch.job.enabled=false
#SPRING-BOOT
spring.freemarker.check-template-location=false
spring.velocity.checkTemplateLocation=false
server.servletPath=/*
spring.datasource.url=jdbc:mysql://localhost:3306/spring_batch_test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#DB
ENVIRONMENT=mysql
#TOMCAT
server.port=8080
I afraid I got some collision between spring-batch && spring-batch-admin && spring boot configurations
I defined inside batch-mysql.proprties the jdbc props and also in application.properties
btw: Spring-batch-admin managed to write into the database into it's own tables
I added Spring jpa support and I get different error this time:
No transactional EntityManager available
new classes:
public class AbstractJpaDAO<T, PK extends Serializable> {
#PersistenceContext
protected EntityManager entityManager;
...
public interface NotificationDao {
NotificationJobEntity save(NotificationJobEntity entity);
}
execution code:
#Override
public NotificationJobEntity save(final NotificationJobEntity entity) {
super.persist(entity);
logger.debug("Persist a Notification entity in persistence store with Job-ID {}", entity.getJobId());
return entity;
}
thank you
I am not sure if thats the right way
what I did was to use Spring JPA
added entity manager
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="default" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
</bean>
</property>
</bean>
and Using AbstractJpaDAO
this way:
public class AbstractJpaDAO<T, PK extends Serializable> {
#PersistenceContext
protected EntityManager entityManager;
private Class<T> persistentClass;
protected AbstractJpaDAO(final Class<T> persistentClass) {
this.persistentClass = persistentClass;
}
public void persist(T entity) {
entityManager.persist(entity);
}
public void update(T entity) {
entityManager.merge(entity);
}
public T find(PK pk, Class<T> t) {
return entityManager.find(t, pk);
}
public void delete(T entity) {
entityManager.remove(entity);
}
#SuppressWarnings("unchecked")
public Collection<T> findAll() {
return this.entityManager.createQuery("select obj from " + this.persistentClass.getName() + " obj").getResultList();
}
#SuppressWarnings("unchecked")
public Collection<T> findAll(int page, int pageSize) {
TypedQuery<T> query = (TypedQuery<T>) entityManager.createQuery("select obj from " + this.persistentClass.getName() + " obj");
query.setFirstResult(page * pageSize);
query.setMaxResults(pageSize);
return query.getResultList();
}
}
too bad I couldnt find a way somehow to use Spring-data and earn all this code
Hello I started an app with Jersey integrated with spring. To test my resources I´m using spring-test, like this:
#ContextConfiguration(locations = { "classpath*:testApplicationContext.xml" })
#RunWith(SpringJUnit4ClassRunner.class)
#TransactionConfiguration(defaultRollback = false) //just to check if txmanager was working
public class UserDAOTest {
#Autowired
private UserDAO dao;
#Autowired
private AuthorizationVerifyer verifyer;
#Before
public void init() {
User user = new User(null, "name", "email", "pass", DateTime.now(), true);
User savedUser = dao.save(user);
assertNotNull(savedUser);
assertNotNull(savedUser.getId());
}
the problem is that all my tests break in the #Before method. Why? Because the User ID is null.
Lets go over my testApplicationContext.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.sifionsolution.sig.authorization" />
<!-- Inject properties -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>testDatabase.properties</value>
</list>
</property>
</bean>
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${user}"/>
<property name="password" value="${password}"/>
</bean>
<!-- JPA EntityManagerFactory -->
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
depends-on="flyway">
<property name="dataSource" ref="dataSource" />
<property name="persistenceProvider">
<bean class="org.hibernate.ejb.HibernatePersistence" />
</property>
<property name="packagesToScan">
<list>
<value>com.sifionsolution.sig.authorization.entity</value>
</list>
</property>
</bean>
<!-- Transaction manager -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf" />
</bean>
<bean id="flyway" class="org.flywaydb.core.Flyway" init-method="migrate">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
My UserDAO class:
#Component
public class UserDAO {
private GenericDAO<Long, User> dao;
#PersistenceContext
private EntityManager manager;
#Transactional
User save(User user) {
return dao.save(user);
}
...
Can some one help me to get this working?
thank you
EDIT Adding some of the Console logs:
13/10/14 14:16:50 INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader:315
Loading XML bean definitions from URL [file:/D:/workspace/sig-authorization-jax-rs/bin/testApplicationContext.xml]
13/10/14 14:16:50 INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader:315
Loading XML bean definitions from URL [file:/D:/workspace/sig-authorization-jax-rs/bin/testApplicationContext.xml]
13/10/14 14:16:50 INFO org.springframework.context.annotation.ClassPathBeanDefinitionScanner:231
JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning
13/10/14 14:16:50 INFO org.springframework.context.annotation.ClassPathBeanDefinitionScanner:231
JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning
13/10/14 14:16:50 INFO org.springframework.context.annotation.ClassPathBeanDefinitionScanner:239
JSR-330 'javax.inject.Named' annotation found and supported for component scanning
13/10/14 14:16:50 INFO org.springframework.context.annotation.ClassPathBeanDefinitionScanner:239
JSR-330 'javax.inject.Named' annotation found and supported for component scanning
13/10/14 14:16:50 INFO org.springframework.context.support.GenericApplicationContext:510
Refreshing org.springframework.context.support.GenericApplicationContext#162cc04e: startup date [Mon Oct 13 14:16:50 BRT 2014]; root of context hierarchy
13/10/14 14:16:50 INFO org.springframework.context.support.GenericApplicationContext:510
Refreshing org.springframework.context.support.GenericApplicationContext#162cc04e: startup date [Mon Oct 13 14:16:50 BRT 2014]; root of context hierarchy
13/10/14 14:16:50 INFO org.springframework.beans.factory.config.PropertyPlaceholderConfigurer:172
Loading properties file from class path resource [testDatabase.properties]
13/10/14 14:16:50 INFO org.springframework.beans.factory.config.PropertyPlaceholderConfigurer:172
Loading properties file from class path resource [testDatabase.properties]
13/10/14 14:16:50 INFO org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor:141
JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
13/10/14 14:16:50 INFO org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor:141
JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
13/10/14 14:16:50 INFO org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean:287
Building JPA container EntityManagerFactory for persistence unit 'default'
13/10/14 14:16:50 INFO org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean:287
Building JPA container EntityManagerFactory for persistence unit 'default'
13/10/14 14:16:51 INFO org.springframework.beans.factory.support.DefaultListableBeanFactory:603
Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#247fd5c5: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,tokenDAO,userDAO,tokenCreator,tokenValidator,authorizationVerifyer,authenticatedUserBuilder,permissionBuilder,roleWrapperBuilder,org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0,dataSource,emf,transactionManager,flyway,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
13/10/14 14:16:51 INFO org.springframework.beans.factory.support.DefaultListableBeanFactory:603
Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#247fd5c5: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,tokenDAO,userDAO,tokenCreator,tokenValidator,authorizationVerifyer,authenticatedUserBuilder,permissionBuilder,roleWrapperBuilder,org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0,dataSource,emf,transactionManager,flyway,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
13/10/14 14:16:51 INFO org.springframework.context.support.GenericApplicationContext:1042
Closing org.springframework.context.support.GenericApplicationContext#162cc04e: startup date [Mon Oct 13 14:16:50 BRT 2014]; root of context hierarchy
13/10/14 14:16:51 INFO org.springframework.context.support.GenericApplicationContext:1042
Closing org.springframework.context.support.GenericApplicationContext#162cc04e: startup date [Mon Oct 13 14:16:50 BRT 2014]; root of context hierarchy
13/10/14 14:16:51 INFO org.springframework.beans.factory.support.DefaultListableBeanFactory:444
Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#247fd5c5: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,tokenDAO,userDAO,tokenCreator,tokenValidator,authorizationVerifyer,authenticatedUserBuilder,permissionBuilder,roleWrapperBuilder,org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0,dataSource,emf,transactionManager,flyway,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
13/10/14 14:16:51 INFO org.springframework.beans.factory.support.DefaultListableBeanFactory:444
Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#247fd5c5: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,tokenDAO,userDAO,tokenCreator,tokenValidator,authorizationVerifyer,authenticatedUserBuilder,permissionBuilder,roleWrapperBuilder,org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0,dataSource,emf,transactionManager,flyway,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
13/10/14 14:16:51 INFO org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean:441
Closing JPA EntityManagerFactory for persistence unit 'default'
13/10/14 14:16:51 INFO org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean:441
Closing JPA EntityManagerFactory for persistence unit 'default'
EDIT 2 After putting Transactional annotation in my test class I got:
Caught exception while allowing TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener#47b42535] to process 'after' execution for test: method [public void com.sifionsolution.sig.authorization.dao.UserDAOTest.shouldLogInActiveUser()], instance [com.sifionsolution.sig.authorization.dao.UserDAOTest#3f6df5a], exception [java.lang.AbstractMethodError: org.joda.time.contrib.hibernate.PersistentDateTime.nullSafeSet(Ljava/sql/PreparedStatement;Ljava/lang/Object;ILorg/hibernate/engine/spi/SessionImplementor;)V]
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:522)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:755)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:724)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener$TransactionContext.endTransaction(TransactionalTestExecutionListener.java:591)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener.endTransaction(TransactionalTestExecutionListener.java:297)
at org.springframework.test.context.transaction.TransactionalTestExecutionListener.afterTestMethod(TransactionalTestExecutionListener.java:192)
at org.springframework.test.context.TestContextManager.afterTestMethod(TestContextManager.java:406)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:91)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: javax.persistence.RollbackException: Error while committing the transaction
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:92)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:513)
... 25 more
Caused by: org.hibernate.AssertionFailure: null id in com.sifionsolution.sig.authorization.entity.User entry (don't flush the Session after an exception occurs)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:79)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:194)
EDIT 3 GenericDAO
public class GenericDAO<PK, T> {
private final EntityManager entityManager;
private final Class<?> clazz;
public GenericDAO(Class<?> clazz, EntityManager entityManager) {
this.clazz = clazz;
this.entityManager = entityManager;
}
#SuppressWarnings("unchecked")
public T getById(PK pk) {
return (T) entityManager.find(clazz, pk);
}
public T save(T entity) {
entityManager.persist(entity);
return entity;
}
public void update(T entity) {
entityManager.merge(entity);
}
public void delete(T entity) {
entityManager.remove(entity);
}
#SuppressWarnings("unchecked")
public List<T> findAll() {
return entityManager.createQuery(("FROM " + clazz.getName() + " obj")).getResultList();
}
public List<?> listByHql(String hql, HqlParameter... params) {
Query query = entityManager.createQuery(hql);
for (HqlParameter param : params)
param.apply(query);
return query.getResultList();
}
public Object uniqueResultByHql(String hql, HqlParameter... params) {
Query query = entityManager.createQuery(hql);
for (HqlParameter param : params)
param.apply(query);
try {
return query.getSingleResult();
} catch (NoResultException e) {
return null;
}
}
}
EDIT 4 User entity code
#Entity
#Table(name = "tb_user")
#XmlRootElement
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
private String password;
#Type(type = "org.joda.time.contrib.hibernate.PersistentDateTime")
private DateTime registration;
#Column(columnDefinition = "TINYINT(1)")
private Boolean active;
#OneToMany(mappedBy = "user")
private List<UserRole> userRoles;
#OneToMany(mappedBy = "user")
private Set<UserPermission> userPermissions;
public User() {
}
EDIT 5 database
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| password | varchar(128) | NO | | NULL | |
| email | varchar(255) | NO | UNI | NULL | |
| active | tinyint(1) | NO | | NULL | |
| registration | datetime | NO | | NULL | |
+--------------+--------------+------+-----+---------+----------------+
6 rows in set (0.04 sec)
EDIT 6 I changed this line:
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
And now I´m getting another exception:
java.lang.AbstractMethodError: org.joda.time.contrib.hibernate.PersistentDateTime.nullSafeSet(Ljava/sql/PreparedStatement;Ljava/lang/Object;ILorg/hibernate/engine/spi/SessionImplementor;)V
at org.hibernate.type.CustomType.nullSafeSet(CustomType.java:155)
at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2602)
Summary of chat discussion
Adding #Transactional to test class
Adding transactionManager in #TransactionConfiguration
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
#Transactional
//Test Class
Some forum suggest to use Jadira
with this annotation
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTimeWithZone")
I am quite new to Spring and Spring-Batch in particular.
Still I somehow managed to install the Spring Batch-Admin. I added custom jobs and Hibernate/JPA for persistence.
Everything is working as expected, up to the point where the first chunk should be persisted. Then I receive the following error-message:
org.springframework.transaction.CannotCreateTransactionException:
Could not open JPA EntityManager for transaction;
nested exception is java.lang.IllegalStateException: Already value
[org.springframework.jdbc.datasource.ConnectionHolder#60d31437]
for key [org.springframework.jdbc.datasource.DriverManagerDataSource#12da4b19]
bound to thread [jobLauncherTaskExecutor-1]
This is the full stacktrace:
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException: Already value [org.springframework.jdbc.datasource.ConnectionHolder#43f9e588] for key [org.springframework.jdbc.datasource.DriverManagerDataSource#84f171a] bound to thread [jobLauncherTaskExecutor-1]
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:427)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:335)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy41.saveIfUnique(Unknown Source)
at com.qompa.batch.ArticleItemWriter.write(ArticleItemWriter.java:28)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.writeItems(SimpleChunkProcessor.java:171)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.doWrite(SimpleChunkProcessor.java:150)
at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor$3.doWithRetry(FaultTolerantChunkProcessor.java:313)
at org.springframework.batch.retry.support.RetryTemplate.doExecute(RetryTemplate.java:240)
at org.springframework.batch.retry.support.RetryTemplate.execute(RetryTemplate.java:187)
at org.springframework.batch.core.step.item.BatchRetryTemplate.execute(BatchRetryTemplate.java:213)
at org.springframework.batch.core.step.item.FaultTolerantChunkProcessor.write(FaultTolerantChunkProcessor.java:402)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:194)
at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:74)
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:386)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:264)
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:76)
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:367)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:214)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:143)
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:250)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:135)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:61)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:281)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: java.lang.IllegalStateException: Already value [org.springframework.jdbc.datasource.ConnectionHolder#43f9e588] for key [org.springframework.jdbc.datasource.DriverManagerDataSource#84f171a] bound to thread [jobLauncherTaskExecutor-1]
at org.springframework.transaction.support.TransactionSynchronizationManager.bindResource(TransactionSynchronizationManager.java:189)
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:402)
... 36 more
The same Job executes fine in a standalone application. The problem occurs only in the Spring-Batch-Admin environment. Below you can see the project structure and dependencies:
This is the app-context.xml that overrides/extends the Batch-Admin configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.1.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">
<context:component-scan base-package="com.company.batch" />
<context:property-placeholder location="classpath:batch.properties" />
<import resource="classpath:/META-INF/spring/batch/jobs/article-job.xml" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${batch.jdbc.driver}" />
<property name="url" value="${batch.jdbc.url}" />
<property name="username" value="${batch.jdbc.user}" />
<property name="password" value="${batch.jdbc.password}" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.qompa.batch" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="POSTGRESQL"></property>
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="com.company.utils.persistence.CustomPGDialect" />
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto"></prop>
</props>
</property>
</bean>
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />
<!-- schedule tasks -->
<task:scheduled-tasks>
<task:scheduled ref="articleRetrieval" method="run"
cron="0 0 */4 * * *" />
<task:scheduled ref="articleConversion" method="run"
cron="0 15 */4 * * *" />
</task:scheduled-tasks>
</beans>
What I understand so far is that it has to do with the ThreadPoolTaskExecutor to which the jobLauncherTaskExecutor bean refers. It seems to handle connection pooling for concurrently running jobs ... but to be honest I have no clue how to change my configurations to make these things work.
[Edit]: I am not even sure wether it is the afromentioned ThreadPoolTaskExecutor. But it seem s to be an implementation of the TaskExecutor interface.
If anyone ran into a similar issue, or has a suggestion how to configure my application in a way that transactions can be created for my persistence methods: Please give me a hint!
The error comes from JpaTransactionManager line 403:
TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
The error means that the transaction manager is trying to bind the datasource (not the entity manager) to the thread, but the datasource is already there and this is unexpected.
Note that the transaction manager had not started yet to bind the Entity Manager to the thread, that would happen next at JpaTransactionManager line 416:
There are two possible explanations:
Somebody (another transaction manager?) is adding the datasource to the thread before the transaction manager and this is unexpected.
Or no one is adding the datasource to the transaction manager, is just that at the end of the task execution no one cleans the thread before returning it to the pool, maybe due an error or an unhandled exception.
One question, does this also happen for only one execution thread, or only when there are several?
To find out what the problem is, these are some steps:
run with a minimal number of threads that cause the problem
put a breakpoint in TransactionSynchronizationManager.bindResource() to see who adds the connection to the thread. The breakpoint can be a conditional breakpoint with a condition on the thread name: "jobLauncherTaskExecutor-1".equals(Thread.currentThread().getName())
put also a breakpoint in TransactionSynchronizationManager.unbindResource(), to see if the datasource is unbound from the thread. when the breakpoints hit, scroll down the stacktrace and see which classes are causing this.
This normally happens when you have multiple transaction managers in place.
Some hints..
When using annotaion #EnableBatchProcessing, Spring Batch automatically registers a transaction manager , and your JpaTransactionManager may never get used.
If you want to change the transaction manager that spring batch uses, you have to implement the interface BatchConfigurer.(https://blog.codecentric.de/en/2013/06/spring-batch-2-2-javaconfig-part-3-profiles-and-environments/).
You can specify transaction manager for tasklets as follows:
<tasklet transaction-manager="transactionManager">
If you have 2 dataSource, I suggest you to read:
https://github.com/spring-projects/spring-boot/issues/3012
So... configure the main datasource (is important the transaction manager's name)
#Configuration
#EnableJpaRepositories(
entityManagerFactoryRef = "entityManager",
transactionManagerRef = "transactionManager",
basePackages = "a.b.c")
#PropertySource({"classpath:db_persistence.properties"})
#EnableTransactionManagement
and the other datasource:
#Configuration
#EnableJpaRepositories(
entityManagerFactoryRef = "another_EntityManager",
transactionManagerRef = "another_transactionManager",
basePackages = "x.y.z")
#PropertySource({"classpath:db_persistence.properties"})
#EnableTransactionManagement
I hope that this help you.
return stepBuilderFactory.get("orderStep1").<sourceBean, destBean>chunk(5)
.reader(reader)
.processor(batchFileRowProcessor)
.writer(batchFileRowDataWritter)
.taskExecutor(taskExecutor)
.transactionManager(platformTransactionManager)
.throttleLimit(1).build();
platformTransactionManager is the qualified bean from the data source configuration
I was able to solve a similar issue by implementing a spring batch configuration for JPA
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.configuration.BatchConfigurationException;
import org.springframework.batch.core.configuration.annotation.BatchConfigurer;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.explore.support.JobExplorerFactoryBean;
import org.springframework.batch.core.explore.support.MapJobExplorerFactoryBean;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.transaction.PlatformTransactionManager;
#Configuration
public class JpaBatchConfigurer implements BatchConfigurer {
private static final Logger logger = LoggerFactory
.getLogger(JpaBatchConfigurer.class);
#Inject
private DataSource dataSource;
#Inject
private PlatformTransactionManager transactionManager;
private JobRepository jobRepository;
private JobLauncher jobLauncher;
private JobExplorer jobExplorer;
protected JpaBatchConfigurer() {
}
#Override
#Bean
public JobRepository getJobRepository() {
return jobRepository;
}
#Override
public PlatformTransactionManager getTransactionManager() {
return transactionManager;
}
#Override
#Bean
public JobLauncher getJobLauncher() {
return jobLauncher;
}
#Override
#Bean
public JobExplorer getJobExplorer() {
return jobExplorer;
}
#PostConstruct
public void initialize() {
try {
if (dataSource == null) {
logger.warn("No datasource was provided...using a Map based JobRepository");
if (this.transactionManager == null) {
this.transactionManager = new ResourcelessTransactionManager();
}
MapJobRepositoryFactoryBean jobRepositoryFactory = new MapJobRepositoryFactoryBean(
this.transactionManager);
jobRepositoryFactory.afterPropertiesSet();
this.jobRepository = jobRepositoryFactory.getObject();
MapJobExplorerFactoryBean jobExplorerFactory = new MapJobExplorerFactoryBean(
jobRepositoryFactory);
jobExplorerFactory.afterPropertiesSet();
this.jobExplorer = jobExplorerFactory.getObject();
} else {
this.jobRepository = createJobRepository();
JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean();
jobExplorerFactoryBean.setDataSource(this.dataSource);
jobExplorerFactoryBean.afterPropertiesSet();
this.jobExplorer = jobExplorerFactoryBean.getObject();
}
this.jobLauncher = createJobLauncher();
} catch (Exception e) {
throw new BatchConfigurationException(e);
}
}
private JobLauncher createJobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository);
jobLauncher.setTaskExecutor( new SimpleAsyncTaskExecutor());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
protected JobRepository createJobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setIsolationLevelForCreate("ISOLATION_SERIALIZABLE");
factory.setDataSource(dataSource);
factory.setTransactionManager(transactionManager);
factory.setValidateTransactionState(false);
factory.afterPropertiesSet();
return factory.getObject();
}
#Bean
public JobBuilderFactory jobBuilderFactory(JobRepository jobRepository){
return new JobBuilderFactory(jobRepository);
}
#Bean
public StepBuilderFactory stepBuilderFactory(JobRepository jobRepository, PlatformTransactionManager transactionManager){
return new StepBuilderFactory(jobRepository, transactionManager);
}
}
This was copied from:https://github.com/hantsy/spring4-sandbox/blob/master/batch-jpa/src/main/java/com/hantsylabs/example/spring/config/JpaBatchConfigurer.java
These kind of problems occur with older version of java like jdk 6 or further lower versions.Upgrade your jdk version to 7 or above. Even i do had the same kinda issue before which gone when i updated my jdk version to 7.