Not loading children nodes in layout javafx - spring

I'm trying to do a simple startup window for my application.
ClassLoader cachingClassLoader = new MyClassLoader(FXMLLoader.getDefaultClassLoader());
URL resource = MainApp.class
.getResource("/startupWindow.fxml").toURI().toURL();
FXMLLoader loader = new FXMLLoader(resource);
loader.setClassLoader(cachingClassLoader);
BorderPane rootLayout = (BorderPane) loader.load();
scene = new Scene(rootLayout,512,384);
this.primaryStage.initStyle(StageStyle.UNDECORATED);
this.primaryStage.setTitle(TITLE);
this.primaryStage.setScene(scene);
this.primaryStage.show();
//configuration main layout and add it to the stage
Unfortunately, after the start, application shows up startup window, however without any content. Throughout the loading of the main layout the startup window content is empty. Besides I had no exceptions.
I noticed that the problem with the content loading occurs when additional code is after the calling primaryStage.show(). And a content of layout is rendered at the end of additional code, for example:
this.primaryStage.setScene(scene);
this.primaryStage.show();
Thread.sleep(2000L);
// Content is displayed,( after 2 seconds ).
I have no idea how to make it work. Any advices will be helpful.
EDIT:
The issue I'm actually facing is create a startup window while loading Spring application context. I've been trying to create application context in separate Thread and it just hangs up with no exception occuring.
EDIT 2:
After some debugging I've found an exception:
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'SomePresenter': Invocation of init method failed;
nested exception is java.lang.IllegalStateException:
Not on FX application thread; currentThread = Thread-3
By the way, application follows MVP design pattern and Spring application context loads automatically views and presenters.
EDIT 3:
The piece of code where I create new thread is:
Task loadingTask = new Task() {
#Override
protected ApplicationContext call() throws Exception {
return new ClassPathXmlApplicationContext("./spring/application_context.xml");
}
};
loadingTask.setOnSucceeded(event -> {
context = (ApplicationContext)loadingTask.getValue();
MainPresenter mainPresenter = (MainPresenter) context.getBean("MainPresenter");
mainPresenter.getView().setPrimaryStage(primaryStage);
scene = new Scene(mainPresenter.getView(), bounds.getWidth(), bounds.getHeight());
scene.getStylesheets().add(getClass().getResource("/styles/styles.css").toExternalForm());
this.primaryStage.setScene(scene);
});
new Thread(loadingTask).start();

The start() method is executed on the FX Application Thread, which is the thread responsible for rendering the UI and processing user input. It is also the only thread on which some actions are legal, such as accessing the state of nodes in the scene graph and creating Scenes and Stages.
The problem is that you are executing code that blocks this thread, meaning that the UI doesn't have a chance to be rendered. If you have time-consuming (non-UI) code to execute, you should execute that in a separate thread, and then when that is complete schedule an update to happen to the UI on the FX Application thread.
The Task class is designed for this use case.
So you can do something like this:
public void start(Stage primaryStage) {
primaryStage.initStyle(StageStyle.UNDECORATED);
primaryStage.setTitle(TITLE);
primaryStage.setScene(scene);
primaryStage.show();
Task<SomeDataType> startupTask = new Task<SomeDataType>() {
#Override
protected SomeDataType call() {
SomeDataType result = ... ; // result of time-consuming operation
return result ;
}
};
startupTask.setOnSucceeded(event -> {
// this is executed on the FX Application Thread
SomeDataType result = startupTask.getValue();
// update UI using result ...
});
new Thread(startupTask).start();
}

If possible, you should check the EAP of JDK 1.8.0_40 as it enables you to build UI in background tasks as far as I understand what they are trying to do (out of JavaFX Application Thread):
See their JIRA:
https://javafx-jira.kenai.com/browse/RT-17716
Building UI in background tasks does make sense in some cases, especially with big FXML files as it is quite slow.
If does not solve your problem, you will have to check your Spring integration, are you using a custom FXMLLoader with a builder factory / controller factory? Does Spring run in a separate thread or in JavaFX Application Thread?

Related

Vaadin: Update UI after data returned

