portlet间通信无法转换为ActionResponse

时间:2016-01-13 17:26:12

标签: ajax jsf primefaces liferay

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

我尝试了基于事件的解决方案,效果很好。在我的view.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位于同一页面上时,以下方法才有效: 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>

Portlet 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>

这就是全部。

1 个答案:

答案 0 :(得分:1)

你是对的 - JSR-286-portlet间通信只涉及动作(和事件)阶段,既不在渲染也不在资源阶段。该规范刚刚出现有点太早,无法想象这一点。

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

相关主题(但对手头的具体情况不太有帮助)可能是Liferay的SPA(单页应用程序),您不再需要完整页面重新加载 - 而是门户网站进程并传输portlet的delta状态,同时仍然构建经典portlet。