Did you know? DZone has great portals for Python, Cloud, NoSQL, and HTML5!

JSF

  • submit to reddit

RichFaces 4.0

A Next Generation JSF Framework

By Nick Belaevski, Ilya Shailkovsky, Max Katz and Jay Balunas

11,854 Downloads · Refcard 138 of 151 (see them all)

Download
FREE PDF


The Essential RichFaces 4 Cheat Sheet

RichFaces 4.0 is an advanced JSF 2.0 based framework that provides a complete range of rich Ajax enabled UI components as well as a component development kit, dynamic resource support, and skinning. The 4.0 release brings complete JSF 2.0 support to the project. This DZone Refcard will get you started with RichFaces 4.0 and introduce the core JSF 2 extensions, render options, queue, client-side validation, rich tags, client functions, and skinning. It will also cover the component development kit, the rich components JavaScript API, and even Google AppEngine Support.
HTML Preview
RichFaces 4.0 A Next Generation JSF Framework

RichFaces 4.0: A Next Generation JSF Framework

By Nick Belaevski, Ilya Shailkovsky, Max Katz, and Jay Balunas

INTRODUCTION

RichFaces 4.0 is an advanced JSF 2.0 based framework that provides a complete range of rich Ajax enabled UI components, as well as other features such as a component development kit, dynamic resource support, and skinning. The 4.0 version brings complete JSF 2.0 support to the project.

RichFaces is made up of two component tag libraries. “a4j:” represents core Ajax functionality, and page wide controls. While the “rich:” component set represent self contained and advanced UI components such as calendars, and trees.

JavaServer Faces 2.0

The second version of JSF added many features such as, core Ajax functionality, integrated Facelets support, annotations, view parameters, and more. RichFaces 4.0 has been specifically redesigned to not only work with these new features, but to extend them.

Hot Tip

JSF 2.0 is covered in detail in the DZone JavaServer Faces 2.0 Refcard.

GETTING STARTED

RichFaces can be used in any container that JSF 2.0 is compatible with. This means all servers compliant with the EE6 specification ( JBoss AS6/7, Glassfish 3 ) and all major servlet containers (Tomcat, Jetty).

Hot Tip

Check the RichFaces project page for the latest information and downloads: http://richfaces.org

Installing RichFaces

Since RichFaces is build on top of JSF 2.0 its installation is as easy as adding a few jars to your project.

For Maven-based projects configure your repositories following the Maven Getting Started Guide here:
http://community.jboss.org/wiki/MavenGettingStarted-Users

Then simply add the following to you projects pom.xml.


<dependencyManagement>
  <dependencies>
   	<dependency>
	  <groupId>org.richfaces</groupId>
	  <artifactId>richfaces-bom</artifactId>
	  <version>${richfaces.version}</version>
	  <scope>import</scope>
	  <type>pom</type>
	</dependency>
  </dependencies>
</dependencyManagement>
…
<dependency>
  <groupId>org.richfaces.ui</groupId>
  <artifactId>richfaces-components-ui</artifactId>
</dependency>
<dependency>
  <groupId>org.richfaces.core</groupId>
  <artifactId>richfaces-core-impl</artifactId>
</dependency>

For other build systems such as Ant just add the following jars to your projects WEB-INF/lib directory: richfaces-core-api-<ver>.jar, richfaces-core-impl-<ver>.jar, richfaces-components-api-<ver>.jar, richfaces-components-ui-<ver>.jar, sac-1.3.jar, cssparser-0.9.5.jar, and google-guava-r08.jar.

Hot Tip

No filters or other updates to your web.xml are needed to install RichFaces 4.0.

Page Setup

To use RichFaces components in your views add:


xmlns:a4j=”http://richfaces.org/a4j”
xmlns:rich=”http://richfaces.org/rich”

Maven Archetypes

The project also contains several Maven archetypes to quickly create projects (including one for Google App Engine targeted project).

Simple project generation:

mvn archetype:generate
-DarchetypeGroupId=org.richfaces.archetypes
-DarchetypeArtifactId=richfaces-archetype-simpleapp
-DarchetypeVersion=<version> -DgroupId=<yourGroupId>
-DartifactId=<yourArtifactId> -Dversion=<yourVersion>

From the generated project directory you can build, and deploy as with any Maven project.

Hot Tip

Easily import in JBoss Tools using m2eclipse http://jboss.org/tools.

CORE JSF 2 EXTENSIONS

a4j:ajax

Upgrades the standard f:ajax tag/behavior with more features.


<h:inputText value=”#{bean.input}”>
  <a4j:ajax execute=”#{bean.process}” render=”#{bean.update}”/>
</h:inputText>
<h:panelGrid id=”list1”>...</h:panelGrid>

Execute & Render EL Resolution

JSF 2.0 determines the values for execute and render attributes when the current view is rendered. In the example above if #{bean.update} changes on the server the older value will be used. RichFaces processes attribute values on the server side so you will always be using the most current value.

Addition Common Enhancements

All RichFaces components that fire Ajax requests share the features above, and all of the ones from below:

Attribute Description
limitRender Turns off all auto-rendered panels (see Render Options section).
bypassUpdates When set to true, skips Update Model and Invoke Application phases. Useful for form validation requests.
onbegin JavaScript code to be invoked before Ajax request is sent.
onbeforedomupdate JavaScript code to be invoked after response is received but before Ajax updates happen.
oncomplete JavaScript code to be invoked after Ajax request processing is complete.
status Name of status component to show during Ajax request.

a4j:commandButton, a4j:commandLink

Similar to standard h:commandButton and h:commandLink tags but with Ajax behavior built-in.


<a4j:commandButton value=”Add”
  action=”#{bean.add}” render=”cities”/>
<h:panelGrid id=”cities”>...</h:panelGrid>

Hot Tip

Default execute value for both controls is @form.

a4j:poll

Periodically fires an Ajax request based on polling interval defined via interval attribute and can be enabled/disabled via enabled attribute (true|false). For example, in the following code snippet, an Ajax request will be sent every 2 seconds and render the time component:


<a4j:poll interval=”2000” enabled=”#{bean.active}”
	action=”#{bean.count}” render=”time”/>
<h:outputText id=”time” value=”#{bean.time}”/>

a4j:jsFunction

