views:

24

answers:

1

Hey guys,

I've implemented an EJB3/JPA web service without any major problems, and now I've moved on a Spring-WS/JPA web service. Both are being deployed to Glassfish.

My understanding of JPA is limited, but by default transactions are container managed? How do you change this? With EJB3 things were straight forward as I could just inject the EntityManager in to the "DAO" (a discussion for another time!) with @PersistentConext and the container would take care of transaction demarcation. In terms of basic configuration that's about it. As the container uses JTA then I've specified the transaction type "JTA" on the persistence unit. In my very simple example application with one persistence unit I do not have to care about its name - Do things get more complicated if you have multiple persistence units or will the container take care of this?

Now I've built an equivelent web service with Spring-WS and have reused my entities/dao's, but I've struggled to get it working. I've included in my application context a bean definition for the EntityManagerFactory (LocalContainerEntityManagerFactoryBean) as well as for the JpaTransationManager (bean reference to EntityManagerFactory). I've also included the PersistenceAnnotationBeanPostProcessor and the tx namespace. I wouldn't have thought I'd need to do anything else but it wont deploy with a No persistence providers available for "null" error.

Do I need to specify the actual persistence unit I want to create a manager for?

Thanks,

Update:

Ok, I'm getting the following error: javax.persistence.PersistenceException: No Persistence provider for EntityManager named null.

It's probably my spring configuration for the factory/manager:

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManager" />

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

<tx:annotation-driven/>

I think I may need or inject something else in to it...

Another update:

Fixed that issue - Was using the LocalEntityManager instead of LocalContainerEntityManager.

Now I'm having problems persisting my objects. I have a parent object with a child object as a property. I can see the child object being persisted in the logs when I call em.persist(parent), but the parent doesn't get persisted.

Last update:

The parent object was getting persisted, but the transaction had not committed before I tried to retrieve it (I'm mocking without mocking so to speak). Think I've got the jist of it now.

A: 

My understanding of JPA is limited, but by default transactions are container managed?

In a Java EE environment, the default entity manager type for a session bean is container-managed and transaction-scoped.

How do you change this?

Change what exactly? And in what context? In an Java EE environment, you would have to use a Bean Managed Transaction (BMT) session bean and to control a UserTransaction.

Do things get more complicated if you have multiple persistence units or will the container take care of this?

I'm not sure about this one, it might be container specific. So if you have multiple persistence units, my advice would be to define the unitName.

Now I've built an equivelent web service with Spring-WS (...) Do I need to specify the actual persistence unit I want to create a manager for?

This shouldn't be required. This article provides a nice summary of the default mechanisms (maybe it's explained in the documentation too but I couldn't find something as succinct):

Spring's LocalContainerEntityManagerFactoryBean loads the persistence unit configuration from the persistence unit descriptor (e.g., META-INF/persistence.xml) whose name is equivalent to the value of the persistenceUnitName property specified on this factory bean (refer to Listings 1 and 2). If a persistence unit name is not provided, the first configuration in the persistence unit descriptor is selected. The injection of the persistence manager into properties of Spring beans annotated with @PersistenceContext is handled by a special bean post-processor, which must be registered in the Spring configuration file, shown in Listing 9.

(...)

When Spring encounters a @PersistenceContext annotation on a bean property, it uses the value of the annotation's unitName attribute to locate an EntityManagerFactory-producing factory bean with a matching persistenceUnitName property value, matching against the bean ID as a fallback. If a unitName attribute is not specified in the annotation, then Spring uses the first EntityManagerFactory-producing factory bean defined in the Spring configuration. An example of using the @PersistenceContext to inject a transaction-scoped EntityManager into a Spring bean is shown in Listing 10. (If there is only a single persistence unit in your application, you can safely leave off the unitName attribute.) (...)

Back to your problem, my suggestions would be to:

  • update your question with the relevant bits of your persistence.xml and Spring configuration
  • activate logging (in particular of org.springframework.orm) to see if everything goes well at initialization time
  • see what you get when you specify the unitName
Pascal Thivent
Cheers fella, I'll get the relevant snippets up later.
pertinky