25
Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK [email protected]

Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK [email protected]

Embed Size (px)

Citation preview

Page 1: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

Developing Portlets With Java Server Faces

Dave Meredith NGS Grid Development, e-Science Centre, Daresbury

Laboratory, UK

[email protected]

Page 2: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

Overview

JSR 168 – Some Comments

Why develop portlets with Java Server Faces

Required Steps to Deploy a JSF Web Application as a Portlet

Some Development Issues

Summary / Useful Links

Page 3: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

JSR 168 – Some Comments

Assumes developers will be happy to ignore other (well known) development development frameworks like Velocity, Struts, and Java Server Faces and learn new Portlet API.

168 nvolves developing a GenericPortlet extension for every single portlet they develop.

Can result in complicated processAction() and doView() methods.

Will have to replicate functionality that is provided with web app framework.

Assumes developers will be happy with the JSR 168 portlet-style Model-View-Controller.

Fortunately, it is possible to map these other web application frameworks to portlet actions (portal bridges – e.g. Struts portal bridge).

Page 4: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

Why Develop Portlets with Java Server Faces ?

JSF designed from the outset to be compatible with portals/ portlets. Some other frameworks involve quite complex portal-bridges – have heard using a portal bridge is comparable to ‘trying to fit a square peg in a round hole.’(Stan Silvert, Java One Online 2005)

Can deploy a JSF web application either as a standalone web application, or as a portlet for inclusion in a JSR168 portal container.

Existing JSF Applications can be (semi-transparently) deployed as a Portlet application. Helps move away from common notion that portlets are mostly small apps.

This requires a little (or no modification) – steps to do this will be shown later in talk.

Page 5: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

Same JSF Application Deployed in Pluto Portal Container as Single Portlet

JSF Application Deployed As Standalone Web Application(Cog4, JPA + Hibernate, JSF, JSDL, Jargon, JAX-WS, Vine ?)

Page 6: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

Why Develop Portlets with Java Server Faces ?

Same reasons as for developing regular JSF web applications

JSF is standard

Powerful MVC programming framework for building (large) Web Applications: Enforces good structuring of code – cleanly splits view from model Well defined navigation rules Managed beans / backing beans for logic (POJOs) Event handling (action events, action listeners, value-change events, phase listeners) Can interact with JSF processing lifecycle at different levels – (v.powerful if required) Powerful form validation Dependency injection via “faces-config.xml” file Not dependent on J2EE Application Server (can run is servlet container like Tomcat)

Reusable UI components:e.g. tabbed panes, scrolling tables, calendars, hierarchical trees, table models .....etcApache MyFaces has over 100 reusable components with addition of Oracle ADF (Trinidad). Future – AJAX enabled UI components (hope it will save me from having to learn AJAX and JS)

Good tool support: e.g. drag 'n' drop design of JSF components in JSP using Sun Studio Creator.

Developers may already be familiar with JSF: – have own code base (for me, this was a strong reason that I started to develop portlets with JSF).

Page 7: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

In JSP (View - No logic / scriptlets):

<h:form id="saveRunForm"> <h:panelGrid columns="3">

<h:outputText value="Job Profile Name:"/> <h:inputText id="jsdlNameInputText" value="#{ActiveJobProfile.name}" required=”true” validator="#{ActiveJobProfile.validateName}" valueChangeListener="#{ActiveJobProfile.valueChangeName}" /> <h:message for="jsdlNameInputText" styleClass="errorMessage"/>

In Backing Bean (Model):

public class ActiveJobProfileBean implements Serializable { private String name;

public void validateName(FacesContext context, UIComponent component, Object val) throws ValidatorException { /**TODO implement validation logic, throw ValidatorException if 'val' is incorrect */ }

public void valueChangeName(ValueChangeEvent event){ /**TODO implement logic if value has changed */ }}

Why Develop Portlets with Java Server Faces ? Enforces good structuring of code

Backing Beans are POJO’s with no dependency on container. Beans define logic. Display values of bean attributes in jsp view. Call bean methods to perform logic (actions, value change events, validators)

Page 8: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

<!-- One shared DB Util object in application scope (creates single JPA EntityManagerFactory and serves ThreadLocal EntityManager instances ) --> <managed-bean> <managed-bean-name>J2seEntityManagerUtil</managed-bean-name> <managed-bean-class>org.davemeredith.J2seEntityManagerUtil</managed-bean-class> <managed-bean-scope>application</managed-bean-scope> <managed-property> <property-name>persistenceUnitName</property-name> <value>NgsJobProfileDbHibernateJ2SE</value> </managed-property> </managed-bean>

