Missing OpenFilesEvent for JavaFX on Mac - java

I have a JavaFX 8 desktop application and I'm creating an .app application bundle to distribute the application to Mac users. I use the Oracle “Self-Contained Application Packaging” tool to generate the bundle.
The problem that I have relates to the files associated with my application. I am associating the extension .wordy with these files. If I have the application open and I double click one of these files in the Mac Finder, my application receives an OpenFilesEvent containing the path to the file and everything works perfectly. If, however, the application is not open, double clicking a .wordy file in the Finder opens my application as I would expect but I never receive the event containing the path to the file that the user double-clicked on.
The file association is done in the Ant script for the Oracle “Self-Contained Application Packaging” tool, as follows:
<project name="VocabHunter Packaging" basedir=""
xmlns:fx="javafx:com.sun.javafx.tools.ant">
...
<fx:info title="VocabHunter">
<fx:association description="VocabHunter session"
extension="wordy"
mimetype="application/x-vnd.VocabHunterSession"
icon="${basedir}/icons/mac/VocabHunterSession.icns"/>
</fx:info>
...
</project>
In the Java code, I obtain an instance of com.apple.eawt.Application and then register the listener for the OpenFilesEvent as follows:
Application application = Application.getApplication();
application.setOpenFileHandler(new OsxOpenFilesHandler(listener));
You can see the full code here.
Does anyone know how to fix this so that I receive an event containing the path to the .wordy file even if the application was not running at the moment that the file was double clicked?
In the interests of completeness, I'm using the Oracle JDK 1.8.0_66 for Mac.

I tested with your code and also met this problem.
But when I used code directly in start(Stage primaryStage) method in to listen like this:
Application lowLevelApp = com.sun.glass.ui.Application.GetApplication();
lowLevelApp.setEventHandler {...}
I can get the OpenFilesEvent when first double clicked on file.

There is an entry in the bug database for this issue.
https://bugs.openjdk.java.net/browse/JDK-8187992

You probably call the application.setOpenFileHandler() code too late during the application initialization. Try calling it as early as possible in main() and see if that solves the problem. I am not sure exactly when Mac OS X passes the OpenFile event to Java, but if at that time you haven't prepared by calling application.setOpenFileHandler() then the event will get lost.

For future reference: getting the openFileHandler to work correctly can be very tricky. The handler is invoked from an event handler on the UI event thread, which means there is no guarantee that main() has completed when the handler is run. For best results, the openFileHandler should be set up using a static initializer, and main() and the open file handler should both invoke the same initialization code on the UI event thread, and the initialization code should be written to work if called more than once.

Related

Execute a jar file ever Windows initialize and after the user logon (Not as a Service) that call a process with a GUI

I have a jar file and I wanted to run this file as a service. When this .jar executes, it opens another program that I want to be able to see it GUI. But note: only the second program needs a GUI (the .jar not). I open this second program using the following:
ProcessBuilder processBuilder = new ProcessBuilder(cmdCommand);
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
Searching about this issue I saw that if I performed my .jar file as a service, I could not see the process started GUI because services executing in another desktop since Windows Vista. To create a service, I used Java Service Wrapper. On this tutorial, they teach how to use the wrapper.ntservice.interactive configuration to make for the service to display a GUI. They alert too:
"Starting with Windows Vista and Server 2008, Microsoft changed the way services are allowed to interact with the desktop. They decided that for security reasons, services are now only allowed to show their GUI on a special desktop that only the service can interact with. Unfortunately, this makes interactive features pretty much useless. We are looking into ways to display a GUI in a different way. Stay tuned.
If you do a search on the Internet with keywords of "Interactive services dialog Vista", you will find a number of references to the way Windows will display a dialog on the user desktop whenever a service has updated into GUI on the services desktop.
There are some important security reasons why this was disabled in Windows. But if you really need to reenable this functionality, it is possible to do so by editing the Windows Registry and setting HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Windows\NoInteractiveServices to 0. Always be very careful editing the registry as you can easily mess up your system by changing the wrong values."
I've been tried to configuration the NoInteractiveServices to 0, but yet do not work.
So, how can I execute a .jar program when windows initialize and the user do the login, and still be able to see the GUI of my opened process?

Saving a source code while running in java

This is my own version of karel the Robot. The Janitor Robot that can only run un eclipse. My problem is when I open and i click run in a first time the robot moves according to the codes. but when i tried to edit the codes while the window is open, when i click the run button again it did not moves and need to close again.
This is my source code in the run method:
I have a janibot class that is implemented by a runnable and then. and i create its instance dynamically by this code.
Object tempJanibot = Class.forName(className).newInstance();
janibot = (Janibot) tempJanibot;
janibot.run()
where classname is the subclass of Janibot that is takingTurns in the screenshots.
It successfully created the instance of takingTurns class.
But I thought when i edit the code while the program is running and I click the run method the takingTurns class must be updated also but unfortunately it will not update and so I need to close again and click the run button.
What you are looking for is hot loading of the Java class. The default mechanism in Java is to load the class once in classloader reference and re-use it when required. So while Java application is running and if the class is recompiled, it will not pick up the new definition. If you wish to achieve similar functionality, you can look for solutions like JRebel or spring loaded.
"It's not a bug, it's a feature!" Eclipse cannot recompile your code while it is running and merge those changes into your currently running program. You'll have to restart the program each time.

