JSF action method not completing if a new Thread was started [duplicate] - jsf

I could not find a definitive answer to whether it is safe to spawn threads within session-scoped JSF managed beans. The thread needs to call methods on the stateless EJB instance (that was dependency-injected to the managed bean).
The background is that we have a report that takes a long time to generate. This caused the HTTP request to time-out due to server settings we can't change. So the idea is to start a new thread and let it generate the report and to temporarily store it. In the meantime the JSF page shows a progress bar, polls the managed bean till the generation is complete and then makes a second request to download the stored report. This seems to work, but I would like to be sure what I'm doing is not a hack.

Check out EJB 3.1 #Asynchronous methods. This is exactly what they are for.
Small example that uses OpenEJB 4.0.0-SNAPSHOTs. Here we have a #Singleton bean with one method marked #Asynchronous. Every time that method is invoked by anyone, in this case your JSF managed bean, it will immediately return regardless of how long the method actually takes.
#Singleton
public class JobProcessor {
#Asynchronous
#Lock(READ)
#AccessTimeout(-1)
public Future<String> addJob(String jobName) {
// Pretend this job takes a while
doSomeHeavyLifting();
// Return our result
return new AsyncResult<String>(jobName);
}
private void doSomeHeavyLifting() {
try {
Thread.sleep(SECONDS.toMillis(10));
} catch (InterruptedException e) {
Thread.interrupted();
throw new IllegalStateException(e);
}
}
}
Here's a little testcase that invokes that #Asynchronous method several times in a row.
Each invocation returns a Future object that essentially starts out empty and will later have its value filled in by the container when the related method call actually completes.
import javax.ejb.embeddable.EJBContainer;
import javax.naming.Context;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class JobProcessorTest extends TestCase {
public void test() throws Exception {
final Context context = EJBContainer.createEJBContainer().getContext();
final JobProcessor processor = (JobProcessor) context.lookup("java:global/async-methods/JobProcessor");
final long start = System.nanoTime();
// Queue up a bunch of work
final Future<String> red = processor.addJob("red");
final Future<String> orange = processor.addJob("orange");
final Future<String> yellow = processor.addJob("yellow");
final Future<String> green = processor.addJob("green");
final Future<String> blue = processor.addJob("blue");
final Future<String> violet = processor.addJob("violet");
// Wait for the result -- 1 minute worth of work
assertEquals("blue", blue.get());
assertEquals("orange", orange.get());
assertEquals("green", green.get());
assertEquals("red", red.get());
assertEquals("yellow", yellow.get());
assertEquals("violet", violet.get());
// How long did it take?
final long total = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start);
// Execution should be around 9 - 21 seconds
assertTrue("" + total, total > 9);
assertTrue("" + total, total < 21);
}
}
Example source code
Under the covers what makes this work is:
The JobProcessor the caller sees is not actually an instance of JobProcessor. Rather it's a subclass or proxy that has all the methods overridden. Methods that are supposed to be asynchronous are handled differently.
Calls to an asynchronous method simply result in a Runnable being created that wraps the method and parameters you gave. This runnable is given to an Executor which is simply a work queue attached to a thread pool.
After adding the work to the queue, the proxied version of the method returns an implementation of Future that is linked to the Runnable which is now waiting on the queue.
When the Runnable finally executes the method on the real JobProcessor instance, it will take the return value and set it into the Future making it available to the caller.
Important to note that the AsyncResult object the JobProcessor returns is not the same Future object the caller is holding. It would have been neat if the real JobProcessor could just return String and the caller's version of JobProcessor could return Future<String>, but we didn't see any way to do that without adding more complexity. So the AsyncResult is a simple wrapper object. The container will pull the String out, throw the AsyncResult away, then put the String in the real Future that the caller is holding.
To get progress along the way, simply pass a thread-safe object like AtomicInteger to the #Asynchronous method and have the bean code periodically update it with the percent complete.