#SpringUI
public class VaadinUI extends UI {
...
String sql = "SELECT * FROM table1";
button.addClickListener(e -> layout.addComponent(new Label(service.evalSql(sql))));
...
Currently, when button is pressed, the page waits for evalSql() to get a result back from the database before adding a new Label.
How can I change this so, when button is pressed, a new Label is immediately added, set to an initial placeholder string ("Fetching result..") but updated to the result string after the database returns something?
The good news is that what you want, to have a widget in your Vaadin user-interface later updated by work done in the background on the server without blocking the UI's responsiveness to the user, can be done. It can be done very well with Vaadin and its Java-based backend.
The bad news is that if you are new to concurrency and threading, you have a learning curve to climb.
Asynchronous
The technical term for wanting your app to do something in the background and check back later without blocking is: asynchronous update.
We can accomplish this in Java using threads. Spawn a thread to run your SQL service code. When that code finishes the database work, that code posts a request by calling UI::access(Runnable runnable) to have the original user-interface (UI) thread update the Label widget.
Push technology
As discussed in the Answer by Lund updating of the Label widget requires Push Technology to update the browser from a server-side generated event. Fortunately, Vaadin 8 and later has excellent support for Push and makes instituting Push in your app extraordinarily easy.
Tip: Push in general, and WebSocket especially, has evolved greatly in recent years. Using the latest generation of Servlet container will improve your experience. For example, if using Tomcat I recommend using the latest version of Tomcat 8.5 or 9.
Threads
Java has excellent support for threading. Much of the necessary work is handled for you by the Executor framework built into Java.
If you are new to threading, you have some serious learning ahead of you. Start by studying the Oracle Tutorial on concurrency. Eventually you'll need to read and re-read a few times the excellent book Java Concurrency in Practice by Brian Goetz et al.
ServletContextListener
You will likely want to set-up and tear-down your thread-juggling executor service as your Vaadin app launches and exits. The way to do that is to write a class separate from your Vaadin servlet class. This class must implement the ServletContextListener. You can easily do that by implementing the two required methods, and annotating the class with #WebListener.
Be sure to tear-down the executor service. Otherwise the background threads it manages may survive the shutdown of your Vaadin app and possibly even the shutdown of your web container (Tomcat, Jetty, etc.), continuing to run indefinitely.
Never access widget from background thread
A key idea in this work: Never ever access any Vaadin UI widget directly from any background. Do not call any methods on the UI widgets, nor access any values, from any widget in code running in a background thread. The UI widgets are not thread-safe (making a user-interface technology thread-safe is terribly difficult). You might get away with such a background call, or terrible things may happen at runtime.
Java EE
If you happen to be using a full-blown Jakarta EE (formerly known as Java EE) server rather than either a web container (such as Tomcat or Jetty) or a Web Profile server (such as TomEE), then the work discussed above with the executor service and ServletContextListener is done for you. Use the features defined in Java EE 7 and later: JSR 236: Concurrency Utilities for JavaTM EE
Spring
Your Question is tagged with Spring. Spring may have features to help with this work. I don’t know, as I am not a Spring user. Perhaps Spring TaskExecutor?
Search Stack Overflow
If you search Stack Overflow you will find that all these topics have been addressed.
I have already posted two full example apps demonstrating Vaadin with Push:
A contrived minimalist example, just to give you a taste of what is involved. That particular approach should never be used in real work, as noted in that Answer.
For real work, see a more complicated example app posted in this Answer.
Complete example
Start with the Vaadin 8.4.3 app generated by the Maven archetype, vaadin-archetype-application provided by the Vaadin Ltd. company.
package com.basilbourque.example;
import javax.servlet.annotation.WebServlet;
import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.Button;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
/**
* This UI is the application entry point. A UI may either represent a browser window
* (or tab) or some part of an HTML page where a Vaadin application is embedded.
* <p>
* The UI is initialized using {#link #init(VaadinRequest)}. This method is intended to be
* overridden to add component to the user interface and initialize non-component functionality.
*/
#Theme ( "mytheme" )
public class MyUI extends UI {
#Override
protected void init ( VaadinRequest vaadinRequest ) {
final VerticalLayout layout = new VerticalLayout();
final TextField name = new TextField();
name.setCaption( "Type your name here:" );
Button button = new Button( "Click Me" );
button.addClickListener( e -> {
layout.addComponent( new Label( "Thanks " + name.getValue() + ", it works!" ) );
} );
layout.addComponents( name , button );
setContent( layout );
}
#WebServlet ( urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true )
#VaadinServletConfiguration ( ui = MyUI.class, productionMode = false )
public static class MyUIServlet extends VaadinServlet {
}
}
As discussed above, we need to assign your SQL-service work as a task to be done on a background thread. The Executor framework in Java 5 and later does all the heavy-lifting for such thread work. We need to establish an executor service backed by a thread pool to do all the updating of all the new labels being added on all the users’ web browser windows. The question is where do we setup, store, and teardown that executor service object?
We want the executor service to be available for the entire lifecycle of our web app. Before the first user request arrives to our freshly-launched web app, we want to setup the executor service. And when we are trying to shutdown our web app, we need to teardown that executor service, so that the threads in its backing thread pool are terminated. How do we tie into the lifecycle of our Vaadin web app?
Well, Vaadin is an implementation of Java Servlet, albeit a very large and sophisticated servlet. In Servlet terminology, your web app is known as a “context”. The Servlet specification requires that all Servlet containers (such as Tomcat, Jetty, etc.) notice any class marked as a listener to certain events. To take advantage of this we must add another class to our Vaadin app, a class implementing the ServletContextListener interface.
If we annotate our new class as #WebListener, the Servlet container will notice this class, and when launching our web app will instantiate our listener object, and then call its methods at the appropriate times. The contextInitialized method is called after the servlet has been properly initialized but before any incoming web browser requests have been handled. The contextDestroyed method is called after the last web browser request has been handled, after that last response has been sent back to the user.
So our class implementing the ServletContextListener is the perfect place to setup and teardown our executor service with its backing thread pool.
One more problem: After setting up our executor service, where do we store a reference to be found and used later in our Vaadin servlet when the users are adding their Label objects? One solution is to store the executor service reference as an “attribute” in the “context” (our web app). The Servlet spec requires that every Servlet container provide each context (web app) with a simple key-value collection where the key is a String object and the value is an Object object. We can invent some string to identify our executor service, and then our Vaadin servlet can later do a loop-up to retrieve the executor service.
Ironically enough, that discussion above is longer than the actual code!
package com.basilbourque.example;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
#WebListener
// Annotate to instruct your web container to notice this class as a context listener and then automatically instantiate as context (your web app) lanuches.
public class MyServletContextListener implements ServletContextListener {
static final public String executorServiceNameForUpdatingLabelAfterSqlService = "ExecutorService for SQL service update of labels";
#Override
public void contextInitialized ( final ServletContextEvent sce ) {
// Initialize an executor service. Store a reference as a context attribute for use later in our webapp’s Vaadin servlet.
ExecutorService executorService = Executors.newFixedThreadPool( 7 ); // Choose an implementation and number of threads appropriate to demands of your app and capabilities of your deployment server.
sce.getServletContext().setAttribute( MyServletContextListener.executorServiceNameForUpdatingLabelAfterSqlService , executorService );
}
#Override
public void contextDestroyed ( final ServletContextEvent sce ) {
// Always shutdown your ExecutorService, otherwise the threads may survive shutdown of your web app and perhaps even your web container.
// The context addribute is stored as `Object`. Cast to `ExecutorService`.
ExecutorService executorService = ( ExecutorService ) sce.getServletContext().getAttribute( MyServletContextListener.executorServiceNameForUpdatingLabelAfterSqlService );
if ( null != executorService ) {
executorService.shutdown();
}
}
}
Now, back to our Vaadin app. Modify that file:
Annotate the Servlet with #Push to engage Vaadin’s ability to have a server-side generated event update the user-interface widgets.
Modify the creation of each Label.
Change the initial text for the Label to include "Created: " with current date-time.
Move the instantiation to its own line.
Add behavior so that after instantiating a new Label, we retrieve our executor service from the context attribute collection, and submit to it a Runnable that will eventually be run to do our SQL service. To simulate the work of that SQL service, we sleep the background thread random number of seconds under half a minute. Upon waking, that background thread asks our UI object representing our web app’s content displayed in the web browser to schedule yet another Runnable to eventually be run on its main user-interface thread. As discussed above, never directly access a UI widget from a background thread! Always politely ask the UI object to schedule widget-related work on its own timetable in its own thread.
If you are new to threading and concurrency, this may be daunting. Study this code, and it some time to sink in. You could structure this in other manners, but I wanted to make it simple here for teaching purposes. Focus not on the structure/arrangement of the code but on the idea of:
User clicks button, an event in main Vaadin UI thread.
Code on the button submits to an executor service a task (a Runnable) to be run later in a background thread.
That background thread, when eventually run, calls on your SQL service to get some work done. When done, we post a request (another Runnable) to the UI to do some widget-related work (our Label text updating) on our behalf.
When convenient to the UI, when it is not too busy handling other user-related events generated in the user-interface, the UI gets around to running our Runnable to actually modify the text of the Label that was added a while ago.
Here is our modified Vaadin app.
package com.basilbourque.example;
import javax.servlet.ServletContext;
import javax.servlet.annotation.WebServlet;
import com.vaadin.annotations.Push;
import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.Button;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
/**
* This UI is the application entry point. A UI may either represent a browser window
* (or tab) or some part of an HTML page where a Vaadin application is embedded.
* <p>
* The UI is initialized using {#link #init(VaadinRequest)}. This method is intended to be
* overridden to add component to the user interface and initialize non-component functionality.
*/
#Push // This annotation enables the Push Technology built into Vaadin 8.4.
#Theme ( "mytheme" )
public class MyUI extends UI {
#Override
protected void init ( VaadinRequest vaadinRequest ) {
final VerticalLayout layout = new VerticalLayout();
final TextField name = new TextField();
name.setCaption( "Type your name here:" );
Button button = new Button( "Click Me" );
button.addClickListener( ( Button.ClickEvent e ) -> {
Label label = new Label( "Thanks " + name.getValue() + ", it works!" + " " + ZonedDateTime.now( ZoneId.systemDefault() ) ); // Moved instantiation of `Label` to its own line so that we can get a reference to pass to the executor service.
layout.addComponent( label ); // Notes current date-time when this object was created.
//
ServletContext servletContext = VaadinServlet.getCurrent().getServletContext();
// The context attribute is stored as `Object`. Cast to `ExecutorService`.
ExecutorService executorService = ( ExecutorService ) servletContext.getAttribute( MyServletContextListener.executorServiceNameForUpdatingLabelAfterSqlService );
if ( null == executorService ) {
System.out.println( "ERROR - Failed to find executor serivce." );
} else {
executorService.submit( new Runnable() {
#Override
public void run () {
// Pretending to access our SQL service. To fake it, let's sleep this thread for a random number of seconds.
int seconds = ThreadLocalRandom.current().nextInt( 4 , 30 + 1 ); // Pass ( min , max + 1 )
try {
Thread.sleep( TimeUnit.SECONDS.toMillis( seconds ) );
} catch ( InterruptedException e ) {
e.printStackTrace();
}
// Upon waking, ask that our `Label` be updated.
ZonedDateTime zdt = ZonedDateTime.now( ZoneId.systemDefault() );
System.out.println( "Updating label at " + zdt );
access( new Runnable() { // Calling `UI::access( Runnable )`, asking that this Runnable be run on the main UI thread rather than on this background thread.
#Override
public void run () {
label.setValue( label.getValue() + " Updated: " + zdt );
}
} );
}
} );
}
} );
layout.addComponents( name , button );
setContent( layout );
}
#WebServlet ( urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true )
#VaadinServletConfiguration ( ui = MyUI.class, productionMode = false )
public static class MyUIServlet extends VaadinServlet {
}
}
When doing such asynchronous threaded work, the exact order of execution cannot be predicted. You do not know exactly when and in which order the background threads well be executing. You do not know when the UI object will get to our request to update the Label object’s text. Notice in this screenshot that while running this app, different Label objects were updated at different times in an arbitrary order.
Related Questions:
Hook for my Vaadin web app starting and stopping?
How to access ServletContext from within a Vaadin 7 app?
You need to use #Push in your UI and update the content of the Label when query has been completed using UI.access(..). There is good documentation about it with some examples here:
https://vaadin.com/docs/v8/framework/advanced/advanced-push.html

Why use Device.BeginInvokeOnMainThread() in a Xamarin application?

My code looks like this:
public void Init() {
if (AS.pti == PTI.UserInput)
{
AS.runCardTimer = false;
}
else
{
AS.runCardTimer = true;
Device.BeginInvokeOnMainThread(() => showCards().ContinueWith((arg) => { }));
}
}
The Init method is called from the constructor. Can someone please explain to me why the developer might have added the Device.BeginInvokeOnMainThread() instead of just calling the method showCards?
Also what does the ContinueWith((arg)) do and why would that be included?
The class where this Init() method is might be created on a background thread. I'm assuming showCards() are updating some kind of UI. UI can only be updated on the UI/Main thread. Device.BeginInvokeOnMainThread() ensures that the code inside the lambda is executed on the main thread.
ContinueWith() is a method which can be found on Task. If showCards() returns a task, ContinueWith() makes sure the task will complete before exiting the lambda.
UI actions must be performed on UI thread (different name for main thread). If you try to perform UI changes from non main thread, your application will crash. I think developer wanted to make sure it will work as intended.
The simple answer is: Background thread cannot modify UI elements because most UI operations in iOS and Android are not thread-safe; therefore, you need to invoke UI thread to execute the code that modifies UI such MyLabel.Text="New Text".
The detailed answer can be found in Xamarin document:
For iOS:
IOSPlatformServices.BeginInvokeOnMainThread() Method simply calls NSRunLoop.Main.BeginInvokeOnMainThread
public void BeginInvokeOnMainThread(Action action)
{
NSRunLoop.Main.BeginInvokeOnMainThread(action.Invoke);
}
https://developer.xamarin.com/api/member/Foundation.NSObject.BeginInvokeOnMainThread/p/ObjCRuntime.Selector/Foundation.NSObject/
You use this method from a thread to invoke the code in the specified object that is exposed with the specified selector in the UI thread. This is required for most operations that affect UIKit or AppKit as neither one of those APIs is thread safe.
The code is executed when the main thread goes back to its main loop for processing events.
For Android:
Many People think on Xamarin.Android BeginInvokeOnMainThread() method use Activity.runOnUiThread(), BUT this is NOT the case, and there is a difference between using runOnUiThread() and Handler.Post():
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);//<-- post message delays action until UI thread is scheduled to handle messages
} else {
action.run();//<--action is executed immediately if current running thread is UI thread.
}
}
The actual implementation of Xamarin.Android BeginInvokeOnMainThread() method can be found in AndroidPlatformServices.cs class
public void BeginInvokeOnMainThread(Action action)
{
if (s_handler == null || s_handler.Looper != Looper.MainLooper)
{
s_handler = new Handler(Looper.MainLooper);
}
s_handler.Post(action);
}
https://developer.android.com/reference/android/os/Handler.html#post(java.lang.Runnable)
As you can see, you action code is not executed immediately by Handler.Post(action). It is added to the Looper's message queue, and is handled when the UI thread's scheduled to handle its message.

