Can I start a ManagedThread in a Singleton Enterprise Java Bean? - java

I'm trying to start a thread in a Singleton EJB but java.lang.IllegalStateException is being thrown. This is my (cut-down) class:
Singleton
#LocalBean
#Startup
public class WatcherEJB {
#Resource(name = "concurrent/masterActionsThreadFactor")
ManagedThreadFactory threadFactory;
Thread watcherThread;
#PostConstruct
public void startUp() {
//Setup the listener using the ThreadFactory
watcherThread = threadFactory.newThread(new Runnable() {
#Override
public void run() {
//System.out.println("Watcher Thread started");
}
});
watcherThread.start(); //java.lang.IllegalStateException thrown here
}
}
I'm assuming that there's a problem with when I'm trying to start the Thread object or does Java EE 7 not allow Managed threads in singletons?

What application server do You use?
If it's WildFly You probably run into this issue: https://issues.jboss.org/browse/WFLY-2343

I came across this thread when looking for a solution and I thought that I would post this link to a thread which I believe answers the question. I know it has been a while since this question was asked but it should be useful for future reference!
Glassfish 4 - Using Concurrency API to create Managed Threads

Related

Java EE EJB as Runnable executor

Is this code copmliant to Java EE spec and can be used?
#Stateless
public class SomeBean {
#Inject
protected TransactedRunner txRunner;
public void someFunc() {
txRuner.run(new Runnable(){
Connection c = ds.getConnection();
//do jdbc stuff or jpa stuff
//close everything etc.
});
}
}
#Stateless
public class TransactedRunner {
#TransactionAttribute(REQUIRES_NEW)
public void run(Runnable r) {
r.run();
}
}
In this case a new transaction should be started and every thing that will be done in runnable will be transacted. Is that right? Or there is some trick in which I should suffer from EE?
This should work as intended. But be aware, that multiple calls of txRunner.run during one service call might lead to inconsistent data if anything happens between or during those calls, like connection-timeout, transaction-timeout, or the node dies or something. And the calling transaction (if there is any) might not see the changes done during the call until it itself has been committed.
There is an annotation in JavaEE6 called #Asynchronous which is specifically for this purpose. Here is the official tutorial: http://docs.oracle.com/javaee/6/tutorial/doc/gkkqg.html
#Stateless
public class SomeBean {
#Inject
private SomeBean self;
public void someFunc() {
self.doSomething();
}
#TransactionAttribute(REQUIRES_NEW)
#Asynchronous
private void doSomething() {
Connection c = ds.getConnection();
//do jdbc stuff or jpa stuff
//close everything etc.
}
}
Also it's not allowed to create or manage Threads within a EJB Container. Check out: http://www.oracle.com/technetwork/java/restrictions-142267.html#threads
Why is thread creation and management disallowed?
The EJB specification assigns to the EJB container the responsibility for managing threads. Allowing enterprise bean instances to create and manage threads would interfere with the container's ability to control its components' lifecycle. Thread management is not a business function, it is an implementation detail, and is typically complicated and platform-specific. Letting the container manage threads relieves the enterprise bean developer of dealing with threading issues. Multithreaded applications are still possible, but control of multithreading is located in the container, not in the enterprise bean.
Method "run" will be executed in transaction, that's true. But it has nothing in common with threading or using executor. In your example, the calling thread will execute your "run" method. Runnable interface itself won't create a separate thread for you.
If you need this call to be executed by separate thread, you can use asynchronous calls, or, starting from EE7, a ManagedExecutorService is available:
http://docs.oracle.com/javaee/7/api/javax/enterprise/concurrent/ManagedExecutorService.html

Thread spawning libraries in EJB

