BT
x Your opinion matters! Please fill in the InfoQ Survey about your reading habits!

Developing Portlets using JSF, Ajax, and Seam (Part 3 of 3)

Posted by Wesley Hales on Sep 16, 2008 |

In part 1 and part 2 of this series I explained what the portlet bridge is, how you can install and use it in a basic JSF and RichFaces(Ajax) based portlet, and the key differences in the portal servers that are currently supported to run the JBoss Portlet Bridge. This final article is focused on Seam portlet development along with a recap of all the features and benefits covered in the latest Beta 4 release of JBoss Portlet Bridge. However, It may benefit readers who are new to portlets to go back and read the previous two articles.

 

Now let's jump straight into Seam portlet development.

Seam Portlet Setup

Development Tools:

To follow along with this guide, download the latest version of Maven. (I am using 2.0.9)
Install Maven 2.0.9+
Set the Maven binaries on your path

Project Creation:

Each flavor of the bridge comes with its own Maven archetype. To setup your Seam portlet project, run the following from the command line:

mvn archetype:generate
 -DarchetypeGroupId=org.jboss.portletbridge.archetypes
 -DarchetypeArtifactId=seam-basic -DarchetypeVersion=1.0.0.B4
 -DgroupId=org.my.project -DartifactId=seamproject
 -DarchetypeRepository=http://repository.jboss.org/maven2/ -Dversion=1.0.0.B4 

This particular archetype is modular, meaning that the generated project is divided into sub projects for easier maintenance and better separation of code, resources, and configurations. The 'web' directory contains markup, images and WEB-INF xml configuration resources. 'ejb' contains all of your Seam EJB3 source code and any xml configurations related to persistence and ejb deployment. And finally, the 'ear' directory is mainly used to piece the project together and build the ear.

If you used the archetype command above you should now have a 'seamproject' directory. Go ahead and navigate to the root of this directory and run:
mvn install
This command should download any artifacts you don't already have in your local Maven repository and will also compile and build your ear file.

Running and deploying your portlet:

 

Now that you have a deployable ear, this next command makes it simple for you to start and deploy your new portlet to the latest version of JBoss Portal bundled in JBoss Application Server. If you have a local installation or bundle that you have already downloaded or created yourself, you can find instructions on using your custom configuration in the bridge documentation.

Navigate to the {seamproject}/ear directory and run:

mvn cargo:start -Premote-portal-Dportal-2.7.0.B1

This command will take a few minutes (depending on your connection) to download the latest JBoss Application Server + JBoss Portal versions located on SourceForge.net. You should see a log similar to the above image before you proceed to the next step. *Note - you may also see WSRP messages continually scroll in the log, this is also a sign that you are ready for the next step.

Now to deploy your Seam project ear, in a newly opened terminal, run the following from the same {seamproject}/ear directory:

mvn cargo:deploy-Premote-portal -Dportal-2.7.0.B1

After you see that the ear has deployed in your server log, visit http://localhost:8080/portal/portal/default/seamproject and you will see the following page:

Now we have a Seam portlet ready for development. Of course, it's up to the developer on how the application is written. But, this will get you off to an easy start not having to worry about trivial configuration issues.

Configuration

There are only a few configurations that must be made to convert your JSF portlet to a full blown Seam application. The following settings are in addition to the settings mentioned in the previous (part 1 and part 2) articles. For a full breakdown, please see the configuration section of the bridge documentation.

web.xml
------------------

