JavaFx in headless mode - javafx

Is it possible to run JavaFx in headless mode(in Java 7)? It is being used to generate images on the server but is asking for an X-Server. Does there exist something like java.awt.headless in JavaFx ?(I can't use Xvfb )

Here is how I solved this problem for server-side image geneartion on Ubuntu linux environment with jetty application server. It uses xvfb but only as a "library" - without any additional special actions on server:
apt-get install xvfb
// then on application server start:
export DISPLAY=":99"
start-stop-daemon --start --background --user jetty --exec "/usr/bin/sudo" -- -u jetty /usr/bin/Xvfb :99 -screen 0 1024x768x24
You can see the details of my server-side image generation solution in this SO question.

This is a kind of problem which I encountered while capturing images in Mac OS.
I have solved this issue by using
static {
System.setProperty("java.awt.headless", "false");
}
See for reference : Headless environment error in java.awt.Robot class with MAC OS

Answer by Shreyas Dave didn't work for me anymore. Though I don't know why, here is what I did:
public static void main(String[] args) {
// to avoid
// [JRSAppKitAWT markAppIsDaemon]: Process manager already initialized: can't fully enable headless mode.
System.setProperty("javafx.macosx.embedded", "true");
java.awt.Toolkit.getDefaultToolkit();
// end
launch(args);
}
This was also pointed out here: JavaFX screencapture headless exception on OSX

If you have the source code of the JavaFX application you could also try to use TestFX run the application in a headless mode, to control it and to make screenshots. To run your TestFX application in headless mode you have to start it with the following JVM parameters (to enable Monocle):
-Dtestfx.robot=glass -Dglass.platform=Monocle -Dmonocle.platform=Headless -Dprism.order=sw
Moreover you might need to install Monocle first. See Headless testing with JavaFx and TestFx for more information.

I have an application that can be used interactively (displaying JavaFx dialogs) but also must be able to run non-interactive on a server without display.
Even though no GUI element is used in non-interactive mode, we got
Caused by: java.lang.UnsupportedOperationException: Unable to open DISPLAY
at com.sun.glass.ui.gtk.GtkApplication.<init>(GtkApplication.java:68)
This happens as soon as a class derived from javafx.application.Application is instantiated, which you normally do with your main class.
Here is the way I solved the problem:
I created an additional class GuiAppExecution:
import java.util.List;
import javafx.application.Application;
import javafx.stage.Stage;
/**
* JavaFx launch class for {#link AppExecution}.
*/
public class GuiAppExecution extends Application {
#Override
public void start(Stage stage) throws Exception {
List<String> parameters = getParameters().getRaw();
AppExecution appExecution = new AppExecution();
appExecution.launch(parameters);
}
/**
* Launches the {#link AppExecution} as JavaFx {#link Application}.
*
* #param parameters program parameters
*/
public void launchGui(String[] parameters) {
launch(parameters);
}
}
In the main class AppExecution I created a method
public void launch(List<String> parameters) {
which parses the parameters and launches the application for both interactive and non-interactive execution.
The main method looks like this:
public static void main(String[] parameters) {
List<String> parameterList = Arrays.asList(parameters);
if (parameterList.stream().anyMatch(p -> p.equalsIgnoreCase(BATCH_PARAMETER))) {
AppExecution appExecution = new AppExecution();
appExecution.launch(parameterList);
}
else {
GuiAppExecution guiAppExecution = new GuiAppExecution();
guiAppExecution.launchGui(parameters);
}
}
with
private static final String BATCH_PARAMETER = "-batch";
as the program option that request the non-interactive execution.
Since GuiAppExecution (which is derived from javafx.application.Application) is not instantiated for non-interactive execution, the JavaFx environment is not started.

Related

WinSvc and Its Console version to Test

I have a ConsoleApp but I think to move it into a WinSvc application base. And I consider to move the soruce code as a library project and use it in both the old Console to TEST for other possible developments purpose and in the WinSvc for the real WORK area. Thus, when I add something new to the base library It will cause to appear in both apps. And It will be able to make my tests in the ConsoleApp environment and there will only need to rebuild for WinSvc part for real environment (It is to avoid to use the attached debug mode).
So, What can you say about this model? Or Is this a good approach? Or do you have any other suggestion?
This can be a solution:
public static void Main(string[] args)
{
MyWinSvcClass mySvc = new MyWinSvcClass();
if (Environment.UserInteractive)
{
// If the executable is started on console
mySvc.RunAsConsole(args);
}
else
{
// If the executable is started as a service
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { mySvc };
ServiceBase.Run(ServicesToRun);
}
}
Define RunAsConsole() In your service class:
public void RunAsConsole(string[] args)
{
Log("Service is started on console:");
OnStart(args);
Log("Service session is ended.");
OnStop();
}

How to reduce slow start for picocli apps due to reflection

Picocli has to introspect the command tree. Doing so it needs to load the domain object classes for every Command which slows down the jvm startup.
What options are there to avoid this startup lag? One solution I've come up with is described in https://github.com/remkop/picocli/issues/482:
I am using reflection to postpone any class loading until after the command is selected. This way only the command classes themselves are loaded and finally the classes which implement the single command requested by the user:
abstract class BaseCommand implements Runnable {
interface CommandExecutor {
Object doExecute() throws Exception;
}
// find the CommandExecutor declared at the BaseCommand subclass.
protected Object executeReflectively() throws Exception {
Class<?> innerClass = getExecutorInnerClass();
Constructor<?> ctor = innerClass.getDeclaredConstructor(getClass());
CommandExecutor exec = (CommandExecutor) ctor.newInstance(this);
return exec.doExecute();
}
private Class<?> getExecutorInnerClass() throws ClassNotFoundException {
return getClass().getClassLoader().loadClass(getClass().getName() + "$Executor");
}
public void run() {
try {
executeReflectively();
} catch(...){
/// usual stuff
}
}
}
A concrete commend class:
#Command(...)
final class CopyProfile extends BaseCommand {
#Option String source;
#Option String dest;
// class must NOT be static and must be called "Executor"
public class Executor implements CommandExecutor {
#Override
public Object doExecute() throws Exception {
// you can basically wrap your original run() with this boilerplate
// all the CopyProfile's field are in scope!
FileUtils.copy(source, dest);
}
}
}
It seems like https://github.com/remkop/picocli/issues/500 may provide the ultimate solution to this. What are the other options until then?
UPDATE February 2020:
Upgrading to a recent version of picocli should fix this issue.
From the picocli 4.2.0 release notes:
From this release, subcommands are not instantiated until they are matched on the command line. This should improve the startup time for applications with subcommands that do a lot of initialization when they are instantiated.
An alternative that doesn’t require any code changes is to use GraalVM to compile your picocli-based application to a native image.
This article shows how to do this and the resulting startup time is 3 milliseconds.

javafx programmatically set arguments for virtual keyboard

I have a desktop application that will be used on computers with no keyboard, input will be on a touch screen. I can get the virtual keyboard to show up on textfields fine when running from eclipse. I used these arguments
-Dcom.sun.javafx.touch=true
-Dcom.sun.javafx.isEmbedded=true
-Dcom.sun.javafx.virtualKeyboard=none
The following link shows me where to add the arguments.
how to add command line parameters when running java code in Eclipse?
When I make a runnable jar file the keyboard does not show up. I am looking for a way to set these arguments programmatically so that the runnable jar file will display the virtual keyboard on any computer. Any help will be greatly appreciated.
The only working solution I could find came from here
Gradle build for javafx application: Virtual Keyboard is not working due to missing System property
Create a wrapper class and set the system properties before invoking the applications original main method.
public class MainWrapper {
public static void main(String[] args) throws Exception
{ // application - package name
Class<?> app = Class.forName("application.Main");
Method main = app.getDeclaredMethod("main", String[].class);
System.setProperty("com.sun.javafx.isEmbedded", "true");
System.setProperty("com.sun.javafx.touch", "true");
System.setProperty("com.sun.javafx.virtualKeyboard", "javafx");
Object[] arguments = new Object[]{args};
main.invoke(null, arguments);
}
}
When making the runnable jar file just point to the MainWrapper class for the launch configuration.
The -D option to the JVM sets a system property. So you can achieve the same by doing the following:
public class MyApplication extends Application {
#Override
public void init() {
System.setProperty("com.sun.javafx.touch", "true");
System.setProperty("com.sun.javafx.isEmbedded", "true");
System.setProperty("com.sun.javafx.virtualKeyboard", "none");
}
#Override
public void start(Stage primaryStage) {
// ...
}
}

what is the equivalence of contextDestroyed() in ServletContainerInitializer?

I have to create a class that implements ServletContextListener to add an event during the initialization or the shutdown of Tomcat. However, the class has to be located in a jar file inside WEB-INF/lib. After doing some readings, I found out that this is not possible, and the alternative is to use ServletContainerInitializer. However, only onStartup() method is available.
Is there any other alternatives where I can also add an event during the shutdown or destruction of the web application?
I am using Tomcat 8 and Java 8 btw.
Let your ServletContainerInitializer programmatically add a ServletContextListener which in turn does the desired job in its contextDestroyed().
servletContext.addListener(YourServletContextListener.class);
Not sure how you tested your code. But this the ServletContextListener works fine for me on Tomcat 8.5.5. Just try this code, no need to put this to separate JAR file.
#WebListener
public class AppContextListener implements ServletContextListener{
Logger log = LoggerFactory.getLogger(AppContextListener.class);
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
log.info("### Context is destroyed ###");
}
}

Jersey app-run initialization code on startup to initialize application

I have an app built with Jersey.I need to do some initialization on startup of the webapp/war in the Tomcat 7 container by running an application specific login/code.
What is the best way to do this with Jersey ? I have used ContextListener with contextInitialized()before in a Servlet environment. I need to make sure the Jersey resources are loaded before I make this call.
Not sure what you mean by "Jersey resources are loaded before", but if you want to really plug in into Jersey init process.. Jersey has several "monitoring" plugin points (not widely advertised or documented) and what I'm going to describe is being called after initialization of AbstractResourceModel - so right after app startup.
Try this:
#Provider
public class Listener implements AbstractResourceModelListener {
#Override
public void onLoaded(AbstractResourceModelContext modelContext) {
System.out.println("##### resource model initiated");
}
}
It should happen only once per app lifecycle, I'm not very sure about reloading, but you don't need to bother by it if you are not using that feature (anyway, you should put some check there to avoid multiple invocation if could cause some issues).
For Jersey 2.x you can do the following:
#Provider
private static class MyFeature implements Feature {
#Override
public boolean configure(FeatureContext context) {
//code goes here
return true;
}
}

Resources