<!-- One shared JobProfileBO in application scope with injected reference to J2seEntityManagerUtil --> <managed-bean> <managed-bean-name>JobProfileBO</managed-bean-name> <managed-bean-class>uk.ac.escience.ngs.portal.jobSubmit.dbBO.JobProfileBO</managed-bean-class> <managed-bean-scope>application</managed-bean-scope> <managed-property> <property-name>entityManagerUtil</property-name> <value>#{J2seEntityManagerUtil}</value> </managed-property> </managed-bean> <!-- Each user has an ActiveJobProfile with injected reference to JobProfileBO --> <managed-bean> <managed-bean-name>ActiveJobProfile</managed-bean-name> <managed-bean-class>uk.ac.escience.ngs.portal.jobSubmit.ActiveJobProfileBean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> <managed-property> <property-name>jobProfileBO</property-name> <value>#{JobProfileBO}</value> </managed-property> </managed-bean>

Why Develop Portlets with Java Server Faces ? JSF Dependency Injection (can ‘order’ the injection sequence,- no need for listeners !)

(In faces-config.xml)

Page 9: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

Overview

Why develop portlets with Java Server Faces

Required Steps to Deploy a JSF Web Application as a Portlet

Some Development Issues

Summary / Useful Links

Page 10: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

Required Steps to Deploy a JSF Web Application as a Portlet

1) Make necessary modifications to your code: a) Use JSF navigation rules only b) Use abstracted ExternalContext in web application logic

2) Create portlet.xml deployment descriptor for your JSF application

3) Add jsf-portlet.jar to WEB-INF/lib of your application (JSF RI only, not necessary when using Apache MyFaces)

4) Package JSF portlet into a deployable .war file

4) Deploy JSF portlet application to your portal container and register it with the portal so it can be viewed within the portal interface (specifics vary according to the portal container you are using)

Page 11: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

a) Ensure page navigation in web application is implemented by JSF navigation rules only (remove any re-direct links). JSF components are rendered so that URL processing is delegated to a ViewHandler which can either create portlet URLs if hosted in a portal, or a FacesServlet URLs if a regular JSF app.

Remove links/re-directs:

<a href="./faces/ActiveJobProfile.jsp">Back</a>

With JSF navigation rules: (In faces-config.xml) <!-- below rule applies to all pages because no from-view-id is specified --> <navigation-rule> <navigation-case> <from-outcome>goActiveJobProfile</from-outcome> <to-view-id>/ActiveJobProfile.jsp</to-view-id> </navigation-case> </navigation-rule>

(In Jsp) <h:commandLink action="goActiveJobProfile" value="Back"/>

1) Make Some Necessary Modifications to Your Code

Page 12: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

b) A JSF portlet application must not rely on any servlet-specific APIsUse abstracted 'ExternalContext' class to get access to methods and objects that you would normally get from HttpServletRequest, HttpServletResponse, ServletContext.

/** to get the ExternalContext */ FacesContext fc = FacesContext.getCurrentInstance(); ExternalContext ec = fc.getExternalContext();

/** wrong ! */ HttpServletRequest req = (HttpServletRequest) ec.getRequest(); Map paramMap = req.getParameterMap(); String cp = req.getContextPath(); Cookies[] cookies = req.getCookies(); /** right ! */ Map paramMap = ec.getRequestParameterMap(); String cp = ec.getRequestContextPath(); Map cookies = ec.getRequestCookieMap();

/** useful functions for portlet deployment */ String remoteUserUUID = ec.getRemoteUser(); boolean inRole = ec.isUserInRole("userA");

c) Ensure 3rd party libs / packages / dependencies can be deployed to target container (some issues with shared libs and web-app/WEB-INF/libs and security)

1) Make Some Necessary Modifications to Your Code

Page 13: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

2) Create a portlet.xml Deployment Descriptor for JSF web application (using JSF Reference Implementation)

<portlet> <portlet-name>NgsJobSubmit_Portlet</portlet-name> <portlet-class>com.sun.faces.portlet.FacesPortlet</portlet-class>

