[SOLVED] Is it possible to use a single jar file to start as an applet and as an application?

The public knowledge pool and discussion forum of the OWS community. Do not post confidential information here!
pkeusem
Posts: 4
Joined: 08 Feb 2021, 22:53

[SOLVED] Is it possible to use a single jar file to start as an applet and as an application?

Post by pkeusem »

Hello,

Our Java client application is currently implemented to run as a Java Applet. This works fine when run on the Java plugin from IE or started with Oracle's Java Web Start but we are trying to add support for using OpenWebStart.

I understand that OpenWebStart does not support running Applets but from what I have read, it should be possible to use the same class in the same jar file both as an Applet and as an application with separate JNLP files. I have a simple HelloWorld class that extends Applet but also has a main method. The class is bundled into a jar file and configured as the Main-Class for the jar. I have an HTML file I can use to run the app via the <applet> tag and I have two HTML files with matching JNLP files (one with <applet-descr> and one with <application-descr>). I can run the app as an Applet with appletviewer (or from a web page) using the HTML file and I can run it as an application with "java -jar" so that much appears to be working. However, when I try to run the app with the JNLP files (either from the command line or from a web server) it always runs as an applet. This is OK when using Oracle's Java Web Start but the app crashes immediately after painting the app frame.

Here's the JNLP file for running as an Applet:
----

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" codebase="http://point:8080/hello" href="HelloWorldGuiApplet.jnlp">
    <information>
        <title>HelloWorldGuiApplet</title>
	<offline-allowed/>
    </information>
    <resources>
        <j2se version="1.8+"/>
        <jar href="lib/HelloWorldGuiApplet.jar" main="true"/>
    </resources>
    <applet-desc name="HelloWorldGuiApplet" main-class="HelloWorldGuiApplet" width="1024" height="768">
	<argument>Hello world!!!!</argument>
    </applet-desc>
    <security>
        <all-permissions/>
    </security>
</jnlp>
----

and here's the JNLP file for running as an application:
----

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" codebase="http://point:8080/hello" href="HelloWorldGuiApplet.jnlp">
    <information>
        <title>HelloWorldGuiApplet</title>
	<offline-allowed/>
    </information>
    <resources>
        <j2se version="1.8+"/>
        <jar href="lib/HelloWorldGuiApplet.jar" main="true"/>
    </resources>
    <applet-desc name="HelloWorldGuiApplet" main-class="HelloWorldGuiApplet" width="1024" height="768">
	<argument>Hello world!!!!</argument>
    </applet-desc>
    <security>
        <all-permissions/>
    </security>
</jnlp>
----

Any tips or pointers appreciated.

Andreas Ehret
Posts: 81
Joined: 25 Mar 2020, 12:21

Re: Is it possible to use a single jar file to start as an applet and as an application?

Post by Andreas Ehret »

In your second file that you describe as running as an application it looks like you also using the applet-descr tag instead of the application-descr tag

Janak Mulani
Posts: 726
Joined: 24 Mar 2020, 13:37

Re: Is it possible to use a single jar file to start as an applet and as an application?

Post by Janak Mulani »

Hi

In the JNLP file for running as an application you still have:

Code: Select all

 <applet-desc name="HelloWorldGuiApplet" main-class="HelloWorldGuiApplet" width="1024" height="768">
	<argument>Hello world!!!!</argument>
    </applet-desc>
Is this a copy+paste error? Changing it to application-desc should work.

Btw, what does your main class HelloWorldGuiApplet look like?

pkeusem
Posts: 4
Joined: 08 Feb 2021, 22:53

Re: Is it possible to use a single jar file to start as an applet and as an application?

Post by pkeusem »

Yep, copy paste error. Or more likely copy, paste, paste.

Here's the second JNLP file:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" codebase="http://point:8080/hello" href="HelloWorldGuiApplet.jnlp">
    <information>
        <title>HelloWorldGuiApplet-main</title>
	<offline-allowed/>
    </information>
    <resources>
        <j2se version="1.8+"/>
        <jar href="lib/HelloWorldGuiApplet.jar" main="true"/>
    </resources>
    <application-desc name="HelloWorldGuiApplet-main" main-class="HelloWorldGuiApplet" width="1024" height="768">
	<argument>Hello world!!!!</argument>
    </application-desc>
    <security>
        <all-permissions/>
    </security>
