如何通过 jee-7 中的 mdb-> websocket 更新数据 table 单元格? (db pk, client Id 映射)

Howto update a data table cell via mdb-> websocket in jee-7? (db pk, clientId mapping)

我有一个带有分页的 jsf-2.2 primefaces 数据table。一列显示网络组件的状态,在 table 加载时,我通过资源适配器异步查询外部服务。当加载数据 table 时,状态单元格显示为 "Status unknown"。有时,我会在消息驱动 Bean 中收到来自单个网络组件的状态数据包,如 json。然后我想通过 websocket 将此状态发送到浏览器以更新 table 单元格。 json 状态数据包包含网络组件的主要数据库密钥,但在浏览器的 javascript 端,我需要数据 table 单元格的 clientIds。 clientIds 的格式为 "switchTable:swths:2:switchActive",仅中间的索引不同。

我的第一个想法是写一个 facelet 并用网络组件的主键覆盖 id,但我认为这不是可行的方法。

是否有推荐的方法将 clientIds 映射到各个主键?此映射需要包括会话,因为有多个会话具有相同的 clientId。我想更新 table 单元格,我在 DOM 中找到的 document.getElementById 立即带有状态文本。

我想出了这个有趣问题的 2 个解决方案。

解决方案 1

  • 定义隐藏的 table 列,其中包含 'ID' 文本,
  • 通过遍历所有行并匹配 ID 列单元格的 'value',使用 javascript 查找数据 table 行和单元格

解决方案 2

  • 利用 JSF2 命名空间 xmlns:pt="http://xmlns.jcp.org/jsf/passthrough" 到 'programatically' 设置 html id 列单元格元素的属性,
  • 使用 javascript 的 document.getElementById 函数查找单元格元素

例子

xhtml 页数

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui" 
    xmlns:pt="http://xmlns.jcp.org/jsf/passthrough" >

    <f:view contentType="text/html">
        <h:head>
            <h:outputScript library="primefaces" name="jquery/jquery.js" />
        </h:head>

        <h:body>
            <p:dataTable id="dataTable" widgetVar="dataTableWidget" value="#{switchController.switches}" var="switch" paginator="true" rows="5">
                <p:column headerText="id" style="display:none">
                    <h:outputText value="#{switch.id}"/>
                </p:column>
                <p:column headerText="Name">
                    <h:outputText value="#{switch.name}"/>
                </p:column>
                <p:column headerText="status">
                    <h:outputText value="#{switch.status}" pt:id="dataTable:switch:#{switch.id}:status"/>
                </p:column>
            </p:dataTable>

            <p:commandButton value="Change status" type="button" onclick="changeStatusExample()"/>
        </h:body>
    </f:view>
</html>

Backing Bean(仅用于此示例)

public class SwitchController {

    List<Switch> switches;

    @PostConstruct
    public void init() {
        switches = new ArrayList<>();
        for (int i = 1; i < 11; i++) {
            switches.add(new Switch(i, "Switch " + i, "STATUS_UNKNOWN"));
        }
    }

    public List<Switch> getSwitches() {
        return switches;
    }

    public void setSwitches(List<Switch> switches) {
        this.switches = switches;
    }
}

其中 Switch 是具有 idnamestatus 字段的 POJO。

Javascript

// SOLUTION 1
function getTableCellByIdVer1(switchId, colNumber) {
    //get table rows
    var tableRows = PF('dataTableWidget').tbody[0].childNodes;
    //loop through rows    
    for (i = 0; i < tableRows.length; i++) {
        //get cells of current row
        var cells = tableRows[i].cells;
        //get value of hidden ID column cell
        var id = cells[0].innerText;
        if (id === switchId) {
            return tableRows[i].cells[colNumber];
        }
    }
    return null;
}

// SOLUTION 1
function changeSwitchStatusVer1(changedSwitch) {
    var statusCell = getTableCellByIdVer1(changedSwitch.id, 2);
    if (statusCell) {
        //row exists...now we can change the status
        statusCell.innerText = changedSwitch.status;
    } else {
        console.log('Row with switch id=' + changedSwitch.id + ' not found');
    }
}

// SOLUTION 2
function changeSwitchStatusVer2(changedSwitch) {
    //find cell element by html ID attribute given in xhtml
    var elementId='dataTable:switch:' + changedSwitch.id + ':status';
    var statusCell = document.getElementById(elementId);
    if (statusCell) {
        statusCell.innerText = changedSwitch.status;
    } else {
        console.log('Element with id=' + elementId + ' not found');
    }
}

// EXAMPLE
function changeStatusExample() {
    //simulating situation when websocket pushes info about changed switch to browser page
    // SOLUTION 1
    var changedSwitch = {id: '2', status: 'STATUS_ON'};
    changeSwitchStatusVer1(changedSwitch);

    // SOLUTION 2
    //another switch status changed..using another approach to update table cell
    changedSwitch = {id: '4', status: 'STATUS_OFF'};
    changeSwitchStatusVer2(changedSwitch);
}

重要:请注意,只有当(更改的开关)ID 是当前 'visible' 数据 table 页面的一部分时,这两种解决方案才有效。