<!-- jsf RI required parameter. The "home page" of your JSF application --> <init-param> <name>com.sun.faces.portlet.INIT_VIEW</name> <value>/index.jsp</value> </init-param> <expiration-cache>0</expiration-cache> <supports> <mime-type>text/html</mime-type> <portlet-mode>VIEW</portlet-mode> </supports> <supported-locale>en</supported-locale> <portlet-info> <title>NgsJobSubmit_Portlet</title> <keywords>NGS, HPC, Job Submission</keywords> </portlet-info> </portlet>

JSF RI does not have a concept of modes, so you (usually) need to disable EDIT and HELP modes in portlet.xml.

Page 14: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

<portlet> <portlet-name>NgsJobSubmit_Portlet</portlet-name> <portlet-class>org.apache.myfaces.portlet.MyFacesGenericPortlet</portlet-class> <!-- MyFaces required parameter. The "home page" of your JSF application --> <init-param> <name>default-view</name> <value>/ActiveJobProfile.jsp</value> </init-param> <expiration-cache>0</expiration-cache> <supports> <mime-type>text/html</mime-type> <portlet-mode>VIEW</portlet-mode> </supports> <supported-locale>en</supported-locale> <portlet-info> <title>NgsJobSubmit_Portlet</title> <keywords>NGS, HPC, Job Submission</keywords> </portlet-info> </portlet>

MyFaces can support EDIT and HELP modes by subclassing MyFacesGenericPortlet. Only supported with MyFaces 1.0.9+

2) Create a portlet.xml Deployment Descriptor for JSF web application (using Apache MyFaces)

Page 15: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

jsf-portlet.jar is the portlet integration library that must reside with your application in the WEB-INF/lib subdirectory. That way, your application can run as a portlet. javaserverfaces_portlet.class

Go to http://javaserverfaces.dev.java.net and download javaserverfaces_portlet.class (look under Documents & Files menu item)

Use"java -cp . javaserverfaces_portlet.class" to install. Based on JSF 1.x release

This generates jsf-portlet.jar

or, use jsf-portlet.jar that comes with Sun Studio Creator (free download). Also has a project template for creating a JSF portlet using the JSF RI.

3) Add jsf-portlet.jar to WEB-INF/lib of your application (JSF Reference Implementation)

Page 16: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

4) Deploy JSF portlet application to your portal container and register it with the portal

This is different according to the portlet container you are using. For Pluto (Reference Implementation of JSR 168 portlet container), modify 3 Pluto files and add some Pluto boilerplate code to web.xml:

Pluto Files to Modify:

<PLUTO_HOME>/webapps/pluto/WEB-INF/data/ portletcontext.txt portletentityregistry.xml pageregistry.xml

a) portletcontext.txt (lists the context path of each portlet application)

/testsuite/pluto/SimpleMyFacesPortletsMixed/SimpleRIPortlet /chapter04/chapter05/NgsJobSubmissionPortlet1

Page 17: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

b) portletentityregistry.xml (registers the portlet with the portal container)

<portlet-entity-registry>

<application ...>...</application> ....

<!-- Specify portlet application and give it an id value --> <application id="12"> <!-- Specify name of the JSF portlet app as listed in portletcontexts.txt --> <definition-id>NgsJobSubmissionPortlet1</definition-id> <!-- Give portlet an id value --> <portlet id="0"> <!-- “<portlet app> . <portlet class as specified in portlet.xml>” --> <definition-id>NgsJobSubmissionPortlet1.NgsJobSubmit_Portlet</definition-id> </portlet> </application> </portlet-entity-registry>

Page 18: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

c) pageregistry.xml (defines the layout of the portlets in the portal)

<portal>

<fragment name="NGS" type="page" > <navigation> <title>NgsJobSubmit</title> <description>NGS Job Submission / JSDL Job Profiles Portlet</description> </navigation> <fragment name="row1" type="row"> <fragment name="col1" type="column"> <fragment name="p1" type="portlet"> <!-- <portlet application id> . <portlet id> --> <property name="portlet" value="12.0"/> </fragment> </fragment> </fragment> </fragment> </portal>

Page 19: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