Introduction
Spawning threads from within a session scoped managed bean is not necessarily a hack as long as it does the job you want. But spawning threads at its own needs to be done with extreme care. The code should not be written that way that a single user can for example spawn an unlimited amount of threads per session and/or that the threads continue running even after the session get destroyed. It would blow up your application sooner or later.
The code needs to be written that way that you can ensure that an user can for example never spawn more than one background thread per session and that the thread is guaranteed to get interrupted whenever the session get destroyed. For multiple tasks within a session you need to queue the tasks.
Also, all those threads should preferably be served by a common thread pool so that you can put a limit on the total amount of spawned threads at application level.
Managing threads is thus a very delicate task. That's why you'd better use the built-in facilities rather than homegrowing your own with new Thread() and friends. The average Java EE application server offers a container managed thread pool which you can utilize via among others EJB's #Asynchronous and #Schedule. To be container independent (read: Tomcat-friendly), you can also use the Java 1.5's Util Concurrent ExecutorService and ScheduledExecutorService for this.
Below examples assume Java EE 6+ with EJB.
Fire and forget a task on form submit
#Named
#RequestScoped // Or #ViewScoped
public class Bean {
#EJB
private SomeService someService;
public void submit() {
someService.asyncTask();
// ... (this code will immediately continue without waiting)
}
}
#Stateless
public class SomeService {
#Asynchronous
public void asyncTask() {
// ...
}
}
Asynchronously fetch the model on page load
#Named
#RequestScoped // Or #ViewScoped
public class Bean {
private Future<List<Entity>> asyncEntities;
#EJB
private EntityService entityService;
#PostConstruct
public void init() {
asyncEntities = entityService.asyncList();
// ... (this code will immediately continue without waiting)
}
public List<Entity> getEntities() {
try {
return asyncEntities.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new FacesException(e);
} catch (ExecutionException e) {
throw new FacesException(e);
}
}
}
#Stateless
public class EntityService {
#PersistenceContext
private EntityManager entityManager;
#Asynchronous
public Future<List<Entity>> asyncList() {
List<Entity> entities = entityManager
.createQuery("SELECT e FROM Entity e", Entity.class)
.getResultList();
return new AsyncResult<>(entities);
}
}
In case you're using JSF utility library OmniFaces, this could be done even faster if you annotate the managed bean with #Eager.
Schedule background jobs on application start
#Singleton
public class BackgroundJobManager {
#Schedule(hour="0", minute="0", second="0", persistent=false)
public void someDailyJob() {
// ... (runs every start of day)
}
#Schedule(hour="*/1", minute="0", second="0", persistent=false)
public void someHourlyJob() {
// ... (runs every hour of day)
}
#Schedule(hour="*", minute="*/15", second="0", persistent=false)
public void someQuarterlyJob() {
// ... (runs every 15th minute of hour)
}
#Schedule(hour="*", minute="*", second="*/30", persistent=false)
public void someHalfminutelyJob() {
// ... (runs every 30th second of minute)
}
}
Continuously update application wide model in background
#Named
#RequestScoped // Or #ViewScoped
public class Bean {
#EJB
private SomeTop100Manager someTop100Manager;
public List<Some> getSomeTop100() {
return someTop100Manager.list();
}
}
#Singleton
#ConcurrencyManagement(BEAN)
public class SomeTop100Manager {
#PersistenceContext
private EntityManager entityManager;
private List<Some> top100;
#PostConstruct
#Schedule(hour="*", minute="*/1", second="0", persistent=false)
public void load() {
top100 = entityManager
.createNamedQuery("Some.top100", Some.class)
.getResultList();
}
public List<Some> list() {
return top100;
}
}
See also:
Spawning threads in a JSF managed bean for scheduled tasks using a timer

I tried this and works great from my JSF managed bean
ExecutorService executor = Executors.newFixedThreadPool(1);
#EJB
private IMaterialSvc materialSvc;
private void updateMaterial(Material material, String status, Location position) {
executor.execute(new Runnable() {
public void run() {
synchronized (position) {
// TODO update material in audit? do we need materials in audit?
int index = position.getMaterials().indexOf(material);
Material m = materialSvc.getById(material.getId());
m.setStatus(status);
m = materialSvc.update(m);
if (index != -1) {
position.getMaterials().set(index, m);
}
}
}
});
}
#PreDestroy
public void destory() {
executor.shutdown();
}

