EntityManager not injected from factory - spring

I'm using JPA/Hibernate to build a web app. I'm using a LocalContainerEntityManagerFactoryBean with <property name="packagesToScan" value="<pkg>" /> to build my entities from a java package, and a jdbc.datasource.DriverManagerDataSource configured for PostgreSQL, so I don't have a defined persistence context.
Can I build an EntityManager with these constraints, using either Spring annotations or xml?
EDIT:
I'm using a code of the following form to get a user data for login. In the Spring Security context the EntityManager is always null.
#Repository
public class UserDao implements UserDetailsService {
#PersistenceContext
private EntityManager entityManager; // With getter and setter
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
// Used by spring-security, here entityManager is null
}
}
EDIT2: Added context configuration
<context:spring-configured />
<context:annotation-config />
<context:component-scan base-package="<BasePackage>" />
EDIT3: Added entity manager factory config:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="default_unit" />
<property name="dataSource" ref="dataSource" />
<property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence"></property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
</bean>
</property>
<property name="packagesToScan" value="<package>" />
<property name="jpaProperties">
<value>
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.hbm2ddl.auto=create-drop
hibernate.hbm2ddl.import_files=/loaded-on-startup/import.sql
<!-- ALSO CHECK IMPORT.SQL -->
</value>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
/// CONNECTION CONFIG ///
</bean>
I also have added default-autowire="byType" to my beans tag and autowire="byType" to the security authentication bean definition.

Yes. Take a look here . You need to provide a datasource and use LocalContainerEntityManagerFactoryBean bean
Edit
It may be because of no transaction available.Read here

Related

Embedded H2 Database for Spring unit test with Liquibase: No data in tables when running test