stop javafx task concurrent

I developed a JavaFX application using MVC and DAO patterns. From the user interface the user can press a button to start export from MS Access to SQLite. This may take a long time, so I created a task (in the Controller). The task invokes a method of the Model "exportFromAccessToSQLite". All the logic of the database is in the Model. It all works fine. But I'd like to add a button in the user interface which when pressed stops the current operation. I would like to enter the code in the controller. How can I do?
The code is this:
Model objModel = new Model();
Task worker = new Task() {
#Override
protected Void call() throws Exception {
objModel.exportFromAccessToSQLite(fileAccess, directoryDest);
updateProgress(1, 1);
return null;
}
};
prgEspIndicator.progressProperty().bind(worker.progressProperty());
new Thread(worker).start();

Unit testing a custom control in a windows store project

I want to unit test the custom controls I create for a windows store project. Just simple things like "there is a button when X is true".
However, I can't seem to even instantiate the controls in a testing context. Whenever I try to invoke the constructor, I get an exception related to not being run in the UI context. I've also been unable to create coded UI test projects that target windows store projects.
How do I programmatically instantiate a control to test? How do I create a WinRT UI synchronization context?
How do I programmatically send "user" command events to a control?
How do I programmatically instantiate/teardown the entire application?
I've found a hacky way to make non-interactive parts work: with the function Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync.
Obvious, right? However, this still leaves open the question of how to emulate user actions.
/// Runs an action on the UI thread, and blocks on the result
private static void Ui(Action action) {
Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
CoreDispatcherPriority.Normal,
() => action()
).AsTask().Wait();
}
/// Evaluates a function on the UI thread, and blocks on the result
private static T Ui<T>(Func<T> action) {
var result = default(T);
Ui(() => { result = action(); });
return result;
}
[TestMethod]
public void SliderTest() {
// constructing a Slider control is only allowed on the UI thread, so wrap it in UI
var slider = Ui(() => new Slider());
var expected = 0;
// accessing control properties is only allowed on the UI thread, so same deal
Assert.AreEqual(expected, Ui(() => slider.Value));
}