Related

Close dialog after big process command button jsf

I'd like close a dialog after one big process in my back bean. I tried some many things and now I am tried. I want leave a message to the user that the process is keeping going and,of course, show a progressbar n process and close it after take some minutes...simple. Normal approach... but doesn't work. I leave my code to explain better ...
public void sendPush() {
//validacitions...
requestContext.execute("PF('dlg1').show()");//work well...we can see the dialog with the process
myProcess();
}
public void myProcess() {
//simulation only...here will be like 1 minute
Thread one = new Thread() {
public void run() {
try {
Thread.sleep(4000);
} catch(InterruptedException v) {
System.out.println(v);
}
requestContext.execute("PF('dlg1').hide()");//here is the problem...don't close the dialog but when I debug the process pass here
System.out.println("pass here");
}
};
one.start();
}
First of it's not advised to spawn thread in a managed bean. See this.
Secundo the new thread as no reference to the requestContext I think. That is why it doesn't close the dialog.
So have your managed bean call a service :
#Named
#RequestScoped
public class Mymngedbean{
#EJB
private SomeService ss;
public void yourmethod(){
ss.asyncTask(RequestContext.getCurrentInstance());
}
Your service:
#Stateless
public class SomeServiceImpl implements SomeService {
#Asynchronous
public void asyncTask(RequestContext context) {
// ...
context.execute("PF('dlg1').hide()");
}
}
Addind a thread might not be necessary though.
You could use the AjaxStatus, if you dont need realtime interaction, and instant progression

Injecting a service inside of TimerTask

I need to run daily a process in order to do maintenance work on the server (update records).
I have a singleton scope class that runs a timer and an inner class with the injection of the service I need. When I run the programm the timer throws a NullPointerException because the service has not been injected.
#Named("demonService")
#Singleton
public class DemonImpl implements IDemonService
{
private static Logger log = Logger.getLogger(DemonioImpl.class);
#PostConstruct
public void init()
{
log.info("-->Demon");
Calendar today = new GregorianCalendar();//Every day at 2:00am (from now)
today.set(Calendar.HOUR_OF_DAY, 2);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.SECOND, 0);
try
{
Timer timer = new Timer(true);
timer.schedule(new Updater(), today.getTime(), 24*60*60*1000);
}
catch(Exception e)
{
log.fatal(e.getLocalizedMessage());
e.printStackTrace();
}
log.info("--> Demon: exit");
}
private class Updater extends TimerTask
{
private Logger log = Logger.getLogger(Updater.class);
#Inject
#Named("updaterService")
private IUpdaterService updaterService;
#Override
public void run()
{
log.info("Task: update records (start)");
List<Record> list = updaterService.getAll();//<-- This throws the exception
for(Record item : list)
{
updaterService.update(item);
}
log.info("Task: update records (exit)");
}
}
The error is
Exception in thread "Timer-3" java.lang.NullPointerException
at test.service.impl.DemonImpl$Updater.run(DemonImpl.java:66)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
The application works fine except for this class. How can I inject the service when the application is fully working?
Normally you have a NPE when the Class is not a CDI Bean. If you make new Updater() this is not considered by CDI. you have to #Inject the Updater in your Singleton.
CDI won't manage the instance since you instantiate your Updater by calling the constructor of it yourself.
Now there are two ways to fix this:
Inject an instance of the Updater class in DemonImpl and use that one.
Create a new CDI managed instance at runtime by injecting a Provider<Updater> instance in DemonImpl and get a new instance of the Updater class from it.

JavaFX: How to bind two values?

I'm new guy here :)
I have a small problem which concerns binding in JavaFX. I have created Task which is working as a clock and returns value which has to be set in a special label (label_Time). This label presents how many seconds left for player's answer in quiz.
The problem is how to automatically change value in label using the timer task? I tried to link value from timer Task (seconds) to label_Time value in such a way...
label_Time.textProperty().bind(timer.getSeconds());
...but it doesn't work. Is it any way to do this thing?
Thanks in advance for your answer! :)
Initialize method in Controller class:
public void initialize(URL url, ResourceBundle rb) {
Timer2 timer = new Timer2();
label_Time.textProperty().bind(timer.getSeconds());
new Thread(timer).start();
}
Task class "Timer2":
public class Timer2 extends Task{
private static final int SLEEP_TIME = 1000;
private static int sec;
private StringProperty seconds;
public Timer2(){
Timer2.sec = 180;
this.seconds = new SimpleStringProperty("180");
}
#Override protected StringProperty call() throws Exception {
int iterations;
for (iterations = 0; iterations < 1000; iterations++) {
if (isCancelled()) {
updateMessage("Cancelled");
break;
}
System.out.println("TIK! " + sec);
seconds.setValue(String.valueOf(sec));
System.out.println("TAK! " + seconds.getValue());
// From the counter we subtract one second
sec--;
//Block the thread for a short time, but be sure
//to check the InterruptedException for cancellation
try {
Thread.sleep(10);
} catch (InterruptedException interrupted) {
if (isCancelled()) {
updateMessage("Cancelled");
break;
}
}
}
return seconds;
}
public StringProperty getSeconds(){
return this.seconds;
}
}
Why your app does not work
What is happening is that you run the task on it's own thread, set the seconds property in the task, then the binding triggers an immediate update of the label text while still on the task thread.
This violates a rule for JavaFX thread processing:
An application must attach nodes to a Scene, and modify nodes that are already attached to a Scene, on the JavaFX Application Thread.
This is the reason that your originally posted program does not work.
How to fix it
To modify your original program so that it will work, wrap the modification of the property in the task inside a Platform.runLater construct:
Platform.runLater(new Runnable() {
#Override public void run() {
System.out.println("TIK! " + sec);
seconds.setValue(String.valueOf(sec));
System.out.println("TAK! " + seconds.getValue());
}
});
This ensures that when you write out to the property, you are already on the JavaFX application thread, so that when the subsequent change fires for the bound label text, that change will also occur on the JavaFX application thread.
On Property Naming Conventions
It is true that the program does not correspond to JavaFX bean conventions as Matthew points out. Conforming to those conventions is both useful in making the program more readily understandable and also for making use of things like the PropertyValueFactory which reflect on property method names to allow table and list cells to automatically update their values as the underlying property is updated. However, for your example, not following JavaFX bean conventions does not explain why the program does not work.
Alternate Solution
Here is an alternate solution to your countdown binding problem which uses the JavaFX animation framework rather than the concurrency framework. I prefer this because it keeps everything on the JavaFX application thread and you don't need to worry about concurrency issues which are difficult to understand and debug.
import javafx.animation.*;
import javafx.application.Application;
import javafx.beans.*;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.event.*;
import javafx.geometry.Pos;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
public class CountdownTimer extends Application {
#Override public void start(final Stage stage) throws Exception {
final CountDown countdown = new CountDown(10);
final CountDownLabel countdownLabel = new CountDownLabel(countdown);
final Button countdownButton = new Button(" Start ");
countdownButton.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent t) {
countdownButton.setText("Restart");
countdown.start();
}
});
VBox layout = new VBox(10);
layout.getChildren().addAll(countdownLabel, countdownButton);
layout.setAlignment(Pos.BASELINE_RIGHT);
layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 20; -fx-font-size: 20;");
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) throws Exception {
launch(args);
}
}
class CountDownLabel extends Label {
public CountDownLabel(final CountDown countdown) {
textProperty().bind(Bindings.format("%3d", countdown.timeLeftProperty()));
}
}
class CountDown {
private final ReadOnlyIntegerWrapper timeLeft;
private final ReadOnlyDoubleWrapper timeLeftDouble;
private final Timeline timeline;
public ReadOnlyIntegerProperty timeLeftProperty() {
return timeLeft.getReadOnlyProperty();
}
public CountDown(final int time) {
timeLeft = new ReadOnlyIntegerWrapper(time);
timeLeftDouble = new ReadOnlyDoubleWrapper(time);
timeline = new Timeline(
new KeyFrame(
Duration.ZERO,
new KeyValue(timeLeftDouble, time)
),
new KeyFrame(
Duration.seconds(time),
new KeyValue(timeLeftDouble, 0)
)
);
timeLeftDouble.addListener(new InvalidationListener() {
#Override public void invalidated(Observable o) {
timeLeft.set((int) Math.ceil(timeLeftDouble.get()));
}
});
}
public void start() {
timeline.playFromStart();
}
}
Update for additional questions on Task execution strategy
Is it possible to run more than one Task which includes a Platform.runLater(new Runnable()) method ?
Yes, you can use multiple tasks. Each task can be of the same type or a different type.
You can create a single thread and run each task on the thread sequentially, or you can create multiple threads and run the tasks in parallel.
For managing multiple tasks, you can create an overseer Task. Sometimes it is appropriate to use a Service for managing the multiple tasks and the Executors framework for managing multiple threads.
There is an example of a Task, Service, Executors co-ordination approach: Creating multiple parallel tasks by a single service In each task.
In each task you can place no runlater call, a single runlater call or multiple runlater calls.
So there is a great deal of flexibility available.
Or maybe I should create one general task which will be only take data from other Tasks and updating a UI?
Yes you can use a co-ordinating task approach like this if complexity warrants it. There is an example of such an approach in in Render 300 charts off screen and save them to files.
Your "Timer2" class doesn't conform to the JavaFX bean conventions:
public String getSeconds();
public void setSeconds(String seconds);
public StringProperty secondsProperty();

