Почему Liferay Faces не обрабатывает события действия портлета JSF?

У меня возникли проблемы с попыткой использовать Liferay Faces вместе с любыми компонентами JSF для запуска событий действия.

Я успешно прошел первую часть страницы с инструкциями по разработке портлетов JSF Liferay вплоть до (но не включая) раздела "Интернационализация портлетов JSF". Я продолжил и добавил некоторые другие компоненты JSF с некоторым успехом, однако, события не работают.

Цель этого примера - создать текстовое поле, в котором пользователь может изменить текст по умолчанию "World", а текстовая область будет обновляться с помощью AJAX при каждом нажатии клавиши с помощью "Hello, XXX" (где XXX - текст из поля). Да, в отдельном проекте JSF я опробовал view.xhtml и TestBean.java, и это работает.

На портале Liferay появляется портлет, и когда я набираю текст, я получаю обратную передачу на сервер. Результатом DebugPhaseListener является только BEFORE/AFTER RESTORE_VIEW 1 и BEFORE/AFTER RENDER_RESPONSE 6. Между ними нет этапов, которые, как я предполагаю, указывают на проблему. (Примечание. Мост портлета Liferay Faces связывает события жизненного цикла портлета и эмулирует жизненный цикл JSF.)

Я использую Liferay 6.2, работаю в Eclipse Luna с последним пакетом Liferay Tomcat и последним плагином eclipse с сайта обновлений Liferay. Java 1.7.0_71.

Вот все активы и код, которые, я думаю, имеют отношение к выяснению того, что происходит. Любая помощь, которую вы можете оказать, будет принята с благодарностью.

View.xhtml:

<?xml version="1.0"?>

<f:view
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui"
>
    <h:head />
    <h:body>
        <h:form id="someForm">
            <p:calendar id="myCal" mode="inline" value="#{testBean.myDate}" actionListener="#{testBean.updateDate}">
                <p:ajax actionListener="#{testBean.updateDate}" update="myMsgs"/>
            </p:calendar>
            <br/>
            <p:commandButton value="Hi there" actionListener="#{testBean.updateDate}" update="myMsgs"/>
            <br/>
            <p:messages id="myMsgs"/>
            <br/>
            Test String=#{testBean.testString}
            <br/>
            Output Text test string = <h:outputText value="#{testBean.testString}"/>


            <h:outputLabel value="Name" for="nameInput" />
            <h:inputText id="nameInput" value="#{testBean.name}">
                <f:ajax render="output" event="keyup" />
            </h:inputText>
            <br/>

            <p>
                <h:panelGroup id="output">
                    <strong> <h:outputText value="Hello, #{testBean.name}" />
                    </strong>
                </h:panelGroup>
            </p>

            <h:commandButton id="reset" value="Reset"
                actionListener="#{testBean.reset}">
                <f:ajax render="@form" />
            </h:commandButton> - Reset The Form to "World"
            <br/>

            <h:messages />

        </h:form>
    </h:body>
</f:view>

TestBean.java

import java.io.Serializable;
import java.util.Date;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ActionEvent;


@ManagedBean(name="testBean")
@SessionScoped
public class TestBean
    implements Serializable
{
    private static final long serialVersionUID = 1L;

    public String getTestString()
    {
        return "Test String";
    }

    private Date myDate = new Date();
    public Date getMyDate() { return myDate; }
    public void setMyDate(Date value) { System.out.println("setMyDate value="+value); myDate = value; }

    public void updateDate()
    {
        System.out.println("updateDate - myDate="+myDate);
    }

    /**
     * Stores the name which will be used to greet the application user.
     */
    private String name;

    /**
     * Initializes {@link #name} with the value {@code "World"}.
     */
    @PostConstruct
    public void postContruct()
    {
        this.name = "World";
    }

    /**
     * Returns {@link #name}.
     *
     * @return {@link #name}
     */
    public String getName()
    {
        return name;
    }

    /**
     * Set {@link #name}.
     *
     * @param value
     */
    public void setName(String value)
    {
        System.out.println("Setting name to " + value);
        name = value;
    }

    /**
     * Resets {@link #name} to the default value {@code "World"}.
     *
     * @param ae
     * ignored
     */
    public void reset(ActionEvent ae)
    {
        setName("World");
    }
}

portlet.xml

<?xml version="1.0"?>