<servlet> <servlet-name>NgsJobSubmit_PortletServlet</servlet-name> <display-name>NgsJobSubmit_Portlet Wrapper</display-name> <description>Automated generated Portlet Wrapper</description> <servlet-class>org.apache.pluto.core.PortletServlet</servlet-class> <init-param> <param-name>portlet-guid</param-name> <!-- Enter the path to the portlet: <context path>.<portlet name in portlet.xml> --> <param-value>NgsJobSubmissionPortlet1.NgsJobSubmit_Portlet</param-value> </init-param> <init-param> <param-name>portlet-class</param-name> <param-value>org.apache.myfaces.portlet.MyFacesGenericPortlet</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>NgsJobSubmit_PortletServlet</servlet-name> <url-pattern>/NgsJobSubmit_PortletServlet/*</url-pattern> </servlet-mapping>

Add Pluto boilerplate code to web.xml

Define a new servlet mapping that wraps the JSF portlet.

Note, this code is added when you use Pluto hot-deploy page

Page 20: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

Overview

Why develop portlets with Java Server Faces

Required Steps to Deploy a JSF Web Application as a Portlet

Some Development Issues

Summary / Useful Links

Page 21: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

Some Development Issues

1) Mixing JSF portlets with other portlets in the same portlet application

A portal container can host multiple JSF and 168 portlets in the same portal.

portal |_ webapps/ |_ 168 portlet application (.war) Portlet applications must communicate |_ JSF portlet application (.war) by an external mechanism (e.g. db, |_ JSF portlet application (.war) Web services) |_ 168 portlet application (.war)

However, only one JSF portlet can be integrated into a single portlet application. Theproblem of inter-portlet communication still exists – (wait for JSR 286)

.war |_ WEB-INF/ |_ <Portlet.xml> |_ <JSF portlet> Can write a single portlet application |_ <168 portlet> with one JSF portlet and multiple 168 |_ <168 portlet> portlets (all share same portlet application |_ <168 portlet> session and share data). .war |_ WEB-INF/ |_ <Portlet.xml> |_ <JSF portlet> Cant write a single portlet application |_ <JSF portlet> with more than one JSF portlet |_ <168 portlet> |_ <168 portlet>

Page 22: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

Some Development Issues

2) web.xml VersioningIn Pluto, I could only deploy a JSF portlet application if web.xml is based on web app version 2.3.dtd, not version 2.4.xsd (may be resolved with later releases of pluto)

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"><web-app> ....</web-app>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> ....</web-app>

3) Have not yet tried JSF 1.2 JSF 1.2 provides new unified expression language (unified EL) , which is essentially an amalgamation of the JSP EL and the JavaServer Faces 1.1_01 EL.

Page 23: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

Turn off MyFaces AutoScroll

<!-- If true, a javascript function will be rendered that is able to restore the former vertical scroll on every request. Convenient feature if you have pages with long lists and you do not want the browser page to always jump to the top if you trigger a link or button action that stays on the same page. Note, has to be false if want to run as JSR 168 portlet ! --> <context-param> <param-name>org.apache.myfaces.AUTO_SCROLL</param-name> <param-value>false</param-value> </context-param>

Client State Saving Method, not as Server <!-- Specify where the state should be saved. If state is saved on client, the state of the entire view is rendered to a hidden field on the page. JSR-168 independent but seems buggy when "server" specified (makes sense as are depending more on the portlet container ??) --> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>client</param-value> </context-param>

Page 24: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

Apache MyFaces / Trinidadhttp://www.myfaces.org

JSF homehttp://javaserverfaces.dev.java.net

Good talk on portlet development with JSF(Building Killer Portlets with JSF – Stan Silvert, Java One Online, 2005)http://developers.sun.com/learging/javaone/online

Summary

JSF (in my opinion), is a viable framework for the development of powerful web-application like portlets (and standalone web apps).

Can deploy existing JSF Web apps as a single portlet.

JSF is a standard – always best for future support.

There are a few ‘gotchas’ that developers need to be aware of.

Intra-portlet communication the main problem, (believe this will be addressed in JSR 286).

Page 25: Developing Portlets With Java Server Faces Dave Meredith NGS Grid Development, e-Science Centre, Daresbury Laboratory, UK d.j.meredith@dl.ac.uk

A portlet is a piece of Java code that manages the content of one section of a web portal’s HTML.

It can do anything else that a Java web application can do. You can connect a portlet to a database, invoke a web service,

download an RSS feed, etc. It lives in a portlet container, which creates, manages, and

destroys all the portlets of the portal. Portlet containers are part of portals.

Portals must do other things like manage login, users, groups, layouts, etc.

JSR 168 standardizes two main things: How the portlet container manages portlet lifecycles How the portlets are programmed.