0
votes

I have an application (javaee / wildfly / Maven) who works like that : Thread processA (trigger Thread processB in background)

I'm using Stateless EJB with @PersistenceContext everything is working fine in the processA, my issue is on the processB the entity persisted inside processA are not up to date in processB, I assume it's because @PersistenceContext has a cache on each process is it right ? So first I wanted to find a way to "refresh" the cache when the only method I used in processB is called, but I don't find anything to do that ...

Then after more readings I discover that the EntityManager is not thread safe and it's better to use a @singleton with an EntityManagerFactory created only once because it's expensive like here : https://subhadipsblog.wordpress.com/2017/09/16/correct-way-of-using-entitymanager-in-singleton-ejb/

@Singleton
public class PersistenceService
{
 @PersistenceUnit(name="somePU")
 EntityManagerFactory emf;

And creating EntityManager as below:

public void persistenceMethod(Entity myEntity)
{
 EntityManager em = emf.createEntityManager();
 ... //Persistence operations
 em.close();
}

EDIT : So I've added this :

@Singleton
public class PersistenceService {

    @PersistenceUnit(name="MyPu")
    EntityManagerFactory emf;

    public ImportState createEntity(MyEntity myEntity) {

        EntityManager em = emf.createEntityManager();
        em.merge(myEntity);
        em.close();
        }

    public List<MyEntity> getMyEntities() {

        EntityManager em = emf.createEntityManager();
        List<MyEntity> myEntities = em.createQuery("from MyEntity as myEntity, MyEntity.class)
                .getResultList();
        em.close();
        return myEntities;
    }
}

And in my services :

@EJB PersistenceService persistenceService;

But I still have the same issue ...

  • ThreadA -> persistenceService.createEntity(myEntity) -> entity is created in Database (org.hibernate.jpa.internal.EntityManagerFactoryImpl@3097af5)
  • ThreadB -> persistenceService.getMyEntities() -> entity created by ThreadA is not seen (org.hibernate.jpa.internal.EntityManagerFactoryImpl@3097af5)

EDIT threadB creation :

ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("debut tache " + Thread.currentThread().getName());
                try {
                    System.err.println(persistenceService.getMyEntities());
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("fin tache");
            }
        });
1
ThreadB will take the data from DB. Do you ever commit a transaction that inserts myEntity in ThreadA?Stanislav Bashkyrtsev
When I was using Stateless EJB with @PersistenceContext commit was automatic, so no I don't commit transaction and even if I add em.getTransaction().commit(); before closing the em I have "A JTA EntityManager cannot use getTransaction" error and em.flush() doesn't change anything / The entity (Thread A) is created in the database I've checked itAliiiiiiii
How are you creating the "Thread processB"? Which version of WildFly are you using?Nikos Paraskevopoulos
Wildfly 10, I've added the code regarding the creation of Thread processBAliiiiiiii

1 Answers

0
votes

This is likely because your thread does not have the correct contexts setup. You'd need to copy the contexts, which may be rather cumbersome. If you want to create threads you should use the Java EE Concurrency utilities.