</jnlp>
And here's the Java code:

Code: Select all

/*
 * HelloWorldGuiApplet
 *
 * http://math.hws.edu/javanotes/c6/s1.html
 */

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.security.AccessControlException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class HelloWorldGuiApplet extends Applet {

    private static String Greeting = "Hello World!";


    private void printStack() {
        Exception stkEx = new Exception();

        stkEx.printStackTrace(System.out);
    }

    private void printStack(String msg) {
        Exception stkEx = new Exception(msg);

        stkEx.printStackTrace(System.out);
    }


    public HelloWorldGuiApplet(String[] args) {
        super();
        logMsg("In HWGA constructor...");
        printStack();
        init(args);
        logMsg("In HWGA constructor...done.");
    }


    public HelloWorldGuiApplet() {
        this(null);
    }


    public static class HelloWorldDisplay extends JPanel {
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawString(Greeting, 20, 30);
        }
    }
   
    public static class ButtonHandler implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            System.exit(0);
        }
    }

    protected static void init(String[] args) {
        logMsg("HWGA.init(), initializing...");
        logSysInfo();

        if (args != null && args.length > 0) {
            logMsg("HWGA.init(), setting Greeting...");
            StringBuffer greeting = new StringBuffer(args[0]);
            for (int i = 1; i < args.length; i++) {
                greeting.append(" " + args[i]);
            }

            Greeting = greeting.toString();
            logMsg("HWGA.init(), setting Greeting...done.");
        }

        logMsg("HWGA.init(), Greeting: \"" + Greeting + "\"");

        HelloWorldDisplay displayPanel = new HelloWorldDisplay();
        JButton okButton = new JButton("OK");
        ButtonHandler listener = new ButtonHandler();
        okButton.addActionListener(listener);

        JPanel content = new JPanel();
        content.setLayout(new BorderLayout());
        content.add(displayPanel, BorderLayout.CENTER);
        content.add(okButton, BorderLayout.SOUTH);

        JFrame window = new JFrame("GUI Test");
        window.setContentPane(content);
        window.setSize(250,100);
        window.setLocation(100,100);
        window.setVisible(true);
        logMsg("HWGA.init(), initializing...done.");
    }

    protected static String getSystemProperty(String propName) {
        try {
            return System.getProperty(propName);
        } catch(AccessControlException e) {
            return e.getMessage();
        }
    }

    protected static void logMsg(String msg) {
        logMsg(msg);
    }

    protected static void logSysInfo() {
        logMsg("Java Version = " + getSystemProperty("java.version"));
        logMsg("Java VM version = " + getSystemProperty("java.vm.version"));
        logMsg("Java VM name = " + getSystemProperty("java.vm.name"));
        logMsg("Java Vendor = " + getSystemProperty("java.vendor"));
        logMsg("Java VM vendor = " + getSystemProperty("java.vm.vendor"));
        logMsg("Java home = " + getSystemProperty("java.home"));
        logMsg("Java native library path = " + getSystemProperty("java.library.path"));
        logMsg("Java classpath = " + getSystemProperty("java.class.path"));
        //logMsg("Java command line flags = " + getCommandLineFlags());
        logMsg("Java temp dir = " + getSystemProperty("java.io.tmpdir"));
        logMsg("Java Architecture = " + getSystemProperty("os.arch"));
        logMsg("Java Data Model = " + getSystemProperty("sun.arch.data.model"));
        logMsg("Operating system = " + getSystemProperty("os.name"));
        logMsg("File Encoding = " + getSystemProperty("file.encoding"));
        //logMsg("Started at = " + LazyDate.formatDate(m_serverStartTime));
        logMsg("User Dir = " + getSystemProperty("user.dir"));
        logMsg("User Home = " + getSystemProperty("user.home"));
        logMsg("User Name = " + getSystemProperty("user.name"));
        logMsg("Time Zone = " + getSystemProperty("user.timezone"));
    }


    public static void main(String[] args) {

        logMsg("HWGA.main(), In main()...");
        logMsg("HWGA.main(), Args:");

        for (int i = 0; i < args.length; i++) {
            logMsg("  args[" + i + "]: \"" + args[i] + "\"");
        }
        
        init(args);

        logMsg("HWGA.main(), In main()...done.");
    }
   
}
Thanks!

