WebAppRunner – Run your web applications standalone

Last week I wrote a blog post about how Java objects can be passed to JavaScript code running in the SWT Browser control. I mentioned that I was working on an Eclipse RCP app that could run web apps as standalone apps in the SWT browser control.

That application is now ready. If you want to give it a try, download it from following links. The application is about 21 MB in size.

JRE is not packaged in the above application. You will have to download and install it, if you don’t have it already.

I have also created a sample app to show how a web page can call Java APIs. The application uses JDK File APIs to get list of files. Download FileListApp from here. Below is a screen shot of this application –

So what exactly can WebAppRunner do for you –

  • It provides a container to run web applications as standalone desktop apps. It does not bundle any web browser, but uses IE browser on Windows and Safari on Mac.
  • But is is not just a container for web apps. It lets you call Java APIs from JavaScript running in those apps. When you run web application in a standalone browser, your application cannot have access to local resources such as files. By letting you use Java APIs from JavaScript, WebAppRunner extend capabilities of HTML/JS application by letting it call Java APIs.

WebAppRunner can run application from a folder, or from a file packaged as ZIP. It looks for index.html in the root of the folder and opens it in the SWT browser control. So make sure that you have index.html in the root of the folder or zip file. The application can provide a few configuration information in manifest.mf. This file also has to be in the root of application folder/zip. Currently following configuration properties are supported –

Manifest-Version – This is required.
Application-Name – Its value appears in the title bar.
Window-Width – Width of application window.
Window-Height – Height of application window.
Show-Menubar – true/false. Specify if menus (and hence menu bar) of WebAppRunner be displayed when the application is opened.
Classpath – comma separated list of path of jar files that needs to be loaded. This is useful if you want to access custom Java Class from JavaScript

Note that manifest.mf is optional. Also WebAppRunner loads all jar files in the application root. So you need not specify classpath in the manifest if all your jar files are in the application root. Here is how manifest.mf of FileListApp looks like –

Manifest-Version: 1.0
Application-Name: File Browser App
Window-Width: 600
Window-Height: 400

Where can you use WebAppRunner:

The primary use case is to create desktop standalone applications, even if they don’t need web interface. It is easy to create powerful UI with HTML,JS and CSS. The main application logic can be in a jar packaged with your app. Or you can build complete standalone HTML5 application using local DB storage feature that uses SQLite/IndexDB.

You can also use it as a wapper for you existing browser based web apps, which can be enhanced by allowing access to local resources e.g. allowing (of course, trusted) web application to search files on your local disk.

JavaScript APIs to use Java Objects:

