Loading...
Important Notice - Forums is archived

To simplify things and help our users to be more productive, we have archived the current forum and focus our efforts on helping developers on Stack Overflow. You can post new questions on Stack Overflow or join our Discord channel.

Product icon
TUTORIAL

Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.

Adding Applet as a Vaadin Component

Jesus Martinez
1 decade ago May 25, 2010 6:55pm
Sami Ekblad
1 decade ago Jun 07, 2010 5:12pm

Hi,

I took a look at this and you are absolutely right. The embedded (as per 6.3.3) does not support applets like that at all.
We need a ticket for this...

Anyway, I would have suggested using the AppletIntegration add-on, but I noticed it had some problems too. I fixed these and made the version 1.0.3 of the add-on available. Get it here:

http://vaadin.com/directory#addon/87

You use this by subclassing the AppletIntegration like this:

package com.example.applettest;

import java.util.Arrays;

import org.vaadin.applet.AppletIntegration;

public class MyApplet extends AppletIntegration {

    private static final long serialVersionUID = -4871198728412311481L;

    public MyApplet() {
        // Actual applet loaned from here: http://www.w3.org/People/mimasa/test/object/java/Othello
        setAppletArchives(Arrays.asList(new String[] { "Othello.jar" }));
        setCodebase("http://www.w3.org/People/mimasa/test/object/java/applets/");
        setAppletClass("Othello.class");
        setWidth("800px");
        setHeight("500px");
    }
}

Or, if you prefer less class files, here is how to make that inline:

AppletIntegration applet = new AppletIntegration() {

            private static final long serialVersionUID = 1L;

            @Override
            public void attach() {
                // Actual applet loaned from here:
                // http://www.w3.org/People/mimasa/test/object/java/Othello
                setAppletArchives(Arrays.asList(new String[] { "Othello.jar" }));
                setCodebase("http://www.w3.org/People/mimasa/test/object/java/applets/");
                setAppletClass("Othello.class");
                setWidth("800px");
                setHeight("500px");

            }
        };
        mainWindow.addComponent(applet);
Jesus Martinez
1 decade ago Jun 08, 2010 1:03am

Great, thanks for responding. I actually found another way to solve this issue.

I got your applet-integration.jar and modified the VAppletIntegration.java file. More specifically I modified the getHTML() method since the width and height were hardcoded to be '0'. I modified so user can set them as attributes.

Here is the VAppletIntegration.java I am currently using. You will notice now how I added communication attributes for the height and the width. You will also note I added some extra parameters (e.g. window = opaque, mayscript) since i am noticing some problems with the z-order of embedded components (let that be applet, flash).

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.ui.HTML;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.ValueMap;

/**
 * Client side applet integration widget which communicates with the server.
 *
 *
 * @author Sami Ekblad
 *
 */
public class VAppletIntegration extends HTML implements Paintable {

    protected static final String PARAM_APP_SESSION = "appSession";
    protected static final String PARAM_APP_URL = "appUrl";
    protected static final String PARAM_APP_DEBUG = "appDebug";
    protected static final String PARAM_PAINTABLE_ID = "paintableId";
    protected static final String PARAM_APPLET_ID = "appletId";

    /** Client-server communication attributes. */
    public static final String ATTR_APPLET_SESSION = "appletSession";
    public static final String ATTR_APPLET_CLASS = "appletClass";
    public static final String ATTR_APPLET_ARCHIVES = "appletArchives";
    public static final String ATTR_APPLET_PARAM_NAMES = "appletParamNames";
    public static final String ATTR_APPLET_PARAM_VALUES = "appletParamValues";
    
    public static final String ATTR_APPLET_WIDTH = "appletWidth";
    public static final String ATTR_APPLET_HEIGHT = "appletHeight";
    
    public static final String ATTR_CMD = "cmd";
    public static final String ATTR_CMD_PARAMS = "cmdParams";

    /** Set the CSS class name to allow styling. */
    public static final String CLASSNAME = "v-applet";

    /** The client side widget identifier */
    protected String paintableId;

    /** Reference to the server connection object. */
    protected ApplicationConnection client;

    /** Generated applet id. Unique across the application. */
    private String appletId;

    /** Has the applet been initialized. Applet is initialized only once. */
    private boolean appletInitialized;
    private String appletClass;
    private String[] archives = new String[] {};
    private Map<String, String> appletParameters;
    private String appletSession;
    private int width;
    private int height;
    
