36
1 A portlet-API based approach for application integration Wolfgang Habicht Magnolia Conference, Basel 2009-09-10

A portlet-API based approach for application integration

Embed Size (px)

DESCRIPTION

A portlet-API based approach for application integration

Citation preview

Page 1: A portlet-API based approach for application integration

1

A portlet-API based approach for application integration

Wolfgang HabichtMagnolia Conference, Basel

2009-09-10

Page 2: A portlet-API based approach for application integration

2

Agenda

MotivationConceptThe portlet API and portlet basicsImplementation detailsMagnolia integrationReal world experiences & findings

Page 3: A portlet-API based approach for application integration

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

Page 4: A portlet-API based approach for application integration

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

Page 5: A portlet-API based approach for application integration

5

Concept

§ Two-phase model

action render

Somewhere in filter chain While page rendering

Phase 1 Phase 2

Page 6: A portlet-API based approach for application integration

6

Interaction overview

Page 7: A portlet-API based approach for application integration

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

Page 8: A portlet-API based approach for application integration

8

interface Portlet{void init(PortletConfig);void processAction(ActionRequest, ActionResponse);void render(RenderRequest, RenderResponse);void destroy();

}

Portlet API (simplified)

interface ActionRequest extends PortletRequest{String getParameter(String);String[] getParameterValues(String name);Collection<String> getParameterNames();

}

interface PortletRequest{Object getAttribute(String);Collection<String> getAttributeNames();

}

Page 9: A portlet-API based approach for application integration

9

interface Portlet{void init(PortletConfig);void processAction(ActionRequest, ActionResponse);void render(RenderRequest, RenderResponse);void destroy();

}

Portlet API (simplified)

interface ActionRequest extends PortletRequest{String getParameter(String);String[] getParameterValues(String name);Collection<String> getParameterNames();

}

interface PortletRequest{Object getAttribute(String);Collection<String> getAttributeNames();

}

Page 10: A portlet-API based approach for application integration

10

Portlet API (simplified, continued)

interface PortletResponse{}

interface ActionResponse extends PortletResponse{void sendRedirect(String);void setRenderParameter(String, Object);HttpServletResponse handleResponseMyself();

}

Page 11: A portlet-API based approach for application integration

11

Portlet API (simplified, continued)

interface RenderRequest extends PortletRequest{}

interface RenderResponse extends PortletResponse{PortletURL createActionURL(String);Writer getWriter();

}

interface PortletURL{void setParameter(String, String)void setParameter(String, String[])String toString();

}

Page 12: A portlet-API based approach for application integration

12

Portlet API (simplified, continued)

interface RenderRequest extends PortletRequest{}

interface RenderResponse extends PortletResponse{PortletURL createActionURL(String);Writer getWriter();

}

interface PortletURL{void setParameter(String, String)void setParameter(String, String[])String toString();

}

Page 13: A portlet-API based approach for application integration

13

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() { }}

Portlet API usage example

Page 14: A portlet-API based approach for application integration

14

Portlet API usage examplepublic 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() { }}

Page 15: A portlet-API based approach for application integration

15

Portlet API usage examplepublic 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() { }}

Page 16: A portlet-API based approach for application integration

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

Page 17: A portlet-API based approach for application integration

17

API extensions

ActionResponse {HttpServletResponse handleResponseMyself();

}

§ Portlet must (and can!) do any further request handling itself

§ “Generalization” of the redirect concept

Page 18: A portlet-API based approach for application integration

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”

A basic principle in the portlet context

Caching the RenderRequests for every portlet on the page allows independent portlet behaviour!

Page 19: A portlet-API based approach for application integration

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(…)

Page 20: A portlet-API based approach for application integration

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

Page 21: A portlet-API based approach for application integration

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

Page 22: A portlet-API based approach for application integration

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!

Page 23: A portlet-API based approach for application integration

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

Page 24: A portlet-API based approach for application integration

24

PortletFilter

Get all portlets of current page

Portlets found?

Remove old container

no

Get action

Have action?

Have container

entry?

yes

no

yes

Store in new containeryes

Call processAction

Get default action

More portlets?no

yes

no

Redirect?

no

yes

Page 25: A portlet-API based approach for application integration

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(…)

Page 26: A portlet-API based approach for application integration

26

Configuration (backend)

§ configure portlet classname and portletId§ content2bean à pass any configuration value(s)

Page 27: A portlet-API based approach for application integration

27

Configuration (frontend)

Portlet-Paragraph to add Portletsà choose portlet

and default action

Alternativ: “PortletApps” with preconfigured values

Portlet-specific configuration values:§ add subparagraph(s) inside your portlet§ access values by iterating through JCR nodes

Page 28: A portlet-API based approach for application integration

28

Advanced configuration (portlet config dialog)

portlet config dialog

Page 29: A portlet-API based approach for application integration

29

Advanced configuration (subparagraphs)

portlet config dialog

Page 30: A portlet-API based approach for application integration

30

Interaction overview (repetition)

Page 31: A portlet-API based approach for application integration

31

Putting all together: seamless Magnolia integration

text paragraph

portlet paragraph

applicational pages

CMS (only) pages

Page 32: A portlet-API based approach for application integration

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

Page 33: A portlet-API based approach for application integration

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

Page 34: A portlet-API based approach for application integration

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

Page 35: A portlet-API based approach for application integration

35

Findings

Intuitive and flexibleSimple API (no specific framework to use)Proper model phase supportFusing with Magnolia (menu, mix paragraphs, …)

Few programmer supportConfiguration dependencies (links to other pages)

Complexity of bigger applications

Page 36: A portlet-API based approach for application integration

36

Any Questions?