Following APIs are available for JavaScript code running in WebAppRunner –

  • createJava: For creating a new Java object.
    • Signature : createJava (className, constructor_args …, variableName)
    • Arguments :
      • The first argument is Class name. It should be fully qualified name e.g. java.lang.String
      • It is followed by arguments to the constructor
      • The last argument is name of the variable in which you want to save the instance of this Java class
    • Returns : Name of the variable (sent as the last argument) , if Object is created successfully, else returns null.
    • Example :
      var ret = createJava(“java.io.File”, path, “fileObj”);
      if (!ret) {
      alert(“Error creating file object”);
      }
  • executeJava: For calling method on a Java object
    • Signature : executeJava (objVariableName, methodName, methodArgs…,returnVariableName)
    • Arguments:
      • The first argument is variable name, returned by createJava function described above.
      • The second argument is method name
      • It is followed by arguments to the method
      • The last argument is return variable name. Evan if method does not return anything (void), you have to pass the last argument. It could be null for void methods.
    • Returns:Only basic data types e.g. String, numbers (int, float, double etc.) and boolean. Any other Java object is stored in a variable passed as the last argument. Note that if the Java method returns one of the basic data types, then executeJava returns the same and no return variable is created even if you specify valid variable name in the last argument.
    • Example :
      var fileList = executeJava(“fileObj”, “listFiles”, “fileList”); //calls listFiles method on fileObj, which is of type java.io.File, and is created using createJava method.
  • getJavaProperty: For accessing object properties/fields
    • Signature : getJavaProperty(objVarName, fieldName, returnVarName)
    • Arguments:
      • The first argument is variable name, returned by createJava function described above.
      • Second argument is the field name
      • Third argument is return variable name. It is required, but can be null. See description of executeJava for more details.
    • Returns : Value of the field/property in the given Java object. See return value description of executeJava above for more information.
    • Example:
      var len = getJavaProperty(“fileList”, “length”, null);
  • getJavaArrayAt: For getting array element from Java array
    • Signature : getJavaArrayAt(arrayVarName, index, returnVarName)
    • Arguments:
      • First argument is variable name of array
      • Second argument is index number
      • Third argument is return variable name. It is required, but can be null.See description of executeJava above for more details.
    • Returns: Object at given index in the array. See return value description of executeJava above for more information.
    • Example :
      getJavaArrayAt(“fileList”, i, “fileAtIndex”) ;// fileList points to Java array
  • executeStaticJava : For calling static methods.
    • Signature : executeJava (className, methodName, methodArgs…,returnVariableName)
    • Arguments:
      • The first argument is the fully qualified class name
      • The second argument is method name
      • It is followed by arguments to the method
      • The last argument is return variable name. Evan if method does not return anything (void), you have to pass the last argument. It could be null for void methods.
    • Returns:Only basic data types e.g. String, numbers (int, float, double etc.) and boolean. Any other Java object is stored in a variable passed as the last argument. Note that if the Java method returns one of the basic data types, then executeJava returns the same and no return variable is created even if you specify valid variable name in the last argument.
    • Example :
      var fileList = executeJava(“java.lang.System”, “getProperties”, “sysProperties”); //calls getProperties method on class
      //java.lang.System and saves result in sysProperties variable
  • setJavaProperty : For seting value if a object property/field
    • Signature : setJavaProperty (varName, fieldName, value)
    • Arguments:
      • The first argument is variable name, returned by createJava function described above.
      • Second argument is the field name
      • Third argument is value to be set
    • Example:
      var len = getSavaProperty(“empObj”, “name”, “Ram”);
  • getApplicationPath: For getting path of the curently opened application with”Open File” or “Open Folder” method. This is useful when application is packaged as a zip and opened with WebAppRunner. Applications in Zip files are unzipped in a temporary folder before executing them. One of the usecase for getApplicationPath is that application is packaged as a zip file and you want to save application specific preferences in a property file in the same folder as the zip. With this API, you can get path of the folder where application zip file exists.
    • Signature : getApplicationPath()
    • Returns : String contining full path of the folder that contains application/zip file
    • Example:
      var appPath – getApplicationPath();
  • exitWebAppRunner: For closing WebAppRunner. Does not ask for the confirmation.
    • Example:
      exitWebAppRunner();

If you want to pass already created Java object instance as an argument to any of the above functions then you need to prefix variable name with $, for example empVO (employee Value Object) points to an instance of a Java class and you want to pass that as an argument to addEmployee function, then you can pass it as –

executeJava("empMgr", "addEmployee", "$empVO", null);

Checkout FileAPIs.js in the FileListApp and emp.js in SQLiteApp to see how above APIs can be used in a HTML/JS application.

Executing applications using WebAppRunner:

You can pass folder path or zip file path as argument to WebAppRunner. You can also use ‘Open File’ and ‘Open Folder’ options under File menu if you want to load application when WebAppRunner is already opened.

-Ram Kulkarni

21 Replies to “WebAppRunner – Run your web applications standalone”

  1. Hi!
    I am trying to start WebAppRunner.app with an argument to start my html file with terminal on macosx! How has the argument to look like to start the html file?

  2. Hi There.

    This looks great. I have one question How would launch a specific folder in WebappRunner using the command line or command prompt?

          1. Hi Ram,

            that works great on windows but how about mac I can’t get get it to open using the mac equivelant open -a WebAppRunner.app “path to app” do have any ideas for that?

  3. Hello,
    nice application 😉

    It seems you are using Jetty as the web server. So I assume this can run WAR files and Servlets. But your explanation in this page seems to be assuming that the app is a simple HTML+JS app.

    Is it possible to deploy a WAR file? If yes, how? Then ti would also need to force waiting the load of the index.html until the WAR is deployed.

    Thanks.
    _sm

    1. Yes I used Jetty web server. I used it only as web server and not servlet container. In the present form, you cannot deploy war in this application. I did not see any need to support war deployment.

  4. Hello Ram,

    I was looking for such long time to get something like this. Thx man. Good work.. (really)

    But i try to figuring out how to really hide the toolbar.
    I have the following config.

    Manifest-Version: 1.0
    Application-Name: Proof 1.0
    Window-Width: 600
    Window-Height: 400
    Show-Menubar: false

    I understand from your text that the last rule in config does hide the Menubar like “File” and “Help”.

    Or does it do not ?

    Sincerely

    Ray

Leave a Reply