Is it possible to reference FacesContext from a TimerTask or ScheduledExecutorService on application startup?

I am attempting to create functionality in a JSF1.2/ADF web app that will periodically & dynamically generate a sitemap for a website that will have hundreds of pages whose content will change daily. The catch is that I need to read some config from the application to use as the basis of the sitemap and to do so, I need FacesContext.
Here is what I have attempted to do: I created a class that implements a ServletContextListener and instantiates an application scoped bean. This bean does the heavy lifting to create sitemap.xml using FacesContext. I created a class that extends TimerTask that accesses the bean from application scope, calls the sitemap method and schedules future occurrences. When I run the application, the class that implements ServletContextListener fires and the bean appears to be created, but the class that extends TimerTask is never fired. Any help would be appreciated. If I can answer any questions or if I left anything out, please let me know.
Here are my code samples:
public class WebhomesApplicationContextListener implements ServletContextListener {
private static final String attribute = "SiteMapGenerator";
public void contextInitialized(ServletContextEvent event) {
SiteMapGenerator myObject = new SiteMapGenerator();
event.getServletContext().setAttribute(attribute, myObject);
}
public void contextDestroyed(ServletContextEvent event) {
SiteMapGenerator myObject = (SiteMapGenerator) event.getServletContext().getAttribute(attribute);
event.getServletContext().removeAttribute(attribute);
}
}
public class SiteMapGenerator {
public void generateSitemap() {
// code to generate map...
}
}
public class Scheduler extends TimerTask {
public void run() {
SiteMapGenerator sitemap = (SiteMapGenerator)FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().get("SiteMapGenerator");
sitemap.generateSitemap();
}
}
class MainApplication {
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(
new Scheduler(),
1000 * 60);
}
}
No, you can't. The FacesContext is only available in the thread associated with the HTTP servlet request whose URL matched the URL pattern of the FacesServlet and has invoked it. Instead, just pass the SiteMapGenerator to the Scheduler on its construction.
public class Scheduler {
private SiteMapGenerator sitemap;
public Scheduler(SiteMapGenerator sitemap) {
this.sitemap = sitemap;
}
// ...
}
The SiteMapGenerator is surely available at the point you're constructing the Scheduler.
Unrelated to the concrete problem, It's strongly discouraged to use TimerTask in a Java EE application. See also Spawning threads in a JSF managed bean for scheduled tasks using a timer.

