Portlet Development II Portlet Actions and Services Jason Novotny novotny@aei.mpg.de Michael Russell russell@aei.mpg.de Oliver Wehrens wehrens@aei.mpg.de Albert Einstein Institute HelloWorld continued HelloWorld example just shows portlet presentation How to handle actions? Action handling is performed by actionPerformed(ActionEvent event) portlet method To make the example more interesting, allow the user to click a button which will display a personalized message Involves two steps: Create a JSP page used to render presentation Augment existing HelloWorld portlet with actionPerformed method Portals & Portlets 2003; July 14 -17 2003; Edinburgh HelloWorld Portlet Modify the HelloWorld portlet doView method to create an action and include a JSP page: package examples.portlets; public class ActionHelloWorld extends AbstractPortlet { public void doView(PortletRequest request, PortletResponse response) throws PortletException, IOException { PortletURI uri = response.createURI(); uri.addAction("hello_action"); request.setAttribute("action", uri.toString()); getPortletConfig().getContext().include("/jsp/helloworld/actionhello.jsp", request, response); } } Portals & Portlets 2003; July 14 -17 2003; Edinburgh HelloWorld JSP Create webapp/jsp/hello.jsp to display a welcome message and a form: <jsp:useBean id="action" class="java.lang.String" scope="request"/> <jsp:useBean id="name" class="java.lang.String" scope="request"/> Welcome, <b><%= name %>!</b> <form method="POST" action="<%= action %>"> <table> <tr> <td>Enter your name:</td> <td><input type="text" name="name" size="20" maxlength="20"/></td> </tr> </table> </form> Portals & Portlets 2003; July 14 -17 2003; Edinburgh HelloWorld Portlet Add the actionPerformed implementation which sets the name in the request to be rendered by hello.jsp package examples.portlets; public class HelloWorld extends AbstractPortlet { public void actionPerformed(ActionEvent event) { PortletRequest req = event.getPortletRequest(); String actionName = event.getAction().getName(); if (actionName.equals(“hello_action”)) { String name = req.getParameter(“name”); req.setAttribute(“name”, name); } } … } Portals & Portlets 2003; July 14 -17 2003; Edinburgh Portlet Actions Actions are created either in forms or in links Actions are created using the PortletURI to construct an identifier to refer to the calling portlet Actions are defined by an action name e.g. ‘hello_action’ and may contain additional parameters. PortletURI offers method “addParameter(String name, String value)” to associate name value pairs with an action Action information is obtained from ActionEvent in the actionPerformed method of a portlet GridSphere UI tag library makes creation and use of tags easier (in next tutorial) Portals & Portlets 2003; July 14 -17 2003; Edinburgh Check the new portlet! Re-deploy tutorial webapp “cd projects/tutorial; ant deploy” Restart servlet container ‘cd $CATALINA_HOME; bin/startup’ Portals & Portlets 2003; July 14 -17 2003; Edinburgh Portlet Services Purpose is to encapsulate business or logic operations that can be reused across portlets Minimize logic placed in portlet and make it available as a reusable library Services are created and destroyed by a PortletServiceFactory PortletServices provide init and destroy lifecycle methods “User services” provide method level access control based on a User’s access control information Service tests can be developed and executed using Junit and Cactus frameworks Services are defined by a portlet services descriptor Portals & Portlets 2003; July 14 -17 2003; Edinburgh Portlet Service Example Create HelloWorld service that keeps track of supplied user names. need to create an interface, implementation and descriptor of the service Create src/services/examples/HelloService.java with two service methods: public interface HelloService extends PortletService { public void addName(String name); public List getNames(); } Portals & Portlets 2003; July 14 -17 2003; Edinburgh Portlet Service Example Create HelloWorld service implementation in src/services/examples/impl/HelloServiceImpl.java: public class HelloServiceImpl implements PortletServiceProvider, HelloService { private List list = new ArrayList(); public void init(PortletServiceConfig config) { } public void destroy() { } // for now don’t use public void addName(String name) { list.add(name); } public List getNames() { return list; } } Portals & Portlets 2003; July 14 -17 2003; Edinburgh Portlet Service Example Add service descriptor entry to webapps/WEBINF/PortletServices.xml: <service> <name>HelloService</name> <description>an example service</description> <interface>services.examples.HelloService</interface> <implementation>services.examples.impl.HelloServiceImpl</implementation> </service> Portals & Portlets 2003; July 14 -17 2003; Edinburgh Use Portlet Service The HelloService may now be used from a portlet A service instance is obtained via PortletContext public class HelloWorld extends AbstractPortlet { public void init(PortletConfig config) throws UnavailableException { hello = (HelloService)config.getContext().getService(HelloService.class); } public void actionPerformed(ActionEvent event) { PortletRequest req = event.getPortletRequest(); String actionName = event.getAction().getName(); if (actionName.equals(“hello_action”)) { String name = req.getParameter(“name”); hello.addName(name); } } Portals & Portlets 2003; July 14 -17 2003; Edinburgh Portlet User Services A “User service” provides method level access control Development approach is to create a service implementation like before, but should be a singleton: public class HelloServiceImpl implements PortletServiceProvider, HelloService { private HelloWorldServiceImpl instance = new HelloWorldServiceImpl(); private HelloServiceImpl() {} public static HelloWorldServiceImpl getInstance() { return instance; } } Portals & Portlets 2003; July 14 -17 2003; Edinburgh Portlet User Services Create a decorator service class that handles method level authorization: Constructor must take PortletServiceAuthorizer as parameter public class HelloUserServiceImpl implements PortletServiceProvider, HelloService { private PortletServiceAuthorizer auth = null; private HelloServiceImpl hello = HelloServiceImpl.getInstance(); public HelloUserServiceImpl(PortletServiceAuthorizer auth) { this.auth = auth; } public List getNames() { auth.authorizeSuperUser(); return hello.getNames(); } } Portals & Portlets 2003; July 14 -17 2003; Edinburgh Portlet User Services Modify service descriptor entry in webapps/WEBINF/PortletServices.xml: User services must set “user-required” attribute true <service> <name>HelloService</name> <user-required>true</user-required> <description>an example service</description> <interface>services.examples.HelloService</interface> <implementation>services.examples.impl.HelloUserServiceImpl </implementation> </service> Portals & Portlets 2003; July 14 -17 2003; Edinburgh Use Portlet User Service A user service instance is obtained via PortletContext as before, but requires User to be supplied public class HelloWorld extends AbstractPortlet { public void actionPerformed(ActionEvent event) { PortletRequest req = event.getPortletRequest(); User user = req.getUser(); // get a hello service instance appropriate for this type of user hello = (HelloService)config.getContext().getService(HelloService.class,user); // will only work for super user List names = hello.getNames(); } } Portals & Portlets 2003; July 14 -17 2003; Edinburgh