This document discusses using a portlet API-based approach for integrating applications into Magnolia. It describes the portlet API concept of separate action and render phases. Implementing portlets as JSR-168 components allows seamless integration into Magnolia by adding a portlet filter and rendering portlets during page generation. Configuration is done through content types and portlet parameters can be accessed. Real-world use has shown this approach works well for small applications but has limitations for more complex integrations.
3. 3
Application Integration
Application integration is a generic problem
§ Not CMS specific
§ Depending on specific application issues
In general huge range of options
§ Link, IFrame, “merged” content, integrated menu
§ Adapting the application may be possible. Needed effort???
4. 4
Discussed solution
Possible solution for
§ Seamless integration into Magnolia
§ Small, new applications
Portlet-API based approach offers:
§ Simple and flexible API
§ Dynamic flow over several pages
§ Different applications on the same page
§ Configuration in AdminCentral
7. 7
Portlet
§ JSR-168 (and JSR-286)
§ Standard for developing portal components with Java
§ Run in a Portlet Container / Portal Server
§ Action / render phase
§ Simple API
13. 13
Portlet API usage example
public class DemoPortlet implements Portlet
{
public void init(PortletConfig config) {
String myJspTemplate = config.getParameters().get("myJspTemplate");
}
public void processAction(ActionRequest request, ActionResponse response) {
String action = request.getAttribute(ActionRequest.ACTION_ATTRIBUTE_NAME);
if ("redirect".equals(action))
response.sendRedirect(request.getParameter("target"));
response.setRenderParameter("jsp", myJspTemplate);
}
public void render(RenderRequest request, RenderResponse response) {
Writer out = response.getWriter();
PortletURL url = response.createActionURL("new_action");
out.write("<a href="" + url.toString() + "">execute new_action</a>");
String jspTemplateName = (String) request.getAttribute("jsp");
((WebContext) MgnlContext.getInstance()).include(jspTemplateName, out);
}
public void destroy() { }
}
14. 14
Portlet API usage example
public class DemoPortlet implements Portlet
{
public void init(PortletConfig config) {
String myJspTemplate = config.getParameters().get("myJspTemplate");
}
public void processAction(ActionRequest request, ActionResponse response) {
String action = request.getAttribute(ActionRequest.ACTION_ATTRIBUTE_NAME);
if ("redirect".equals(action))
response.sendRedirect(request.getParameter("target"));
response.setRenderParameter("jsp", myJspTemplate);
}
public void render(RenderRequest request, RenderResponse response) {
Writer out = response.getWriter();
PortletURL url = response.createActionURL("new_action");
out.write("<a href="" + url.toString() + "">execute new_action</a>");
String jspTemplateName = (String) request.getAttribute("jsp");
((WebContext) MgnlContext.getInstance()).include(jspTemplateName, out);
}
public void destroy() { }
}
15. 15
Portlet API usage example
public class DemoPortlet implements Portlet
{
public void init(PortletConfig config) {
String myJspTemplate = config.getParameters().get("myJspTemplate");
}
public void processAction(ActionRequest request, ActionResponse response) {
String action = request.getAttribute(ActionRequest.ACTION_ATTRIBUTE_NAME);
if ("redirect".equals(action))
response.sendRedirect(request.getParameter("target"));
response.setRenderParameter("jsp", myJspTemplate);
}
public void render(RenderRequest request, RenderResponse response) {
Writer out = response.getWriter();
PortletURL url = response.createActionURL("new_action");
out.write("<a href="" + url.toString() + "">execute new_action</a>");
String jspTemplateName = (String) request.getAttribute("jsp");
((WebContext) MgnlContext.getInstance()).include(jspTemplateName, out);
}
public void destroy() { }
}
16. 16
createActionURL
Creates a link to the active portlet on the current
page with specified action
§ Use the original URI of the current request as target address
§ Set “action” and “portletId” parameters
§ Add all (other) parameters of the current request
17. 17
API extensions
ActionResponse {
HttpServletResponse handleResponseMyself();
}
§ Portlet must (and can!) do any further request handling
itself
§ “Generalization” of the redirect concept
18. 18
Reply caching
§ Not every page load has an “action” and “render” phase!
Example: Page with a shopping cart and a weather forecast
§ Remove one item of the shopping cart
§ Change the displayed location in the weather gadget
à the last shopping cart action is “invalid”
Caching the RenderRequests for every portlet on the page
allows independent portlet behaviour!
A basic principle in the portlet context
19. 19
Implementation details
ActionRequestImpl:
§ Special handling for action and uuid
§ Needs access to HttpServletRequest
ActionResponseImpl:
§ Needs access to HttpServletResponse
§ Store redirect location if called
RenderRequestImpl:
§ Needs ActionResponse in constructor
RenderResponseImpl:
§ Needs HttpServletRequest and Writer in constructor
§ createActionURL(…)
20. 20
Implementation details (2)
PortletURLImpl:
§ “Merge” parameters and action/portletId and create
parameter string
PortletConfig:
§ Bean to provide the configuration (content2bean)
§ classname
§ portletId
§ Description
§ Map<String, String> parameters
21. 21
Keeping the RenderRequest
§ Put portlet id, portlet object and RenderRequest in a
container
§ Store container in session
§ G container is page-specific
On a request:
§ Check for action command à do it!
§ store in new container in session
§ Check for stored container entry
§ move to new container and keep in session
§ render it later during rendering
§ Call default action for missing entries and store them
§ Remove old container
22. 22
Default action
Provide a default action per portlet and page
§ Place the same portlet on different pages with different
functionality (i.e. login, logout, display data, edit data, …)
§ Simple and intuitive menu integration
§ Configure the default action on the page
§ Allows one portlet per application
(in principle, different portlets could share the same data /
state)
§ Transparent for the portlet!
23. 23
Integration into Magnolia
Action phase:
§ Add a portlet filter
§ Alternative: action phase in template’s model (Mgnl 4.x)
(in the paragraph’s model it’s already too late)
Render phase:
§ Called while rendering the paragraph containing the portlet
24. 24
PortletFilter
Get all portlets Call
Get action
of current page processAction
yes Get default
action
Redirect? yes
Portlets Have
yes no
found? action? no
no
Have
Store in new
no yes container yes
container
entry?
Remove old More
no
container portlets?
25. 25
Render a portlet
§ JSP or Freemarker-template with only one tag:
<mgnlportlet:portlet/>
(integrated in Magnolia as paragraph)
§ Tag implementation:
§ get portletId out of current content node
§ get portlet object and render request out of container
§ call portlet.render(…)
31. 31
Putting all together: seamless Magnolia integration
applicational pages
h
r a g ra p
te xt pa
para graph
portlet
CMS (only) pages
32. 32
Unaddressed issues
§ Caching
§ Deployment
§ Several applications on same page may conflict (due to
redirects)
à how should the applications behave?
§ Integration of 3rd party frameworks
33. 33
Real world experiences
§ Used in production
§ Several applications integrated and live:
§ virtual portfolio system
§ serving personalized content (account information)
§ CSV download of table content
(render into a CSV file instead of a HTML table)
§ form editor (for Magnolia 3.5 / 3.6)
§ wizards
34. 34
Real world experiences (2)
§ Well-suited for small applications
§ Multi-page setup is fragile
§ Additional configuration inside the paragraph possible
§ Use “normal” CMS page for additional content (help, …)
§ Mixing of portlet-paragraphs and normal paragraphs on
same page possible
35. 35
Findings
Intuitive and flexible
Simple API (no specific framework to use)
Proper model phase support
Fusing with Magnolia (menu, mix paragraphs, …)
Few programmer support
Configuration dependencies (links to other pages)
Complexity of bigger applications