Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-users] Spring: Attempting to execute an operation on a closed EntityManager.

Hi Tim,
The pure JPA setup that you can find in examples works fine, until you stress the DAO with multiples simultaneous clients. In my case I receive errors when trying to save/delete data. This is related with the fact that the EntityManager defined in the DAO's is the same for all the references:
	http://static.springframework.org/spring/docs/2.0.x/api/org/springframework/orm/jpa/JpaTemplate.html#method_summary
" NOTE: JpaTemplate mainly exists as a sibling of JdoTemplate and HibernateTemplate, offering the same style for people used to it. For newly started projects, consider adopting the standard JPA style of coding data access objects instead, based on a "shared EntityManager" reference injected via a Spring bean definition or the JPA PersistenceContext annotation. (Using Spring's SharedEntityManagerBean / PersistenceAnnotationBeanPostProcessor, or using a direct JNDI lookup for an EntityManager on a Java EE 5 server.)"

This is way I prefer the JpaTemplate in which I inject the EntityManagerFactory (this generates a new instance of EntityManager by each DAO). To avoid the lazy initialization problem only use OpenEntityManagerInView if you are creating an Web Application

Here is an example of the generic dao and one example:

@Repository
public class GenericDaoJPAImpl<T, PK extends Serializable> extends JpaDaoSupport implements GenericDao<T, PK> {

	private Class<T> cPersistentT;

	@Autowired
	private EntityManagerFactory emf;

	@SuppressWarnings("unchecked")
	public GenericDaoJPAImpl(final Class<T> cType) {
this.cPersistentT = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}

       @PostConstruct
	private void postConstruct() {
		setEntityManagerFactory(emf);
	}

	@Transactional(propagation = Propagation.REQUIRED)
	public void delete(final T oEntity2Remove) {
		getJpaTemplate().remove(oEntity2Remove);
		flush();
	}

	@Transactional
	public void delete(final PK oID) {
		T instanceToRemove = getJpaTemplate().find(cPersistentT, oID);
		getJpaTemplate().remove(instanceToRemove);
		flush();
	}

	@SuppressWarnings("unchecked")
	public List<T> findAll() {
return getJpaTemplate().find("select objects from " + cPersistentT.getSimpleName() + " objects");
	}

	public T findById(PK oID) {
		return getJpaTemplate().find(getPersistentClass(), oID);
	}

	@Transactional(propagation = Propagation.REQUIRED)
	public void flush() {
		getJpaTemplate().flush();
	}

	public Class<T> getPersistentClass() {
		return cPersistentT;
	}

	@Transactional(propagation = Propagation.REQUIRED)
	public T save(T oInstance) {
		T oReturn = getJpaTemplate().merge(oInstance);
		flush();
		return oReturn;
	}
}

@Repository
public class ExampleDaoImpl extends GenericDaoJPAImpl<Example, Long> implements I ExampleDao {

	public ExampleDaoImpl() {
		super(Example.class);
	}
}

With this example you need Java 1.6 o 1.5 with the JSR-250 jar (for the @PostConstruct annotation).


On 26-09-2008, at 11:48, Tim Hollosy wrote:

Thanks Shaun,
I've completely given up on tomcat at this point, I'll be in an OC4J
environment in production anyway.

The problem I'm running into now  is there are about 4,000 ways to use
JPA in Spring:

I can get things to work if I use their JpaDaoSupport class, however I
would prefer a more "pure" method....which just happened to FINALLY
work as I typed this, that method was using the @PersistenceContext
annotation to inject an EntityManager.

Unfortunately, now that it works I have no idea why :) I do see now
that AspectJ is reporting it's doing stuff, so I think my problems
before might have been with weaving on some level.

I think part of the problems I was dealing with was two-fold: My Lack
of any real understanding on the Spring Framework and lack of any real
examples.

Once I take the time now to analyze what's going on I'll try to remedy
the latter.

If anyone can impart some best practices for using Eclipselink with
Spring 2.5 I'd be all ears in the mean time.

./tch



On Fri, Sep 26, 2008 at 11:24 AM, Shaun Smith <shaun.smith@xxxxxxxxxx> wrote:
Hi Tim,

  If you're using Spring with EclipseLink you must copy
spring-tomcat-weaver.jar into $CATALINA_HOME/server/lib see the Spring Manual for details. Tomcat absolutely will not support dynamic weaving in Spring (or anything else for that matter) unless you use a technique like this. You didn't mention you did this so don't think you did. Once you have this in place and you've setup your Spring config properly, Spring will do @PersistenceContext injection. Take a look at the TopLink Essentials JPA
version of the Spring PetClinic for an example.

   Shaun

Tim Hollosy wrote:

So no luck em.isOpen returns true.

I can't get my friggin AspectJ Weaver to output anything even though I
have an aop.xml like this:

<!DOCTYPE aspectj PUBLIC
"-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/ aspectj.dtd">
<aspectj>
   <weaver options="-debug -verbose -showWeaveInfo
- XmessageHandlerClass:org .springframework.aop.aspectj.AspectJWeaverMessageHandler">
       <include within="com.redacted.*"/>
   </weaver>
    <aspects>
       <aspect
name = "org .springframework.transaction.aspectj.AnnotationTransactionAspect"/>
   </aspects>
</aspectj>


