Vaadin, JPA and Spring

Hi all,
I’m writing a Vaadin application using JPA for the data model. As far as now i’ve just needed to manipulate signle entity using Item.getProperty(); using JPAContainer.

First a little digression: JPAContainer need a Provider that need EntityManager, as now i’m getting it from a thread local:

MyApplication.getCurrent().getEntityManager();

that give me a singleton instance (for the session).

The singleton instance is created in the init() :

@Override
	protected void init(VaadinRequest request) {
		EntityManagerFactory factory = Persistence
				.createEntityManagerFactory("EScrumDataModel");
		entityManager = factory.createEntityManager();
}

Is this the right way?

Now i need to work on multiple entities:

@Entity
@Table(name="USER")
public class User {
    
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;

    @Column(name="name")
    private int name;

    @Column(name="age")
    private int age;

   @ManyToOne()
   @JoinColumn(name = "group_id")
   private Group group;

//lot of code omitted 

}
@Entity
@Table(name="GROUP")
public class Group{
    
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;

    @Column(name="name")
    private int name;

//lot of code omitted 

}

Now i need the oldest user in the group, so i need a ServiceLayer (since i cant execute a query inside the entity).

I’d like to introduce Spring, i still dont get it at all, but i know it can inject the EntityManager in a class (even if i still dont know how and when):

public class GroupService {
    @PersistenceContext
    private EntityManager em;

    public User getOldestUser(Group group) {
        em.createQuery(...);
        ...
        return user;
   }
}

(i’m a bit confused about the configurations to make this work…but)
How do i get an instance of the service ?

Do i need to create a method in MyApplication? so i can:

MyApplication.getCurrent().getGroupService();

but this way MyApplication must know all the entities type the app use.

Any tips?

I would advise against the approach of above. If you have to store something , you should store the EntityManagerFactory, and create (and close after use) the EntityManager for your requests…

Better would be for the Container to inject the EntitiyManager into your EntityProvider, refere to
21.5. Entity Providers - section - 21.5.3. Entity Providers as Enterprise Beans

Make the GroupService a Stateless Bean


@Stateless
@LocalBean
@TransactionManagement(TransactionManagementType.CONTAINER)
public class GroupService {
    @PersistenceContext
    private EntityManager em;

    /** 
       Carefull , Make sure you know if the entity you passed as parameter here is detached. if so get a managed entity from the entiy manager via em.find() before you try to access lazy load properties like OneToMany etc.. 
    */
    public User getOldestUser(Group group) {
        em.createQuery(...);
        ...
        return user;
   }
}

Worse , you need access the PersistenceUnit of the EJB ( unless you duplicate the persistence.xml for the web module )

  1. Move the persistence.xml to its own module/jar ( It contains nothing but the persistence.xml ), this way you will have access to the persistence unit from outside the ejb module.
  2. add the persistence jar as dependency to your ear project.
  3. I suggest you take a look at
    cdi-utils
    to simplify use of injection and inject the GroupService stateless bean into your view’s Presenter

@SuppressWarnings("serial")
@AbstractPresenter.ViewInterface(SampleView.class)
@PersistenceContext(name = "persistence/Sample", unitName = "sample.ejb.StorePU")
@TransactionManagement(TransactionManagementType.CONTAINER)
public class SamplePresenter extends AbstractPresenter {

    @EJB
    private transient GroupService groupService;
    @PersistenceContext(name = "persistence/Sample", unitName = "sample.ejb.StorePU")
    private transient EntityManager eManager;
    @Resource
    private transient UserTransaction trx;

    /**
       Note you might need to manually start Transaction
    */
    public void someSampleEvent(@Observes @CDIEvent("Sample-Event") final ParameterDTO parameters) {
        try {
            trx.begin();
            eManager.joinTransaction();
            User user = groupService.getOldestUser( someGroup ) ;
            trx.commit();
        } catch (Exception e) {
            _displayError(view.getWindow(), "someSampleEvent() failed", e);
            try {
                if ((trx.getStatus() == 0) || (trx.getStatus() & Status.STATUS_MARKED_ROLLBACK) != 0) {
                    trx.rollback();
                }
            } catch (Exception ex) {
                logger.log(Level.FINEST, "someSampleEvent()  rollback failed", ex);
            }
        }
    }
}

OR you could simply get a jndi reference to your GroupService bean ,



SomeClass {

    // You could hard code these , check the application servers' logs to see what name the GroupService bean is registered with.
    @Resource(lookup = "java:module/ModuleName")
    private String moduleName;
    @Resource(lookup = "java:app/AppName")
    private String appName;


    public GroupService getGroupService() throws NamingException {
        final InitialContext initialContext = new InitialContext();
        return (GroupService) initialContext.lookup("java:global/" + appName + "/" + moduleName + "/GroupService!your.package.name.GroupServiceBeanLocal");
    }
    
}

look at the wiki for some sample projects :
wiki/Main/Coding

sorry for the delay, i don’t get the notification email…

is it not heavy creating the entity manager on each request ? (but i’ll surely inject them)

On a second thought Spring might be too heavy and complex for my needs, i’m looking to Google Guice as dependency injector.

All the annotations you mentioned (i’ll document about) are sring-related or can and should i use them ?

Creating the EntityManger is not expensive , creating the EntityManagerFactory is the expensive thing that should be done only once ( if possible )