I use karaf 4.0.5 and hibernate 4.2.15 And I want get EntityManager in my BaseDao class.
If I tried get EntityManager in my service
<bean id="subscriberService" class="domain.payment.impl.subscriber.SubscriberServiceImpl" scope="singleton"
init-method="init">
<tx:transaction method="*" />
</bean>
and in class
#PersistenceContext(unitName="payment")
private EntityManager entityManager;
I get EntityManager normaly.
But if I tried it in another class
public class BaseJpaDao<E> implements BaseDao<E>{
protected Class<?> entityClass;
#PersistenceContext(unitName="payment")
private EntityManager entityManager;
public BaseJpaDao(Class<?> entityClass) {
this.entityClass = entityClass;
}
#Override
public E persist(E e) {
entityManager.persist(e);
return e;
}
My entityManager is NULL;
I tried
<bean id="baseDao" class="domain.payment.impl.base.BaseJpaDao" scope="singleton"
init-method="init">
<tx:transaction method="*" />
</bean>
But it not help.
In Spring project it work fine, but in OSGi I have many problems.
really only from the services I can get entityManager?
Have you checked the log ? The BaseJpaDao does not seems to have a public empty constructor, so there should be an error in karaf.log saying the the baseDaobean cannot be created...
Related
I tried create BaseDao and inject EntityManager to it. In Spring I was make this:
public abstract class BaseJpaDao<E> implements BaseDao<E>{
protected Class<?> entityClass;
#PersistenceContext(unitName = "access")
protected EntityManager entityManager;
public BaseJpaDao(Class<?> entityClass) {
this.entityClass = entityClass;
}
#Override
public E persist(E e) {
entityManager.persist(e);
return e;
}
but now I tried make this in OSGI and I not understand how do it. I treid write in blueprint.xml
<bean id="baseJpaDao" class="domain.access.impl.BaseJpaDao" >
<jpa:context unitname="access" property="entityManager"/>
<tx:transaction method="*" value="RequiresNew"/>
</bean>
and after this
public abstract class BaseJpaDao<E> implements BaseDao<E>{
protected Class<?> entityClass;
private EntityManager entityManager;
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public BaseJpaDao(Class<?> entityClass) {
this.entityClass = entityClass;
}
#Override
public E persist(E e) {
entityManager.persist(e);
return e;
}
I treid like this link
but not help.
I tried this
EntityManagerFactory emf = Persistence.createEntityManagerFactory("access", System.getProperties());
em = emf.createEntityManager();
but not help.
In Aries JPA 1.x that does not work.
In Aries JPA 2.x you can use exactly the same code as in spring. See TaskServiceImpl.java. You just need to add the jpa:enable and jta:enable elements to you blueprint context to activate the functionality.
Alternatively you can use the blueprint-maven-plugin to generate the whole blueprint.xml from annotations. Btw version 1.3.0 should be fine. You do not need the snapshot.
Thanks for the configuration snippets. The problem is that you use the wrong namespace for jpa. Try these:
xmlns:jpa="http://aries.apache.org/xmlns/jpa/v2.0.0"
xmlns:tx="http://aries.apache.org/xmlns/transactions/v1.2.0"
I'm trying to get CDI (with Open Web Beans) working from within a unit test using Delta Spike (#RunWith(CdiTestRunner.class)). Dependency injection is working fine but my EntityManagerFactory is always null:
public class EntityManagerProducer {
#PersistenceContext(unitName = "sbPersistenceUnit")
private EntityManagerFactory emf; //Always null
#Produces
public EntityManager create() {
return emf.createEntityManager();
}
public void close(#Disposes EntityManager em) {
if (em.isOpen()) {
em.close();
}
}
}
I know that my persistence.xml is okay because I can create the Session Factory manually:
EntityManagerFactory test = Persistence.createEntityManagerFactory("sbPersistenceUnit");
and all other injections are working fine. Does anybody know what might be missing?
In an unit-test you aren't in a managed environment.
OpenWebBeans would support it via the openwebbeans-resource module + #PersistenceUnit, but that isn't portable.
So you need to use e.g.:
#Specializes
public class TestEntityManagerProducer extends EntityManagerProducer {
private EntityManagerFactory emf = Persistence.createEntityManagerFactory("...");
#Produces
//...
#Override
protected EntityManager create() {
return emf.createEntityManager();
}
#Override
protected void close(#Disposes EntityManager em) {
if (em.isOpen()) {
em.close();
}
}
}
in the test-classpath
If you ask such questions on their mailing-list, you get answers petty quickly.
You will need to use #PersistenceUnit to inject EntityManagerFactory. #PersistentContext is used for EntityManager injection.
Do you define your entitymanagerFactory as a bean?
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
I am new to JPA, Hibernate as well as Spring. Currently I am creating a spring web service which work with a database with a large number of tables. To access those tables I have created separate class annotating #Entity. Then I created a generic DAO class as all my entities need similar operations.
#Transactional
public class GenericJpaDao<T, ID extends Serializable> {
private Class<T> persistentClass;
private EntityManager entityManager;
public GenericJpaDao(Class<T> persistentClass) {
this.persistentClass = persistentClass;
}
protected EntityManager getEntityManager() {
return entityManager;
}
#PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public Class<T> getPersistentClass() {
return persistentClass;
}
#Transactional(readOnly = true)
public T findById(ID id) {
T entity = (T) getEntityManager().find(getPersistentClass(), id);
return entity;
}
#SuppressWarnings("unchecked")
#Transactional(readOnly = true)
public List<T> findAll() {
return getEntityManager().createQuery("select x from " + getPersistentClass().getSimpleName() + " x").getResultList();
}
public T save(T entity) {
getEntityManager().persist(entity);
return entity;
}
public T update(T entity) {
T mergedEntity = getEntityManager().merge(entity);
return mergedEntity;
}
public void delete(T entity) {
entity = getEntityManager().merge(entity);
getEntityManager().remove(entity);
}
public void flush() {
getEntityManager().flush();
}
}
Now I tried to instantiate this GenericJpaDao in the code with relevant Entitiy Class as the persistentClass. But then I could not find a way to set the entitiyManager as I am configuring it via datasource-config.xml as
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml"></property>
<property name="persistenceUnitName" value="hibernatePersistenceUnit" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="dataSource" ref="dataSource" />
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
So according to what I understood from the samples available I need to create separate DAO classes for all my entity classes and instantiate them in spring-ws-servlet.xml.
<bean id="testDao" class="com.sample.dao.TestDao" />
<bean id="service"
class="com.sample.service.DefaultService">
<property name="testDao" ref="testDao" />
</bean>
I think this will be a problem in the long run as I need to have two separated classes for each table in the database, instaintiating them in the xml, keep track of all of them at my service class. Is there any method to overcome this or any best practice available?
You wont need to create a specific DAO for each of your classes.
But you will have to remove the constructor and change your method signatures to include the needed persistentClass (or an instance where you call getClass on).
Basically you need to remove the persistentClass property and change the methods to use the class dynamically from the generic parameter of type T or Class.
That way you have ONE spring managed DAO which is able to handle all of your entities.
I need to inject EntityManager in EntityListener class so that I can perform CRUD operation on it.
POJO:
#Entity
#EntityListner(AuditLogging.class)
class User
{
//Getter / setter of properties
}
AuditLogging (Listner class)
public class AuditInterceptor
{
#PersistenceContext
EntityManager entityManager;
public void setEntityManager(EntityManager entityManager)
{
this.entityManager = entityManager;
}
#PrePersist
public void prePersist(Object obj)
{
// Here I want to use ENTITY manager object so that I can perform CRUD operation
// with prePersist coming object.
entityManager.unwrap(Session.class).save(obj);
// But I am getting NULL POINTER EXCEPTION for entity manager object
}
}
JDBC-CONFIg.xml
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />
<property name="packagesToScan" value="com.XXXXX.entity" />
<property name="jpaProperties">
</bean>
<!-- Datasource -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.driver.classname}" />
<property name="jdbcUrl" value="${jdbc.url}" />
</bean>
<!-- transaction Manager -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
EntityListener is not managed by any of the container.EntityListeners are instanciated by JPA, so Spring does not have an opportunity to inject EntityManager.
My question is, how we can inject inject EntityManager in EntityListener class so that I can perform CRUD operation on it ???
I have faced a similar problem where I was trying to create history records for an entity using EntityListeners.
In order to resolve this problem, I have created utility class BeanUtil with a static method to get the bean and used this util class to get bean inside my Entitylistener class
#Service
public class BeanUtil implements ApplicationContextAware {
private static ApplicationContext context;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static <T> T getBean(Class<T> beanClass) {
return context.getBean(beanClass);
}
}
Now we can call BeanUtil.getBean() to get the bean of any type
public class FileEntityListener {
#PrePersist
public void prePersist(File target) {
perform(target, INSERTED);
}
#Transactional(MANDATORY)
private void perform(File target, Action action) {
EntityManager entityManager = BeanUtil.getBean(EntityManager.class);
entityManager.persist(new FileHistory(target, action));
}
}
We can use this BeanUtil class to get any spring managed bean from anywhere, To know more you can read my article JPA Auditing: Persisting Audit Logs Automatically using EntityListeners.
Anyways, I got this done by getting entityManager reference from EntityManagerFactory bean which is configured in my jdbc-config.xml. But again this is not what I wanted. I wanted to work around with #PersistenceContext.
#Autowired
EntityManagerFactory entityManagerFactory;
private static EntityManager entityManager;
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
entityManager=entityManagerFactory.createEntityManager();
this.entityManagerFactory = entityManagerFactory;
}
Here are few notes that we need to keep in mind:
We can't inject an EntityManager into an EntityListener (through
#PersistenceContext). EntityListener is not managed by any of the
containers
#PersistenceContext class cannot be static. So we cant
attain the instance while class loading.
EntityListeners are
instantiated by JPA, so Spring does not have an opportunity to
inject EntityManager
Well, the first solution which came into my mind is a little "hack", but should work.
public class AuditInterceptor {
static setEntityManager emf;
#Autowired
public void setEntityManagerFactory(EntityManager emf) {
AuditInterceptor.emf = emf;
}
#PrePersist
public void prePersist(Object obj) {
EntityManager entityManager = emf.getEntityManager();
// Here I want to use ENTITY manager object so that I can perform CRUD operation
// with prePersist coming object.
entityManager.unwrap(Session.class).save(obj);
// But I am getting NULL POINTER EXCEPTION for entity manager object
}
}
Inside of your code use EntityManager entityManager = emf.getEntityManager()
Declare your AuditInterceptor as a spring bean (#Component with component-scan or define AuditorInterceptor as a bean)
I used a ThreadLocal to pass the Spring Application Context which contains EntityManager around. Though I am not sure if it is safe Is it safe to pass in the Spring Application Context into a ThreadLocal associated with a request? but so far it is working for me.
The listener can be modified to have autowiring like this. However this needs to be done on on the handlers and not the constructor (doing it on the constructor seems less predictable). You are also not limited to the EntityManager but you have access to the whole context.
#Autowired
private EntityManager entityManager;
#Autowired
private MyDao myDao;
#PrePersist
public void pre() {
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
Objects.requireNotNull(myDao);
myDao.doSomething();
}
I understand we need to keep #Transactional boundaries as short as possible. Here is the code :
I am using userDAO object through Spring dependency injection :
private static ApplicationContext context ;
private UserDAO userDAO;
public TransactionsTest() {
userDAO = (UserDAO) context.getBean("userDAO");
}
I am calling testSaveUserAccounts() from TransactionsTest class trying to use userDAO for insertion/updation of data.
Case 1:
#Transactional
public void testSaveUserAccounts() {
UserAccounts userAccounts = new UserAccounts();
userAccounts.setCommunityId(10L);
userDAO.saveObject(userAccounts);
}
// This method is inside UserDAO
public void saveObject(Object object) {
entityManager.merge(object);
}
Case 2:
#Transactional
public void testSaveUserAccounts() {
UserAccounts userAccounts = new UserAccounts();
userAccounts.setCommunityId(10L);
userDAO.saveObject(userAccounts);
}
// This method is inside UserDAO
#Transactional(propagation=Propagation.REQUIRED)
public void saveObject(Object object) {
entityManager.merge(object);
}
Spring Context :
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSourceLocal" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="persistenceUnitName" value="spring-jpa" />
</bean>
UserDAO :
#Repository
public class UserDAO extends BaseDAO {
#Transactional(propagation=Propagation.REQUIRED)
public void saveObject(Object object) {
entityManager.merge(object);
}
}
BaseDAO :
public abstract class BaseDAO {
protected EntityManager entityManager;
protected HashMap<String,Long> eventIdMap = new HashMap<String,Long>();
#PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this. entityManager = entityManager;
}
public <T> T getById(final Class<T> clazz, final Serializable id) {
T object = clazz.cast(entityManager.find(clazz, id));
return object;
}
#Transactional
public Object save(Object ob) {
Object object = entityManager.merge(ob);
return object;
}
#Transactional
public void persist(Object ob) {
entityManager.persist(ob);
}
#SuppressWarnings("unchecked")
public <T> ArrayList<T> getAll(final Class<T> clazz) {
String hqlQuery = "from "+ clazz.getSimpleName();
ArrayList<T> list = (ArrayList<T>)entityManager.createQuery(hqlQuery).getResultList();
return list;
}
}
I have been experimenting around several transactional boundaries REQUIRED, REQUIRES_NEW, SUPPORTS, etc but couldn't confidently make out as to why Case 1 (when method2 is called which is inside transactional boundary of method1) does not merges the data, while, this is solved in Case 2.
Why do I need to specify #Transactional in inner methods as well when already I have marked calling function within Transaction boundary ?
Your transaction test class is not a Spring Bean that is why Case 1 does not work. Spring needs to detected that a method has #Transactional on it and it does that when spring registers the bean with the spring bean factory.
Also keep in mind that the if you are doing Proxy Based AOP calls within the same bean will not be caught by the transaction aspect unless you use AspectJ load time weaving or AspectJ compile time weaving.
Also putting #Transactional on your Dao's is not a really a good idea because transaction boundaries are best marked at the service layer. The reason why is that a particular service method might need to interact with multiple Dao's and you would want those Dao's actions to be part of the tx started by the service layer, rather than having to analyze the Dao's to see what the propagation behavior is.
Can you post the complete code for the test class?
#Transactional does nothing locally, it only has an effect when called from a different service. In other words, you have to leave your current context for transaction annotations to do anything. so calling method 1 is identical in both cases, Case 2 only does anything if method2 is called from another service.