Search code examples
jsfwebsocketprimefacesomnifaces

How can I piggyback request arguments from a web socket message without manually constructing array?


I've got an application scoped bean pushing json objects to a channel like this:

        <o:socket channel="controllerEventChannel" onmessage="function(message) {

                var controllerId = message.controllerId;
                var deviceId = message.deviceId;
                var companyKey = message.companyKey;

                onMessage([
                    { name: 'controllerId', value: controllerId },
                    { name: 'deviceId', value: deviceId },
                    { name: 'companyKey', value: companyKey }
                    ]);
        }"
        />

<p:remoteCommand name="onMessage" actionListener="#{controllerGroupDashboardBean.refreshListener()}"
                         update="MainForm:showList MainForm:equipmentView MainForm:mapEquipmentView"/>

But I'm tired of repeating myself and would much rather pass a json array to the channel which could be passed directly to the remote command like this:

        <o:socket channel="controllerEventChannel" onmessage="function(message) {
                onMessage(message);
        }"
        />

<p:remoteCommand name="onMessage" actionListener="#{controllerGroupDashboardBean.refreshListener()}"
                         update="MainForm:showList MainForm:equipmentView MainForm:mapEquipmentView"/>

However, this does not seem to work. I extract the parameters like this:

Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
        
String companyKey = params.get("companyKey");
String controllerId = params.get("controllerId");
String deviceId = params.get("deviceId");

Every parameter resolves to null and, weirdly, the map seems to contain the parameter "undefined" mapped to "" (i.e. blank string).

Anyone?


Solution

  • I'm using OmniFaces commandScript for that, without any problems.

    Edit:

    To get request parameters, use OmniFaces for neater code:

    String myParam = Faces.getRequestParameter("myJsonField", String.class);
    

    Edit2:

    <!-- When browser receive notification, this commandScript will be called -->
        <h:form id="myCommandScriptForm">
            <o:commandScript name="onNotification" actionListener="#{myBean.onNotification}" render="@none" />
        </h:form>
    

    And in socket something like this:

    <o:socket channel="my-channel" onmessage="function(notificationEvent) {onNotification(notificationEvent);}" />
    

    In MyBean something like:

    Long entityId = Faces.getRequestParameter("entityId", Long.class);
    

    If you wanna be fancy you can update from MyBean (notice i have render="@none" in XHTML, this is because i can conditionaly determine what to update in bean):

    public void onNotification() {
        if (myList.contains(myEntity)) {
            PrimeFaces.current().ajax().update(":myWrapperJsfElement");
        }
    }
    

    OP ADDENDUM: o:commandScript was removed from OmniFaces after it was added in JSF 2.3.