The following settings are common amongst any Seam application and are no different for the portlet environment:

      <listener>
      <listener-class>
              org.jboss.seam.servlet.SeamListener
          </listener-class>
    </listener>
    <servlet>
      <servlet-name>Seam Resource Servlet</servlet-name>
      <servlet-class>
              org.jboss.seam.servlet.SeamResourceServlet
          </servlet-class>
    </servlet>
    <servlet-mapping>
      <servlet-name>Seam Resource Servlet</servlet-name>
      <url-pattern>/seam/resource/*</url-pattern>
    </servlet-mapping>
    <filter>
      <filter-name>Seam Filter</filter-name>
      <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
    </filter>
    <filter-mapping>
      <filter-name>Seam Filter</filter-name>
      <servlet-name>Faces Servlet</servlet-name>
      <dispatcher>FORWARD</dispatcher>
      <dispatcher>REQUEST</dispatcher>
      <dispatcher>INCLUDE</dspatcher>
   </filter-mapping>

The ExceptionHandler context param allows the bridge to properly handle Seam based exceptions by using the out-of-box exception handler. You can use your own implementation here if desired:

<context-param>
    <param-name>org.jboss.portletbridge.ExceptionHandler</param-name>
    <param-value>
       org.jboss.portletbridge.SeamExceptionHandlerImpl
    </param-value>
 </context-param>

Bridgelet is the name for a portlet bridge extension. The portlet bridge community is actively developing extensions that enhance or bring together features of JBoss Portal, Seam, and Richfaces. For example, the PortalIdentity(SSO) seam component allows you to drop the jar in your classpath and you instantly have SSO between Seam and Portal. This extension can also be configured as a dependency in your Maven pom (as seen below).

If you have an idea for a Bridgelet or would like to help with development of any part of the JBoss Portlet Bridge, we encourage you to become active on our forums and submit Jira tasks.

Single Sign On between JBoss Portal and your Seam application

The Seam Booking Demo is available as a portlet for developers to use as a reference for development and testing. To follow along and try out the SSO Bridgelet you can check out the demo source code from http://anonsvn.jboss.org/repos/portletbridge/tags/1.0.0.B4/examples/seam/booking/ and run the exact same maven deployment commands mentioned in this article (or the shortened version below) to get the application deployed and running.

The short version is:
Navigate to the {SeamBooking} root and run:
mvn install

Navigate to the {SeamBooking}/ear directory and run:
mvn cargo:start -Premote-portal-Dportal-2.7.0.B1

Now to deploy your Seam project ear, in a newly opened terminal, run the following from the same {SeamBooking}/ear directory:
mvn cargo:deploy-Premote-portal -Dportal-2.7.0.B1

Once you have the demo up and running, visit http://localhost:8080/portal/portal/default/SeamBooking and go ahead and create a new account by clicking "Register New User" and login with your newly created username and password:

After login, you will see the hotel search screen and all of the role based parts of the aplication. However, if you look to the top right hand corner of your screen, you see that your logging into the Seam application has nothing to do with your JBoss Portal user/admin account:

This is the reason we have the SSO Bridgelet. It allows your JBoss Portal username to authenticate via the Seam identity module. So let's try it out:
With the server still running and from the same terminal that you deployed from, we will now navigate back one directory to the {SeamBooking}/ root and run:
mvn install -Psso

Next navigate back to the {SeamBooking}/ear directory and run:
mvn cargo:deploy-Premote-portal -Dportal-2.7.0.B1

With these commands we embedded the SSO jar into the application and then redeployed the ear.

Now, let's go back to our portlet at http://localhost:8080/portal/portal/default/SeamBooking and this time, login to the portal and not the Seam application. Click on the portal login at the very top, right hand corner of the page and use 'admin' for both the username and password.

If this were a real-world application, we would change the UI a little bit to hide the Seam application login form, and would edit other role based parts of the site since we now have SSO. But, as I stated earlier, this is a direct port from the original Seam booking demo with minor changes.

After logging into JBoss Portal you should see the following in your Seam and Portal UI:

From here, creating your application will be much easier to build when dealing with identity and permissions between Portal and your Seam aplication. If your Seam portlet is Maven based, all that is required is the following in your pom.xml:

  <dependency>
      <groupId>org.jboss.portletbridge.extensions.seam</groupId>
      <artifactId>PortalIdentity</artifactId>
      <version>1.0.0.B4</version>
 </dependency>

Or you can just drop the PoralIdentity.jar in your application WEB-INF/lib and you are done. No other configuration is required.

JBoss Portlet Bridge Beta4 Recap

Since this is the last article in the three part series, this final section is about the new features in Beta 4, released September 11th.

Supporting PortletMode Changes

A PortletMode represents a distinct render path within an application. There are three standard modes: view, edit, and help. The bridge's ExternalContext.encodeActionURL recognizes the query string parameter javax.portlet.faces.PortletMode and uses this parameter's value to set the portlet mode on the underlying portlet actionURL or response. Once processed it then removes this parameter from the query string. This means the following navigation rule causes one to render the \edit.jspx viewId in the portlet edit mode:

 <navigation-rule>
     <from-view-id>/register.jspx</from-view-id>
     <navigation-case>
     <from-outcome>edit</from-outcome>
       <to-view-id>/edit.jspx?javax.portlet.faces.PortletMode=edit</to-view-id>
     </navigation-case>
 </navigation-rule>

Navigating to a mode's last viewId

 

By default a mode change will start in the mode's default view without any (prior) existing state. One common portlet pattern when returning to the mode one left after entering another mode (e.g.. view -> edit -> view) is to return to the last view (and state) of this origin mode. The bridge will explicitly encode the necessary information so that when returning to a prior mode it can target the appropriate view and restore the appropriate state. The session attributes maintained by the bridge are intended to be used by developers to navigate back from a mode to the last location and state of a prior mode. As such a developer needs to describe a dynamic navigation: "from view X return to the last view of mode y". This is most easily expressed via an EL expression such as:

 <navigation-rule>
     <from-view-id>/edit.jspx*</from-view-id>
     <navigation-case>
       <from-outcome>view</from-outcome>
       <to-view-id>#{sessionScope['javax.portlet.faces.viewIdHistory.view']}</to-view-id>
      </navigation-case>
  </navigation-rule>

Note to Portlet Developers

Depending on the bridge implementation, when using values from these session-scoped attributes or any viewIds which may contain query string parameters it may be necessary to use the wildcard syntax when identifying the rule target. For example, the above <to-view-id> expression returns a viewId of the form /viewId?javax.portlet.faces.PortletMode=view&.... Without wildcarding, when a subsequent navigation occurs from this new view, the navigation rules wouldn't resolve because there wouldn't be an exact match.

Likewise, the above edit.jspx <from-view-id> is wildcarded because there are navigation rules that target it that use a query
string (<to-view-id> /edit.jspx?javax.portlet.faces.PortletMode=edit </to-view-id>). Developers are encouraged to use such wildcarding to ensure they execute properly in the broadest set of bridge implementations.

Handling Ajax Errors in a Portlet

By default, error handling is sent to a standard servlet page for Ajax requests. To handle the errorb inside the portlet, use the following javascript:

<script type="text/javascript">
     A4J.AJAX.onError = function(req,status,message){
          window.alert("Custom onError handler "+message); 
     }

     A4J.AJAX.onExpired = function(loc,expiredMsg){
     if(window.confirm("Custom onExpired handler "+expiredMsg+" for a location: "+loc)){
          return loc;
     } else {
          return false;
     }
  }
 </script>

Conclusion

As mentioned before, the portlet bridge community has already started contributing patches and other help to the project in its early beta stages. Although the core of the project is the JSR-301 specification, there is limitless potential to integrating Seam, Richfaces, and Portal with Bridgelets and other supporting enhancements. There are several developers contributing to the project and we extend a special thanks to all of the people who have already contributed patches, enahncements, and helped answer questions on the forums.

In the end, this is a community based project, and the more developers that offer help and feedback, the faster we will get new releases out with better code and enhancements. The GA release is expected in early '09.

Feedback on the forums is extremely useful and welcome. For more information about the JBoss Portlet Bridge project visit the project page and the documentation.

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

SSO In booking portlet throws exception after clicking search by David Paterson

So I've got the SSO bridgelet B6 working with the booking demo. The SSO piece seems to be working. As soon as I click search in the search form I get the following exception, appears related to AJAX call perhaps. Do you have the same problem when you deploy the Booking portlet? Perhaps I've got something configured incorrectly? Seems like some kind of infinite loop is happening:


12:59:33,046 INFO [STDOUT] 2009-01-28 12:59:33,046 INFO [org.jboss.portletbridge.bridge] - Finish rendering portletbridge for namespace jbpns_2fdefault_2fSeamB
ooking_2fseamBookingPortletWindowsnpbj
12:59:38,000 WARN [lifecycle] phase(RESTORE_VIEW 1,org.jboss.portletbridge.context.FacesContextImpl@17627b7) threw exception: java.lang.StackOverflowError null
java.lang.ThreadLocal.getMap(ThreadLocal.java:177)
java.lang.ThreadLocal.get(ThreadLocal.java:125)
javax.faces.context.FacesContext.getCurrentInstance(FacesContext.java:392)
org.jboss.portletbridge.extension.seam.PortalIdentity.getPrincipal(PortalIdentity.java:113)
org.jboss.seam.web.IdentityRequestWrapper.getUserPrincipal(IdentityRequestWrapper.java:33)
org.jboss.portletbridge.context.ServletExternalContextImpl.getUserPrincipal(ServletExternalContextImpl.java:387)
org.jboss.portletbridge.extension.seam.PortalIdentity.getPrincipal(PortalIdentity.java:113)
org.jboss.seam.web.IdentityRequestWrapper.getUserPrincipal(IdentityRequestWrapper.java:33)
org.jboss.portletbridge.context.ServletExternalContextImpl.getUserPrincipal(ServletExternalContextImpl.java:387)
org.jboss.portletbridge.extension.seam.PortalIdentity.getPrincipal(PortalIdentity.java:113)
....

Re: SSO In booking portlet throws exception after clicking search by Wesley Hales

There is a new identity model in Seam 2.1.x and this bridgelet is for the pre 2.1 versions of Seam. It is a known issue and we should have it working in the next bridge release.

Seam Booking Demo not working by Philip Puthenvila

Hi
I am trying t run the seam booking demo. I changed the url to to point to the demo source. repeated all other steps for seamproject, at the end I got the same seamproject portlet. I want to develop an application ,So i decide to go with seam and jsf . what I have to do get the seam hotel booking to run.Please help
Regards
Philip

Re: Seam Booking Demo not working by Mahesh Lavannis

Hi Philip,
FYI - Here is how I got it to work:
I downloaded the Booking example from labs.jboss.com/portletbridge/downloads/ - it is part of the src download for JBoss Portlet Bridge. I ran mvn install in the 'booking' directory, copied the SeamEAR.ear into the server/default/deploy of the JBoss portal server and it works.

Hope this helps,
Mahesh

Re: Seam Booking Demo not working by Mahesh Lavannis

You can also get a maven setup archetype for Seam Portlet here:

www.jboss.org/files/portletbridge/docs/1.0.0.CR...

But I haven't tried it out myself yet.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

5 Discuss

Educational Content

General Feedback
Bugs
Advertising
Editorial
InfoQ.com and all content copyright © 2006-2014 C4Media Inc. InfoQ.com hosted at Contegix, the best ISP we've ever worked with.
Privacy policy
BT