Restart an Application in JavaFx

I want to close and then restart a already running application (automatically) that I am making, by clicking a button or something like that, I want to do that for the purpose of re-launching the application in an other language, I'm new to JavaFx and Java in general, please can you give me a solution for this problem ?
This question lacks details. You did mention a JavaFX application but it is important to know how that application is being deployed. Is it running in the web browser, as a java webstart application, a stand-alone jar, or a self-contained native application? How are you starting the application to begin with? Having the answer to these questions will make it easier to answer your question with specifics.
While the following example is not JavaFX, the approach used here would work for some of the ways in which a JavaFX application can be deployed. One approach for restarting an application that works nicely is to start the application from a script. Inside the script would be a while loop that continually restarts the program based on the program exit code. Here is an example for a bash shell script which starts IntelliJ on a Linux platform:
while true ; do
eval "$JDK/bin/java" $ALL_JVM_ARGS -Djb.restart.code=88 $MAIN_CLASS_NAME $*
test $? -ne 88 && break
done
In this example, the startup script is passing "jb.restart.code" as an application parameter. If IntelliJ wishes to restart, it will return that value 88 as the exit code. The script observes the application exit code, and restarts the application if the value is 88.
This approach works well on most platforms, but requires the application to be initiated via a script.
One solution is to pass commandline and working dir in your start script to your main() method. Using ProcessBuilder you then can restart the appliation. Another possibility is to start the whole application in a custom classloader (e.g. Spring project has suitable classloaders in their source base), you then can basically restart by starting your main in anouther classloader, however you then need proper housekeeping to free threads and resources of the first instance.
retstart.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent t) {
if(getOnCloseRequest()!=null){
getOnCloseRequest().handle(new WindowEvent(getScene().getWindow(), WindowEvent.WINDOW_CLOSE_REQUEST));
//write code to invoke application instance again
}else{
close();
}
}
});

Using OS X 10.8 Notification Center (NSUserNotification) with Java

I'm struggling with the notification center in OS X 10.8. I wrote a wrapper to provide Java access to the NSUserNotification and NSUserNotificationCenter classes via JNA, however the functionality is limited. I am able to send a notification and it will display as long as the .jar is being run from an .app bundle via JavaApplicationStub. However, the line below is always logged to the console when the the notification style is set to "Alerts":
11/29/12 8:37:12.537 PM usernoted[162]: Failed to validate application at (null) -67061
Next, clicking the notification results in the following being logged to the console:
11/29/12 8:38:15.291 PM usernoted[162]: Cannot find originating application to launch for event action. file://localhost/Users/geoffodonnell/Projects/bin/GuiTest.app/ is not the same app as the one that sent the original notification.
I did provide the NSUserNotificationCenter class with a delegate, however those methods only get run when the .jar is executed outside of a bundle. Naturally, this defeats the purpose since the notification will never be displayed.
Can anyone provide any insight into the two errors above?
I am wondering if the JavaApplicationStub is getting in the way, however I'm in the dark when it comes to how exactly a typical application would respond the notification center events.
This issue is solved by updating to JDK 7u10 (Developer Preview) located here,
http://jdk7.java.net/download.html
And using the appbundler tool described here,
http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/packagingAppsForMac.html
to create your application bundle. This tool creates an application bundle with a different executable stub file, so perhaps JavaApplicationStub (and/or JRE 1.6) was the culprit.

Launch a java application from another java application

I'm doing a Java Record/Replay tool and I need to launch Java applications from my main Java app.
I need access to the EventDispatchThread in order to intercept the events and record them, so I'm launching the application through reflection with (code snippet simplified):
Class<?> app = Class.forName(mainClass);
Method m = app.getMethod("main", new Class[] { String[].class });
m.invoke(null, new Object[] { new String[] {} });
I previously dynamically load all the jars to the classpath and the application is launching almost perfectly.
The problem occurs when the application needs to access any file and does it with relative paths. Because the application is launched through my application the path is not the same as launched from its normal path and the files are not found.
What can I do to solve this problem? dynamically change the execution environment? any ideas?
I would suggest loading your code as a "Java Agent" whilst starting the target application.
(With your method you will also find that the system class loader is wrong.)
In general, there's no way to do this.
http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=30b24551130ee4ffffffffc17df8d7ce8a9c3?bug_id=4117557
You can try System.setProperty("user.dir", "C:\\Some\\Location"); but it probably won't work for all cases and will give you weird behavior.
It's a pretty bad design for an app to rely on the directory from which it was launched.
The best advice I can give you is to launch your app from the directory from which the misbehaving app expects to be launched (assuming you know what that directory is).
Otherwise, hell, copy/symlink the data files into your directory so that the client app can find them...

Categories

Resources