Portlet 间通信不能强制转换为操作响应



我正在使用JSF Primefaces 5.3在Liferay 6.2上开发一个Web应用程序。网络应用程序在Tomcat上运行。我在同一页面上有 Portlet 1 和 Portlet 2。我想在用户与 Portlet 2 中的控件交互后,设置属于 Portlet 1 的某个后端对象的状态。

我尝试了一个基于事件的解决方案,效果很好。在我看来.xhtml我有这样的东西:

<p:selectOneMenu value="#{operationBox.selected}"
            valueChangeListener="#{broker.operationChanged}" onchange="submit()"
            style="width:50%">
            <f:selectItems value="#{operationBox.operations}" />
        </p:selectOneMenu>

代理类 (Portlet 2) 处理操作,在 ActionResponse 对象中设置定制事件,侦听器 (Portlet 1) 接收该事件。

但是,我

不想提交表单,因为这会导致页面刷新,而我不需要。我不打算在 Portlet 1 中渲染任何内容。我的经纪人类看起来就像Liferay教程和演示应用程序中提供的示例:

    public void submit() {
    logger.debug("Submitting booking changes.");
    QName qName = new QName("http://liferay.com/events", "ipc.customerEdited");
    ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
    ActionResponse actionResponse = (ActionResponse) externalContext.getResponse();
    actionResponse.setEvent(qName, bookingsModelBean.getCustomer());
}

我不知道是 ajax 还是 selectOneMenu 标签(或两者兼而有之)让我失望:如果我执行以下操作 <f:ajax event="change" listener="#{broker.handle}"/>我的代理 Bean 得到的响应对象是 ResourceResponse ,我不能将其转换为 ActionResponse 以调用setEvent(QName qname, String string)

selectOneMenu有没有办法触发对值更改的操作?操作是否仅与提交/页面重新加载相关联?

我需要一种方法将数据从 Portlet 2 发送到 Portlet 1 的服务器端。您认为我的最佳选择是什么?

多谢

使用最终解决方案进行编辑

事实证明,这不能通过当前规范的服务器端事件处理来完成。我最终设法用客户端javascript做到了这一点。仅当所涉及的 Portlet 位于同一页面上时,以下方法才有效:组件 1 - 火灾事件:

<p:selectOneMenu value="#{operationBox.selected}"
                onchange="return myFireEvent('operation',this.value);>

<script>
    function myFireEvent(caller, value) {
        var payload = ...; // process your parameters
        Liferay.fire('my-event-name', {
            payload: payload
        });
        return false;
    };
</script>

组件 2 - 接收事件:我用来将数据发送到服务器端的解决方法是通过<p:remoteCommand>标签调用自定义 js 函数,您必须将其放置在<h:form>

<p:remoteCommand name="handleEvent" actionListener="#{icpReceiver.handleEventJS}"/>

这是由Liferay API提供的js接收器函数调用的:

<script>
    Liferay.on('my-event-name', function(event) {
        handleEvent([{name:'payload', value:event.payload}]);
    });
</script>

仅此而已。

你是对的 - JSR-286-portlet-communication 只涵盖动作(和事件)阶段,在渲染和资源阶段都不可用。规范出来得有点太早了,无法想象这一点。

您仍然可以执行基于 ajax 的 IPC,但您必须自己执行此操作 - 通常在前端,例如通过一个页面上的 Portlet 之间的 Javascript 通信。它不会是JSR-286-IPC。

一个相关的主题(但对于手头的具体情况不太有帮助)可能是Liferay的SPA(单页应用程序),其中您不再需要重新加载整页 - 而是门户处理和传输Portlet的增量状态,而您仍在构建经典Portlet。