Andreas Ehret
Posts: 81
Joined: 25 Mar 2020, 12:21

Re: Is it possible to use a single jar file to start as an applet and as an application?

Post by Andreas Ehret »

I don't see any issue in doing this, having a jar file with a regular Java application main that you run with OWS. As long as you run it with a JNLP and application-desc. OWS does not support Applets but it does not care if there is code in it that is not used.

pkeusem
Posts: 4
Joined: 08 Feb 2021, 22:53

Re: Is it possible to use a single jar file to start as an applet and as an application?

Post by pkeusem »

The problem is regardless of which HTML/JNLP I use, it always runs as an Applet. Here a the log messages from two attempted runs. The first is from HelloWorldGuiApplet-jnlp.html / HelloWorldGuiApplet.jnlp which attempts to run the HelloWorldGuiApplet class as an applet using the <applet-desc> tag:

Code: Select all

In HWGA constructor...
HWGA.init(), initializing...
HWGA.init(), Greeting: "Hello World!"
HWGA.init(), initializing...done.
In HWGA constructor...done.
The second is from HelloWorldGuiApplet-main-jnlp.html / HelloWorldGuiApplet-main.jnlp which attempts to run the HelloWorldGuiApplet class as an application using the <application-desc> tag:

Code: Select all

In HWGA constructor...
HWGA.init(), initializing...
HWGA.init(), Greeting: "Hello World!"
HWGA.init(), initializing...done.
In HWGA constructor...done.
In both cases, the application starts, gets a far as painting an empy frame and then crashes. I am logging a stack trace from inside the constructor to see what is going on and in both cases, the HelloWorldGuiApplet constructor is invoked from net.sourceforge.jnlp.Launcher.createApplet(). I've attached the full logs below.
Attachments
2021-02-11_07_23_36.661-ows-stage1.log
(53.69 KiB) Downloaded 235 times
2021-02-11_07_23_56.924-ows-stage1.log
(50.05 KiB) Downloaded 243 times

Janak Mulani
Posts: 726
Joined: 24 Mar 2020, 13:37

Re: Is it possible to use a single jar file to start as an applet and as an application?

Post by Janak Mulani »

Hi,

Are you using the same Java class that you have attached in a post above?

This class leads to StackOverflow as the logMsg method is called recursively.

I had a look at your class. In my opinion you need to clean up its code.

Here is my implementation of the class that will run both in applet mode as well as jnlp mode:

Code: Select all

import javax.swing.*;
import java.applet.Applet;
import java.awt.*;

public class HelloWorldGuiApplet extends Applet  {

    private static int count = 0;
    @Override
    public void init() {
        super.init();
        createUI(this);
    }

    private static void createUI(Container panel) {
        panel.setLayout(new BorderLayout());
        final JTextField textField = new JTextField("Hello World", 20);
        panel.add(textField, BorderLayout.NORTH);
        final JButton button = new JButton("PrintHello");
        button.addActionListener(e -> textField.setText("Hello World! : " + ++count));
        panel.add(button, BorderLayout.CENTER);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("HelloWorldGui");
        JPanel panel = new JPanel();
        createUI(panel);
        frame.getContentPane().add(panel);
        frame.setSize(300, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

pkeusem
Posts: 4
Joined: 08 Feb 2021, 22:53

Re: Is it possible to use a single jar file to start as an applet and as an application?

Post by pkeusem »

Yeah I noticed the logMsg earlier.

It's not the Java code that's the problem though, it's the JNLP files. I went over everything again and I noticed that when I copied the applet JNLP file to create the application JNLP file, I forgot to update the href in the JNLP tag, so the application JNLP file was not referring to itself but to the applet JNLP file. Fixing that resolved the problem.

Thanks!

Post Reply