According to its JavaDoc, PersistenceAnnotationBeanPostProcessor seems to be responsible for injecting the EntityManager with the annotation #PersistenceContext. It appears to imply without this bean declared in the Spring application context xml, the #PersistenceContext annotation won't work.
However, based on my experiments, this is not the truth.
Persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="default" transaction-type="RESOURCE_LOCAL" />
</persistence>
Spring application context XML
<context:component-scan base-package="com.test.dao" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="persistenceUnitName" value="default"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="true"/>
<property name="databasePlatform" value="org.hibernate.dialect.DerbyDialect"/>
</bean>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.apache.derby.jdbc.ClientDriver"/>
<property name="url" value="jdbc:derby://localhost:1527/c:\derbydb\mydb"/>
<property name="username" value="APP"/>
<property name="password" value="APP"/>
</bean>
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!--
<bean id="persistenceAnnotation" class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
-->
UserDaoImpl
#Repository("userDao")
public class UserDaoImpl implements UserDao {
#PersistenceContext
protected EntityManager entityManager;
#Transactional
public void save(User user) {
entityManager.persist(user);
}
}
Whether I comment or uncomment the persistenceAnnotation bean, the result is the same. It doesn't hurt to leave the bean around, but what's the use of this bean?
I am using Spring 3.0.5.
Could someone provide a scenario where taking out this bean will result in failure?
Also I am not fond of creating an empty persistence unit just to fool Spring. Luckily this problem has been addressed in Spring 3.1.0.
The PersistenceAnnotationBeanPostProcessor transparently activated by the <context:component-scan /> element. To be precise it's the <context:annotation-config /> element that activates the bean but this element in turn gets transparently activated by <context:component-scan />.
As Oliver Gierke mentioned, org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor is automatically loaded into App Context by Spring when using annotation based configuration. One of its duties is to search the proper entity EntityManagerFactory that would provide the EntityManager for you #PersistenceContext annotated properties.
If you have multiple EntityManagerFactory beans in you spring config/context and you have #PersistenceContext annotations without a unitName attribute (lets say you are using a framework that comes with such a bean, and you can't touch framework code), you may run into this exception: org.springframework.beans.factory.NoUniqueBeanDefinitionException.
I found this workaround in case you tun into this:
<bean id="org.springframework.context.annotation.internalPersistenceAnnotationProcessor"
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" >
<property name="defaultPersistenceUnitName" value="entityManagerFactory"/>
</bean>
This would override the default PersistenceAnnotationBeanPostProcessor loaded by Spring with a new one with defaultPersistenceUnitName.
Related
In our application, we want to set multiple data source with Spring and JPA. Hence we have created 2 entityManagerFactory, 2 data source and 2 transaction- manager.
web.xml
<param-value>
/WEB-INF/a_spring.xml
/WEB-INF/b_spring.xml
</param-value>
Persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="db1" transaction-type="RESOURCE_LOCAL">
<class>com.rh.domain.RcA</class>
</persistence-unit>
<persistence-unit name="db2" transaction-type="RESOURCE_LOCAL">
<class>com.rh.domain.Rcb</class>
</persistence-unit>
</persistence>
a_spring.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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
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-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id = "RcMaintenanceService" class="com.rh.services.RcAbcMaintenanceServiceImpl" autowire="byName" />
<aop:config>
<aop:pointcut id="rOperation" expression="execution(* com.rh.services.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="rOperation"/>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/db1" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="db1" />
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="false"/>
<property name="database" value="MYSQL" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>
</bean>
</property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect">
</bean>
</property>
</bean>
I also declare another entityManagetFactory,Transaction Manager and dataSource to b_spring.xml.
Error
Initialization of bean failed; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
unique bean of type [javax.persistence.EntityManagerFactory] is
defined: expected single bean but found 2 Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
unique bean of type [javax.persistence.EntityManagerFactory] is
defined: expected single bean but found 2 at
org.springframework.beans.factory.BeanFactoryUtils.beanOfTypeIncludingAncestors(BeanFactoryUtils.java:303)
at
org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:451)
at
org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:428)
at
org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$AnnotatedMember.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:582)
at
org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$AnnotatedMember.resolve(PersistenceAnnotationBeanPostProcessor.java:553)
at
org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$AnnotatedMember.inject(PersistenceAnnotationBeanPostProcessor.java:489)
In case of multiple data source configuration, we need to define which one will be considered as a primary data source. we can specify that using #Primary annotation in java config or primary=true in XML bean config.
As there is two entity manager being created in XML, we need to use #Qualifier to specify which bean should be injected where. In your case, something like this.
#PersistenceContext(unitName = "db1")
public void setEntityManager(#Qualifier("entityManagerFactory") EntityManager entityMgr) {
this.em = entityMgr;
}
for XML configuration, we can do something like this
<bean id="BaseService" class="x.y.z.BaseService">
<property name="em" ref="entityManagerFactory"/>
<property name="em1" ref="entityManagerFactory1"/>
</bean>
<bean id = "RcMaintenanceService" class="com.rh.services.RcAbcMaintenanceServiceImpl" autowire="byName" parent="BaseService"/>
Did you try providing the package details which contains your EntityManagerFactory bean?
You can provide the package details as a property in you bean definition -
<property name="packagesToScan" value="com.XX.XX.XX.XX" />
new property to be added in this block -
<bean id="entityManagerFactory1" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="db2" />
<property name="dataSource" ref="dataSource1"/>
<-- add here for both beans -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="false"/>
<property name="database" value="MYSQL" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>
</bean>
</property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect">
</bean>
</property>
</bean>
Also, you are missing the persistenceXmlLocation property -
<property name="persistenceXmlLocation" value="***/persistence.xml" />
The error message you've posted indicates that you're autowiring by type for an object of type EntityManagerFactory. None of the code you've shown so far contains such an injection, which implies that it's probably in some code you haven't yet posted.
If you were to post the full stack trace of the error, you'd be able to walk up the stack to see which bean contains the un-satisfiable reference to an EntityManagerFactory object, which in turn would let you change how you're referencing it to allow a reference to the specific bean you want.
Update
Based on the further information you provided (thank you) and some Googling, it seems as though other users have similarly found that specifying a unitName isn't enough to get the correct EntityManager injected. Several posts online back up #lucid's recommendation to use the #Qualifier annotation to get Spring to select the correct bean, but unfortunately that annotation was introduced in 2.5 so it's only available to you if you upgrade. (Which, given the age of the Spring framework that you're using, is probably a good idea, but that's a separate conversation.)
However, several users have indicated that an alternate approach is available in 2.0.5, using a single PersistenceUnitManager that references multiple data sources rather than multiple persistence units that each reference a single data source. From the official Spring docs: https://docs.spring.io/spring/docs/2.0.x/reference/orm.html#orm-jpa-multiple-pu.
Overall I'd suggest you consider upgrading to a version of Spring that's not more than a decade old, which would let you specify an #Qualifier annotation per #lucid's answer. But if that's not possible for some reason, the PersistenceUnitManager approach should give you a way to make it work within Spring 2.0.5.
There are a couple of things that don't look good to me. The name of the setters won't match the property names, I think that is important, the second thing is about the inheritance, some annotations sometimes only works in concrete classes not in base classes. I would try to change the base service as follow.
public class BaseService {
#PersistenceContext(unitName = "db2")
private EntityManager em;
#PersistenceContext(unitName = "db1")
private EntityManager em1;
public EntityManager getEm() {
return em;
}
protected EntityManager getEm2() {
return em1;
}
public void setEm(EntityManager entityMgr) {
this.em = entityMgr;
}
public void setEm1(EntityManager entityMgr) {
this.em = entityMgr;
}
}
If that does not work I probably try to remove the base class and see if I put the annotation under the concrete class I can make that works, I would do that moving just the annotations to the RcAbcMaintenanceServiceImpl class and remove the extend statement that inherits from the BaseService
Also, I noticed that the PersistenceContext annotation has another param https://docs.oracle.com/javaee/6/api/javax/persistence/PersistenceContext.html, so you could try to use the name as well to match the id on the bean definition.
In our project we are using spring with Junit for Junit testing. We have used #ContextConfiguration annotation for loading multiple file. We have two classes AbstractContextJUnitTest and ContextJUnitTest and ContextJUnitTest extends AbstractContextJUnitTest.
During code flow I have noticed that same bean Id in multiple files with different bean types. When I am testing these Junits and getting the below error.
Error:
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean
named 'voterId' is expected to be of type [com.spring.test2.Student]
but was actually of type [com.spring.test2.Parent]
My requirement is Student bean should load with VoterId instead of Parent Bean.
Below are the java files and spring bean xml files:
test.xml:
<beans>
<context:annotation-config/>
<bean id="voterId" class="com.spring.test2.Parent">
<property name="Name" value="hai"/>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#localhost:1521:xe" />
<property name="username" value="system" />
<property name="password" value="system" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
test1.xml
<beans>
<context:annotation-config/>
<bean id="voterId" class="com.spring.test2.Student">
<property name="name" value="hello"/>
<property name="number" value="2080"/>
</bean>
</beans>
AbstractContextJUnitTest.java
#ContextConfiguration(locations="classpath:/com/spring/test2/test1.xml")
public class AbstractContextJUnitTest extends AbstractTransactionalJUnit4SpringContextTests{
}
ContextJUnitTest.java
#ContextConfiguration(locations={"classpath:/com/spring/test2/test.xml"})
public class ContextJUnitTest extends AbstractContextJUnitTest{
#Test
public void testStudent(){
Student stud=applicationContext.getBean("voterId",Student.class);
assertEquals(stud.getNumber(), 2080);
}
}
Did you tried #Primary?
<bean id="voterId" class="com.spring.test2.Student" primary="true">
<property name="name" value="hello"/>
<property name="number" value="2080"/>
</bean>
You have to use #Qualifier for com.spring.test2.Parent wherever you need.
Or you can get the bean with type as:
applicationContext.getBeansOfType(Student.class).get("voterId")
This is probably because you have extended classes in that order..and your test.xml doesn't have any bean with of Student. So it is simply following inheritance and found parent.
Below lines make it look for bean voterid in test.xml first and it found it there.
ContextConfiguration(locations={"classpath:/com/spring/test2/test.xml"}) public class ContextJUnitTest
I migrating my spring batch processes from a command line application to a spring boot webapp including the spring-batch-admin-manager (version 1.3.0).
My old command-line app worked with two JPA databases and two TransactionManager instances. I remember it has been a hell of configuration to get that running. I expected things to get more comfortable, when starting with Spring Boot, but now things seem to be even worse:
Spring is unable to choose the right TransactionManager instance for transactions.
On application startup Spring is visiting one of my classes to execute a #PostConstruct annotated code block, from where a transactional method should be called.
#PostConstruct
public void init() {
eventType = eventTypeBo.findByLabel("Sport"); // <-- Calling transactional method
//...
}
From here the error is thrown. Have a look at the stacktrace:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined:
expected single matching bean but found 2: transactionManager,osm.transactionManager
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:313)
at org.springframework.transaction.interceptor.TransactionAspectSupport.determineTransactionManager(TransactionAspectSupport.java:337)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:252)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy89.findByLabel(Unknown Source)
at com.company.model.service.impl.EventTypeBo.findByLabel(EventTypeBo.java:43)
at com.company.batch.article.utils.converter.SomeConverter.init(SomeConverter.java:83)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
//...
As you can see from the error log my TransactionManagers are named "transactionManager" and "osm.transactionManager". Transactions are configured accordingly:
<!-- DATABASE 1 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- DATABASE 2 -->
<bean id="osm.transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="osm.entityManagerFactory" />
</bean>
<tx:advice id="txAdvice" transaction-manager="osm.transactionManager">
<tx:attributes>
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="osmServiceOperation"
expression="execution(* com.qompa.osm.service.spec..*Service.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="osmServiceOperation" />
</aop:config>
I am using two different GenericDao implementions to distinguish between PersistenceContexts when accessing data:
public class OsmGenericDao<T> implements IGenericDao<T> {
#PersistenceContext(unitName = "osm.entityManagerFactory")
protected EntityManager em;
//...
}
public class GenericDao<T> implements IGenericDao<T> {
#PersistenceContext(unitName = "entityManagerFactory")
protected EntityManager em;
//...
}
Everything seems to be fproperly configured: But still it fails!
EDIT: As far as I can follow Spring's TransactionAspectSupport tries to determine the transactionmanager via a qualifier (determineTransactionManager). Because the findByLabel's #Transactional annotation has no qualifier it tries to determine the correct bean with help of DefaultListableBeanFactory"s getBean method, where two beans of the same type are found that can't be further distinguished.
There must be a way to tell Spring to choose the transactionManager according to the persistence context!
Any ideas?
Here's my working configuration with 2 persistence contexts:
<!-- METADATA -->
<!-- Metadata connection pool -->
<bean id="scprMetadataDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass"
value="..." />
<property name="jdbcUrl"
value="..." />
<property name="user"
value="..." />
<property name="password"
value="..." />
<property name="maxPoolSize"
value="..." />
<property name="minPoolSize"
value="..." />
</bean>
<!-- Metadata entity manager factory -->
<bean id="scprMetadataEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="database" value="H2" />
</bean>
</property>
</bean>
<!-- Metadata transaction manager -->
<bean id="scprMetadataTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="scprMetadataEntityManagerFactory" />
</bean>
<!-- DOMAIN -->
<!-- Domain connection pool -->
<bean id="scprDomainDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass"
value="..." />
<property name="jdbcUrl"
value="..." />
<property name="user"
value="..." />
<property name="password"
value="..." />
<property name="maxPoolSize"
value="..." />
<property name="minPoolSize"
value="..." />
</bean>
<!-- Domain entity manager factory -->
<bean id="scprDomainEntityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="database" value="SQL_SERVER" />
</bean>
</property>
</bean>
<!-- Domain transaction manager -->
<bean id="scprDomainTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="scprDomainEntityManagerFactory" />
</bean>
Other config (missing in your question):
<persistence-unit name="scpr_metadata" transaction-type="RESOURCE_LOCAL">
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<class>...</class>
<class>...</class>
<class>...</class>
</persistence-unit>
<persistence-unit name="scpr_domain" transaction-type="RESOURCE_LOCAL">
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<class>...</class>
<class>...</class>
<class>...</class>
</persistence-unit>
And in my java class:
#Repository
public final class MetadataRepositoryImpl implements MetadataRepository {
#PersistenceContext(unitName = "scpr_metadata")
private EntityManager em;
And:
#Repository
public final class DomainRepositoryImpl implements DomainRepository {
#PersistenceContext(unitName = "scpr_domain")
private EntityManager em;
Hope this helps you.
I am implementing Spring Security in project. I have reached an impasse stuck here since hours.
I am getting this error
Error creating bean with name 'org.springframework.security.authentication.dao.DaoAuthenticationProvider#0': Cannot resolve reference to bean 'UserDAOImpl' while setting bean property 'userDetailsService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myUserDetailService' is defined
The project setup is very simple
spring-security.xml
<authentication-manager>
<authentication-provider user-service-ref="myUserDetailService">
</authentication-provider>
</authentication-manager>
dispatcher-servlet.xml
<context:component-scan base-package="app.com,app.com.controller,app.com.dao,app.com.service,app.com.model"/>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"
p:basename="messages"/>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/view/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
ApplicationContext.xml
<context:annotation-config />
<!-- <context:property-placeholder> XML element automatically registers a new PropertyPlaceholderConfigurer
bean in the Spring Context. -->
<context:property-placeholder location="classpath:database.properties" />
<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="hibernateTransactionManager"/>
<!-- Creating DataSource -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${database.driver}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.user}" />
<property name="password" value="${database.password}" />
</bean>
<!-- To persist the object to database, the instance of SessionFactory interface is created.
SessionFactory is a singleton instance which implements Factory design pattern.
SessionFactory loads hibernate.cfg.xml and with the help of TransactionFactory and ConnectionProvider
implements all the configuration settings on a database. -->
<!-- Configuring SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>app.com.model.User</value>
<value>app.com.model.Roles</value>
<value>app.com.BaseEntity</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
</props>
</property>
</bean>
<!-- Configuring Hibernate Transaction Manager -->
<bean id="hibernateTransactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
CustomUserDetailsService.java
#Service("myUserDetailService")
#Transactional
public class CustomUserDetailsService implements UserDetailsService {
#Autowired
private UserDAO userDAO;
/*#Override
public UserDetails loadUserByUsername(String arg0)
throws UsernameNotFoundException, DataAccessException {
// TODO Auto-generated method stub
return null;
}
}
I also tried declaring the bean in both dispatcher-servlet.xml & application-context.xml it doesn't work
checked the context-component base package. It is scanning all the other classes present just fine. When I remove myUserDetailService from authentication provider the server starts just fine without any error.
I am really tired. Can anyone please help me in fixing this?
the reason why you got this working after moving the definitions to your context file is because in spring, the definitions inside the dispatcher servlet are only visible to mvc, and definitions inside context are global (to servlet and security), here is a page where its clearly explained https://weblogs.java.net/blog/sgdev-blog/archive/2014/07/05/common-mistakes-when-using-spring-mvc
phew... got it working.
Moved
<context:component-scan base-package="app.com,app.com.controller,app.com.dao,app.com.service,app.com.model"/>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"
p:basename="messages"/>
from dispatcher-servlet to application-context.xml
Would anyone care to tell why it started working?
I understand that this is a very long question, but i wanted to ask everything because i'm
stuck with these things for more than 2 weeks and i'm in a situation to solve this within
this week. Please guide me in this matter.
I'm Using EclipseLink jpa version 2, Spring 3, jdk6, MySQL5 and tomcat7.
I have configured the following in each of my DAO classes.
#PersistenceContext
private EntityManager em;
I have the following in my Spring xml:
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
<property name="url" value="jdbc:mysql://localhost:3306/xxxxx"/>
<property name="username" value="xxxx"/>
<property name="password" value="xxxx"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
</bean>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="jpaDialect" ref="jpaDialect"/>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<property name="jpaDialect" ref="jpaDialect"/>
</bean>
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter" >
<property name="showSql" value="true"/>
<property name="generateDdl" value="true" />
</bean>
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect"/>
From Persistence.xml:
<persistence-unit name="xxxxx" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<-- class mappings -->
</persistence-unit>
I've got few confusion about what i have done:
Is the EntityManager injected by Spring? (I understand that #PersistenceContext is a
J2EE annotation, so wondering whether it is injected without Spring's contribution).
As i have already mentioned, i have injected EntityManager in all the DAO classes. Is
this a good practice? or should i make it Singleton by having a separate class like
PersistenceManager, which has EntityManager attribute wired, and have
getEntityManager() method?
As you can see above, i have configured Spring transactions. But when i do CRUD
operations continuously for 2-3 times, application gets stuck and fails with EclipseLink
exception saying unable to get lock, timeout etc. Am i doing anything wrong here or
missing any transaction configurations??
With the above configurations, i can only use #Transactional annotation with default
values which are PROPAGATION_REQUIRED,ISOLATION_DEFAULT. If i change these for any other
values, such as #Transactional(PROPAGATION_REQUIRED,ISOLATION_SERIALIZABLE) etc,
application throws exception as Custom isolation levels are not supported. Again, am
i missing any configurations?
Thanks.
Yes, spring recognizes the #PersistenceContext annotation and injects the entity manager
Spring takes care of that - it injects the same EntityManager instance in all DAOs. In fact, it injects a proxy so that each request uses a different entity manager.
Normally everything should run fine. You need <tx:annotation-driven /> in order to use #Transactional
JPA only supports the default isolation level. You can work this around by customizing the spring jpa dialect, but there's nothing built-in. The way to go is extend XJpaDialect (in your case X=EclipseLink), override the beingTransaction, obtain the Connection (in an eclipse-link specific way), set the desired isolation level (accessible through the transaction definition), and configure this as a property of your LocalContainerEntityManagerFactoryBean:
<property name="jpaDialect">
<bean class="com.foo.util.persistence.EclipseLinkExtendedJpaDialect" />
</property>