|
I'm using CDI to build my EntityManager.
When building it, Hibernate doesn't manage to retrieve my DataSource using JNDI.
It's not a problem of my persistence.xml or context.xml because when my EntityManager is built sooner (in a @WebListener > .contextInitialized(ServletContextEvent)), the DataSource is correctly found using the same JNDI address.
I debugged the application and saw that new javax.naming.InitialContext().lookup("java:/comp/env/jdbc/myproject") was correctly returning the DataSource until Thread.currentThread().setContextClassLoader( aggregatedClassLoader ) in :
public <T> T withTccl(Work<T> work) {
final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
boolean set = false;
try {
Thread.currentThread().setContextClassLoader( aggregatedClassLoader );
set = true;
}
catch (Exception ignore) {
}
try {
return work.perform();
}
finally {
if ( set ) {
Thread.currentThread().setContextClassLoader( tccl );
}
}
}
After the execution of that line, new javax.naming.InitialContext().lookup("java:/comp/env/jdbc/myproject") throws javax.naming.NameNotFoundException: Name java:/comp/env/jdbc/myproject is not bound in this Context.
Here is the complete stack :
Here are the classes :
@Path("/administration/userSearch")
@ApplicationScoped
public class UserSearchWS {
@Inject
private ProfileService profileService;
@GET
@Path("/init")
public StreamingOutput init() {
final List<Profile> profileList = profileService.findAll();
...
@Transactional
@ApplicationScoped
public class ProfileService extends JPAEntityService<Profile, Integer> {
@Inject
private Instance<EntityManager> entityManagerInstance;
public List<Profile> findAll() {
return entityManagerInstance.get().createQuery("from Profile").getResultList();
}
}
@Interceptor
@Transactional
public class TransactionalInterceptor {
@Inject
Instance<EntityManager> entityManagerInstance;
@AroundInvoke
public Object interceptTransactional(final InvocationContext invocationContext) throws Exception {
EntityManager entityManager = null;
EntityTransaction transaction = null;
try {
entityManager = entityManagerInstance.get();
transaction = entityManager.getTransaction();
} catch (final ContextException e) {
...
@ApplicationScoped
public class EntityManagerFactoryProducer {
@Produces @ApplicationScoped
public EntityManagerFactory createEntityManagerFactory() {
return Persistence.createEntityManagerFactory("com.mycompany.myproject");
}
@Produces @RequestScoped
public EntityManager createEntityManager(final EntityManagerFactory entityManagerFactory) {
return entityManagerFactory.createEntityManager();
}
...
...
<persistence-unit name="com.mycompany.myproject" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<non-jta-data-source>java:/comp/env/jdbc/myproject</non-jta-data-source>
...
And when I use that DataInitializer, I'm getting no problem, the previous code passes because the EntityManagerFactory is correctly initialized :
@WebListener
public class DataInitializer implements ServletContextListener {
@Override
public void contextInitialized(final ServletContextEvent sce) {
try {
final Context ctx = new InitialContext();
final BeanManager beanManager = (BeanManager) ctx.lookup("java:comp/env/BeanManager");
final Bean<EntityManagerFactory> bean = (Bean<EntityManagerFactory>) beanManager.resolve(beanManager.getBeans(EntityManagerFactory.class));
final EntityManagerFactory entityManagerFactory = beanManager.getContext(bean.getScope()).get(bean, beanManager.createCreationalContext(bean));
final EntityManager entityManager = entityManagerFactory.createEntityManager();
} catch (final NamingException e) {
throw new IllegalStateException("Problem while initializing", e);
}
}
...
In that case, here is the stack when correctly creating my EntityManagerFactory & EntityManager :
I've tested with latest Tomcat (7.0.53) and still have the same behaviors.
|