I have embedded H2 database for my Spring unit tests. The tables and data should be initialized with Liquibase. However, when a test is running, there are no data in the table.
I'm using Spring 4.2.1, Liquibase 4.7.1 and H2 2.1.210.
Below is my implementation:
The datasource is declare in .xml file
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.h2.Driver" />
<property name="url" value="jdbc:h2:mem:test;MODE=Oracle;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE" />
<property name="username" value="test" />
<property name="password" value="test" />
</bean>
<bean id="liquibase" class="liquibase.integration.spring.SpringLiquibase">
<property name="dataSource" ref="dataSource" />
<property name="changeLog" value="classpath:liquibase/changelog/sil_client_init.h2.sql" />
<property name="contexts" value="test" />
</bean>
<!-- Session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:hibernate-config.xml" />
</bean>
<!-- Transaction manager -->
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
The sil_client_init.h2.sql file contains SQL contains changeset for creating and inserting several data in the table.
I have a super class which load the context, including the "liquibase" bean declared above.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath*:applicationContext.xml" })
#Ignore
public class SpringApplicationContextIT {
#Before
public void setUp() {
BasicConfigurator.configure();
FacesContextMocker.mockFacesContext();
assertNotNull(applicationContext);
}
#Autowired
private ApplicationContext applicationContext;
}
From which my test class inherits
public class ClientDAOTest extends SpringApplicationContextIT {
#Autowired
private IClientDAO simpleClientDAO;
#Test
#Transactional
public void getAllClients() throws ClientDAOException {
simpleClientDAO.find();
}
When running getAllClients(), the context are loaded and there is log showing that my changesets Liquibase were running. However, when the test arrives at simpleClientDAO.find(), my Client table is empty.
Any idea of how to fix, how this could happen or how I could investigate the reason would be appreciated. Thank you so much in advance!
For those who might have the same problem, turn out the datasource is properly loaded but my sessions are not correctly connected.
I had to specify a package to scan for my sessionFactory bean:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<value>com.myApp.dao.entity</value>
</property>
<property name="configLocation" value="/WEB-INF/classes/hibernate-config.xml" />
</bean>

From TransactionProxyFactoryBean to a Declarative transaction management?

I want to migrate from old style of transaction management with TransactionProxyFactoryBean to a Declarative transaction management recommended by spring.
So that will be possible to avoid exceptions with transactions that appear from time to time.
This is my configuration xml file:
<beans xmlns=...>
<context:annotation-config/>
<context:component-scan base-package="prof" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation">
<value>WEB-INF/classes/hibernate.cfg.xml</value>
</property>
</bean>
<import resource="prof-dao-spring.xml" />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
...
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<bean id="ProfileService" parent="baseTransactionProxy">
<property name="target">
<bean class="tv.clever.hibernate.service.ProfileService"></bean>
</property>
</bean>
</beans>
ProfileService looks like:
#Component
public class ProfileService {
#Autowired
#Qualifier("baseDAO")
protected BaseDAO baseDAO;
private static ProfileService profileService;
public ProfileService() {
setProfileService(this);
}
public void setProfileService(ProfileService ps) {
profileService = ps;
}
public void save(final Collection transientObjects) {
baseDAO.save(transientObjects);
}
...
}
From where do I need to start?
Assuming you want to use annotations slap a #Transactional on your service class, add <tx:annotation-driven /> to your configuration and remove the TransactionalProxyFactoryBean declaration and all beans using that as a parent.
Additional pro-tips:
Use #Service for service classes and #Repository for daos
<context:annotation-config /> is implied by <context:component-scan />
Your service
#Service
#Transactional
public class ProfileService { ... }
Configuration
<beans xmlns=...>
<context:component-scan base-package="prof" />
<import resource="prof-dao-spring.xml" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation">
<value>WEB-INF/classes/hibernate.cfg.xml</value>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven />
</beans>
Restart application.

Hibernate + Spring two persistence units with their own entity subsets

I am new to Spring but in general I am aware of it's features so I decided to use it in one of my projects. Main problem however is with Hibernate. Before this idea of introducing spring the premise is this:
My application (not web) had to connect to a DB and gather information from it using "persistence_1.xml" with it's own set of entity classes. In other words everything related to "persistence_1.xml" was read only so that no tragedies would occur. Also "persistence_1.xml" with persistence-unit of name "p1" came from web-app dependencies. So picture is this: my app (not-web) written with the support of maven, took dependencies of the other application to access database and gather information.
And the other "persistence_2.xml" with persistence-unit name of "p2" and it's own subset of entities was created by me to store gathered and processed information into the same database.
So originally I had two entity managers one responsible for "p1" another for "p2".
I have seen some material on the internet where they show how to configure two entity managers with different dataSources but I can not figure out how to create two entity managers in SPRING using their own set of ENTITIES.
Let's say "test" is only associated with "UserEntity" and "dummy" is only associted with "DumbEntity".
Now everything get's mashed up along the way and no matter which PU name I type in in #PersistenceContext(name = "test") - it can query for any entity in database.
This is example of persistence.xml:
<persistence-unit name="test" type="RESOURCE_LOCAL">
<class>org.test.db.UserEntity</class>
</persistence-unit>
<persistence-unit name="dummy" type="RESOURCE_LOCAL">
<class>org.test.db.DumbEntity</class>
</persistence-unit>
Bean definition:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="url" value="jdbc:mysql://localhost:3306/spring"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="test" />
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="true" />
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
</bean>
</property>
</bean>
<bean id="entityManagerFactory2" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="dummy" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="true" />
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
</bean>
</property>
</bean>
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="transactionManager2" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory2"/>
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean name="userDao" class="org.test.services.UserDaoImpl" />
My UserDaro service
public class UserDaoImpl implements UserDao {
#PersistenceContext(unitName = "test")
private EntityManager entityManager;
public UserDaoImpl() {
}
public UserDaoImpl(EntityManager entityManager) {
this.entityManager = entityManager;
}
#Transactional(propagation = Propagation.REQUIRES_NEW)
#Override
public void saveUser(UserEntity user) {
entityManager.persist(user);
}
#Transactional(propagation = Propagation.REQUIRES_NEW)
#Override
public void saveUser(DumbEntity user) {
entityManager.persist(user);
}
#Override
public List<UserEntity> fetchAllUsers() {
String sql = "FROM UserEntity";
Query query = entityManager.createQuery(sql);
return query.getResultList();
}
#Override
public List<DumbEntity> fetchAllUsers2() {
String sql = "FROM DumbEntity";
Query query = entityManager.createQuery(sql);
return query.getResultList();
}
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
}
In any way whether or not I use fetchAllUsers() or fetchAllUsers2() I get the result, but I would like that each of these would only work with entityManager that only has the knowledge about about specific entities.
I would like you to share your thoughts on this one. Thank You.

how to get transaction supporting proxy from spring application context?

i need to use bean from spring application context not in a spring managed bean, so i do next: annotate bean with #Service annotation, so instance of bean created during spring loading.
<bean id="customRevisionListener" class="ru.csbi.registry.services.impl.envers.CustomRevisionListener" />
This instance is ApplicationContextAware, so application context is injected in this bean instance and i save it to static variable:
#Service
public class CustomRevisionListener implements EntityTrackingRevisionListener, ApplicationContextAware {
private static ApplicationContext applicationContext;
private ModelInformationService modelInformationService;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
CustomRevisionListener.applicationContext = applicationContext;
}
private ModelInformationService getModelInformationService() {
if (modelInformationService == null) {
modelInformationService = applicationContext.getBean(ModelInformationService.class);
}
// TransactionProxyFactoryBean
return modelInformationService;
}
After that another instance of CustomRevisionListener created in not spring context(hibernate envers context). Here i use static variable to receive spring applicationContext
after that i'm getting beans from application context:
private ModelInformationService getModelInformationService() {
if (modelInformationService == null) {
modelInformationService = applicationContext.getBean(ModelInformationService.class);
}
the problem is that this bean has all #Autowired properties injected correctly:
#Service
public class ModelInformationServiceImpl implements ModelInformationService {
#Autowired
private EntityChangeService entityChangeService; // injected correctly
#Autowired
private PropertyService propertyService; // injected correctly
#Autowired
private ru.csbi.registry.services.reflection.HibernateDomainService hibernateService; // injected correctly
, but they are simple instances of java classes not Proxies supporting #Transactional annotation, which they are for my regular spring code:
getModelInformationService().getClass().getName() is "ru.csbi.registry.services.impl.envers.ModelInformationServiceImpl"
and must be something like
$Proxy71
How to get transaction supporting proxies, which spring genereates for example when injecting beans in #Controller, in bean not managed by spring?
i'm using next spring config:
<bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<constructor-arg ref="lazyConnectionDataSourceProxy"/>
</bean>
<bean id="lazyConnectionDataSourceProxy" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<property name="targetDataSource">
<ref local="dataSourceTarget" />
</property>
</bean>
<bean id="dataSourceTarget" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${ds.driver}" />
<property name="url" value="${ds.url}" />
<property name="username" value="${ds.user}" />
<property name="password" value="${ds.password}" />
<property name="initialSize" value="${ds.initialSize}" />
<property name="maxActive" value="${ds.maxActive}" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<!--property name="entityInterceptor">
<bean class="ru.csbi.registry.utils.audit.AuditLogInterceptor">
<property name="sessionFactory" ref="auditSessionFactory" />
</bean>
</property-->
<property name="dataSource" ref="dataSource" />
<property name="lobHandler" ref="oracleLobHandler" />
<property name="packagesToScan" value="ru.csbi.registry.domain" />
<property name="hibernateProperties">
<bean id="hibernatePropertiesFactoryBean" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>file:${realtyregistry.settings.path}/hibernate-config.properties</value>
</list>
</property>
</bean>
</property>
<property name="eventListeners">
<map>
<entry key="post-insert" value-ref="auditEventListener" />
<entry key="post-update" value-ref="auditEventListener" />
<entry key="post-delete" value-ref="auditEventListener" />
<entry key="pre-collection-update" value-ref="auditEventListener" />
<entry key="pre-collection-remove" value-ref="auditEventListener" />
<entry key="post-collection-recreate" value-ref="auditEventListener" />
</map>
</property>
</bean>
<bean id="auditEventListener" class="org.hibernate.envers.event.AuditEventListener" />
<bean id="persistenceManagerHibernate" class="ru.csbi.registry.utils.PersistenceManagerHibernate">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

In spring, what code is used to inject the value for the #PersistenceContext annotated variables?

Using a ClassPathXmlApplicationContext object I want to get the same EntityManager that is being used by other parts of the app which get it injected via:
#PersistenceContext(unitName="accessControlDb") private EntityManager em;
Using ctx.getBean("access-emf") I can get the EntityManagerFactory which is defined in the applicationContext.xml. Using that I can create a new EntityManager, but I can't get the existing EntityManager used by the rest of the app.
I just can't figure out what code is executed to inject the value for the #PersistenceContext annotation.
<bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/>
<bean id="innerNgsdpDataSource" class="org.enhydra.jdbc.standard.StandardXADataSource">
<property name="driverName" value="${ngsdp.jdbc.driver}"/>
<property name="url" value="${ngsdp.jdbc.url}"/>
<property name="user" value="${ngsdp.jdbc.username}"/>
<property name="password" value="${ngsdp.jdbc.password}"/>
<property name="transactionManager" ref="jotm"/>
</bean>
<bean id="ngsdpDataSource" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource">
<property name="transactionManager" ref="jotm"/>
<property name="dataSource" ref="innerNgsdpDataSource"/>
<property name="user" value="${ngsdp.jdbc.username}"/>
<property name="password" value="${ngsdp.jdbc.password}"/>
<property name="maxSize" value="4"/>
<property name="checkLevelObject" value="2"/>
<property name="jdbcTestStmt" value="select 1 from dual"/>
</bean>
<bean id="myEmf" name="moservices" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="ngsdpDataSource"/>
<property name="persistenceXmlLocation" value="WEB-INF/moservices-persistence.xml" />
<property name="jpaVendorAdapter" ref="hibernate_jpa_vendor_adapter" />
<property name="jpaPropertyMap" ref="jpa_property_map"/>
<property name="jpaDialect" ref="hibernate_jpa_dialect"/>
</bean>
If using spring-managed transactions, you can get the current EntityManager by calling
EntityManagerFactory emFactory = ctx.getBean("access-emf");
EntityManagerHolder emHolder =
(EntityManagerHolder) TransactionSynchronizationManager.getResource(emFactory);
EntityManager em = emHolder.getEntityManager();
This is most often the current EntityManager. But this is something which should be avoided (except possibly in unit-tests), as stated in the spring docs:
To be used by resource management code but not by typical application code
Another approach might be to intercept your service calls using Spring AOP, inject the #PersistenceContext in the advice, and set in in a ThreadLocal of yours. Later, you can get it from that ThreadLocal.

Resources