5

I have a requirement where I have to persist some data in a table and the persisting may take sometime. Basically I want to persist a log. I don't want the execution to wait till the persisting finishes.

I know I have to use threads to accomplish this task and I know that it is discouraged to create threads in an enterprise application.

So I started reading about worker manager and understood and tried a sample program in websphere application server 8.5.

I used asynchbeans.jar from websphere and now I am bothered that I am writing vendor specific code.

Then I came across commonj work api which is described in oracle java documentation. Now I am thinking to use commonj api from fabric3.

My doubt is, is there a better way to accomplish the same task? An EJB way? Or work manager is good for my requirement?

ᄂ ᄀ
  • 5,669
  • 6
  • 43
  • 57
Krishna Chaitanya
  • 2,533
  • 4
  • 40
  • 74

3 Answers3

7

You have some options:

  1. Asynchronous beans. These are vendor-specific, as you mention.
  2. commonj is just barely not vendor-specific. As far as I know, it was only implemented by IBM WebSphere Application Server and BEA WebLogic. The API was effectively superseded by Concurrency Utilities for Java EE, which is really the best choice.
  3. EJB @Asynchronous methods. Requires using EJBs (unwanted complexity for some).
  4. EJB timers. Requires using EJBs, requires serializable data.
  5. JMS. Probably requires using MDBs to receive the message, requires serializable data.
  6. Actually create threads. The EE specs do not recommend this, but as long as you don't attempt to use EE constructs (lookup("java:..."), JPA, UserTransaction, etc.), then you should be fine.
Brett Kail
  • 33,593
  • 2
  • 85
  • 90
  • I have seen some code which uses `java.util.concurrent.Executors.newSingleThreadExecutor()` to obtain an `ExecutorService` and then submits a `Callable` instance. In the `call` method of the `Callable` instance there is some code to persist data in db. Is this a valid approach in ee applications? I want to use jndi in the Callable instance. Can I do that? – Krishna Chaitanya Jan 18 '16 at 10:52
  • 1
    @KrishnaChaitanya You can't reliably use a `java:...` JNDI lookup from such a thread, and direct lookup of JNDI names from the default namespace isn't a Java EE best practice. So, no, not really. You're better off looking up the data source and passing that to the Callable (final local variable or constructor/member variable). – Brett Kail Jan 18 '16 at 15:30
  • for 6: NO! From Section 21.1.2 of the EJB Spec: `The enterprise bean must not attempt to manage threads. The enterprise bean must not attempt to start, stop, suspend, or resume a thread, or to change a thread’s priority or name. The enterprise bean must not attempt to manage thread groups.` Any attempt to do so violates the EJB spec. – searchengine27 Feb 04 '19 at 15:33
  • 1
    Yes, I know the EJB spec says that, but I stand by my statement: sometimes, creating threads yourself is the fastest way to accomplish your goals. If you step outside the spec, then you need to be aware that the services provided by the spec are no longer necessarily available to you, but sometimes it's still the right choice. – Brett Kail Feb 05 '19 at 03:30
4

JavaEE7 has the managed executor, that you can try. You can spawn a task with it, and recieve managed callbacks in a handler. This is part of EE standard and should be platform agnostic.

See JDoc here:

http://docs.oracle.com/javaee/7/api/javax/enterprise/concurrent/ManagedExecutorService.html

Richard Tyregrim
  • 582
  • 2
  • 12
0

If you need to be sure that all your log entries are safely written, then you probably should use JMS with persistent messages. Otherwise you could use @Asynchronous EJB methods.

Gas
  • 17,601
  • 4
  • 46
  • 93