среда, 15 мая 2013 г.

Liferay вложенные портлеты 3

Последние грабли с runtime портлетов внутри портлета, с которыми я столкнулся, это runtime под Liferay 6.1.1 GA2. Бьёт ошибку: PortalUtil.renderPortlet throws exception "javax.servlet.ServletException: File "/html/common/themes/portlet.jsp" not found". Подробности http://issues.liferay.com/browse/LPS-31508

Если же отключить обрамление и дефолтный шаблон для включаемого портлета, как в принципе и требовалось мне, то runtime отрабатывает. Итого, для моего кастомного портлета, в portlet.xml:
    <portlet>
        <portlet-name>MultimediaToolbar</portlet-name>
        <display-name>MultimediaToolbar</display-name>
        <portlet-class>com.vaadin.terminal.gwt.server.ApplicationPortlet2</portlet-class>
        <init-param>
            <name>application</name>
            <value>ru.snetwork.liferay.multimedia.portlet.back.ToolbarApplication</value>
        </init-param>
        <init-param>
            <name>view-jsp</name>
            <value>/view.jsp</value>
        </init-param>
        <expiration-cache>0</expiration-cache>
        <supports>
            <mime-type>text/html</mime-type>
            <portlet-mode>view</portlet-mode>
        </supports>
        <resource-bundle>ru.snetwork.liferay.multimedia.ToolbarPortlet</resource-bundle>
        <portlet-info>
            <title>MultimediaToolbar</title>
            <short-title>MultimediaToolbar</short-title>
        </portlet-info>
        <portlet-preferences>
            <preference>
                <name>portlet-setup-show-borders</name>
                <value>false</value>
            </preference>
        </portlet-preferences>
    </portlet>
В liferay-portlet.xml:
    <portlet>
        <portlet-name>MultimediaToolbar</portlet-name>
        <use-default-template>false</use-default-template>
        <instanceable>true</instanceable>
        <ajaxable>false</ajaxable>
        <header-portlet-css>/css/backoffice-multimedia.css</header-portlet-css>
        <add-default-resource>true</add-default-resource>
    </portlet>
Кроме того, чтобы не било ошибку "Reject ServeResource" на ресурсы портлеты (картинки, css, js - портлет Vaadin-овский), добавил через Hook в portal.properties:
portlet.add.default.resource.check.whitelist=58,86,87,88,103,113,145,MultimediaToolbar_WAR_SnCommonPortlets

Liferay вложенные портлеты 2

Способ вызова портлета внутри портлета предложенный в первом посте не работает в Liferay 5.2.3, который идет в бандле с Tomcat 6. Использовать PortletBagPool для получения портального ServletContext бесполезно, т.к. в версии 5.2.3 PortletBagPool не содержить встроенные портлеты.

Получить портальный ServletContext можно получить из аттрибутов ServletRequest - оказывается он передается с ключом WebKeys.CTX. Кроме того PortalUtil в API 5.2.3 немного отличается:
    public static String renderPortlet(final PortletRequest request, final PortletResponse response, final String portletId, final String queryString) {
        String result = "Error occured while running portlet";
        try {
            // Get servlet request / response
            HttpServletRequest servletRequest = PortalUtil.getHttpServletRequest(request);
            HttpServletResponse servletResponse = PortalUtil.getHttpServletResponse(response);
            HttpServletRequest portalServletRequest = PortalUtil.getOriginalServletRequest(servletRequest);

            // Get theme display
            final ThemeDisplay themeDisplay = (ThemeDisplay) servletRequest.getAttribute(WebKeys.THEME_DISPLAY);
            // Backup current state
            PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
            PortletDisplay portletDisplayClone = new PortletDisplay();
            portletDisplay.copyTo(portletDisplayClone);
            final Map requestAttributeBackup = new HashMap();
            for (final String key : Collections.list((Enumeration) servletRequest.getAttributeNames())) {
                requestAttributeBackup.put(key, servletRequest.getAttribute(key));
            }
            // Render the portlet as a runtime portlet
            try {
                StringBuilder sb = new StringBuilder();
                com.liferay.portal.model.Portlet portlet = PortletLocalServiceUtil.getPortletById(PortalUtil.getCompanyId(request), portletId);
                servletRequest.setAttribute(WebKeys.RENDER_PORTLET_RESOURCE, Boolean.TRUE);
                ServletContext ctx = (ServletContext) portalServletRequest.getAttribute(WebKeys.CTX);
                PortalUtil.renderPortlet(sb, ctx, servletRequest, servletResponse, portlet, queryString);
                result = sb.toString();
            } finally {
                // Restore the state
                portletDisplay.copyFrom(portletDisplayClone);
                portletDisplayClone.recycle();
                for (final String key : Collections.list((Enumeration) servletRequest.getAttributeNames())) {
                    if (!requestAttributeBackup.containsKey(key)) {
                        servletRequest.removeAttribute(key);
                    }
                }
                for (final Map.Entry entry : requestAttributeBackup.entrySet()) {
                    servletRequest.setAttribute(entry.getKey(), entry.getValue());
                }
            }
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
        }
        return result;

    }