简体   繁体   中英

How do I run a gui Java application headless, without control of the source code?

I want to execute a Jar file using javax swing GUI with 1 radial option, a file selector and a button. The goal is to be able to automate the jar through CLI and select the radial option, file and then click the button.

I do not have access to edit the source of the jar

Is this possible?

You can look up JAuto , which is aJVMTI agent that is capable of expose UI widget attributes such as class names, screen coordinates. You talk to JAuto by sending a command to a named pipe. It responds by writing a file. A communication scheme like this works in bash scripts .

With the help of xdotool as an input simulator, you can achieve automation under the Linux X11 environment, inside a docker container.

Although depending on the complexity of the Java app, automating it in a headless manner can also be time-consuming. You may also need a VNC setup to inspect program behavior. Checkout this project IBGA and see how it uses JAuto and xdotool to automate a program.

Disclaimer: I'm the author of both JAuto and IBGA.

What you can accomplish with a jar through command-line arguments is limited to the command-line features that are already provided as part of the application bundled in the jar. Presumably this would be documented somewhere. The rest of this answer will assume that the target application does not provide the functionality you want, namely to select an option, set a file, and click a button.

One possibility to get around this limitation is to write your own small command-line interface as a wrapper for the application.

For example, let's say the target application looks like this:

public class SomeApp { 
    /* public only to simplify the answer. Can always be
     * accessed through reflection if private. */
    public JRadioButton button1 = new JRadioButton("One");
    public JRadioButton button2 = new JRadioButton("Two");
    public JFileChooser fileChooser = new JFileChooser();
    public JButton okButton = new JButton("Ok");

    public SomeApp() {
        JFrame frame = new JFrame();
        /* Build the rest of the frame */
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(SomeApp::new);
    }
}

Then you could write your own wrapper class as follows, put it on the classpath, and execute this instead, passing it the command-line arguments that will control the behavior as desired:

public class Cli {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(()-> {
            SomeApp app = new SomeApp();
            // Fine-tune based on the content of args
            app.button2.setSelected(true);
            app.fileChooser.setSelectedFile(new File("temp.txt"));
            app.okButton.doClick();
        } );
    }
}

Notes: This does not require modifying the source code of the original application, but the exact details of how to accomplish this will depend on the design of the application in the jar. Most likely, the fields of interest might be private. Or, the widgets of interest might not even be stored in fields. There are ways around this, but they would require more work (eg, getting the components through the component graph). But that is somewhat a different topic. Secondly, this does not really constitute running the application "headless", since that usually means, without the GUI. However, the question only makes sense if the GUI is up, since the idea is to programmatically manipulate the GUI.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM