четверг, 28 июня 2012 г.

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

У меня есть Vaadin портлет с интерфейсом управления контентом (кнопки вызывающие различные окна редактирования и т.д.) и мне необходимо его подключить к front-end портлету отображения контента.

Как вложить портлет в портлет? В стандартном лайфреевском портлете "Nested portlets"  используется RuntimePortletUtil.processTemplate. В этом же сервисе есть методы вызова портлета processPortlet. На сайте liferay.com статьи описывающий способ программного вызова этих методов - нет.

Метод тыка результата не приносил.

Просмотрел исходники имплементации RuntimePortletImpl - используется PortalUtil.renderPortlet. По запросу гугл выдал исчерпывающий рабочий пример:
http://www.devatwork.nl/2011/07/liferay-embedding-portlets-in-your-portlet/

Единственное не понял зачем при рендере любого портлета выполняется получение PortletBag соответствующее портлету JOURNAL. После экспериментов выяснил, что  для PortalUtil.renderPortlet первым параметром надо передать портальный ServletContext, иначе будет выдаваться "File "/html/portal/render_portlet.jsp" not found"

Но насколько я понимаю servletContext портала из любого портлета можно получить из PortalUtil.getOriginalServletContext(...).getServletContext(). Мой код практически не отличается от приведенного Bert Willems


    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 {
                com.liferay.portal.model.Portlet portlet = PortletLocalServiceUtil.getPortletById(PortalUtil.getCompanyId(request), portletId);
                servletRequest.setAttribute(WebKeys.RENDER_PORTLET_RESOURCE, Boolean.TRUE);
                result = PortalUtil.renderPortlet(portalServletRequest.getServletContext(), servletRequest, servletResponse, portlet, queryString, false);
            } 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;
    }