480 likes | 609 Views
Portlet Class Prerequisites. You are a Java programmer You know how to write servlet applications You know Struts and/or know MVC fundamentals You are familiar with the Spring framework IoC container. Creating Portlets for OneStart. We’ll be using Spring’s Portlet MVC framework
E N D
Portlet Class Prerequisites • You are a Java programmer • You know how to write servlet applications • You know Struts and/or know MVC fundamentals • You are familiar with the Spring framework IoC container
Creating Portlets for OneStart • We’ll be using Spring’s Portlet MVC framework • Patterned after Spring’s Web MVC, same basic concepts • Portlets can be written with other frameworks.
Comparing Portlets and Servlets Portlets share many similarities with servlets: • Java-based, generate dynamic web content • Interact with web client via request/response
Differences between portlets and servlets • Portlets only generate markup fragments, which the portal aggregates • Portlets are not directly bound to a URL • Portlets have predefined portlet modes and window states • Portlets can exist many times in a portal page • Don’t need CAS. Uses authentication from portal.
Additional Portlet Functionality • Portlets have means for accessing and storing persistent configuration and customization data • Portlets have access to user profile information • Portlets can store transient data in the portlet session in two different scopes: the application-wide scope and the portlet private scope
Portlets can't… • Set the character set encoding of the response • Set HTTP headers on the response • Access the URL of the client request to the portal
Creating the initialportlet.xml file • Specifies portlet settings • User attributes – passed from Portal • Portlet mode – view/edit/help • Windows states • Mime type – text/html • Expiration cache – not used in OneStart. We maintain our own cache. • Portlet title and keywords – not used in OneStart. We use publishing. • Dispatcher Portlet
Window States • Layout of the page. • “normal” is required. • Can support “maximized” or “minimized” if the portal it is running in supports them. • OneStart supports • normal – layout with many portlets on page • maximized – zoomed in mode, keep side bar • fullscreen – OneStart custom window state. It removes the side bar.
Supports (Portlet modes and mime type) • Can create modes for “view”, “edit” and “help” to create separate pages within your portlet • We recommend using view exclusively, but the edit and help modes are still supported • Use text/html for mime type
Supports section of portlet.xml <supports> <mime-type>text/html</mime-type> <portlet-mode>VIEW</portlet-mode> </supports>
More from portlet.xml Expiration Cache (measured in seconds):<expiration-cache>0</expiration-cache> Supported Locale: <supported-locale>en</supported-locale> Portlet info: <portlet-info> <title>Simple Test Portlet</title> <keywords>Simple Test Portlet</keywords> </portlet-info>
Web.xml • As with any web application, portlets must include a web.xml • Specify Web application resources • Mapping for servlet used by SpringDispatcherPortlet
Mapping the ViewRenderer Servlet <servlet> <servlet-name>ViewRendererServlet</servlet-name> <servlet-class> org.springframework.web.servlet.ViewRendererServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>ViewRendererServlet</servlet-name> <url-pattern>/WEB-INF/servlet/view</url-pattern> </servlet-mapping>
Register the Portlet <servlet-name>myPortletName</servlet-name> <servlet-class>org.apache.pluto.core.PortletServlet</servlet-class> <init-param> <param-name>portlet-name</param-name> <param-value>myPortletName</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>myPortletName</servlet-name> <url-pattern>/PlutoInvoker/myPortletName</url-pattern> </servlet-mapping>
Taglibs Include your tag library descriptors (TLDs) with your web.xml<taglib> <taglib-uri> http://java.sun.com/portlet </taglib-uri> <taglib-location> /WEB-INF/tld/portlet.tld </taglib-location> </taglib>
Exercise #1 (Configure Portlet) • In Eclipse, open the file ”portlet.xml" contained in the folder "publisherTraining/WebContent/WEB-INF" and follow the included instructions. • In Eclipse, open the file ”web.xml" contained in the folder "publisherTraining/WebContent/WEB-INF" and follow the included instructions.
Basic Portlet Example package example; import java.io.PrintWriter; import java.io.IOException; import javax.portlet.GenericPortlet; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import javax.portlet.PortletException; public class HelloWorldPortlet extends GenericPortlet { public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException { PrintWriter out = response.getWriter(); out.println("Hello, World"); } }
Generic Portlet • Part of the portlet api. • Default implementation for portlet interface. • Abstract class to override to create portlets • Must override at least one of the following • processAction, to handle action requests • doView, to handle render requests when in VIEW mode • doEdit, to handle render requests when in EDIT mode • doHelp, to handle render request when in HELP mode • init and destroy, to manage resources that are held for the life of the servlet
Action • ActionRequest • Request sent to the portlet to handle an action. • Extends PortletRequest • Need to pass action request parameters to render request • ActionResponse • represents the portlet response to an action request • Extends StateAwareResponse to provide action response functionality to portlets • Redirects • Modifications to database • Changes made to memory
Render • RenderRequest • Represents the request sent to the portlet to handle a render • Extends PortletRequest • RenderResponse • Assist the portlet in sending a response to the portal • Extends MimeResponse to provide specific render response functionality to portlets. • Executed whenever page is rendered • Can be called multiple times per request. • Can route to a view technology, JSP in our case • Retrieves data we’re planning on displaying in our view
Spring’s Dispatcher portlet • Dispatches requests to controllers • We’ll configure our dispatcher with an initialization parameter that provides locations for contexts
SpringDispatcherPortlet.java import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import org.springframework.web.portlet.DispatcherPortlet; public class SpringDispatcherPortlet extends DispatcherPortlet { protected void doRenderService(RenderRequest request, RenderResponse response) throws Exception { String value = (String) request.getAttribute("__portlet_attribute__title"); if (value != null && !"".equals(value.trim())) { response.setTitle(value); } super.doRenderService(request, response); } }
ApplicationContext.xml • Shared XML configuration file among the whole Application by all portlets in this WAR. • Global exception handling • Global request intercepting.
PortletExceptionHandler.java Implements resolveExceptions from HandletExceptionResolver and returns a ModelAndView to be displayed by a JSP: public class PortletExceptionHandler implements HandlerExceptionResolver { public ModelAndView resolveException(RenderRequest request, RenderResponse response, Object handler, Exception ex) { ModelAndView mav = new ModelAndView("Error"); mav.addObject("message", "An error has occurred."); return mav; } }
RequestHandlerInterceptor 5 methods that can be implemented: • preHandleAction() – before action • afterActionCompletion() – after action • preHandleRender() – before render • postHandleRender() – after render from controller, but before jsp render • afterRenderCompletion() –after jsp is rendered
Controllers • Interprets user actions, transforms them to be portrayed by the view Simple interface: public interface Controller { ModelAndView handleRenderRequest(RenderRequest request, RenderResponse response) throws Exception; void handleActionRequest(ActionRequest request, ActionResponse response) throws Exception; }
Selecting Controllers Spring offers a few controllers based on the controller interface, but we're going to focus on two: • AbstractController • SimpleFormController
AbstractController Two methods to override: • handleActionRequestInternal() – executes once on the initial page load • handleRenderRequestInternal() – happens whenever the page is rendered • Used for navigating from page to page in your portlet
SimpleFormController • Intended for situations with a web form and a page to display upon successful completion of the form • Form redisplays if errors occur; can add explanatory text or other information
SimpleFormController Two functions: • Preparing and showing form view • Process submission and showing resulting view Methods to override: • formBackingObject() – open the form • onSubmitAction() – submit form • onSubmitRender() – show result or confirmation from submission
Overriding formBackingObject • By default, instantiates command class to grab command object • Often we want to grab a specific object based on a parameter passed in from the request.
onSubmitAction(), onSubmitRender() onSubmitAction() • Executes when form is submitted • command object is returned from formBackingObject • Doesn’t return a value onSubmitRender() • Executed when the page is rendered • Construct modelAndView here
Validator • Spring’s interface for allowing validation of a form. public void validate(Object obj, Errors errors) { Movie movie = (Movie) obj; if (movie.getTitle() == null || "".equals(movie.getTitle())) { errors.rejectValue("title", "MOVIE_TITLE_REQUIRED", "Please enter a movie title"); } else if (movie.getTitle().length() > 100) { errors.rejectValue("title", "MOVIE_TITLE_MAX_SIZE_EXCEEDED", "Movie title must 100 or less characters."); } } • Object is the command class. Errors is the interface for adding your errors to for display on the jsp.
Exercise #2 (Controllers) • In Eclipse, open the files ”ExampleActionController.java, MovieViewController.java, MovieController.java, MovieValidator.java" contained in the folder "publisherTraining/src/edu.iu.es.espd.portlet.movie.web" and follow the included instructions.
View Resolver <bean id="viewResolver" class="org.springframework.web.servlet. view.InternalResourceViewResolver"> <property name="cache" value="true" /> <property name="viewClass" value="org.springframework.web.servlet. view.JstlView" /> <property name="prefix" value="/WEB-INF/ jsp/movie/" /> <property name="suffix" value=".jsp"/> </bean>
Handler Mapping • Direct portlet requests to appropriate handlers • Map the following: • Portlet Modes • Interceptors • Parameters • Any beans referenced by the items listed above
portletModeHandlerMapping The view in this mapping will be the first page rendered in your Spring portlet. <bean id="portletModeHandlerMapping" class="org.springframework.web.portlet.handler. PortletModeHandlerMapping"> <property name="order" value="20" /> <property name="interceptors"> <list> <ref bean="requestHandlerInterceptor" /> </list> </property> <property name="portletModeMap"> <map> <entry key="view" value-ref="viewHandler" /> <entry key="edit" value-ref="editHandler" /> <entry key="help" value-ref="helpHandler" /> </map> </property> </bean>
ParameterMappingIntercepter • Links ActionRequests to their subsequent RenderRequests • Requires no modification on our part: <bean id="parameterMappingInterceptor" class="org.springframework.web.portlet. handler.ParameterMappingInterceptor" />
PortletModeParameterHandlerMapping • Links parameters provided by actionURLs and renderURLs in our JSPs and maps them to specific handlers. • The handlers then specify a java class to be executed. • Use the “action” parameter to choose which handler to use.
portletModeParameterHandlerMapping example <bean id="portletModeParameterHandlerMapping" class="org.springframework.web.portlet.handler. PortletModeParameterHandlerMapping"> <property name="order" value="10" /> <property name="interceptors"> <list> <ref bean="parameterMappingInterceptor" /> <ref bean="requestHandlerInterceptor" /> </list> </property> <property name="portletModeParameterMap"> <map> <entry key="view"> <map> <entry key="viewInfo" value-ref="myViewController" /> <entry key="updateInfo" value-ref="myUpdateController" /> </map> </entry> </map> </property> </bean>
Abstract Controller In the example below, we are defining a bean for a class extending abstractController. We need • Bean id • the class • Inject any services used in the class <bean id=”myController” class=”myJava.Controller.ClassName"> <property name=”theService" ref=”myService" /> </bean>
SimpleFormController SimpleFormControllers require a few additional pieces of information: • Session form – put in session • Command name – name of object in memory • Command class – java class of the command object • Form view – name of the view (jsp) • Validator class reference. • Any services used in the class
Exercise #3 (movie.xml) • In Eclipse, open the file ”movie.xml" contained in the folder "publisherTraining/WebContent/WEB-INF/context/portlet" and follow the included instructions.
Jsp portlet writing • Only include tags that would be put in the body of a servlet jsp. • Do not put in <html> or <body> tags. • Do not put javascript or css references in jsps. A portlet inherits the css of the portal it is running in. If you need javascript, you will have to discuss this with the team that supports the portal.
Portlet Tags • defineObjects: defines variables for portlet objects • actionURL: triggers an action request; supplied parameter is then mapped to a handler • renderURL: triggers a render request; supplied parameter is then mapped to a handler
Portlet Tags, continued • param: define a parameter to be used by actionURL or render URL • namespace: assign the portlet a unique namespace
Exercise#4 (JSPs) • In Eclipse, open the files ”displayMovies.jsp, movie.jsp, deleteMovie.jsp" contained in the folder "publisherTraining/WebContent/WEB-INF/jsp/movie" and follow the included instructions.
Additional Resources • Spring’s documentation: http://static.springframework.org/spring/docs/2.5.x/reference/portlet.html • JSR168, portlet specificationhttp://jcp.org/aboutJava/communityprocess/final/jsr168/