<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0">

    <portlet>
        <portlet-name>my-calendar-portlet</portlet-name>
        <display-name>My Calendar Portlet</display-name>
        <portlet-class>
            javax.portlet.faces.GenericFacesPortlet
        </portlet-class>
        <init-param>
            <name>javax.portlet.faces.defaultViewId.view</name>
            <value>/views/my-calendar-portlet/view.xhtml</value>
        </init-param>
        <init-param>
            <name>javax.portlet.faces.defaultViewId.edit</name>
            <value>/views/my-calendar-portlet/edit.xhtml</value>
        </init-param>
        <expiration-cache>0</expiration-cache>
        <supports>
            <mime-type>text/html</mime-type>
            <portlet-mode>view</portlet-mode>
            <portlet-mode>edit</portlet-mode>
        </supports>
        <portlet-info>
            <title>My Calendar Portlet</title>
            <short-title>My Calendar Portlet</short-title>
            <keywords></keywords>
        </portlet-info>
        <security-role-ref>
            <role-name>administrator</role-name>
        </security-role-ref>
        <security-role-ref>
            <role-name>guest</role-name>
        </security-role-ref>
        <security-role-ref>
            <role-name>power-user</role-name>
        </security-role-ref>
        <security-role-ref>
            <role-name>user</role-name>
        </security-role-ref>
    </portlet>
</portlet-app>

Liferay-portlet.xml

<?xml version="1.0"?>
<!DOCTYPE liferay-portlet-app PUBLIC "-//Liferay//DTD Portlet Application 6.2.0//EN" "http://www.liferay.com/dtd/liferay-portlet-app_6_2_0.dtd">

<liferay-portlet-app>

    <portlet>
        <portlet-name>my-calendar-portlet</portlet-name>
        <icon>/icon.png</icon>
        <header-portlet-css>/css/main.css</header-portlet-css>
        <footer-portlet-javascript>
            /js/main.js
        </footer-portlet-javascript>
        <css-class-wrapper>
            my-calendar-portlet-portlet
        </css-class-wrapper>
    </portlet>
    <role-mapper>
        <role-name>administrator</role-name>
        <role-link>Administrator</role-link>
    </role-mapper>
    <role-mapper>
        <role-name>guest</role-name>
        <role-link>Guest</role-link>
    </role-mapper>
    <role-mapper>
        <role-name>power-user</role-name>
        <role-link>Power User</role-link>
    </role-mapper>
    <role-mapper>
        <role-name>user</role-name>
        <role-link>User</role-link>
    </role-mapper>
</liferay-portlet-app>

Отладка вывода с каждой нажатой клавиши:

22:18:22,328 DEBUG [DebugPhaseListener:64] BEFORE phaseId=[RESTORE_VIEW 1] viewId=[null]
22:18:22,328 DEBUG [DebugPhaseListener:48] AFTER phaseId=[RESTORE_VIEW 1] viewId=[/views/my-calendar-portlet/view.xhtml]
22:18:22,328 DEBUG [DebugPhaseListener:64] BEFORE phaseId=[RENDER_RESPONSE 6] viewId=[/views/my-calendar-portlet/view.xhtml]
22:18:22,338 DEBUG [DebugPhaseListener:48] AFTER phaseId=[RENDER_RESPONSE 6] viewId=[/views/my-calendar-portlet/view.xhtml]

1 ответ

Решение

Пожалуйста, добавьте следующее к <portlet> раздел вашего WEB-INF/liferay-portlet.xml:

<requires-namespaced-parameters>false</requires-namespaced-parameters>

Убедитесь, что вы следуете DTD и включаете элементы в правильном порядке: https://docs.liferay.com/ce/portal/7.0-latest/definitions/liferay-portlet-app_7_0_0.dtd.html.

Например, ваш liferay-portlet.xml<portlet> раздел должен выглядеть так:

<portlet>
    <portlet-name>my-calendar-portlet</portlet-name>
    <icon>/icon.png</icon>
    <requires-namespaced-parameters>false</requires-namespaced-parameters>
    <ajaxable>false</ajaxable>
    <header-portlet-css>/css/main.css</header-portlet-css>
    <footer-portlet-javascript>
        /js/main.js
    </footer-portlet-javascript>
    <css-class-wrapper>
        my-calendar-portlet-portlet
    </css-class-wrapper>
</portlet>
Другие вопросы по тегам