I'm making a fullscreen JavaFX program, but I want it to run as a screensaver in the background with other applications simultaneously running on top of it. Right now, it automatically creates a separate desktop just for the program. Any solutions?
Swing is definitely an option. Here is a place to start:
public class MyClass {
public void myAction () {
// your logic goes here
System.out.println("hello");
}
public static void main(String[] args) {
MyClass mc = new MyClass();
mc.myAction();
}
}
I'm using Guava Eventbus in Vaadin+Spring project and started to have a problem with posting an event from background thread.
Eventbus is instantiated in wrapper class. Objects communicate with the eventbus using static method defined in main UI class to obtain the eventbus object. It is the same way as proposed in Vaadin Dashboard example (DashboardEventBus).
public class MainUI extends UI implements ViewDisplay
{
private EventBusWrapper eventbus_ = new EventBusWrapper();
public static EventBusWrapper GetEventBusWrapper()
{
return ((MainUI) getCurrent()).eventbus_;
}
}
Problem appears in presenter/services classes where I create new thread class and start the thread.
Inside Runnable implemenation of run method I create another object which makes some job.
public class SearchResultsPresenter extends AbstractPresenter<SearchResultView>
{
public SearchResultsPresenter()
{
EventBusWrapper.register(this);
}
#Subscribe
public void UserSearchRequested(Event.UserSearchRequestEvent e)
{
new UpdateContentComponentThread(e.GetSearchElem()).start();
}
#Subscribe
public void UserSearchAppendFoundElement(Event.UserSearchElementFound e)
{
if(e.GetElement().IsValid())
view_.AddElement(e.GetElement());
}
public class UpdateContentComponentThread extends Thread
{
private final Search searcher_;
UpdateContentComponentThread(SearchElement search)
{
searcher_ = new DefaultSearch(search);
}
#Override
public void run()
{
searcher_.Search();
}
}
}
It performs some validation/checking and creates other helper classes.
public class DefaultSearch implements Search
{
private final Scraper scraper_;
...
#Override
public void Search()
{
if(!scraper_.IsConfigured())
return;
...
scraper_.FindElements();
}
}
Then inside scraper's FindElements body I try to post an event using static post method defined in EventBusWrapper.
public class HttpElementScraper extends WebScraper
{
...
#Override
public Collection<Element> FindElements()
{
...
Element elem = ...
Event.UserSearchElementFound e = new Event.UserSearchElementFound(elem);
EventBusWrapper.post(e);
return foundelements;
}
}
At this moment the NullPointerException is thrown and I cannot solve and help myself with the problem.
Exception in thread "Thread-10" java.lang.NullPointerException
at com.project.MainUI.GetEventBusWrapper(MainUI.java:109)
at com.project.events.EventBusWrapper.register(EventBusWrapper.java:24)
at com.project.service.search.scraper.HttpElementScraper.FindElements(HttpElementScraper.java:92)
at com.project.service.search.DefaultSearch.Search(DefaultSearch.java:38)
at com.project.view.search.SearchResultsPresenter$UpdateContentComponentThread.run(SearchResultsPresenter.java:71)
// I ommited not important lines of code and annotations. Most of the components and services connected with them are UIscoped.
Vaadin assumes that access to Vaadin component (and related) instances is synchronized properly. When using the traditional single-threaded request-response cycle to access components it's synchronized automatically.
When using external threads, you need to synchronize code accessing your Vaadin components by using UI.access(). For example:
getUI().access(() -> label.setValue("Hello"));
In my application I have the following potentially long running classes:
ScheduleLocalNotificationsOperation
UnScheduleLocalNotificationsOperation
SyncEventsToDeviceCalendarOperation
UnSyncEventsToDeviceCalendarOperation
SaveProductsToLocalStorageImpl
and so on.
Most of these are structured this way:
public interface Operation {
void execute();
}
public class ScheduleLocalNotificationsOperation implements Operation {
private MyApplication application;
private List<LocalNotificationDescriptor> localNotifications;
public ScheduleLocalNotificationsOperation (MyApplication application, List<LocalNotificationDescriptor> localNotifications) {
this.application = application;
this.localNotifications = localNotifications;
}
#Override
public void execute() {
// Do some stuff
}
}
Ideally, I would like to design my Operation classes to be concurrency agnostic, and to be able to impose some multithreading policy on them from the outside, like so:
public class MainActivity extends Activity {
public static ExecutorService executorService = Executors.newCachedThreadPool();
#Override
public void onCreate() {
executorService.submit(new Runnable {
#Override
public void run() {
new ScheduleLocalNotificationsOperation(application, createLocalNotificationsList()).execute();
}
});
}
}
But this way I should implement some concurrency policy in every client, every time I call those classes.
On the other hand, I dont want to interrupt the pure logic in those operations by adding concurrency to them, so my question is basically, from design stand point what is the better way to do this, if there is a clearly defined one?
Can I create an OperationsRunner class that will be called by any client and will execute any Operation using polymorphism and make that class be the only one that deals with concurrency?
In a JavaFX application, javafx.application.Application must be subclassed, and the inherited launch() method, although it's public, must be called from within this derived class, otherwise an exception is thrown. The launch() method then uses reflection to instantiate the derived class, making it difficult to set values for the class members without losing them when launching. All that appears totally unusual to me, and I was wondering why starting a JavaFX application is so complicated, if that kind of software design (design pattern?) has a name, or if it's just bad design?
EDIT:
To be more specific, I want to use the observer pattern, so my java application gets notified when a document was loaded, like this:
public class MyDocumentLoader extends Application
{
private ChangeListener<Worker.State> changeListener;
public void setChangeListener(ChangeListener<Worker.State> changeListener)
{
this.changeListener = changeListener;
}
...
public void loadDocument(String url)
{
webEngine.getLoadWorker().stateProperty().addListener(changeListener);
webEngine.load(url);
}
...
}
I need the callback member in several methods, and ideally I can have more than one instances of the class that loads documents, so I can set different ChangeListeners for different URLs.
My guess is that this design was motivated by the (vast) number of Swing applications that were incorrectly written, with the "primary" JFrames being instantiated and shown on the wrong thread (i.e. not on the AWT event dispatch thread). My guess is that so many Swing applications were incorrectly written that they had to defensively code the framework against the incorrect usage, and that they wanted to avoid this scenario with JavaFX.
Forcing (well, almost forcing, there are hack-arounds) an FX Application to start this way makes it much harder to write an application incorrectly in a similar way. The launch method (and the equivalent Oracle JVM startup process if you have an Application subclass without a main method and a call to launch) does quite a bit of boilerplate work: it starts the FX toolkit, instantiates the Application subclass and calls its init() method, then on the FX Application Thread it instantiates the primary Stage and passes it to the Application subclass's start(...) method. This then ensures everything is running on the correct thread.
You should basically consider the start(...) method in a JavaFX application as the replacement for the main(...) method in a "traditional" Java application, with the understanding it is invoked on the FX Application Thread.
My recommendation is that the Application subclass should be as minimal as possible; it should just delegate to something else to actually create the UI, and then should just place it in the primary stage and show it. Include a main method that does nothing other than call launch(...) as a fallback for non-JavaFX-aware JVMs. You should only have one instance of one Application subclass present in any JVM. This way your Application subclass has no class members to set, and so the issues you describe simply don't arise.
If you use FXML, this is actually fairly natural: the start(...) method essentially just delegates to the FXML-controller pair to do the real work. If you don't use FXML, create a separate class to do the actual layout, etc, and delegate to it. See this related question which gets at the same kind of idea.
Note also that your statement
the inherited launch() method, although it's public, must be called
from within this derived class
is not entirely accurate, as there is an overloaded form of the launch(...) method in which you can specify the application subclass. So, if you really need, you can just create a stub for starting the FX toolkit:
public class FXStarter extends Application {
#Override
public void start(Stage primaryStage) {
// no-op
}
}
Now you can do:
public class MyRegularApplication {
public static void main(String[] args) {
// start FX toolkit:
new Thread(() -> Application.launch(FXStarter.class)).start();
// other stuff here...
}
}
Note that launch does not return until the FX toolkit shuts down, so it is imperative to put this call in another thread. This potentially creates race conditions, where you may try to do something needing the FX toolkit before launch(...) has actually initialized it, so you should probably guard against that:
public class FXStarter extends Application {
private static final CountDownLatch latch = new CountDownLatch(1);
public static void awaitFXToolkit() throws InterruptedException {
latch.await();
}
#Override
public void init() {
latch.countDown();
}
#Override
public void start(Stage primaryStage) {
// no-op
}
}
and then
public class MyRegularApplication {
public static void main(String[] args) throws InterruptedException {
// start FX toolkit:
new Thread(() -> Application.launch(FXStarter.class)).start();
FXStarter.awaitFXToolkit();
// other stuff here...
}
}
SSCCE (I just used inner classes for everything so this is convenient to run, but in real life these would be standalone classes):
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class BackgroundProcessDrivenApp {
public static void main(String[] args) throws InterruptedException {
Platform.setImplicitExit(false);
new Thread(() -> Application.launch(FXStarter.class)).start();
FXStarter.awaitFXToolkit();
new MockProcessor().doStuff() ;
}
public static class FXStarter extends Application {
private static final CountDownLatch latch = new CountDownLatch(1);
#Override
public void init() {
latch.countDown();
}
public static void awaitFXToolkit() throws InterruptedException {
latch.await();
}
#Override
public void start(Stage primaryStage) { }
}
public static class MockProcessor {
private final int numEvents = 10 ;
public void doStuff() {
Random rng = new Random();
try {
for (int event = 1 ; event <= numEvents; event++) {
// just sleep to mimic waiting for background service...
Thread.sleep(rng.nextInt(5000) + 5000);
String message = "Event " + event + " occurred" ;
Platform.runLater(() -> new Messager(message).showMessageInNewWindow());
}
} catch (InterruptedException exc) {
Thread.currentThread().interrupt();
} finally {
Platform.setImplicitExit(true);
}
}
}
public static class Messager {
private final String message ;
public Messager(String message) {
this.message = message ;
}
public void showMessageInNewWindow() {
Stage stage = new Stage();
Label label = new Label(message);
Button button = new Button("OK");
button.setOnAction(e -> stage.hide());
VBox root = new VBox(10, label, button);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 350, 120);
stage.setScene(scene);
stage.setAlwaysOnTop(true);
stage.show();
}
}
}
JavaFX supports a great number of deployment and packaging strategies, ref. https://docs.oracle.com/javase/8/docs/technotes/guides/deploy/toc.html, and having a standardized lifecycle entry- and exit-point simplifies supporting all these strategies.
If you are struggling to initialize your main application class, due to it being instanciated by the JavaFX launcher, your best option is to use the Application.init() and Application.stop() methods, as James_D points out.
I'm coming to Java from C#, and I'm really just trying to figure out how to do things in Java world. I'm running Java 8 in IntelliJ IDEA. I found this explaining events in Java as basically being hand-made through manual registration and an interface method call. The code example has enough problems that I assume it was never compiled. After cleaning that up a bit I have this:
Interface MetronomeEvent:
public interface MetronomeEvent {
void Tick(Date tickDate);
}
Class EventFiringSource:
public class EventFiringSource {
// Our collection of classes that are subscribed as listeners of our
protected List<MetronomeEvent> _listeners=new ArrayList();
// Method for listener classes to register themselves
public void addMetronomeEventListener(MetronomeEvent listener)
{
_listeners.add(listener);
}
// "fires" the event
protected void fireMetronomeEvent()
{
if (_listeners != null && !_listeners.isEmpty())
{
for (MetronomeEvent e:_listeners)
{
e.Tick(new Date());
}
}
}
public void Start()
{
fireMetronomeEvent();
}
}
Main console application:
public class MainApp implements MetronomeEvent {
public static void main(String[] args) {
EventFiringSource source = new EventFiringSource();
source.addMetronomeEventListener(this); // Adds itself as a listener for the event
source.Start();
}
public void Tick(Date tickDate)
{
System.out.println(tickDate.toString());
}
}
The one remaining error is source.addMetronomeEventListener(this); where the compiler complains that it cannot reference MyApp.this from a static context. That makes sense, but I don't see any way then that I could, after implementing the MetronomeEvent interface on the main program class, actually pass it to source.addMetronomeEventListener() for registration. Is it impossible to directly register the main program class for events? Am I supposed to create and register a Listener class that implements MetronomeEvent and will act on behalf of the main application? Like this?
public class Listener implements MetronomeEvent {
public void Tick(Date tickDate){
System.out.println(tickDate.toString());
}
}
And then:
public static void main(String[] args) {
EventFiringSource source = new EventFiringSource();
Listener l=new Listener();
source.addMetronomeEventListener(l); // Adds another object to listen on behalf of main()
source.Start();
}
This is not about events, it's about main() and static methods in general.
I would suggest writing your main() as
public static void main(String[] args) {
new MainApp(args).execute();
}
This way you're immediately jumping from static function world into object-oriented world.
Based on Vince Emigh's comment/answer I was led to this Oracle doc on lamda expressions and to this one on method references. I've found 3 ways to do this so far.
1) Anonymous class:
source.addMetronomeEventListener(
new MetronomeEvent() {
#Override
public void Tick(Date tickDate) {
System.out.println("anonymous class:");
System.out.println(tickDate.toString());
}
}
); // Adds itself as a listener for the event
2) Lambda expression:
source.addMetronomeEventListener(d -> System.out.println("lambda:\n"+d.toString()));
3) Method reference, which is the closest to what I am accustomed to. A method is defined in the main class:
public static void processTick(Date tickDate){
System.out.println("method reference:");
System.out.println(tickDate.toString());
}
...and then in the body of main() it is added as an event handler like this:
source.addMetronomeEventListener(MainApp::processTick);