Is it allowed to use libraries inside an EJB which are spawning and manage threads?
I wrote a JavaSE library with a class like this:
public class LibraryClass {
public void longRunningMethod() {
ExecutorService service = Executors.newFixedThreadPool(10);
//schedule tasks
service.shutdown();
try {
service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Example EJB:
#Stateless
class Bean {
public void beanMethod() {
LibraryClass libraryClass = new LibraryClass();
libraryClass.longRunningMethod();
}
}
Would it be ok to use something like this inside an EJB?
The specification states that "The enterprise bean must not attempt to manage threads", would this still apply if the threads are managed outside of the EJB, maybe even out of control of the developer (for example when using 3rd party libraries)?
Hi in general the suggestion is true. It is a bad practice, since you are already running on a 'contained' environment that already does the heavy lifting of thread handling /hread pooling (allocation) for you. In case that you really want to span threads you should, make sure that the container is aware of them or provide him the constructs so that it can handle and monitor it. This is materialized with the use of the Executor Service in Java.See here and here

JNDI look up is failing with in java.util.TimerTask

public class ReferenceDataTimer extends TimerTask
{
private static ReferenceDataTimer refDataTimerTask = new ReferenceDataTimer();
private Timer refDataTimer = null;
public void start()
{
refDataTimer = new Timer();
refDataTimer.schedule(refDataTimerTask, DELAY, refreshTime*PERIOD);
}
#Override
public void run()
{
// Get DB connection using
// InitialContext lookup
// using resource reference
=> This is where it is failing. lookup is not working from this run() method of timer task.
// Then load the data to cache
}
}
public class ReferenceDataManager implements ServletContextListener {
// Invoking ReferenceDataTimer -> start() method.
}
And Im getting JNDI lookup error while getting data source Connection from server context using a resource reference. Please note that look up IS WORKING if I don't use TimerTask.
javax.naming.ConfigurationException: A JNDI operation on a "java:" name cannot be completed because the server runtime is not able to associate the operation's thread with any J2EE application component. This condition can occur when the JNDI client using the "java:" name is not executed on the thread of a server application request. Make sure that a J2EE application does not execute JNDI operations on "java:" names within static code blocks or in threads created by that J2EE application. Such code does not necessarily run on the thread of a server application request and therefore is not supported by JNDI operations on "java:" names.
Can any one please suggest? If it is not possible to get resource (available in server context) with in java.util.Timer task run() method then please suggest an alternative.
I even tried with java.util.concurrent.ScheduledExecutorService -> scheduleAtFixedRate but in vain.
You should not use TimerTask in an EJB application as this will create and start a custom Thread which is not allowed in a Java EE environment.
Instead, use the TimerService. It is part of the Java EE standard.
http://docs.oracle.com/javaee/6/tutorial/doc/bnboy.html

How to run a background job method at fixed intervals? [duplicate]

This question already has answers here:
How to run a background task in a servlet based web application?
(5 answers)
Closed 7 years ago.
I am using JSP/Servlet on Apache Tomcat. I have to run a method every 10 minutes. How can I achieve this?
As you're on Tomcat, which is just a barebones servletcontainer, you can't use EJB's #Schedule for this which is recommended by Java EE specification. Your best bet is then the ScheduledExecutorService from Java 1.5's java.util.concurrent package. You can trigger this with help of a ServletContextListener like follows:
#WebListener
public class BackgroundJobManager implements ServletContextListener {
private ScheduledExecutorService scheduler;
#Override
public void contextInitialized(ServletContextEvent event) {
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new SomeTask(), 0, 10, TimeUnit.MINUTES);
}
#Override
public void contextDestroyed(ServletContextEvent event) {
scheduler.shutdownNow();
}
}
where the SomeTask class look like this:
public class SomeTask implements Runnable {
#Override
public void run() {
// Do your job here.
}
}
If you were actually using a real Java EE container with EJB support and all on em (like Glassfish, JBoss AS, TomEE, etc), then you could use a #Singleton EJB with a #Schedule method. This way the container will worry itself about pooling and destroying threads. All you need is then the following EJB:
#Singleton
public class SomeTask {
#Schedule(hour="*", minute="*/10", second="0", persistent=false)
public void run() {
// Do your job here.
}
}
Note that this way you can continue transparently using container managed transactions the usual way (#PersistenceContext and so on), which isn't possible with ScheduledExecutorService — you'd have to manually obtain the entity manager and manually start/commit/end transaction, but you would by default already not have another option on a barebones servletcontainer like Tomcat anyway.
Note that you should never use a Timer in a supposedly "lifetime long" running Java EE web application. It has the following major problems which makes it unsuitable for use in Java EE (quoted from Java Concurrency in Practice):
Timer is sensitive to changes in the system clock, ScheduledExecutorService isn't.
Timer has only one execution thread, so long-running task can delay other tasks. ScheduledExecutorService can be configured with any number of threads.
Any runtime exceptions thrown in a TimerTask kill that one thread, thus making Timer dead, i.e. scheduled tasks will not run anymore (until you restart the server). ScheduledThreadExecutor not only catches runtime exceptions, but it lets you handle them if you want. Task which threw exception will be canceled, but other tasks will continue to run.
Read on ScheduledExecutorService it has to be initiated by a ServletContextListener
public class MyContext implements ServletContextListener
{
private ScheduledExecutorService sched;
#Override
public void contextInitialized(ServletContextEvent event)
{
sched = Executors.newSingleThreadScheduledExecutor();
sched.scheduleAtFixedRate(new MyTask(), 0, 10, TimeUnit.MINUTES);
}
#Override
public void contextDestroyed(ServletContextEvent event)
{
sched.shutdownNow();
}
}
Also, you may try using the Java Timer from a ServletContextListener but it's not recommended in a Java EE container since it takes away control of the Thread resources from the container. (the first option with ScheduledExecutorService is the way to go).
Timer timer = new Timer("MyTimer");
MyTask t = new MyTask();
//Second Parameter is the specified the Starting Time for your timer in
//MilliSeconds or Date
//Third Parameter is the specified the Period between consecutive
//calling for the method.
timer.schedule(t, 0, 1000*60*10);
And MyTask that implements TimerTask is a class that implements the Runnable interface so you have to override the run method with your code:
class MyTask extends TimerTask
{
public void run()
{
// your code here
}
}

Separate Thread on GlassFish server

I'm doing my graduation project, and have run into a dilemma here.
I need to make an application that generates PDFs and emails them to people on a schedule defined by data in the database.
I'm working for a company with this project, and we already have a GlassFish application server that we use. It would be best if the entire solution is delivered in one package, as it is now.
Client with webstart
Web Application etc. is all in one package
My new service needs to run on a separate thread, generate reports and send them out on emails. From what I can read on the web, running your own threads in an application server as GlassFish is highly discouraged, so it sounds like I need to make my own separate application.
Can this really be? What are your comments, and what are the best practices for this?
#Schedule
If you are using Ejb 3.1 (glassfish 3.x), you may use the #Schedule annotation to have the container invoke a method in a specified interval or at a given calendar time. Allowing you to avoid handling threads in your own code
Read about ejb 3.1 timer
#Stateless
public class LabbBean {
#EJB
WorkerEjb workerEjb;
#Schedule(second="*/5", minute="*",hour="*", persistent=false)
public void myMethod() {
for (all jobs found in db){
workerEjb.workerMethod(job);
}
}
}
#Stateless
public class WorkerEjb {
#Asynchronous
public void workerMethod(job) {
//Send emails
}
}
If you wanted to do the work in separate threads, the #Schedule annotated method could call a worker-ejb with the worker-method annotated as #Asynchronous
#Timeout
I just realised you wanted the schedule to be initiated from the database. An option the would be to initiate a bunch of timers programmatically using a #Singleton ejb with #Startup annotation. The timeout annotated method would be called in separate threads if some timers run out at the same time.
#Singleton
#Startup
public class LabbBean {
#Resource
protected TimerService timerService;
#PostConstruct
public void init() {
//Init your timers from the data in the database here
for (all your timers) {
TimerConfig config = new TimerConfig();
config.setInfo("timer1");
config.setPersistent(false);
ScheduleExpression schedule = new ScheduleExpression();
schedule.dayOfMonth(10);
schedule.minute(2);
timerService.createCalendarTimer(schedule, config);
}
}
//method called when timeout occurs
#Timeout
public void timeoutHandler(Timer timer) {
String name = timer.getInfo().toString();
System.out.println("Timer name=" + name);
}
}

Categories