1
votes

We are trying to build a system, which "produces" an entitymanager depending on the logged-in user (kind of multitenancy). Therefor we implemented a stateless ejb like this:

@Stateless
@TransactionAttribute(TransactionAttributeType.SUPPORTS)
public class CustomEntityManagerFactory {

  @PersistenceContext(unitName = "EM1")
  private EntityManager em1;

  @PersistenceContext(unitName = "EM2")
  private EntityManager em2;

  @Produces
  @RequestScoped
  public EntityManager getEntityManager() {
    // check which entitymanager to return
  }
}

The entitymanager is injected like this:

@Stateless
public class EmployeeService {

  @Inject
  private EntityManager em;

  ...

}

This producer works as long as only an entitymanager without extended persistence context is needed (in stateless ejb). Unfortunately we also have some stateful ejbs, which need the extended persistence context. Is there a way to implement a CDI producer for this purpose or does this approach only work for stateless ejb with transactional entitymanager?

1
I don't understand the problem. Elaborate exactly what the problem is. For example is the code posted working or not? Can you paste some code that is not working?Karl Kildén
Yes my code is working as long as the entitymanager is injected into stateless ejbs. But what can I do, if I need an entitymanager in a stateful ejb (annotated with @PersistenceContext(type = PersistenceContextType.EXTENDED)? I tried to build a producer method for this as well, but I think the CDI lifecycle differs from the EJB lifecycle, so I either get always a new entitymanager (@RequestScoped), or I always get the same entitymanager (@SessionScoped - this leads to an exception since the em is already bound). Unfortunately your suggestion below does not help me in this case.Primi

1 Answers

-1
votes

My guess is you need this: Create two factories here:

@ApplicationScoped
public class EntityManagerFactoryProducer {

    private static EntityManagerFactory factory;
    private static EntityManagerFactory factory2;

    @Produces
    public EntityManagerFactory getEntityManagerFactory(InjectionPoint ip) {
    // if the field is named exactly factory2 then factory2 is produced
    if (ip.getMember().getName().equals("factory2")) {

        if (factory2 == null) {
        factory2 = Persistence.createEntityManagerFactory("EM2");
        }
        return factory2;
    }

    else {
        if (factory == null) {
        factory = Persistence.createEntityManagerFactory("EM1");
        }
        return factory;
    }
    }

Use factories to createEntityManagers

public class EntityManagerProducer {
    @Inject
    private EntityManagerFactory factory;

    @Inject
    private EntityManagerFactory factory2;

    @Produces
    @RequestScoped
    public EntityManager getEntityManager() {
        return factory.createEntityManager();
    }

    @Produces
    @RequestScoped
    @MyCustomQualifier
    public EntityManager getEntityManager2() {
        return factory2.createEntityManager();
    }

}

The qualifier used to differ between entitymanagers

@Qualifier
@Retention(RUNTIME)
@Target({FIELD })
public @interface MyCustomQualifier {
    @Nonbinding
    public String value() default "";
}

end usage:

@Inject
EntityManager em;

@Inject
@MyCustomQualifier
EntityManager em2;

Of course you can use the qualifier to differ between factories instead of checking the name of the field. I just wanted to get some more depth into the answer.