    /**
     * The constructor should first call super() to initialize the component and
     * then handle any initialization relevant to Vaadin.
     */
    public VAppletIntegration() {

        // The content will be changed in update function
        setHTML("");

        // Temporary applet id. Should not be needed.
        appletId = CLASSNAME;

        // This method call of the Paintable interface sets the component
        // style name in DOM tree
        setStyleName(CLASSNAME);

    }

    /**
     * Called whenever an update is received from the server
     */
    public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
        // This call should be made first.
        // It handles sizes, captions, tooltips, etc. automatically.
        if (client.updateComponent(this, uidl, true)) {
            // If client.updateComponent returns true there has been no changes
            // and we do not need to update anything.
            return;
        }

        // Save reference to server connection object to be able to send
        // user interaction later
        this.client = client;

        // Save the client side identifier (paintable id) for the widget
        paintableId = uidl.getId();

        appletId = CLASSNAME + paintableId;

        // Create the Java applet using HTML
        if (!appletInitialized) {

            // Applet class
            if (!uidl.hasAttribute(ATTR_APPLET_CLASS)) {
                ApplicationConnection.getConsole().log(
                        "Missing attribute " + ATTR_APPLET_CLASS);
                return;
            }
            appletClass = uidl.getStringAttribute(ATTR_APPLET_CLASS);
            
            width = uidl.getIntAttribute(ATTR_APPLET_WIDTH);
            height = uidl.getIntAttribute(ATTR_APPLET_HEIGHT);
            
            // Applet session
            if (!uidl.hasAttribute(ATTR_APPLET_SESSION)) {
                ApplicationConnection.getConsole().log(
                        "Missing attribute " + ATTR_APPLET_SESSION);
                return;
            }
            appletSession = uidl.getStringAttribute(ATTR_APPLET_SESSION);

            // Applet archives
            if (!uidl.hasAttribute(ATTR_APPLET_ARCHIVES)) {
                ApplicationConnection.getConsole().log(
                        "Missing attribute " + ATTR_APPLET_ARCHIVES);
                return;
            }
            archives = uidl.getStringArrayAttribute(ATTR_APPLET_ARCHIVES);

            // Applet appletParameters
            appletParameters = getDefaultIntegrationParameters();
            if (uidl.hasAttribute(ATTR_APPLET_PARAM_NAMES)) {
                ValueMap map = uidl.getMapAttribute(ATTR_APPLET_PARAM_NAMES);
                Set<String> keys = map.getKeySet();
                for (String key : keys) {
                    appletParameters.put(key, map.getString(key));
                }
            }

            // Create the HTML
            setHTML(getAppletHTML());
            appletInitialized = true;
        }

        // Execute the command
        String cmd = null;
        String[] cmdParams = null;
        if (uidl.hasAttribute(ATTR_CMD)) {
            cmd = uidl.getStringAttribute(ATTR_CMD);
        }
        if (uidl.hasAttribute(ATTR_CMD_PARAMS)) {
            cmdParams = uidl.getStringArrayAttribute(ATTR_CMD_PARAMS);
        }
        if (cmd != null) {
            execute(cmd, cmdParams);
        }

    }

    /**
     * Execute a command in applet using AbstractVaadinApplet.execute method.
     * Note that this requires that the applet has a method called "execute"
     *
     * @param cmd
     * @param cmdParams
     */
    public void execute(String cmd, String[] cmdParams) {
        ApplicationConnection.getConsole().log(
                "Applet command: " + getAppletId() + ",'" + cmd + "','"
                        + cmdParams + "'");
        if (cmdParams != null && cmdParams.length > 0) {
            internalAppletExecute(getAppletId(), cmd, cmdParams);
        } else {
            internalAppletExecute(getAppletId(), cmd);
        }
    }

    /**
     * This is the internal method that invokes the execute method in applet.
     * Note that this requires that the applet has a method called "execute"
     *
     * @param id
     * @param cmd
     */
    private native void internalAppletExecute(String id, String cmd)
    /*-{
       if ($doc.applets[id]) {
            $doc.applets[id].execute(cmd);
        }
    }-*/;

    /**
     * This is the internal method that invokes the execute method in applet.
     * Note that this requires that the applet has a method called "execute"
     * with string parameters.
     *
     * @param id
     * @param cmd
     * @param cmdParams
     */
    private native void internalAppletExecute(String id, String cmd,
            String[] cmdParams)
    /*-{
       if ($doc.applets[id]) {
            $doc.applets[id].execute(cmd,cmdParams);
        }
    }-*/;

    /**
     * Get paintable id of this widget.
     *
     * @return
     */
    protected String getPaintableId() {
        return paintableId;
    }

    /**
     * Get applet HTML needed to initalize applet.
     *
     * Note: the default implementation does not return anything.
     *
     * @return String containing the APPLET tag needed to initialize the Java
     *         applet.
     */
    protected String getAppletHTML() {

        // Compose dependency JAR files
        List<String> archives = getArchives();
        String archiveAttribute = "";
        if (archives != null) {
            boolean first = true;
            for (String a : archives) {
                if (!first) {
                    archiveAttribute += ",";
                } else {
                    first = false;
                }
                archiveAttribute += a;
            }
        }

        // Compose applet appletParameters
        Map<String, String> appletParams = getAppletParameters();
        String appletParamStr = "";
        if (appletParams != null) {
            for (String name : appletParams.keySet()) {
                appletParamStr += "<param name=\"" + name + "\" value=\""
                        + appletParams.get(name) + "\" />";
            }
        }
        appletParamStr += "<param name=\"" + "wmode" + "\" value=\""
        + "opaque" + "\" />";

        String myscript = "<param name=\"mayscript\" value=\"yes\">";
		String scriptable = "<param name=\"scriptable\" value=\"true\">";
		
        return "<applet mayscript=\"true\" code=\"" + "" + getAppletClass()
                + "" + "\" codebase=\"" + GWT.getModuleBaseURL()
                + "\" width=\"" + width + "\" height=\"" + height + "\" id=\"" + getAppletId()
                + "\" name=\"" + getAppletId() + "\" archive=\""
                + archiveAttribute + "\">" + appletParamStr +  myscript + scriptable + "</applet>";
    }

    /**
     * Get appletParameters for the applet as a Map.
     *
     * @return
     */
    protected Map<String, String> getAppletParameters() {
        return appletParameters;
    }

    /**
     * Get id for this applet.
     *
     * @return
     */
    protected String getAppletId() {
        return appletId;
    }

    /**
     * Get list of archives needed to run the applet.
     *
     * @return
     */
    protected List<String> getArchives() {
        ArrayList<String> res = new ArrayList<String>();
        for (int i = 0; i < archives.length; i++) {
            res.add(archives[i]);
        }
        return res;
    }

    /**
     * Get name of the applet class.
     *
     * @return
     */
    protected String getAppletClass() {
        return appletClass;
    }

    /**
     * Get default appletParameters for the applet.
     *
     * @return
     */
    private Map<String, String> getDefaultIntegrationParameters() {
        Map<String, String> res = new HashMap<String, String>();

        // Add default appletParameters
        res.put(PARAM_APPLET_ID, "" + getAppletId());
        res.put(PARAM_PAINTABLE_ID, "" + getPaintableId());

        String sessionId = appletSession;
        if (sessionId == null) {
            sessionId = Cookies.getCookie("JSESSIONID");
        }
        res.put(PARAM_APP_SESSION, "JSESSIONID=" + sessionId);
        res.put(PARAM_APP_DEBUG, ApplicationConnection.isDebugMode() ? "true"
                : "false");
        res.put(PARAM_APP_URL, GWT.getHostPageBaseURL() + client.getAppUri());

        return res;
    }

}

Now all you have to do is set the attributes yourself, like in the code below, and you will notice the applet embedded within your application.
I believe your appletintegration.jar was doing things right, except for the little detail of height/width being harcoded to '0', which obviously made the applet not appear in the application.

target.addAttribute(VAppletIntegration.ATTR_APPLET_WIDTH,800);
        target.addAttribute(VAppletIntegration.ATTR_APPLET_HEIGHT, 600);
Last updated on Jun, 8th 2010
Sami Ekblad
1 decade ago Jun 08, 2010 6:27am

Looks good and you are right. That is the way it was designed: to provide custom applet at the client-side.

I think that it would be good to have this possible using the server side API too and the size was just. Thats why I added the codebase and width and height.

Your addition to height and width are identical to version 1.0.3, but the mayscript is attribute instead of parameter. Is it required as param by some browsers? A generic way of adding params would be nice.

Jesus Martinez
1 decade ago Jun 08, 2010 4:04pm
Sami Ekblad
1 decade ago Oct 21, 2010 11:03am
Lam Le
1 decade ago Mar 21, 2011 1:22pm
murali pallapu
10 years ago Nov 25, 2012 2:18am