Allows the sending of an Ajax request from any JavaScript function.


<a4j:jsFunction name=”setdrink” render=”drink”>
  <a4j:param name=”param1” assignTo=”#{bean.drink}”/>
</a4j:jsFunction>
...
<td onmouseover=”setdrink(‘Espresso’)”
	onmouseout=”setdrink(‘’)”>Espresso</td>
<h:outputText id=”drink” value=”I like #{bean.drink}” />

When the mouse hovers or leaves a drink, the setdrink() JavaScript function is called. The function is defined by an a4j:jsFunction tag which sets up standard Ajax call. You can also invoke an action. The drink parameter is passed to the server via a4j:param tag.

a4j:status

Displays Ajax request status. The component can display content based on Ajax start, stop, and error conditions. Status can be defined in the following three ways: status per view, status per form and named statuses. The following example shows named status:


<a4j:status name=”ajaxStatus”>
	<f:facet name=”start”>
	  <h:graphicImage value=”/ajax.gif” />
	</f:facet>
</a4j:status>
<a4j:commandButton value=”Save” status=”ajaxStatus”/>

All RichFaces controls which fire an Ajax request have status attribute available.

a4j:repeat

Works just like ui:repeat but also supports partial table update (see Data Iteration):


<ul>
 <a4j:repeat value=”#{bean.list}” var=”city”>
	<li>#{city.name}</li>
 </a4j:repeat>
</ul>

a4j:push

