Dependency Injection with Spring/Junit/JPA - spring

I'm trying to create JUnit tests for my JPA DAO classes, using Spring 2.5.6 and JUnit 4.8.1.
My test case looks like this:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"classpath:config/jpaDaoTestsConfig.xml"} )
public class MenuItem_Junit4_JPATest extends BaseJPATestCase {
private ApplicationContext context;
private InputStream dataInputStream;
private IDataSet dataSet;
#Resource
private IMenuItemDao menuItemDao;
#Test
public void testFindAll() throws Exception {
assertEquals(272, menuItemDao.findAll().size());
}
... Other test methods ommitted for brevity ...
}
I have the following in my jpaDaoTestsConfig.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:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- uses the persistence unit defined in the META-INF/persistence.xml JPA configuration file -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="CONOPS_PU" />
</bean>
<bean id="groupDao" class="mil.navy.ndms.conops.common.dao.impl.jpa.GroupDao" lazy-init="true" />
<bean id="permissionDao" class="mil.navy.ndms.conops.common.dao.impl.jpa.PermissionDao" lazy-init="true" />
<bean id="applicationUserDao" class="mil.navy.ndms.conops.common.dao.impl.jpa.ApplicationUserDao" lazy-init="true" />
<bean id="conopsUserDao" class="mil.navy.ndms.conops.common.dao.impl.jpa.ConopsUserDao" lazy-init="true" />
<bean id="menuItemDao" class="mil.navy.ndms.conops.common.dao.impl.jpa.MenuItemDao" lazy-init="true" />
<!-- enables interpretation of the #Required annotation to ensure that dependency injection actually occures -->
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
<!-- enables interpretation of the #PersistenceUnit/#PersistenceContext annotations providing convenient
access to EntityManagerFactory/EntityManager -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<!-- transaction manager for use with a single JPA EntityManagerFactory for transactional data access
to a single datasource -->
<bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<!-- enables interpretation of the #Transactional annotation for declerative transaction managment
using the specified JpaTransactionManager -->
<tx:annotation-driven transaction-manager="jpaTransactionManager" proxy-target-class="false"/>
</beans>
Now, when I try to run this, I get the following:
SEVERE: Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener#fa60fa6] to prepare test instance [null(mil.navy.ndms.conops.common.dao.impl.MenuItem_Junit4_JPATest)]
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mil.navy.ndms.conops.common.dao.impl.MenuItem_Junit4_JPATest': Injection of resource fields failed; nested exception is java.lang.IllegalStateException: Specified field type [interface javax.persistence.EntityManagerFactory] is incompatible with resource type [javax.persistence.EntityManager]
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessAfterInstantiation(CommonAnnotationBeanPostProcessor.java:292)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:959)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:329)
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:255)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:93)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:130)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:61)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:54)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:52)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: java.lang.IllegalStateException: Specified field type [interface javax.persistence.EntityManagerFactory] is incompatible with resource type [javax.persistence.EntityManager]
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.checkResourceType(InjectionMetadata.java:159)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.(PersistenceAnnotationBeanPostProcessor.java:559)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$1.doWith(PersistenceAnnotationBeanPostProcessor.java:359)
at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:492)
at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:469)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findPersistenceMetadata(PersistenceAnnotationBeanPostProcessor.java:351)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(PersistenceAnnotationBeanPostProcessor.java:296)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:745)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:448)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
at java.security.AccessController.doPrivileged(AccessController.java:219)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:221)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:168)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:435)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:409)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:537)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:180)
at org.springframework.beans.factory.annotation.InjectionMetadata.injectFields(InjectionMetadata.java:105)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessAfterInstantiation(CommonAnnotationBeanPostProcessor.java:289)
... 18 more
It seems to be telling me that its attempting to store an EntityManager object into an EntityManagerFactory field, but I don't understand how or why. My DAO classes accept both an EntityManager and EntityManagerFactory via the #PersistenceContext attribute, and they work find if I load them up and run them without the #ContextConfiguration attribute (i.e. if I just use the XmlApplcationContext to load the DAO and the EntityManagerFactory directly in setUp ()).
Any insights would be appreciated.

