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")
Related
I've added validation to the classes in an app that provides REST APIs and I'm trying to restructure the unit tests to use MockMvc so that the validation will be called. I've seen several tutorials on setting this up, but whenever I try and make a call to one of the APIs, I get a 404 empty response and the log files indicate "Did not find handler method for /xxxxx".
There's probably just something I'm missing in either the XML configuration file or the test class, but I haven't been able to figure it out.
Test Code:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:spring_test.xml")
#TestPropertySource("classpath:test.properties")
#WebAppConfiguration
public class ClientControllerTest {
#Autowired
private Validator validator;
private MockMvc mockMvc;
#Autowired
private WebApplicationContext webApplicationContext;
private static final String baseUrl = "http://localhost:8080";
#Mock
StorageProvider storageProvider;
#Mock
ClientCriteria clientCriteria;
#Mock
UserPermissionChecker userPermissionChecker;
#Before
public void setUp() throws BusinessException {
MockitoAnnotations.initMocks(this);
String identityUserToken = "TEST USER";
Mockito.when(userPermissionChecker.checkPermissions(Mockito.any())).thenReturn(identityUserToken);
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
#Test
public void testMockMvc() throws Exception {
String clientId = "1";
String channel = "internet";
String market = "canada";
String transactionStyle = "blah";
String featureSet = "blah_blah";
Client requestedClient = new Client(clientId, channel, market, transactionStyle, featureSet);
ServletContext sc = webApplicationContext.getServletContext();
assertNotNull(sc);
assertTrue(sc instanceof MockServletContext);
ResultActions ra = mockMvc.perform(post("/myapibase/v1/clients")
.contentType(MediaType.APPLICATION_JSON)
.content(TestUtil.convertObjectToJsonBytes(requestedClient))
);
ra.andDo(print());
Controller:
#RestController
#RequestMapping("/myapibase/v1")
public class ClientController {
#Autowired
private Validator validator;
#Autowired
private StorageProvider storageProvider;
#Autowired
private UserPermissionChecker userPermissionChecker;
private String baseUrl;
private static Logger log = LoggerFactory.getLogger(ClientController.class.getName());
#Autowired
public ClientController(String baseUrl) {
this.baseUrl = baseUrl;
}
#RequestMapping(value = "/clients", method = RequestMethod.POST)
public ResponseEntity<?> addClient(#RequestBody #Valid Client clientToAdd, #RequestHeader HttpHeaders headers, #RequestParam Map<String, String> queryParams) {
String methodName = "addClient";
...
}
XML Configuration
<?xml version="1.0" encoding="UTF-8"?>
<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:security="http://www.springframework.org/schema/security"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:annotation-config />
<tx:annotation-driven/>
<mvc:annotation-driven/>
<!--<mvc:default-servlet-handler/>-->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath:ValidationMessages</value>
</list>
</property>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
<bean id="messageAccessor" class="org.springframework.context.support.MessageSourceAccessor">
<constructor-arg index="0" ref="messageSource"/>
</bean>
</beans>
Application.java
#Configuration
#EnableAutoConfiguration(exclude = MetricRepositoryAutoConfiguration.class)
#EnableAspectJAutoProxy(proxyTargetClass = true)
#EnableServiceFoundation
#ComponentScan(basePackages = { "com.myapp.controllers", "com.myapp.models", "com.myapp.storage", "com.myapp.managers",
"com.myapp.txyz", "com.myapp.util", })
public class Application {
...
}
Log Output:
22:04:30.866 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'org.springframework.web.servlet.support.SessionFlashMapManager'
22:04:30.870 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
22:04:30.871 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'org.springframework.web.servlet.support.SessionFlashMapManager'
22:04:30.871 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Unable to locate FlashMapManager with name 'flashMapManager': using default [org.springframework.web.servlet.support.SessionFlashMapManager#1f7076bc]
22:04:30.871 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Published WebApplicationContext of servlet '' as ServletContext attribute with name [org.springframework.web.servlet.FrameworkServlet.CONTEXT.]
22:04:30.871 [main] INFO o.s.t.w.s.TestDispatcherServlet - FrameworkServlet '': initialization completed in 38 ms
22:04:30.872 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Servlet '' configured successfully
22:04:30.978 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - DispatcherServlet with name '' processing POST request for [/myapibase/v1/clients]
22:04:30.981 [main] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Looking up handler method for path /myapibase/v1/clients
22:04:30.982 [main] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Did not find handler method for [/myapibase/v1/clients]
22:04:30.982 [main] WARN o.s.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/myapibase/v1/clients] in DispatcherServlet with name ''
22:04:30.983 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Successfully completed request
MockHttpServletRequest:
HTTP Method = POST
Request URI = /myapibase/v1/clients
Parameters = {}
Headers = {Content-Type=[application/json]}
Handler:
Type = null
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
MockHttpServletResponse:
Status = 404
Error message = null
Headers = {}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
It is quiet a challenge for me to configure unit testing for service and dao layers. I have tried to follow some tutorials but I still not able to make the test work.
My UserAccountService:
#Transactional(readOnly=true, rollbackFor={UserAccountNotFoundException.class})
public UserAccount findById(int id) throws UserAccountNotFoundException {
LOGGER.debug("Find an UserAccount entry with id: {}" + id);
return userDao.findById(id);
}
My Userdao
public UserAccount findById(int id) {
return (UserAccount) session.get(UserAccount.class, id);
}
My spring-servlet.xml:
<context:component-scan base-package="com.isad" />
<mvc:annotation-driven />
<mvc:resources mapping="/resources/**" location="/WEB-INF/" cache-period="31556926"/>
<!--
Initialize base viewers
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<!--
Error Messages Handling
-->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
<!--
Enable Data Transaction to Database.
-->
<bean id="sessionFactory" scope="singleton"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id ="transactionManager" class = "org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name = "sessionFactory" ref = "sessionFactory"/>
</bean>
My current testing configuration:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({"classpath:spring-servlet.xml"})
#TransactionConfiguration(transactionManager="transactionManager",defaultRollback=true)
#Transactional
public class TestUserAccountDao {
#Autowired
UserAccountService userManager;
#Test
#Transactional
public void testFindUser() throws UserAccountNotFoundException {
UserAccount other = userManager.findById(1);
System.out.println("Hello User: " + other.getUsername());
}
The problem I am having now when I run the above test:
Testing begin
Hibernate: select this_.USER_ID as y0_, this_.USERNAME as y1_, this_.EMAIL as y2_, this_.DISPLAYNAME as y3_ from USER_ACCOUNT this_ where this_.USER_ID=? and this_.ENABLED=? and this_.role=?
UserAccount [id=0, username=null, email=null, password=null, firstname=null, lastname=null, displayname=null, fullName=null, phone=null, fax=null, role=CUSTOMER, enabled=true, createOn=Thu Sep 04 13:45:31 PDT 2014]
INFO | 2014-09-04 13:45:31,084 | TransactionalTestExecutionListener.java | 298 | Rolled back transaction after test execution for test context [DefaultTestContext#160abda0 testClass = TestUserAccountDao, testInstance = com.isad.test.dao.TestUserAccountDao#1b275eae, testMethod = testFindUser#TestUserAccountDao, testException = java.lang.NullPointerException, mergedContextConfiguration = [MergedContextConfiguration#35b8ff6f testClass = TestUserAccountDao, locations = '{classpath:spring-servlet.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]
INFO | 2014-09-04 13:45:31,088 | AbstractApplicationContext.java | 873 | Closing org.springframework.context.support.GenericApplicationContext#625a80df: startup date [Thu Sep 04 13:45:28 PDT 2014]; root of context hierarchy
My hibernate.cfg.xml and spring-servlet.xml are located under src/main/resources.
You got a NPE in your test and being a RuntimeException the TransactionalTestExecutionListener has caught it and rollback your current executing transaction.
Since I don't see any DBUnit or any other code to insert a User with id=1, I can only assume you don't have an User in your database and that's why the:
session.get(UserAccount.class, id);
returns null.
Try changing this:
System.out.println("Hello User: " + other.getUsername());
to
if(other != null) {
System.out.println("Hello User: " + other.getUsername());
} else {
System.out.println("No User found for id : 1 ");
}
I have a single-context Spring-WS application (that is, there is only one file in my project that contains definitions), something-servlet.xml. When I call persist through my DAOs, no entries are getting created in my database. I'm also not getting any exceptions thrown.
If there is any more information I've left out that'd be helpful in determining the issue, please let me know. Thanks.
something-servlet.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:sws="http://www.springframework.org/schema/web-services"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="com.abc.direct.mailserver" />
<context:property-placeholder location="classpath:manager.properties" />
<sws:annotation-driven />
<sws:dynamic-wsdl id="manager" portTypeName="AbcDirect"
locationUri="/mailerManagerService/" targetNamespace="http://ecsdfsds.com/direct/definitions">
<sws:xsd location="/WEB-INF/mailManagerRequest.xsd" />
</sws:dynamic-wsdl>
<bean id="mailServerPersistenceManager"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="directMailDataSource" />
<property name="packagesToScan" value="com.abc.direct.mailserver.dao"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
</bean>
<bean id="directMailDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${database.driverClassName}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
</bean>
</beans>
Dao Classes:
#Entity
#Table(name="virtualusertable")
public class VirtualUser {
#Id
#Column(name="user")
private String user;
// private String domain;
// private String targetAddress;
public VirtualUser(String username) {
this.user = username;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
}
#Component
public class VirtualUsers {
#PersistenceContext
EntityManager entityManager;
public void save(VirtualUser user) {
this.entityManager.persist(user);
}
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
}
Endpoint:
#Endpoint
public class MailManagerEndpoint {
private static final String NAMESPACE_URI = "http://asfsdfs.com/direct/schemas";
static final Namespace NAMESPACE = Namespace.getNamespace(NAMESPACE_URI);
private MailManagerService service;
#Autowired
private VirtualUsers virtualUsers;
#Autowired
public MailManagerEndpoint(MailManagerService mailManagerService) {
this.service = mailManagerService;
}
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "MailManagerRequest")
public #ResponsePayload Element handleRequest(#RequestPayload Element element) throws JDOMException, IOException {
VirtualUser user = new VirtualUser("newuser");
virtualUsers.save(user);
return new Element("success");
}
}
Startup logs: http://pastebin.com/9Z6MWRSG
Transaction logs: http://pastebin.com/ZFEC0EMJ
In the startup logs, I"m really curious as to why this block repeats itself like 7 times:
2014-04-25 10:34:03,634 DEBUG EntityLoader:146 - Static select for entity com.abc.direct.mailserver.dao.VirtualUser [READ]: select virtualuse0_.user as user1_0_0_ from virtualusertable virtualuse0_ where virtualuse0_.user=?
2014-04-25 10:34:03,635 DEBUG QuerySpacesImpl:177 - Adding QuerySpace : uid = <gen:0> -> org.hibernate.loader.plan.build.internal.spaces.EntityQuerySpaceImpl#e58a68d]
2014-04-25 10:34:03,635 DEBUG FetchStyleLoadPlanBuildingAssociationVisitationStrategy:94 - Building LoadPlan...
2014-04-25 10:34:03,635 DEBUG LoadQueryJoinAndFetchProcessor:111 - processing queryspace <gen:0>
2014-04-25 10:34:03,636 DEBUG LoadPlanTreePrinter:72 - LoadPlan(entity=com.abc.direct.mailserver.dao.VirtualUser)
- Returns
- EntityReturnImpl(entity=com.abc.direct.mailserver.dao.VirtualUser, querySpaceUid=<gen:0>, path=com.abc.direct.mailserver.dao.VirtualUser)
- QuerySpaces
- EntityQuerySpaceImpl(uid=<gen:0>, entity=com.abc.direct.mailserver.dao.VirtualUser)
- SQL table alias mapping - virtualuse0_
- alias suffix - 0_
- suffixed key columns - {user1_0_0_}
UPDATE:
persist() output after adding #Transactional and :
2014-04-25 11:24:47,517 DEBUG SharedEntityManagerCreator$SharedEntityManagerInvocationHandler:253 - Creating new EntityManager for shared EntityManager invocation
2014-04-25 11:24:47,950 DEBUG AbstractSaveEventListener:130 - Generated identifier: newuser, using strategy: org.hibernate.id.Assigned
2014-04-25 11:24:48,011 DEBUG EntityManagerFactoryUtils:435 - Closing JPA EntityManager
If you want to insert data to DB, you need a transaction. In order for Spring to provide a transaction, you need to put <tx:annotation-driven /> to your Spring context file, and put #Transactional annotation on the method that you insert data to DB. This way, Spring initiates a transaction for you as the method execution starts, and commits it when the method execution comes to an end (or rolls it back if an exception is thrown).
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
I am tiring to to build a small application with spring+hibernate+maven+postgreSQL but when i am tiring to inject dependency in my controller and service class it creates problem for injecting the dependency here is the code and logs please give your suggestion to solve this wiring problem?
mvc-dispature-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<context:component-scan base-package="com.bms" />
<context:annotation-config />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://localhost:5432/bms" />
<property name="username" value="postgres" />
<property name="password" value="*******" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>com.bms.Domain.Book</value>
</list>
</property>
</bean>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
Controller class BooksEntryController.java
#Controller
#RequestMapping(value = "/dashboard/*")
public class BooksEntryController {
#Resource
private BookFormService bookFormServiceImp;
#RequestMapping(value = "/booksentryform", method = RequestMethod.GET)
public ModelAndView viewBooksEntryForm(Model model) {
model.addAttribute("test", new Book());
return new ModelAndView("bookregistrationform");
}
#RequestMapping(value = "/addbookdetails", method = RequestMethod.POST)
public String addBook(#ModelAttribute("test") Book book, Model model) {
if (book != null) {
bookFormServiceImp.addBooks(book);
return "bookaddsuccessfully";
} else {
throw new NullPointerException();
}
}
}
Service interface BookFormService.java
public interface BookFormService {
void addBooks(Book book);
}
ServiceImp class BookFormServiceImp.java
#Service("bookFormServiceImp")
public class BookFormServiceImp implements BookFormService {
#Resource
private BookFormDao bookFormDaoImp ;
public void addBooks(Book book) {
bookFormDaoImp.addBook(book);
// TODO Auto-generated method stub
}
}
Dao interface BookFormDao .java
public interface BookFormDao {
public void addBook(Book book); }
DaoImp class BookFormDaoImp.java
#Repository("bookFormDaoImp")
public class BookFormDaoImp implements BookFormDao {
#Resource
private SessionFactory sessionFactory;
private Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
public void addBook(Book book) {
// TODO Auto-generated method stub
getCurrentSession().save(book);
}
}
Here is the log :
2013-06-20 00:35:51.528:INFO:/bms:Initializing Spring root WebApplicationContext
Jun 20, 2013 12:35:51 AM org.springframework.web.context.ContextLoader initWebApplicationContext
INFO: Root WebApplicationContext: initialization started
Jun 20, 2013 12:35:51 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing Root WebApplicationContext: startup date [Thu Jun 20 00:35:51 IST 2013]; root of context hierarchy
Jun 20, 2013 12:35:51 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from ServletContext resource [/WEB-INF/mvc-dispatcher-servlet.xml]
Jun 20, 2013 12:35:52 AM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#2df8f8: defining beans [booksEntryController,bookFormDaoImp,bookFormServiceImp,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,dataSource,sessionFactory,org.springframework.web.servlet.view.InternalResourceViewResolver#0,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
Jun 20, 2013 12:35:52 AM org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
INFO: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#2df8f8: defining beans [booksEntryController,bookFormDaoImp,bookFormServiceImp,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,dataSource,sessionFactory,org.springframework.web.servlet.view.InternalResourceViewResolver#0,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
Jun 20, 2013 12:35:52 AM org.springframework.web.context.ContextLoader initWebApplicationContext
SEVERE: Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'booksEntryController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'bookFormServiceImp': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'bookFormDaoImp': Injection of resource dependencies failed; nested exception is java.lang.NoClassDefFoundError: Lorg/hibernate/cache/CacheProvider;
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:306)
...................................
....................................
You are probably not using the right sessionFactory class. If you are using Hibernate 4, use LocalSessionFactoryBean instead of AnnotationSessionFactoryBean.
Replace
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
by
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">