How do I fix a Thread Leak in a JSF application? - jsf-2

I have an ApplicationScoped bean that fires up a separate Thread to do some background work. The Thread has a method for cleanly terminating it called terminate(). If not terminated via that method it runs in an infinite loop, and sleeps for a while if it finds it has nothing to do.
The thing is I am in development mode (Netbeans -> Maven) and each time I recompile the application, the Maven plug-in un-deploys and redeploys the application (most conveniently I must say) but the background Thread from the last deployment hangs around. It eventually terminates with an Exception because it wakes up from its sleep and tries to access a JPA EntityManager that isn't there anymore.
I would prefer to automatically call the terminate() method when the application is stopped. Is there some way to implement a listener that will do that at the JSF 2.0 specification level? If not, how about at the Servlet level?
This is using GlassFish 3.1.1.

Add a #PreDestroy method to you bean which will run when your application is undeployed or stopped and it can stop the background thread, like this:
import javax.annotation.PreDestroy;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
#ApplicationScoped
#ManagedBean
public class AppBean {
public AppBean() {
System.out.println("new AppBean()");
}
#PreDestroy
public void preDestory() {
// call thread.terminate() here
System.out.println("preDestory");
}
}

Related

Avoid duplicate tasks in ManagedScheduledExecutorService

I'm developing a Java EE 7 application on wildfly 8.2 and need to run a periodic background task. I inject an executor service and schedule a task, this part is working fine:
#Resource
private ManagedScheduledExecutorService executorService;
...
executorService.scheduleWithFixedDelay(() -> {
try {
// do some stuff
} catch (Throwable t) {
log.error("Error", t);
}
}, 0, 1, TimeUnit.MINUTES);
Now the (actually nice) feature is that upon redeploy the scheduled task is saved and therefore is still scheduled in the new deployment.
But how can I detect if the task is already scheduled to avoid scheduling it multiple times?
I tried to use a ScheduledFutureand cancel the task on #PreDestroy
and #PrePassivate
reloadTreeFuture = executorService.scheduleWithFixedDelay(() -> {
...
#PreDestroy
#PrePassivate
protected void shutdown() {
reloadTreeFuture.cancel(true);
}
This is working fine as long as the corresponding task is not executing at the very moment the cancel is fired. Since the task is long running and running frequently the chance of hitting it in the middle of an execution is somewhat high.
If the cancel is fired while the task is still executing the cancel seems to do nothing. It immediatly returns and the method ScheduledFuture.isDone() also returns true but from the logs I can see the task is still executing in the background until it hits a point where it needs an injected Bean which is not available due to the undeployment process. The process then ends with org.jboss.msc.service.ServiceNotFoundException - but is still scheduled.
reloadTreeFuture.cancel(true);
while (!reloadTreeFuture.isDone()) {
Thread.sleep(200); // I know this is bad - it's just for testing
}
So basic question: how can I make sure the task is not scheduled twice (or even more)?
You could write down the id of each task and check them before executing. Of course this may be not a best solution, but it works.

JBoss 6: timer starts when application is not fully deployed

I have a problem at deploy time in JBoss 6.
My application contains a Stateless EJB with one method marked with the #Schedule(hour="1") annotation. Such a method uses another Stateless EJB injected by #EJB annotation.
#Stateless
public class AuditRecordCleanerBean implements AuditRecordCleanerLocal
{
#EJB
private RecordManager recordManager;
#Schedule(hour="1")
public void moveRecordsToHistoricTable()
{
recordManager.moveRecords();
...
}
}
Because the timer is persistent in JBoss, when I reboot the application server it can sometimes happen that the timer triggers when the EJB RecordManager is not yet deployed causing a NameNotFoundException.
In server.log I found the following warning:
WARN [org.jboss.ejb3.TimerServiceContainer] (Thread-2) EJBTHREE-2193: using deprecated TimerServiceFactory for restoring timers
Could be this the problem?
How can I delay the first timer execution after the complete deploy of the application?
Best regards,
Fabio

Blackberry: Exception thrown no application instance at app startup

Recently, I've noticed that for any BlackBerry project I run, the JDE throws an error with message
Exception thrown: no application instance...
I've even checked with a sample hello world project, which ends up with the same problem.
I did run clean.bat file, erase file system etc. work arounds to clear the archives, but no luck till now.
Could someone please guide me correctly what should be the fix for this?
I'm assuming the full exception is: "IllegalStateException: no application instance". Since you didn't give us many details of your code, I'll just talk about where I've commonly run into this Exception.
This is commonly caused by trying to get an application instance before you have called the Application's constructor. For example the following code will create that error:
public class HelloWorld extends UiApplication
{
public HelloWorld(){
pushScreen(new HelloWorldScreenBlank());
}
public static void main(String[] args) {
Application app = Application.getApplication();
HelloWorld theApp = new HelloWorld();
theApp.enterEventDispatcher();
}
}
This code produces the following console code:
llegalStateException
no application instance
net_rim_cldc-8(4B84A78F)
Application
getApplication
0x2EFA
HW_5$2e0(4D1A6F55)
HelloWorld
main
0x167
But the following code doesn't produce the exception:
public class HelloWorld extends UiApplication
{
public HelloWorld(){
Application app = Application.getApplication();
pushScreen(new HelloWorldScreenBlank());
}
public static void main(String[] args) {
HelloWorld theApp = new HelloWorld();
theApp.enterEventDispatcher();
}
}
This works because the Application instance is instantiated inside the constructor for the UiApplication object. Were as in the previous code we were trying to get the instance before an Application object existed.
I've commonly run into this trying to startup GPS from main() or in a static block. But there are a few classes which implicitly call getApplicaiton, so if you aren't explicitly calling getApplication then maybe one the API calls your making is. I would try to move code out of main and into your Application's constructor if you can.
Here is a Google search which will produce a list of classes from the 6.0 API which produce this exception:
throws IllegalStateException
Blackberry
site:www.blackberry.com/developers/docs/6.0.0api

BlackBerry - Uncaught exception: Application is not responding; process terminated

I'm developing an application using the Blackberry plugin for eclipse and I am getting the following error when making a call to a web service when I have deployed my application to a production server and handset... it works in my local simulator and development environment. (I can't hook my simulator directly to my production environment)
Uncaught exception: Application
app(150) is not responding; process
terminated
The call is being made from another thread.
The thread is passed to my CustomThreadManager to run
ClientChangeThread thread = new ClientChangeThread();
CustomThreadManager.Start(thread, true);
CustomThreadManager
ProgressPopup _progress = null;
if(showProgress){
_progress = new ProgressPopup("Loading...");
_progress.Open();
}
thread.start();
while (thread.isRunning())
{
try
{
CustomThread.sleep(300);
if(showProgress){
_progress.doPaint();
}
}
catch (InterruptedException e)
{
Dialog.alert("Error contacting webservice\n" + e.getMessage());
Functions.moveBack();
}
}
if(showProgress)
_progress.Close();
Some calls work while others dont.
The web service returns results fairly quickly so Im not sure if its the web service is too slow or problems with the threading.
Any help appreciated.
Thread.sleep() does not release any locks. This means your code to update the progress bar in the while-loop is holding the UI event lock, and prevents other UI updates from happening until the while loop terminates -- in this case when thread.isRunning() returns false.
You can use UiApplication.invokeLater(Runnable, long, boolean) to schedule a repeating UI update that will only hold the event lock while the Runnable is executing.

Where to put GUI based start-up code in a Blackberry App?

I'd like to know the proper place to put GUI based sequential start-up code in my Blackberry app.
In main(), I create MyApp and enterEventDispatcher()
I have UiApplication (MyApp)
In the MyApp CTOR:
- I create a MainScreen (MyMain)
- I call pushScreen() on MyMain
When the event dispatcher starts, is there an event I can listen for in my MainScreen that will give me the event thread where I can happily do synchronous start-up tasks?
I can use invokeLater() but I want each call to block because their order is important in this phase. invokeAndWait() throws an exception in most cases where I've attempted to use it.
I've attempted the code below but I get an exception when trying to run on the "Testing 1 2 3" line.
public class MyApp extends UiApplication {
static public void main(String[] args) {
new MyApp().enterEventDispatcher();
}
public MyApp()
{
MyView theView = new MyView();
theView.startUpdateTimer();
pushScreen(theView);
Dialog.alert("Testing 1 2 3");
}
}
If it's pretty quick UI stuff (creating a screen, pushing it onto the stack), do it from the main thread before calling enterEventDispatcher. You can actually do as much as you want, just the user experience will be worse if your app takes a long time.
The thread that calls enterEventDispatcher basically becomes the event dispatch thread, so you're safe to do any GUI stuff on that thread before calling enterEventDispatcher.
Specifically, don't call invokeAndWait from the main thread - that'll cause deadlock and probably an exception.

Resources