How can a JSF/ICEfaces component's parameters be updated immediately?

I have an ICEfaces web app which contains a component with a property linked to a backing bean variable. In theory, variable value is programmatically modified, and the component sees the change and updates its appearance/properties accordingly.
However, it seems that the change in variable isn't "noticed" by the component until the end of the JSF cycle (which, from my basic understanding, is the render response phase).
The problem is, I have a long file-copy operation to perform, and I would like the the inputText component to show a periodic status update. However, since the component is only updated at the render response phase, it doesn't show any output until the Java methods have finished executing, and it shows it all changes accumulated at once.
I have tried using FacesContext.getCurrentInstance().renderResponse() and other functions, such as PushRenderer.render(String ID) to force XmlHttpRequest to initialize early, but no matter what, the appearance of the component does not change until the Java code finishes executing.
One possible solution that comes to mind is to have an invisible button somewhere that is automatically "pressed" by the bean when step 1 of the long operation completes, and by clicking it, it calls step 2, and so on and so forth. It seems like it would work, but I don't want to spend time hacking together such an inelegant solution when I would hope that there is a more elegant solution built into JSF/ICEfaces.
Am I missing something, or is resorting to ugly hacks the only way to achieve the desired behavior?
Multithreading was the missing link, in conjunction with PushRenderer and PortableRenderer (see http://wiki.icesoft.org/display/ICE/Ajax+Push+-+APIs).
I now have three threads in my backing bean- one for executing the long operation, one for polling the status, and one "main" thread for spawning the new threads and returning UI control to the client browser.
Once the main thread kicks off both execution and polling threads, it terminates and it completes the original HTTP request. My PortableRenderer is declared as PortableRender portableRenderer; and in my init() method (called by the class constructor) contains:
PushRenderer.addCurrentSession("fullFormGroup");
portableRenderer = PushRenderer.getPortableRenderer();
For the threading part, I used implements Runnable on my class, and for handling multiple threads in a single class, I followed this StackOverflow post: How to deal with multiple threads in one class?
Here's some source code. I can't reveal the explicit source code I've used, but this is a boiled-down version that doesn't reveal any confidential information. I haven't tested it, and I wrote it in gedit so it might have a syntax error or two, but it should at least get you started in the right direction.
public void init()
{
// This method is called by the constructor.
// It doesn't matter where you define the PortableRenderer, as long as it's before it's used.
PushRenderer.addCurrentSession("fullFormGroup");
portableRenderer = PushRenderer.getPortableRenderer();
}
public void someBeanMethod(ActionEvent evt)
{
// This is a backing bean method called by some UI event (e.g. clicking a button)
// Since it is part of a JSF/HTTP request, you cannot call portableRenderer.render
copyExecuting = true;
// Create a status thread and start it
Thread statusThread = new Thread(new Runnable() {
public void run() {
try {
// message and progress are both linked to components, which change on a portableRenderer.render("fullFormGroup") call
message = "Copying...";
// initiates render. Note that this cannot be called from a thread which is already part of an HTTP request
portableRenderer.render("fullFormGroup");
do {
progress = getProgress();
portableRenderer.render("fullFormGroup"); // render the updated progress
Thread.sleep(5000); // sleep for a while until it's time to poll again
} while (copyExecuting);
progress = getProgress();
message = "Finished!";
portableRenderer.render("fullFormGroup"); // push a render one last time
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
});
statusThread.start();
// create a thread which initiates script and triggers the termination of statusThread
Thread copyThread = new Thread(new Runnable() {
public void run() {
File someBigFile = new File("/tmp/foobar/large_file.tar.gz");
scriptResult = copyFile(someBigFile); // this will take a long time, which is why we spawn a new thread
copyExecuting = false; // this will caue the statusThread's do..while loop to terminate
}
});
copyThread.start();
}
I suggest looking at our Showcase Demo:
http://icefaces-showcase.icesoft.org/showcase.jsf?grp=aceMenu&exp=progressBarBean
Under the list of Progress Bar examples is one called Push. It uses Ajax Push (a feature provided with ICEfaces) to do what I think you want.
There is also a tutorial on this page called Easy Ajax Push that walks you through a simple example of using Ajax Push.
http://www.icesoft.org/community/tutorials-samples.jsf

Resources