Search code examples
jsfjakarta-eeejb

Can I use an EJB in an infinite thread


I would like to know if it's prohibited to use an EJB in an infinite thread(since it can't be given back to the container).

Something like this:

@ManagedBean(eager = true)
@ApplicationScoped
public class TestListenner {

    private ResultThread result;

    @PostConstruct
    public void init() {
        result = new ResultThread ();
        Thread myThread = new Thread(result);
        myThread.start();
    }
    public ResultThread getResult() {
        return result;
    }
}

And the thread:

public class ResultThread implements Runnable{
    @EJB
    private SomeService service;
    private boolean continueWork = true;

    public void run(){
        while(continueWork){
            service.doSomething();
            //some proccessing
        }
    }

I'm working with EJB's since I started working with databases. I went over daofactories and the likes but I forgot about them(it was a year ago). I use them to do actions on my database when an user request a web page on my web app. But now I need to have a thread that calculate things in my database continuously to decrease the response time. If I cannot use EJB for the reason the container needs to have an handle on them, then what should I use ?

Hopefully I can use a class similar to what I'm used to use :

@Stateless
public class SomeServiceImpl implements SomeService {
    @PersistenceContext(unitName = "my-pu")
    private EntityManager em;

    @Override
    public void updateCategory(SomeClass theclass) {
        em.merge(theclass);
    }
}

Edit: The first answer by BalusC in this topic seems to imply that spawning threads in a ManagedBean wouldn't be dangerous in a case where no additional threads could be spawned. Since my bean is ApplicationScoped, which the web-app uses 1 and only 1 instance of it to do background work on the database (I've actually like a TOP 100 "posts" table that needs to be continually recalculated over time so I can query the table -with another bean- to have a fast answer).


Solution

  • What you have now won't work for at least one reason:

    You can't inject resources into non-managed components. For the @EJB annotation to work, ResultThread ought to be a managed bean, and injected by the container. That means, that you must at least use CDI to inject it, rather than the new ResultThread you have now. What will work will look something like:

    @Inject
    private ResultThread result;
    

    This way, the container gets in on the action.

    The bottom line however, is that there are better ways of doing what you appear to be trying to do.

    It may also interest you to know that EJBs are not allowed to spawn their own threads; in fact, it's frowned upon to do any handmade threading in the container. Why? The container is a managed environment - one where memory and concurrency have already been well thought out and designed. Your handspun thread breaks that model and any guarantees that the container may have been able to give you on your beans and other app components

    Related: