You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 10 Next »

What's this for?

This article is for people who wants to implement web socket support function into their Joget application.

Plugin Info

The following is the code for the plugin. 

There are 4 key methods that you are required to pay attention to:

public void onOpen(Session session)
public void onMessage(String message, Session session) 
public void onClose(Session session) 
public void onError(Session session, Throwable throwable)


package org.joget;

import java.io.IOException;
import java.util.Map;

import javax.websocket.Session;

import org.joget.apps.app.service.AppPluginUtil;
import org.joget.apps.app.service.AppUtil;
import org.joget.apps.form.lib.Radio;
import org.joget.apps.form.model.FormBuilderPalette;
import org.joget.apps.form.model.FormData;
import org.joget.apps.form.model.FormRow;
import org.joget.apps.form.model.FormRowSet;
import org.joget.apps.form.service.FormUtil;
import org.joget.commons.util.LogUtil;
import org.joget.plugin.base.PluginWebSocket;
import org.joget.workflow.model.service.WorkflowUserManager;

public class WebSocketPlugin extends Radio implements PluginWebSocket {

    private final static String MESSAGE_PATH = "message/form/WebSocketPlugin";

    @Override
    public String getName() {
        return "WebSocketPlugin";
    }

    @Override
    public String getVersion() {
        return "5.0.0";
    }

    @Override
    public String getClassName() {
        return getClass().getName();
    }

    @Override
    public String getLabel() {
        //support i18n
        return AppPluginUtil.getMessage("org.joget.WebSocketPlugin.pluginLabel", getClassName(), MESSAGE_PATH);
    }

    @Override
    public String getDescription() {
        //support i18n
        return AppPluginUtil.getMessage("org.joget.WebSocketPlugin.pluginDesc", getClassName(), MESSAGE_PATH);
    }

    @Override
    public String getPropertyOptions() {
        return AppUtil.readPluginResource(getClass().getName(), "/properties/form/" + getName() + ".json", null, true, MESSAGE_PATH);

    }

    @Override
    public FormRowSet formatData(FormData formData) {

        FormRowSet rowSet = null;

        // get value
        String id = getPropertyString(FormUtil.PROPERTY_ID);
        if (id != null) {
            String value = FormUtil.getElementPropertyValue(this, formData);
            if (value != null) {
                // set value into Properties and FormRowSet object
                FormRow result = new FormRow();
                result.setProperty(id, value);
                rowSet = new FormRowSet();
                rowSet.add(result);
            }
        }
        return rowSet;
    }

    @Override
    public String renderTemplate(FormData formData, Map dataModel) {
        String template = "webSocketPlugin.ftl";

        WorkflowUserManager wum = (WorkflowUserManager) AppUtil.getApplicationContext().getBean("workflowUserManager");
        String username = wum.getCurrentUsername();
        dataModel.put("username", username);

        String html = FormUtil.generateElementHtml(this, formData, template, dataModel);
        return html;
    }

    @Override
    public String getFormBuilderTemplate() {
        return "<label class='label'>" + getLabel() + "</label>";
    }

    @Override
    public String getFormBuilderCategory() {
        return FormBuilderPalette.CATEGORY_CUSTOM;
    }

    @Override
    public void onOpen(Session session) {
        try {
            session.getBasicRemote().sendText("Connection established");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onMessage(String message, Session session) {
        try {
            session.getBasicRemote().sendText("Server received: " + message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onClose(Session session) {
        LogUtil.info(getClassName(), "Webscoket connection closed");
    }
    
    @Override
    public void onError(Session session, Throwable throwable) {
        LogUtil.error(getClassName(), throwable, "");
    }

    public boolean isEnabled() {
        if ("true".equalsIgnoreCase(getPropertyString("enableWebsocket"))) {
            return true;
        } else {
            return false;
        }
    }

}


A FTL file is required, you may copy the following code as a starting template.

<div class="form-cell" ${elementMetaData!}>
    <label class="label">
        ${element.properties.label} <span class="form-cell-validator">${decoration}</span>
        <#if error??>
            <span class="form-error-message">${error}</span>
        </#if>
    </label>
    <#if (element.properties.enableWebsocket! == 'true')>
        <input id="isEnabled" name="isEnabled" type="hidden" />
    </#if>

    <#if (element.properties.readonly! == 'true' && element.properties.readonlyLabel! == 'true') >
        <div class="form-cell-value"><span>${value!?html}</span></div>
        <input id="${elementParamName!}" name="${elementParamName!}" type="hidden" value="${value!?html}" />
    <#else>    
        <input type="text" id="messageInput" placeholder="Enter message">
        <button id="sendButton">Send</button>
        <button id="closeButton">Close</button><br>
        <div id='output'></div>
    </#if>

    <script>
    $(document).ready(function() {
        $("#sendButton").off("click");
        $("#closeButton").off("click");

        if ($("#isEnabled").length > 0) {

            const ws = new WebSocket(((window.location.protocol === "https:") ? "wss://" : "ws://") + window.location.host + "${request.contextPath}/web/socket/plugin/org.joget.WebSocketPlugin");

            ws.onopen = function(event) {
                console.log(event);
                $("#output").append('Connection opened with timeStamp: ' + event.timeStamp + '<br/>');
   
                $("#sendButton").on("click", function(){
                    const message = $("#messageInput").val();

                    //send message to endpoint
                    ws.send(message);  
                    $("#output").append("${username} send " + message + '<br/>'); 
                    $("#messageInput").val("");
                    return false;
                });

                $("#closeButton").on("click", function(){
                    if (ws.readyState === WebSocket.OPEN) {
                        //close the endpoint connection
                        ws.close();
                    }
                    $("#sendButton").hide();
                    $("#closeButton").hide();
                    return false;       
                });
            }; 

            ws.onmessage = function(event) {
                $("#output").append(event.data + '<br/>');
            }; 

            ws.onclose = function(event) {
                $("#output").append('Connection closed with timeStamp: ' + event.timeStamp + '<br/>');
                $("#output").append('WebSocket closed<br/>');
            }; 

            ws.onError = function(event) {
                $("#output").append("Error: " + event.data + '<br/>');
            };  
        
        } else {
            $("#output").html('WebSocket is not enable.<br>');
        }
    });
    </script>
    <div style="clear:both;"></div>
</div>

Sample 

This sample plugin code is available at https://github.com/jogetoss/sample-web-socket-plugin. JogetOSS is a community-led team for open source software related to the Joget no-code/low-code application platform. Projects under JogetOSS are community-driven and community-supported, and you are welcome to contribute to the projects.

  • No labels