These are the correct combinations of annotation + interface:
#PersistenceContext
private EntityManager entityManager;
#PersistenceUnit
private EntityManagerFactory entityManagerFactory;
But when using spring's transaction and entity manager support, you don't need the EntityManagerFactory at all.
The reason why you don't need EntityManagerFactory is because the creation of the EntityManager is responsibility of the transaction manager. Here's what happens in short:
the transaction manager is triggered before your methods
the transaction manager gets the EntityManagerFactory (it is injected in it), creates a new EntityManager, sets in in a ThreadLocal, and starts a new transaction.
then it delegates to the service method
whenever #PersistenceContext is encountered, a proxy is injected (in your Dao), which, whenever accessed, gets the current EntityManager which has been set in the ThreadLocal

I had to do the below combination, apart from adding spring-aspects jar to the project properties->Aspect Path and enabling spring aspects in sts. Ofcourse in my application context config file i defined the Entitymanagerfactory.
#ContextConfiguration(locations = { "/META-INF/spring/applicationContext-domain.xml" })
public class ReaderTest extends AbstractJUnit4SpringContextTests {
#PersistenceContext
private EntityManager entityManager;

I too have same problem, When I added java-persistence api problem got resolved.
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
</dependency>

Related

Unable to create mongotemplate in spring

Error:
19-Feb-2016 00:00:16.731 SEVERE [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log StandardWrapper.Throwable
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'personService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.data.mongodb.core.MongoTemplate com.test.app.service.PersonService.mongoTemplate; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoTemplate' defined in ServletContext resource [/WEB-INF/mvc-dispatcher-servlet.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.data.mongodb.core.MongoTemplate]: Constructor threw exception; nested exception is java.lang.NoSuchMethodError: org.springframework.core.convert.support.ConversionServiceFactory.createDefaultConversionService()Lorg/springframework/core/convert/support/GenericConversionService;
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
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/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.2.xsd">
<context:component-scan base-package="com.test.app" />
<mvc:annotation-driven/>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<!-- Factory bean that creates the Mongo instance -->
<bean id="mongo" class="org.springframework.data.mongodb.core.MongoFactoryBean">
<property name="host" value="localhost" />
</bean>
<!-- MongoTemplate for connecting and querying the documents in the database -->
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongo" ref="mongo" />
<constructor-arg name="databaseName" value="test" />
</bean>
<!-- Use this post processor to translate any MongoExceptions thrown in #Repository annotated classes -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean id="personController" class="com.test.app.controller.PersonController" />
<bean id="personService" class="com.test.app.service.PersonService" />
<bean id="person" class="com.test.app.model.Person" />
</beans>
I am seeing many posts regarding this error , but no answers to fix this.
The version of spring-core need match the version of spring-data.
Below is my part pom.xml:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!-- Spring data mongodb -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.8.2.RELEASE</version>
</dependency>
It's fixed.
It's almost the same thing only annotation driven. In the Supplier I'm just casting mongoTemplate (You may not want that). So If you use the spring config everything should work fine.
Regarding your version in XML try creating the mongo factory from SimpleMongoDbFactory with a MongoClient and the database name, Then just give your MongoTemplate bean your factory, and that's it.
Spring Config:
#Configuration
public class SpringConfig {
#Bean
public MongoDbFactory mongoDbFactory() throws UnknownHostException{
return new SimpleMongoDbFactory(new MongoClient(),"games");
}
#Bean
public MongoTemplate mongoTemplate() throws UnknownHostException{
MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory());
return mongoTemplate;
}
}
After that I created a supplier (Google Guava in this case) which may not be needed in your case
public class MongoOperationSupplier implements Supplier<MongoOperations>{
#Override
public MongoOperations get() {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
MongoOperations mongoOperation = (MongoOperations) ctx.getBean("mongoTemplate");
return mongoOperation;
}
}
An annotated class:
#Document(collection="game_suspicious_event")
public class SuspiciousEvent {
#Id
private String id;
private String apiKey;
private String userUniqueId;
private Date date;
private String ip;
private String additionalInformation;
public SuspiciousEvent(){}
public SuspiciousEvent(String apiKey,String userUniqueId,Date date, String ip, String additionalInformation){
this.apiKey=apiKey;
this.userUniqueId=userUniqueId;
this.date=date;
this.ip=ip;
this.additionalInformation=additionalInformation;
}
public String getApiKey() {
return apiKey;
}
}
Then to use:
final MongoOperations mo = new MongoOperationSupplier().get();
mo.save(new SuspiciousEvent(......));
Hope it helps.

Error creating bean with name 'vehicleDao': Injection of autowired dependencies failed:Could not autowire field:

Hii iam doing spring ORM with hibernate. while running the program iam getting bellow error.. iam giving all my config,pojo,daos please check
WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'vehicleDao': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.orm.hibernate3.HibernateTemplate in.JavaHome.SpringHiber.DAO.vehicleDao.template; nested exception is java.lang.NoClassDefFoundError: [Lorg/hibernate/engine/FilterDefinition;
Exception in thread "main" java.lang.NoSuchMethodError: org.springframework.util.ReflectionUtils.clearCache()V
at org.springframework.context.support.AbstractApplicationContext.resetCommonCaches(AbstractApplicationContext.java:879)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:563)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at addVehicle.main(addVehicle.java:11)
Configuration spring is..
<context:component-scan base-package="in.JavaHome.SpringHiber"></context:component-scan>
<bean name="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocations" value="classpath:hibernate.cfg.xml"></property>
</bean>
<bean name="hibTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean name="hibTransManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<tx:annotation-driven transaction-manager="hibTransManager"/>
Dao Class
#Component
public class vehicleDao {
#Autowired
private HibernateTemplate template;
#Transactional
public void addVehicle(vehicle v){
template.save(v);
}
main.java
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext contex= new ClassPathXmlApplicationContext("config.xml");
vehicleDao dao = (vehicleDao) contex.getBean("vehicleDao.class");
vehicle v=new vehicle();
v.setName("S cross");
v.setCost(1500000);
dao.addVehicle(v);
}
Iam new to spring mvc so, please tell me the whr the problem.
Thank u
If my guess is correct, you are following a Tutorial to learn about Spring. If so, congratulations and good luck, Spring is a very powerful framework! Though it appears that you are using a very old tutorial - I'd suggest looking for a more modern spring tutorial example as XML configuration (as well as Hibernate 3) are not modern approach. Perhaps something from: http://spring.io/guides
but for this specific problem it seems likely that you have incompatible jars on your classpath. If you plan to use hibernate 3 you need to ensure it's on the classpath and that you are not using a modern version of spring either. See: compatability of spring 4.0.0 with hibernate 4.30
The problem is you defined bean in xml like this
<bean name="hibTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
but your using template to autowire the bean name should be same or use #Qualifier
#Autowired
private HibernateTemplate template;
change this to
#Autowired
private HibernateTemplate hibTemplate;
or
#Autowired
#Qualifier("hibTemplate")
private HibernateTemplate hibTemplate;

rollback the data from first table if exception is thrown

I am using spring mvc and postgres as database
I have requirement to insert diff data into two tables with second table has one columns as foreignkey from first table
I am using jdbc template to connect with database
if some exception happens while inserting into second table i want to rollback the data from first table also
for this do i need use spring transactions concept? please suggest
I tried to implement transactions in this way
<?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:p="http://www.springframework.org/schema/p"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- Define all the service beans that will be created in ePramaan -->
<context:annotation-config />
<tx:annotation-driven/>
<!-- END OF DAO beans Definitions -->
<bean class="org.springframework.jdbc.core.JdbcTemplate" p:dataSource-ref="dataSource" />
<!-- Create DataSource Bean -->
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/ePramaanDB" />
</bean>
<bean id="jdbcSPProfileRepository"
class="in.cdac.epramaan.sp.dao.JdbcSPProfileRepository">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
JdbcSPProfileRepository is a class it contains method to insert data to database
I annotated class with #Transactional
But when i run the server it is throwing exceptions
14:44:01.223 [localhost-startStop-1] ERROR o.s.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jdbcSPProfileRepository': Injection of autowired depende
ncies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: in.cdac.epramaan.common.bd.
MasterConfigBD in.cdac.epramaan.sp.dao.JdbcSPProfileRepository.masterConfigBD; nested exception is org.springframework.beans.factory.NoSuchBeanD
efinitionException: No qualifying bean of type [in.cdac.epramaan.common.bd.MasterConfigBD] 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=t
rue)}
#Component
#Transactional
public class JdbcSPProfileRepository implements SPProfileRepository {
private static final Logger logger = LoggerFactory
.getLogger(JdbcSPProfileRepository.class);
#Autowired
private JdbcTemplate jdbcTemplate;
/** The master config bd. */
#Autowired
MasterConfigBD masterConfigBD;
#Autowired
public JdbcSPProfileRepository(DataSource dataSource) {
}
#Override
#Transactional
public SPRegistrationResponse saveSPRegistrationDetails(
final SPRegistration spreg) {
SPRegistrationResponse spRegResponse = new SPRegistrationResponse();
Response response = null;
logger.debug("In saveSPRegistrationDetails : ");
try {/////}catch(){}
}
}
can anybody please suggest the solution
You have several options. One as you suggest is use Spring transactions.
http://simplespringtutorial.com/springDeclarativeTransactions.html
Or you can implemente your own ACID method where sharing the connection between transactions make it atomic. Look this example.
http://www.tutorialspoint.com/jdbc/commit-rollback.htm
The key is only commit on you connection("con") when you want finish your transaction. Then if something goes wrong before finish all your micro transactions, since you did not commit yet nothing will be persisted on your database.

Injecting bean declared in xml file using the #Inject annotation

I can't get #Inject to work properly. I'm trying to inject a bean from xml using the #Inject annotation, but I get the error message
"java.lang.IllegalArgumentException: 'dataSource' or 'jdbcTemplate' is required".
I have also been trying in combination with #Qualifier("dataSource"), but wherever I put the #Qualifier it says "The annotation #Qualifier is disallowed for this location".
I have been reading loads of documentation on #Inject and I can't seem to find anything that mentions any special treatment of beans declared in xml.
However, I'm guessing Spring is trying to create the FooDaoImpl bean before scanning the dataSourceBean.
How would I go about using #Inject to inject the dataSource bean declared in the xml file?
Is it even possible, using #Inject?
FooDaoImpl.java
#Repository
public class FooDaoImpl extends NamedParameterJdbcDaoSupport implements FooDao {
#Inject
private DataSource dataSource;
DSLContext create = DSL.using(dataSource, SQLDialect.DB2);
}
Spring-Module.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"
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:annotation-config />
<context:component-scan base-package="com.example.foobar" />
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="com.ibm.db2.jcc.DB2Driver" />
<property name="jdbcUrl" value="jdbc:db2://localhost:50000/BLABLA" />
<property name="user" value="PAPAYA" />
<property name="password" value="COCONUT" />
</bean>
Cheers!
This works fine in Spring. I use the #Autowired annotation, not #Inject.
I managed to use #Inject to inject the dataSource to my Dao. I used a #PostConstruct to achieve this, like so:
#Inject
private DataSource dataSource;
#PostConstruct
private void initialize(){
setDataSource(dataSource);
}
DSLContext create = DSL.using(dataSource, SQLDialect.DB2);
I'm sure there is a better, or "cleaner" way of achieving this, but none that I could find.
Thanks for your suggestions!
To get rid of the The annotation #Qualifier is disallowed for this location message you have to use the annotation #interface.

Injection of autowired dependencies failed while using #Transactional

I testing my DAO, but it didn't work. The following error occurs:
Tests in error:
testAccountOperations(com.tsekhan.rssreader.dao.HibernateControllerTest): Error creating bean with name 'com.tsekhan.rssreader.dao.HibernateControllerTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.tsekhan.rssreader.dao.HibernateController com.tsekhan.rssreader.dao.HibernateControllerTest.hibernateController; nested exception is java.lang.IllegalArgumentException: Can not set com.tsekhan.rssreader.dao.HibernateController field com.tsekhan.rssreader.dao.HibernateControllerTest.hibernateController to $Proxy25
My DAO:
#Service
#Scope("singleton")
public class HibernateController extends HibernateDaoSupport {
#Autowired
public SessionFactory sessionFactory;
#Transactional
public void addAcount(Account account) {
sessionFactory.getCurrentSession().saveOrUpdate(account);
}
}
My test for this DAO:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:/applicationContext.xml")
public class HibernateControllerTest {
#Autowired
HibernateController hibernateController;
private Set<Channel> getTestChannelList(String channelLink) {
Channel testChannel = new Channel();
testChannel.setSourceLink(channelLink);
Set<Channel> testChannelList = new HashSet<Channel>();
testChannelList.add(testChannel);
return testChannelList;
}
private Account getTestAccount(String accountLogin, String channelLink) {
Account testAccount = new Account();
testAccount.setAccountLogin(accountLogin);
testAccount.setChannelList(getTestChannelList(channelLink));
return testAccount;
}
#Test
public void testAccountOperations() {
hibernateController
.addAcount(getTestAccount("test_login", "test_link"));
}
}
My 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.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd"
default-autowire="byName">
<!-- Enabling spring-transaction annotations -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- Enabling annotation-driven configurating -->
<context:annotation-config />
<!-- Creation of transaction manager -->
<bean id="transactionManager" scope="singleton"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="sessionFactory" scope="singleton"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="configLocation" value="classpath:/hibernate.cfg.xml"/>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
</bean>
<!--
A Spring interceptor that takes care of Hibernate session lifecycle.
-->
<bean id="hibernateInterceptor"
class="org.springframework.orm.hibernate3.HibernateInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<bean name="employeeDAO" scope="prototype"
class="com.tsekhan.rssreader.dao.HibernateController" />
<!-- Searching for hibernate POJO files in package com.tsekhan.rssreader.web -->
<context:component-scan base-package="com.tsekhan.rssreader.web" />
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
</beans>
I note, that if you comment #Transactional in DAO, bean is created correctly. What happens?
First of all its realy bad to give name ending in Controller to a DAO its very confusing, Controller and DAO have all together different purpose.
When you add #Transactional to a service or dao class, for spring to make it work in a transaction needs to create a proxy of that class, its a kind of wrapper where in before the execution of proxied class(class in consideration which is proxied) method spring starts the transaction and after the execution in case no exceptions completes the transaction, this can be done in spring via AOP and Annotations. To describe in code.
public class OriginalDaoImpl implements OriginalDao extends DaoSupport {
public void save(Object o){
manager.save(o);
}
}
public class ProxyDaoImpl implements OriginalDao {
private OriginalDao originalDaoImpl; //instance of OriginalDaoImpl
public void save(Object o){
try{
transaction.start();
originalDaoImpl.save(o);
transaction.commit();
}catch(Exception e){
transaction.rollback();
}finally{
//clean up code
}
}
}
As you see this is not an exact implementation but a foundation code, how transaction magically works for you. The key point is there interface OriginalDao which makes this injection easy as OriginalDaoImpl and ProxyDaoImpl both implement same interface. Hence they can be swapped i.e. proxy taking place of original. This dynamic proxy can be created in java by Java dynamic proxy. Now, the question what if your class is not implementing an interface, it gets harder for the replacement to happen.
One of the libraries CGLIB as far as I know, helps in such a scenario, whereby it generates a dynamic subclass for the class in consideration and in overriden method performs the magic as described above, by calling super.save(o) to delegate to original code.
Now to the problem of injection.
Create interface and make your dao implement that and spring will default to JDK proxy as it is behaving now.
Add proxy-target-class="true" attribute to <tx:annotation-driven transaction-manager="transactionManager"/>
As far as exception is concerned it is throwing as it is expecting injected bean to be of type 'HibernateController' but its not.
For you reference you can refer links below.
10.5.6 Using #Transactional
Spring AOP Doc
Hope this helps !!!!!.
If your are using Spring MVC make sure to scan specific controller classes alone in servlet context file. Otherwise it will scan 2 times and transaction is not available on the application context.

Resources