BUT, doing some more reading about weaving I see: at
http://wiki.eclipse.org/EclipseLink/Examples/JPA/Tomcat_Web_Tutorial#Limitations_to_JPA

As Tomcat is not a JEE5 compatible server, there are some limitiations to
JPA.

   * No dynamic weaving (instrumentation) - static weaving of
entities is still available via EclipseLink
   * No @EJB injection of a session bean (containing the
EntityManager) is available - use the persistence factory and manager
directly
   * No @PersistenceContext injection of a container managed
persistence unit is available - use
Persistence.createEntityManagerFactory(JTA_PU_NAME)


Does that mean i can't use the @PersistenceContext annotation with
EclipseLink in Tomcat 6???

I'm confused as to weather Tomcat 6 supports LTW or not, since there
are instructions all over for getting it to weave with Spring...

I may set up an OC4J Instance and see if I have better luck, but right
now I'm confused as all get out.

./tch



On Fri, Sep 26, 2008 at 6:58 AM, Tim Hollosy <hollosyt@xxxxxxxxx> wrote:


Mohsen,
I didn't actually call isOpen, I instead inspected it with the
debugger, and noticed the isOpen boolean was true. I'll try your
obvious suggestion when I get in to the office this morning.

My hunch is something odd is going on with weaving, so I'm going to
put some weaving logging in as well.


I guess this is just growing pains and it doesn't always help when I
choose bleeding edge -- pure annotations & eclipselink for my first
foray into Spring -- but I just can't stand XML, so I've made my bed
:)

Thanks

./tch



On Fri, Sep 26, 2008 at 6:54 AM, Mohsen Saboorian <mohsens@xxxxxxxxx> wrote:


I didn't test it with EclipseLink, but with Hibernate session is
closed after transaction is committed, and it produces a lot of
frustrations with lazy loading, since you usually need to fetch a list
after a transaction is committed.

Spring provides a OpenSessionInViewFilter to work around this. It
keeps session open durig a request life-cycle.

How did you verified that EM is open? EM.isOpen()?

Mohsen.

On Thu, Sep 25, 2008 at 9:58 PM, Tim Hollosy <hollosyt@xxxxxxxxx> wrote:


I'm hoping some Spring gurus can help me out, whenever I try to
execute a query I get the error: Attempting to execute an operation on
a closed EntityManager.

I'm using Spring 2.5 + Tomcat6.

The weird thing is find's work fine. I'm launching tomcat with the
spring-aspects.jar for weaving. I'm new to this whole spring web stuff
so I am probably missing something, but the only thing I could find
online was to make sure I have the @Transactional annotations used
everywhere in my DAO class, which I do.

If I run in the debugger it looks like the EM is open as well, so I'm
kind of stumped. I suspect some weaving shenanigans, but I'm too much
of a neophyte at this right now to debug much more.

Many thanks :)

Here's my config:

applicationcontext.xml;
<context:component-scan base-package="com.redacted" />

      <tx:annotation-driven mode="aspectj"/>

  <bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager"
        p:entityManagerFactory-ref="entityManagerFactory"/>

      <bean id="dataSource"
              class="org.apache.commons.dbcp.BasicDataSource">
              <property name="driverClassName"
value="oracle.jdbc.OracleDriver" />
              <property name="url"
value="jdbc:oracle:thin:@redacted:1521:redacted" />
              <property name="username" value="redacted" />
              <property name="password" value="redacted" />
      </bean>

      <bean id="jpaAdapter"
class ="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
 <property name="databasePlatform"
value ="org.eclipse.persistence.platform.database.oracle.OraclePlatform"
/>
 <property name="showSql" value="true" />
</bean>


<bean id="loadTimeWeaver"
class = "org .springframework .instrument.classloading.InstrumentationLoadTimeWeaver"/>

<bean id="entityManagerFactory"
class = "org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
     <property name="persistenceUnitName" value="ProofOConcept"/>
     <property name="dataSource" ref="dataSource"/>
     <property name="jpaVendorAdapter" ref="jpaAdapter"/>
     <property name="loadTimeWeaver" ref="loadTimeWeaver"/>

  </bean>

      <util:list id="annotatedClasses">
              <value>com.redacted.*</value>
      </util:list>


Here's my DAO class:

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.eclipse.persistence.jpa.JpaEntityManager;
import org.eclipse.persistence.jpa.JpaHelper;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Transactional
@Repository
public class BasicDao {

      @PersistenceContext(unitName = "ProofOConcept")
      private EntityManager em;

      @Transactional(readOnly = true)
      public <T> T find(Class<T> entityClass, Object primaryKey) {
              T result = em.find(entityClass, primaryKey);

              return result;
      }



      @Transactional(readOnly = true)
      public <T> List<T> selectAll(Class<T> clazz) {
JpaEntityManager jpaEm = JpaHelper.getEntityManager(em);
              Query query = jpaEm.createQuery(null, clazz);
              return (List<T>) query.getResultList();
      }

}






./tch
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-users



_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-users



_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-users


--



Shaun Smith | Principal Product Manager, TopLink | +1.905.502.3094
Oracle Fusion Middleware
110 Matheson Boulevard West, Suite 100
Mississauga, Ontario, Canada L5R 3P4

_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-users


_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-users



Back to the top