“Push” server-side events to client using Comet or WebSockets. This is implemented using Atmosphere (http://atmosphere.java.net), and uses JMS for message processing (such as JBoss’s HornetQ - http://www.jboss.org/hornetq). This provides excellent integration with EE containers, and advanced messaging services.

The <a4j:push> tag allows you to define named topics for messages delivery and actions to perform:


<a4j:push address=”topic@chat”
	ondataavailable=”alert(event.rf.data)” />

Server side messages are published and topics are created/configured using a class similar to this:


@PostConstruct
public void init() {
	topicsContext = TopicsContext.lookup();
}
private void say(String message) throws
	MessageException {
	TopicKey key = new TopicKey(“chat”,”topic”);
	topicsContext.publish(key, message);
}
private void onStart() {
	topicsContext.getOrCreateTopic(new
		TopicKey(“chat”));
}	

For more details on usage and setup, including examples please see the RichFaces Component Guide (http://docs.jboss.org/richfaces/latest_4_0_X/Component_Reference/en-US/html/).

a4j:param

Works like <f:param> also allows client side parameters and will assign a value automatically to a bean property set in assignTo :


<a4j:commandButton value=”Select”>
  <a4j:param value=”#{rowIndex}”
	assignTo=”#{bean.row}”/>
</a4j:commandButton>	

a4j:log

Client-side Ajax log and debugging.


<a4j:log/>

ajaxlog

a4j:region

Provides declarative definition of components to be executed during Ajax request instead of using component ids. The following example wouldn’t work without a4j:region as no execute ids are defined on the a4j:poll which defaults to execute=”@this”:


<a4j:region>
	<a4j:poll interval=”10000”/>
	<h:inputText value=”#{bean.name}”/>
	<h:inputText value=”#{bean.email}”/>
</a4j:region>

If components are wrapped inside a4j:region without execute id defined, then the default value is execute=”@region”. You can also explicitly set execute=”@region”.

RENDER OPTIONS

In addition to supporting the standard render attribute in all controls which fire an Ajax request, RichFaces provides a number of advanced rendering options.

a4j:outputPanel

<a4j:outputPanel ajaxRendered=”true”> is an auto-rendered panel. All child components within a4j:outputPanel will be rendered on any Ajax request. There is no need to point to the panel via the render attribute.


<a4j:outputPanel ajaxRendered=”true”>
	<h:outputText />
	<h:dataTable>...</h:dataTable>
<a4j:outputPanel>

In example above, all components within a4j:outputPanel will be always rendered. Note that ajaxRendered must be set to true.

Limiting Rendering

To limit rendering to only components set in current render list, set limitRender=”true”. In the following example, only components c1 and c2 will be rendered (a4j:outputPanel update is turned off):


<a4j:commandLink render=”c1, c2” limitRender=”true”/>
<h:outputText id=”c1”/>
<h:panelGrid id=”c2”></h:panelGrid>
<a4j:outputPanel ajaxRendered=”true”>
	<h:dataTable>...</h:dataTable>
</a4j:outputPanel>

limitRender=true turns off all auto-rendered containers (a4j:outputPanel, rich:message(s)).

QUEUE

JSF 2 provides a basic client request queue out-of the box. RichFaces extends the standard JSF queue, and provides additional features to improve usability.

The RichFaces queue is defined via the a4j:queue tag. Queues can be named or unnamed as described below.

Named Queue

Named queues are given a name and will only be used by components which reference them directly:


<a4j:queue name=”ajaxQueue”>
<h:form>
	<a4j:commandButton>
	  <a4j:attachQueue name=”ajaxQueue”/>
	</a4j:commandButton>
</h:form>

Unnamed Queue

Unnamed queues are used to avoid having to reference named queues for every component and come with the following scopes: global, view, form.

Global level

Global queue is available on all the views and defined in web.xml file:


<context-param>
	<param-name>
	org.richfaces.queue.enabled</param-name>
	<param-value>true</param-value>
</context-param>

View level

Placed outside any form. All Ajax control on the view will use this queue:


<a4j:queue/>
<h:form>...</h:form>

Form-level

Queue definition is placed inside a form. All controls inside the form will use this queue:


<h:form>
<a4j:queue/>
</h:form>

Queue Attributes

Attribute Description
requestDelay Will delay sending the request by that number of millisecond. <a4j:queue requestDelay=”3000”/>
Used to “wait” to combine requests from the same request group
requestGroupingId Combines two or more controls into the same request group.
Requests from this group are treated as if coming from the same “logical” component. <a4j:attachQueue requestGroupingId=”grp1”/>
ignoreDupResponses Response processing for requests will not occur if a similar request is already waiting in the queue, saving the client side processing.

There are two ways to set queue options. Directly on a4j:queue tag:


<a4j:queue name=”ajaxQueue” requestDelay=”3000”/>

Or attaching a4j:attachQueue behavior to Ajax components:


<a4j:queue/>
<a4j:commandButton>
  <a4j:attachQueue requestDelay=”3000”
	requestGroupingId=”ajaxGroup”>
</a4j:commandButton>

CLIENT-SIDE VALIDATION

Bean Validation

Bean Validation (JSR-303) provides a tier agnostic approach to define constraints on model objects. Every tier must then validate those constraints. There are a set of built in constraints, defined by the Bean Validation specification. JSF 2.0 has built in Bean Validation support, but only with server side validation.

rich:validator

RichFaces 4.0 provides true client side validation that seamlessly integrates into JSF 2.0 Bean Validation support. There is an Ajax server side fallback mechanism if client side validation is not possible.

There are two ways to set queue options. Directly on a4j:queue tag:


<a4j:queue name=”ajaxQueue” requestDelay=”3000”/>

Or attaching a4j:attachQueue behavior to Ajax components:


<a4j:queue/>
<a4j:commandButton>
	<a4j:attachQueue requestDelay=”3000”
	  requestGroupingId=”ajaxGroup”>
</a4j:commandButton>

CLIENT-SIDE VALIDATION

Bean Validation

Bean Validation (JSR-303) provides a tier agnostic approach to define constraints on model objects. Every tier must then validate those constraints. There are a set of built in constraints, defined by the Bean Validation specification. JSF 2.0 has built in Bean Validation support, but only with server side validation.

rich:validator

RichFaces 4.0 provides true client side validation that seamlessly integrates into JSF 2.0 Bean Validation support. There is an Ajax server side fallback mechanism if client side validation is not possible.

Object constrained using Bean Validation

public class Foo{
	...
	@NotNull
	@Pattern(regexp=”^\d{5}(-\d{4})?$”)
	private String zipcode;
	...
}

Client side validation on a specific field

<h:inputText id=”input” value=”#{foo.zipcode}>
	<rich:validator event=”keyup”>
</h:inputText>
<rich:message for=”input” ..../>

Hot Tip

rich:message is required for client-side message updates.

The client side versions of constraints, converters, and messages must be implemented for this to work. All standard bean validation constraints are supported.

Hot Tip

Additional constraints and features will be added in the future.

Object Validation

Validate complete objects allowing for complex validation such as cross-field validation before the model gets updated (i.e. in the validation phase). Supports bean validation, but does not support client side validations at this time.

New password validation

<rich:graphValidator “value=”#{passwordBean}”>
	<h:inputText “value=”#{passwordBean.password}” />
	<h:inputText “value=”#{passwordBean.retypePassword}” />
</rich:graphValidator>

PasswordBean Implementation

public class PasswordBean implements Cloneable {

@Size(min=6) @GoodPassword
private String password ;

@Size(min=6)
private String retypePassword ;

@AssertTrue(message=”Passwords do not match”)
public boolean match(){
	return password.equals(retypePassword);
}}

The password bean is cloned, updated, and validated all in the validation phase, allowing only clean data to move to the update model phase.

RICH:* TAGS

Inputs and Selects:

Tag

Component Description
inplaceInput,inplaceSelect Inplace editing components.
inputNumberSpinner,
inputNumberSlider
UI controls for numerical input.
autocomplete Input component with live suggestions.
select Advanced select control. Provides skinning and direct typing feature.
calendar Advanced Date and Time input with various customization options.
fileUpload Asynchronous multiple files upload control.

Output

overview

Component Description
panel, popupPanel,collapsiblePanel Simple panels with header. Expansion, collapse, modal and non modal popups.
tabPanel, accordion,togglePanel Complex switchable panels.
tooltip, progressBar, message,messages Various status/message/ indication components.

Data Iteration

Data Iteration

Component Description
dataTable Customizable table with collapsible master-detail layouts, with sorting, filtering, partial Ajax updates.
extendedDataTable Additional features of: ajax scrolling, frozen columns, rows selection, columns re-adjustment and switching visibility.
list Allows dynamic rendering of any kind of HTML lists.
dataGrid panelGrid analog with dynamic models support
dataScroller paging support for any iteration component

Child components: column, columnGroup, collapsibleSubTable.

Trees

trees

Component Description
tree Rendering of hierarchical data in a tree control. Built in selection and nodes lazy loading.
treeNode Defines representation for a node of a concrete type.
treeModelAdaptor,treeModelRecursiveAdaptor Declarative definition of tree data model from various data structures.

Menus

menu

Component Description
panelMenu Vertical page menu.
dropDownMenu Drop-down menu for popup menus creation.
toolbar Laying out drop-down menus or just menu items.

Child component for content definition: panelMenuItem, panelMenuGroup,menuItem, menuGroup, menuSeparator, toolbarGroup.

Drag and Drop

Component Description
dragSource Add dragging capabilities to the parent component.
dropTarget Marks parent component as target for Ajax drop processing.
dragIndicator Visualization for dragged element.

Misc

Component Description
jQuery Declarative jQuery calls definitions.
componentControl Calling any RichFaces component client-side API.

CLIENT FUNCTIONS

RichFaces provides a number of client-side functions which make it easy to access elements in the browser.

Function Description/Example
rich:clientId(‘id’) Returns client id.
#{rich:client(‘id’)} returns form:id
rich:element(‘id’) Shortcut for
document.getElementById(#{rich:clientId(‘id’)})
rich:component(‘id’) Used to invoke client-side component JavaScript API.
rich:findComponent(‘id’)

Returns an instance of UIComponent taking the
component id.
<h:inputText id=”in”>
  <a4j:ajax />
</h:inputText>
<a4j:outputPanel
  ajaxRendered=”true”>
  #{rich:findComponent(‘in’) .value}
</a4j:outputPanel>

rich:isUserInRole(‘role’) Returns true or false whether current user is in specified role.

RICH COMPONENTS JS API

Using rich:component(‘id’)

Many rich components come with client-side JavaScript API. To use the API, get a reference to the client JavaScript object and invoke the available methods. Full description of each component API can be found in RichFaces Component Guide1. In the following example, show() and hide() method are used to show/hide panel:


<h:outputLink onclick=”#{rich:component(‘pnl’)}.show();”>
	Open
</h:outputLink>
<rich:popupPanel id=”pnl”>
  <h:outputLink onclick=”#{rich:component(‘pnl’)}.hide();”>
	Hide
  </h:outputLink>
</rich:popupPanel>

Using rich:componentControl

An alternative and more declarative approach to call JavaScript API is to use rich:componentControl:


<h:outputLink value=”#”>
  <h:outputText value=”Open” />
  <rich:componentControl operation=”show”
	  target=”pnl” event=”click”/>
</h:outputLink>
<rich:popupPanel id=”pnl”>
 <h:outputLink value=”#”>
    <h:outputText value=”Close” />
	  <rich:componentControl event=”click”
		target=”pnl” operation=”hide”/>
	</h:outputLink>
</rich:popupPanel>

SKINNING

skinning

Basic Architecture

The same three-level hierarchy that is used for RF 3.3.X is used here:

Skin parameters: configure an application-wide look and feel using dozens of parameters.

rf-* classes: added to all the components to provide a default look and feel based on parameters. To be used for redefinitions.

*Class: attributes on components.

New ECSS File Formats

Components use new *.ecss format of stylesheets:


.rf-pnl {
	color:’#{richSkin.panelBorderColor}’;
}

  1. Same CSS under the hood
  2. Dynamic properties using EL expressions

Out-of-the-box Skins

Richfaces provides various skins out of the box:

blueSky, classic, deepMarine, emeraldTown, japanCherry, plain, ruby, wine.

Application Skin Parameter Definition

To have the ability to change skin at runtime use a context parameter in the web.xml:


<context-param>
	<param-name>org.richfaces.skin</param-name>
	<param-value>#{skinBean.skin}</param-value>
</context-param>

The param-value from listing below could be just static string name. (e.g. bluesky).

Skinning Standard Components and Elements

With org.richfaces.enableControlSkinning context parameter set to true all the standard and third-party components will become skinned.

Usage of Skin Parameters on the Page

You could use implicit richSkin object in order to access skin parameters on the pages:


<h:button style=”background-color:’#{richSkin.tableBackgroundColor}’” .../>

The Same as CSS

It is the same as for usuall CSS:

<h:outputStylesheet name=”panel.ecss”/>

or


@ResourceDependency(name = “panel.ecss”)

Skinning using Static Resources

Finally you are able to serve our dynamic skins in a static way (E.g. using CDN):

  1. Add org.richfaces.cdk:maven-resources-plugin to build.
  2. Configure it. You should define directory which should be used to store generated recourses, skin names which should be processed, resources types to be included and so on… Refer to RichFaces GAE archetype or richfaces-showcase pom.xml files for getting complete code.
  3. Define static resources location via org.richfaces. staticResourceLocation context parameter using implicit resourceLocation variable in web.xml

COMPONENT DEVELOPMENT KIT

RichFaces CDK has been developed to boost productivity by providing easy-to-use environment for simplifying common components development tasks. Main features are:

  • Very easy creation and maintenance of classes such as component,converter, validator, etc.
  • Generation of renderer classes from files with VDL-like syntax.
  • Easy-to-use annotation—or XML-based configuration following Convention-over-Configuration principles.
  • Generation of XML configuration files.

GOOGLE APPLICATION ENGINE SUPPORT

Google Application Engine deployments require specific changes to be done at the application level mostly because of GAE’s restrictions and issues related to JSF deployment.

Archetype Usage

RichFaces provides a special archetype to generate an application skeleton for GAE deployments:


mvn archetype:generate -DarchetypeGroupId=org.richfaces.archetypes
-DarchetypeArtifactId=richfaces-archetype-gae -DarchetypeVersion=<archetyp
eVersion>
-DgroupId=<yourGroupId> -DartifactId=<yourArtifactId> -Dversion=1.0-
SNAPSHOT

Now you can run mvn install as usually to build application and use mvn gae:deploy for deployment.

Deployment Requirements

Exploring the application generated by the archetype is the easiest way to check settings which are required to be done for deployment. It includes:

  • static resources for skins has to be used as GAE not allows Java2D usage (see skinning section for details)
  • GAE-specific web.xml settings added

About The Authors

The Authors

Ilya Shaikovsky

Publications: DZone Richfaces 3 Refcard co-author
Projects: RichFaces, JBoss Tools

Nick Belaevski

Publications: DZone Richfaces 3 Refcard co-author
Blog: http://jroller.com/a4j, http://in.relation.to/Bloggers/Ilya
Twitter: http://twitter.com/ilya_shaikovsky

Jay Balunas

Publications: DZone RichFaces 3 Refcard co-author
Projects: RichFaces, Seam, Weld, and TattleTale
Blog: http://in.relation.to/Bloggers/Jay
Twitter: http://twitter.com/tech4j

Max Katz

Publications: DZone, TheServerSide, Practical RichFaces (Apress), DZone RichFaces 3 Refcard co-author
Projects: Flamingo, jsf4birt, Fiji, JavaFX plug-in for Eclipse on exadel.org, Interactive HTML prototypes: http://gotiggr.com
Blog: http://mkblog.exadel.com
Twitter: http://twitter.com/maxkatz

Recommended Book

Practical RichFaces

RichFaces 4.0 is an advanced JSF 2.0 based framework that provides a complete range of rich Ajax enabled UI components, as well as other features such as a component development kit, dynamic resource support, and skinning. The 4.0 version brings complete JSF 2.0 support to the project.

Practical RichFaces 4 describes how the new RichFaces 4 upgrades and extends JSF 2 with new features, advanced functionality and customization. Learn how to use a4j:* tags, rich:* tags, component JavaScript API, skins, and client-side validation. Assuming some JSF background, it shows you how you can radically reduce programming time and effort to create rich enterprise Ajax based applications.

In this definitive RichFaces 4 book, the authors bases all examples on Maven so that any IDE can be used—whether it’s NetBeans, Eclipse, IntelliJ or JBoss Tools.

Share this Refcard with
your friends & followers...

DZone greatly appreciates your support.


Your download should begin immediately.
If it doesn't, click here.

Mastering Portals with a Portlet Bridge

By Wesley Hales

6,758 Downloads · Refcard 132 of 151 (see them all)

Download
FREE PDF


The Essential JBoss Portlet Bridge Cheat Sheet

Portals have long been a thorn in the side of many developers who want to stay cutting edge, but most focus on the needs of the enterprise. About 99% of the time, a portal is the only answer for aggregating many applications into a single UI. A portlet bridge allows you to run application frameworks like JSF in a portal environment without worrying about the underlying portlet API or portlet concepts. Portlet bridge is a must-have mediator when working with portals, and it allows developers to learn a new technology painlessly. This Refcard provides specific configurations for the JBoss Portlet Bridge.
HTML Preview
Mastering Portals with a Portlet Bridge

Mastering Portals with a Portlet Bridge

By Wesley Hales

ABOUT PORTLET BRIDGES

Portals have long been a thorn in the side of many developers who want to stay cutting edge—but must focus on the needs of the enterprise. And 99% of the time, a portal is the only answer for aggregating many applications into one UI.

A portlet bridge allows you to run application frameworks like JSF in a portal environment without worrying about the underlying portlet API or portlet concepts.

The JSR-301/329 portlet bridge boasts ease of transition, ease of initiation, and seamless mappings from JSF to the portal environment. Overall, a portlet bridge is a must-have mediator when working with portals, and it allows developers to learn a new technology painlessly.

ABOUT THE JBOSS PORTLET BRIDGE

This refcard shows specific configurations for the JBoss Portlet Bridge. The JBoss Portlet Bridge is a non-final draft implementation of the JSR-329 specification which supports the JSF 1.2 and 2.0 runtime within a JSR 168 or 286 portlet and with added enhancements to support other web frameworks (such as Seam and RichFaces).

The project follows the spec from JSR-301 to JSR-329 and now maintains an alpha version (3.0) compatible with JSF 2.0 and RichFaces 4.0.

Versions

Since this portlet bridge spans four different JSRs and supports two additional JSF frameworks, understanding versions can be a little daunting. i.e. Just because the portlet bridge is versioned at 2.0 does not mean it covers the JSF 2.0 specification.

JBoss Portlet Bridge Latest Versions Compatible Frameworks
2.1.0.FINAL JSR-286 Portlets, JSF 1.2, RichFaces 3.3.3.FINAL,Seam 2.2.1.CR2
3.0.0.ALPHA SR-286 Portlets, JSF 2.0, RichFaces 4.0

IN THE BEGINNING, THERE WERE PORTLETS

It would only be fair (and cruel in some states) if I gave you a brief primer on portal and portlet technologies. There will come a day when you will need to understand what an ActionRequest is and what you can pull from your FacesContext.ExternalContext() while running as a JSF portlet.

Portal Terminology

Portal

Hosts the presentation layer for personalization, single sign on and content aggregation.

Portlet Container

A portal can host multiple portlet containers, and each portlet container has its own runtime environment.

Portal Page: Aggregation of portlets, organized and displayed on a single page.

Portlet: A portlet is a Java technology-based web component, managed by a portlet container, that processes requests and generates dynamic content.

Portlet Instance: A portlet instance can be placed on multiple pages and will show the same state in regards to the current mode.

Portlets vs. Servlets

Most rookie portlet developers have their roots in the servlet world. So it’s important to know the key differences in what you’re about to dive into from what you’ve been dealing with. Portlets generate a portion or “fragment” of the HTML page they’re being displayed upon. This is the first big bullet point in understanding differences between servlets and portlets. UI wise, they cannot make use of the same html (for instance the standard <html> <head> <title> and <body> are forbidden in the portlet markup). The job of writing these tags belongs to the Portal Page and not you, the developer.

Points To Remember
  • Portlet URLs, which are used as links to other pages within your Portlet window, are dynamically pre-generated by the Portlet code and passed into the markup.
  • Although servlets and portlets are in some respects similar, their containers and lifecycles differ.
  • On the front end, portlets are HTML fragments that compose a larger page which they are unaware of. Servlets provide the entire page.
  • Portlets cannot be accessed by use of a single URL, the way in which servlets are accessed. Instead, the URL points to the page where many portlets may be contained.
  • The portal request paradigm is completely different. There are two requests instead of one. This is talked about in the next section.
  • You now have mode and state buttons that allow you to “minimize” or “maximize” the portlet window or enter “help” mode.
  • Portlets support two scopes within the session (PORTLET_SCOPE and APPLICATION_SCOPE). This allows for cases like sharing data from one portlet to another.
  • Portlets are not allowed to set character encoding on the response, set HTTP headers, or manipulate the URL of the client request to the portal.
Portlet Lifecycle

Once you wrap your head around the fact that there are two requests and the Portal sends them for you, the rest is a piece of cake. What I’m about to explain makes total sense, but it’s a huge change from the way things are done in a Servlet-based web app. In the Servlet world, a Servlet owns the process of receiving an entire web request and rendering output at the same time in one big response. In the Portlet world, the Portal receives the web request then makes separate calls to individual portlets. This separation allows for a different lifecycle method to be introduced in Portlets. The two requests are called Action and Render, and each have their own request and response. You must first keep in mind that when you click a link or submit button in the portlet window, it has been generated by the portal API. Thus, the portal needs to control/remember things like which window is sending the request, modes, parameters, window states, etc. So when an Action link is clicked, the portal will get this information and run processAction() along with a few other methods in your portlet. You are guaranteed that this action will be complete before the rendering phase starts. Once this is done, the portal now needs to re-render the page along with all the other portlets on that page. The best thing to keep in mind is portlets may be asked to render, even when the user is not interacting with them. Conceptually, this makes sense to have the two requests. However, developers have been naturally forced to do both of these things at the same time in the servlet world.

In most cases, when converting an existing servlet based application to a portlet, you must use a portlet bridge so that URLs are generated for the portlet world—along with other framework functionality.

GIVING PORTLETS A SECOND CHANCE

If You Skipped The First Page...

It’s okay because the portlet bridge is created to mask all of those hairy details from the developer so you only have to worry about your web application. You can now take your existing JSF-based application and plug it into a portal painlessly.

Getting Started

Use the following maven archetype command:


mvn archetype:generate
-DarchetypeCatalog=http://bit.ly/jbossportletbridge

frame 1

Choose from the available projects and you will have everything you need to start developing a new portlet. If you are moving an existing application to a portlet, this will serve as a reference point for configuration.

Archetype Options

You will also see other configuration options like “makeremotable” and “richfaces-javascript-namespace” in the archetype generate phase.

Option Purpose
make-remotable Boolean property that will create the configuration for running this portlet remotely over WSRP
richfaces-javascriptnamespace Boolean property that allows for namespacing dynamically generated RichFaces javascript.

CONFIGURATION

The portlet bridge is a mediator between your web application and the portal worlds. It is not a portlet. So here we will review the changes you must make to convert your current JSF application into a portlet.

Core JSF Portlet Setup

portlet.xml

The following config is the backbone of your portlet. It shows where the supplied GenericFacesPortlet is and which JSF pages to render when clicking on the mode buttons (i.e. help, edit, etc...).


<portlet>
<portlet-name>yourPortletName</portlet-name>
<portlet-class>
	javax.portlet.faces.GenericFacesPortlet
</portlet-class>
<init-param>
	<name>javax.portlet.faces.defaultViewId.view</name>
	<value>/welcome.xhtml</value>
</init-param>
<init-param>
	<name>javax.portlet.faces.defaultViewId.edit</name>
	<value>/jsf/edit.xhtml</value>
</init-param>
<init-param>
	<name>javax.portlet.faces.defaultViewId.help</name>
	<value>/jsf/help.xhtml</value>
</init-param>

When preserveActionParams is set to TRUE, the bridge must maintain any request parameters assigned during the portlet’s action request. You should set this as true if your application is not receiving request parameters that were set when a button or link was clicked.


<init-param>
	<name>javax.portlet.faces.preserveActionParams</name>
	<value>true</value>
</init-param>

faces-config.xml

The PortletViewHandler ensures that each JSF portlet instance is properly namespaced. Your application will use a combined portal and JSF namespace.


<faces-config>
<application>
	<view-handler>
	  org.jboss.portletbridge.application.PortletViewHandler
	</view-handler>
	<state-manager>org.jboss.portletbridge.application.
PortletStateManager</state-manager>
</application>

web.xml

The following setting tells your portlet to use the FaceletPortletViewHandler when using RichFaces.


<context-param>
	<param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
	<param-value>org.jboss.portletbridge.application.
FaceletPortletViewHandler</param-value>
</context-param>

ALWAYS_DELEGATE Indicates the bridge should not render the view itself but rather always delegate the rendering. This is the default setting for Facelets. If strictly using .jsp, then set the following to NEVER_DELEGATE.


<context-param>
	<param-name>javax.portlet.faces.RENDER_POLICY</param-name>
	<param-value>
	   ALWAYS_DELEGATE
	</param-value>
</context-param>

RichFaces Portlet Configuration

web.xml

RichFaces maintains dynamic scripts and styles that are injected in the page at render. The recommended settings for a portal environment are:


<context-param>
	<param-name>org.richfaces.LoadStyleStrategy</param-name>
	<param-value>DEFAULT</param-value>
</context-param>
<context-param>
	<param-name>org.richfaces.LoadScriptStrategy</param-name>
	<param-value>ALL</param-value>
</context-param>

RichFaces does not account for multiple components on the same portal page by default. This following parameter renders all RichFaces component javascript to be portal friendly.


<context-param>
	<param-name>org.jboss.portletbridge.WRAP_SCRIPTS</param-name>
	<param-value>true</param-value>
</context-param>

Seam automatically configures your Ajax4JSF/RichFaces Filter, so if you are running a Seam portlet, you do not need the following Filter config.


<filter>
	<display-name>Ajax4jsf Filter</display-name>
	<filter-name>ajax4jsf</filter-name>
	<filter-class>org.ajax4jsf.Filter</filter-class>
</filter>

	<filter-mapping>
	<filter-name>ajax4jsf</filter-name>
	<servlet-name>FacesServlet</servlet-name>
	<dispatcher>FORWARD</dispatcher>
	<dispatcher>REQUEST</dispatcher>
	<dispatcher>INCLUDE</dispatcher>
</filter-mapping>

Seam Portlet Configuration

Hot Tip

It’s important to remember that your portlet may be rendered many times. Since Seam page actions are performed on the RenderRequest, you should only define your navigation in pages.xml.

The SeamExceptionHandler is used to clean Seam contexts and transactions after errors.


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

USING PORTLET 2.0 COORDINATION WITH JSF

Portlet container

Portlet 2.0 coordination gives us two ways to communicate between portlets (events and public render parameters). This means you can deploy a JSF 2 war and another JSF 1.2/Seam 2 ear and they can send events and messages to each other.

One very important thing to note before using either of the following mechanisms is that you must have the proper 2.0 schema and xsd definition at the top of your portlet.xml.


<portlet-app xmlns=”http://java.sun.com/xml/ns/portlet/portletapp_
2_0.xsd”
	version=”2.0”
	xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
	xsi:schemaLocation=”http://java.sun.com/xml/ns/portlet/
portlet-app_2_0.xsd
http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd”>

Hot Tip

Portlet events and public render parameters cannot be set during Ajax requests.

Sending and Receiving Events

The bridge is designed by default to defer to normal portlet processing when sending events. You should set the following parameters allowing portlet events to be sent directly to the bridge (autoDispatchEvents) and which class should process received portlet events (bridgeEventHandler).


<init-param>
	<name>javax.portlet.faces.autoDispatchEvents</name>
	<value>true</value>
</init-param>
<init-param>
	<name>javax.portlet.faces.bridgeEventHandler</name>
	<value>org.foo.eventhandler</value>
</init-param>

For now, you must dispatch the event in the JSF or Seam backing bean. Future versions of the bridge should automate the dispatching and consuming of events.


if (response instanceof StateAwareResponse) {
	StateAwareResponse stateResponse = (StateAwareResponse)
response;
	stateResponse.setEvent(Foo.QNAME, new Bar());
}

Then you must also create the event handler class by implementing the BridgeEventHandler interface to process the event payload.


public class BookingEventHandler implements BridgeEventHandler
  {
public EventNavigationResult handleEvent(FacesContext context,
Event event)
	{
		//process event payload here
	}
  }

Public Render Parameters

Public Render Parameters (or PRPs) are one of the most powerful and simple Portlet 2.0 features. Several portlets (JSF or not) can share the same render parameters. This feature can be used to present a cohesive UI to the user across all portlets on the page (i.e., using an employee ID to display relative data).

The bridge maps a render parameter to a backing bean using settings in your faces-config.xml and portlet.xml. A clear and working example can be found below.

You must define the following init params in your portlet.xml.


<init-param>
<name>javax.portlet.faces.bridgePublicRenderParameterHandler</name>
<value>org.foo.PRPHandler</value>
</init-param>
...
<supported-public-render-parameter>hotelName</supported-publicrender-
parameter>


Create a managed bean and public-parameter-mapping in your faces-config.xml. This should be a simple bean that you can bind the passed parameter to a string with getter and setter.


<managed-bean>
	<managed-bean-name>bookingPRP</managed-bean-name>
	<managed-bean-class>your.class.Name</managed-bean-class>
	<managed-bean-scope>session</managed-bean-scope>
</managed-bean>

<application>
  <application-extension>
	 <bridge:public-parameter-mappings>
	   <bridge:public-parameter-mapping>
		 <parameter>portletName:hotelName</parameter>
		 <model-el>#{bookingPRP.hotelName}</model-el>
	   </bridge:public-parameter-mapping>
	 </bridge:public-parameter-mappings>
  </application-extension>
</application>

Hot Tip

The <parameter> must contain the name of your portlet followed by the parameter name defined in <supportedpublic- render-parameter> from the portlet.xml.

You can set the public render parameter in the JSF or Seam backing bean as follows:


if (response instanceof StateAwareResponse) {
	StateAwareResponse stateResponse = (StateAwareResponse) response;
	stateResponse.setRenderParameter(“hotelName”,selectedHotel.
getName());
}

And finally, in the receiving portlet, you must also implement the BridgePublicRenderParameterHandler interface to process any updates from the received parameter.


public void processUpdates(FacesContext context)
{
ELContext elContext = context.getELContext();
BookingPRPBean bean = (BookingPRPBean) elContext.getELResolver().
getValue(elContext, null, “bookingPRP”);
if(null != bean){
  //Do something with bean.getHotelName());
} else {
}
}

Hot Tip

You can find a working example using all coordination features running on JSF 1.2, RichFaces and Seam here: http://bit.ly/seambooking

SERVING JSF RESOURCES, THE PORTLET WAY

The below example shows how to create a simple bean that uses the portlet resource serving mechanism within a JSF portlet.

By creating a simple class (and defining it in your faces-config.xml) that implements the java.util.Map interface, you can create a “ResourceBean” that will make life much easier on the UI.


public String get(Object key) {
	FacesContext facesContext = FacesContext.getCurrentInstance();
	String url = null;
	if(null == key){
		url = null;
	} else if(null != facesContext){
		url = facesContext.getApplication().getViewHandler().
 getResourceURL(facesContext, key.toString());
		url = facesContext.getExternalContext().encodeResourceURL(url);
	} else {
		url = key.toString();
	}
	  return url;
	}
}

From here, you can serve images and other resources based in your web application by using:


#{resource[‘/img/the-path-to-my-image.png’]}

The source for this example can be found here: http://bit.ly/resourcebean

DEVELOPER TIPS & TRICKS

Excluding Attributes from the Bridge Request Scope

When your application uses request attributes on a per request basis and you do not want that particular attribute to be managed in the extended bridge request scope, you must use the following configuration in your faces-config.xml. Below you will see that any attribute namespaced as foo.bar or any attribute beginning with foo.baz(wildcard) will be excluded from the bridge request scope and only be used per that application’s request.


<application>
<application-extension>
  <bridge:excluded-attributes>
	<bridge:excluded-attribute>foo.bar</bridge:excludedattribute>
attribute>
	<bridge:excluded-attribute>foo.baz.*</bridge:excludedattribute>
attribute>
	</bridge:excluded-attributes>
</application-extension>
</application>

Hot Tip

“From The Spec...” To support Faces, the bridge is responsible for encoding portlet (action) responses in a manner that allows it (and Faces) to reestablish the request environment that existed at the end of the corresponding action phase during subsequent render requests that are identified as pertaining to that action (or event). The term used to describe the scope of this managed data is the bridge request scope.

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>

Hot Tip

PortletMode changes require an ActionRequest, so they cannot change modes during an Ajax or ResourceRequest.

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. E.g.


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


Hot Tip

You should always wildcard your viewId’s as shown in the above from-view-id. Developers are encouraged to use such wildcarding to ensure they execute properly in the broadest set of bridge implementations.

Clearing The View History When Changing Portlet Modes

By default, the bridge remembers the view history when you switch to a different portlet mode (like “Help” or “Edit”). You can use the following parameter in your portlet.xml to use the default viewId each time you switch modes.


<init-param>
	<name>javax.portlet.faces.extension.resetModeViewId</name>
	<value>true</value>
</init-param>

General Error Handling

Hot Tip

If you’re developing a Seam portlet, you can continue to use pages.xml for all error handling.

The following configuration may be used to handle exceptions. This is also useful for handling session timeout and ViewExpiredExceptions. Pay attention to the location element. It must contain the /faces/ mapping to work properly.


<error-page>
	<exception-type>javax.servlet.ServletException</exception-type>
	<location>/faces/error.xhtml</location>
</error-page>
<error-page>
	<exception-type>javax.faces.application.ViewExpiredException</
exception-type>
	<location>/faces/error.xhtml</location>
</error-page>

Custom Ajax Error Handling

By default, error handling is sent to a standard servlet page for Ajax requests. To handle the error 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>

Also, add the following to web.xml.


<context-param>
	<param-name>org.ajax4jsf.handleViewExpiredOnClient</param-name>
	<param-value>true</param-value>
</context-param>

Hot Tip

Remember to provide a link to the normal flow of your JSF application from your error page. Otherwise, the same error page will be displayed forever.

Communication Between Your Portlets

There are roughly 4 different ways to send messages, events, and parameters between portlets which are contained in different ears/wars or contained in the same war. The Portlet Container does not care if you have 2 portlets in the same war or if they are separated, because each portlet has a different HttpSession.

Of course, with the Portlet 2.0 spec, the recommended way to share a parameter or event payload between 2 or more portlets are the Section 3.4.2, “Public Render Parameters” and Section 3.4.1, “Sending and Receiving Events” mechanisms. This allows you to decouple your application from surgically managing objects in the PortletSession.APPLICATION_SCOPE.

But, if these do not meet your use case or you have a different strategy, you can use one of the following methods.

Storing Components in PortletSession.APPLICATION_SCOPE

Sometimes, it makes sense to store your Seam components in the portlet APPLICATION_SCOPE. By default, these objects are stored in the PORTLET_SCOPE; but with the annotation below, you can fish this class out of the PortletSession and use its values in other portlets across different Seam applications.


@PortletScope(PortletScope.ScopeType.APPLICATION_SCOPE)

Then you would pull the statefull object from the session:


YourSessionClass yourSessionClass = (YourSessionClass)
getRenderRequest().getAttribute(“javax.portlet.p./default/
seamproject/seamprojectPortletWindow?textHolder”);

Using the PortletSession

If you need to access the PortletSession to simply share a parameter/value across multiple portlets, you can use the following to do so.


Object objSession = FacesContext.getCurrentInstance().
getExternalContext().

getSession(false);
try
{
	if (objSession instanceof PortletSession)
	{
		PortletSession portalSession = (PortletSession)objSession;
		portalSession.setAttribute(“your parameter name”,”parameter
value”,PortletSession.APPLICATION_SCOPE);
	…
	
Then, in your JSP or Facelets page, you can use:
#{httpSessionScope[‘your parameter name’]}

Linking to Portlet/JSF Pages Using h:outputink

For linking to any JSF/Facelets page within your portlet web application, you may use the following.


<h:outputLink value=”#{facesContext.externalContext.
				requestContextPath}/home.xhtml”>
<f:param name=”javax.portlet.faces.ViewLink” value=”true”/>
navigate to the test page
</h:outputLink>

Redirecting to an External Page or Resource

To link to a non JSF view (i.e. jboss.org), you can use the following parameter.


<h:commandLink actionListener=”#{yourBean.yourListenr}”>
<f:param name=”javax.portlet.faces.DirectLink” value=”true”/>
navigate to the test page
</h:commandLink>

Then in your backing bean, you must call a redirect().


FacesContext.getCurrentInstance().
		getExternalContext().redirect(“http://www.jboss.org”);

Using Provided EL Variables

All EL variables found in the JSR-329 (Portlet 2.0) specification are available in the JBoss Portlet Bridge. For example, you can use the following to edit the portlet preferences on the UI.


<h:form>
  <h:inputText id=”pref” required=”true” value=”#{mutablePortletPrefe
rencesValues[‘userName’].value}” />
  <h:commandButton actionListener=”#{myBean.savePref}” value=”Save
Preferences” />
</h:form>

Then in your backing bean, you must call the PortletPreferences.store() method.


Object request = FacesContext.getCurrentInstance().
getExternalContext().getRequest();
PortletRequest portletRequest = (PortletRequest)request;
if (request instanceof PortletRequest) {
   try {
	 PortletPreferences portletPreferences = portletRequest.
										getPreferences();
	portletPreferences.store();

Remote Portlet Navigation Using Portlet Events

When you send events, you can also leverage the EventNavigationResult and return a JSF navigation rule. For example, by returning:


new EventNavigationResult(“fromAction”,”Outcome”);

The fromAction can be a wildcard “/*” or a nav rule defined in your faces-config.xml and outcome can be the from-outcome node defined in the faces-config.xml navigation rule.

CONCLUSION

With all the bitter sweetness that JSF and portal technologies offer, the portlet bridge does a good job of keeping everything in check. It also gives you possibilities that may not have been thought of when your JSF app was first created. Some examples are integration of legacy applications to leverage existing investments and the ability to develop newer frameworks and technologies without regression.

About The Authors

By Wesley Hales

By Wesley Hales

Wesley Hales is a software developer on several projects at JBoss, by Red Hat. He is the co-founder of the JBoss Portlet Bridge project, a senior developer on GateIn, and serves as the JBoss representative on the JSR 301 & 329 specifications.

Before working for Red Hat, Wesley focused mainly on web framework and UI-related technologies, thus leading to committer roles for Apache, Mozilla, and JBoss. Wesley produces a series of screencasts on vimeo for each bimonthly release of the bridge. He has written a host of articles on infoq.com and posts occasional tutorials to his blog on jroller.com.

For his sins, he evangelizes portlet and portlet bridge technologies at most major conferences including Jazoon, AjaxWorld, JUDCon, DevNexus and whichever ones a daring enough to have a portal talk in their schedule.

Recommended Book

Portlets in Action

Portlets in Action is a comprehensive guide for Java developers with minimal or no experience working with portlets. Fully exploring the Portlet 2.0 API and using widely adopted frameworks like Spring 3.0 Portlet MVC, Hibernate, and DWR, it teaches you portal and portlet development by walking you through a Book Catalog portlet and Book Portal examples. The example Book Catalog Portlet, developed incrementally in each chapter of the book, incorporates most key portlet features, and the accompanying source code can be easily adapted and reused by readers. The example Book Portal application introduces you to the challenges faced in developing web portals.


Share this Refcard with
your friends & followers...

DZone greatly appreciates your support.


Your download should begin immediately.
If it doesn't, click here.

Daily Dose - Release Candidate for PostgreSQL 9.0

After four months in beta, the first release candidate of the open source database, PostgreSQL, is ready for download.  PostgreSQL 9.0 includes some awesome features like Hot Standby and Steaming Replication.  The developers don't think any changes in...

0 replies - 19129 views - 09/02/10 by Mitchell Pronsc... in Daily Dose

Daily Dose - Facebook Going Public, But Not For a While

Facebook Going Public, But Not For a While   The WSJ has been talking with Facebook and gaining some early access to their plans for the future.  Mark Zuckerberg, the founder of Facebook, confirmed that the company will eventually go public, but not...

2 replies - 20447 views - 03/05/10 by Mitchell Pronsc... in Daily Dose

Tech Chat - David Ward on JBoss Developer Studio

DZone recently interviewed JBoss Solutions Architect David Ward to talk about what's new in JBoss Developer Studio (JBDS) and the Enterprise Application...

0 replies - 21579 views - 06/03/08 by Nitin Bharti in Videos