How to run a background task in a servlet based web application?

I'm using Java and I want to keep a servlet continuously running in my application, but I'm not getting how to do it. My servlet has a method which gives counts of the user from a database on a daily basis as well as the total count of the users from the whole database. So I want to keep the servlet continuously running for that.
Your problem is that you misunderstand the purpose of the servlet. It's intented to act on HTTP requests, nothing more. You want just a background task which runs once on daily basis.
EJB available? Use #Schedule
If your environment happen to support EJB (i.e. a real Java EE server such as WildFly, JBoss, TomEE, Payara, GlassFish, etc), then use #Schedule instead. Here are some examples:
#Singleton
public class BackgroundJobManager {
#Schedule(hour="0", minute="0", second="0", persistent=false)
public void someDailyJob() {
// Do your job here which should run every start of day.
}
#Schedule(hour="*/1", minute="0", second="0", persistent=false)
public void someHourlyJob() {
// Do your job here which should run every hour of day.
}
#Schedule(hour="*", minute="*/15", second="0", persistent=false)
public void someQuarterlyJob() {
// Do your job here which should run every 15 minute of hour.
}
#Schedule(hour="*", minute="*", second="*/5", persistent=false)
public void someFiveSecondelyJob() {
// Do your job here which should run every 5 seconds.
}
}
Yes, that's really all. The container will automatically pickup and manage it.
EJB unavailable? Use ScheduledExecutorService
If your environment doesn't support EJB (i.e. you're not using not a real Java EE server, but a barebones servletcontainer such as Tomcat, Jetty, etc), then use ScheduledExecutorService. This can be initiated by a ServletContextListener. Here's a kickoff example:
#WebListener
public class BackgroundJobManager implements ServletContextListener {
private ScheduledExecutorService scheduler;
#Override
public void contextInitialized(ServletContextEvent event) {
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new SomeDailyJob(), 0, 1, TimeUnit.DAYS);
scheduler.scheduleAtFixedRate(new SomeHourlyJob(), 0, 1, TimeUnit.HOURS);
scheduler.scheduleAtFixedRate(new SomeQuarterlyJob(), 0, 15, TimeUnit.MINUTES);
scheduler.scheduleAtFixedRate(new SomeFiveSecondelyJob(), 0, 5, TimeUnit.SECONDS);
}
#Override
public void contextDestroyed(ServletContextEvent event) {
scheduler.shutdownNow();
}
}
Where the job classes look like this:
public class SomeDailyJob implements Runnable {
#Override
public void run() {
// Do your daily job here.
}
}
public class SomeHourlyJob implements Runnable {
#Override
public void run() {
// Do your hourly job here.
}
}
public class SomeQuarterlyJob implements Runnable {
#Override
public void run() {
// Do your quarterly job here.
}
}
public class SomeFiveSecondelyJob implements Runnable {
#Override
public void run() {
// Do your quarterly job here.
}
}
Do not ever think about using java.util.Timer/java.lang.Thread in a Java EE / Servlet based environment
Last but not least, never directly use java.util.Timer and/or java.lang.Thread in Java EE. This is recipe for trouble. An elaborate explanation can be found in this JSF-related answer on the same question: Spawning threads in a JSF managed bean for scheduled tasks using a timer.
I would suggest using a library like quartz in order to run the task at regular intervals. What does the servlet really do ? It sends you a report ?
You can use cron4j. http://www.sauronsoftware.it/projects/cron4j/manual.php
Implement two classes and call startTask() in main.
public void startTask()
{
// Create a Runnable
Runnable task = new Runnable() {
public void run() {
while (true) {
runTask();
}
}
};
// Run the task in a background thread
Thread backgroundThread = new Thread(task);
// Terminate the running thread if the application exits
backgroundThread.setDaemon(true);
// Start the thread
backgroundThread.start();
}
public void runTask()
{
try {
// do something...
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
In a production system that may have multiple non-jee containers running. Use anot enterprise scheduler like Quartz scheduler which can be configured to use a database for task maamgememt.

Resources