Friday, 30 July 2010

Working with JSF's f:convertDateTime and java.util.Date

During a recent class I taught on ICEfaces, one of my students asked me why the calendar was often one day off from what got posted back to the model managed-bean setter.

For example:
// Facelets XHTML Markup:
<ice:selectInputDate value="#{modelManagedBean.dateOfBirth}">
    <f:convertDateTime pattern="MM/dd/yyyy" />
</ice:selectInputDate>

// Java Code
import java.util.Date;
public class ModelManagedBean {

  private Date dateOfBirth;

  public Date getDateOfBirth() {
    return dateOfBirth;
  }

  public Date setDateOfBirth( Date dateOfBirth) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy hh:mm z" );
    // The value printed here during postback was often wrong by 1 day
    System.out.println("dateOfBirth=" + dateFormat.format(dateOfBirth));
    this.dateOfBirth = dateOfBirth;
  }
}


Basically, the JSF DateTimeConverter Javadoc states that if the timeZone attribute is not specified, then the default is GMT. But when you create an instance of java.text.SimpleDateFormat, the default TimeZone is equal to TimeZone.getDefault() which (for me) was EST. So the solution I explained to my students was to make sure we were comparing apples-to-apples the whole way through, by using GMT for the SimpleDateFormat printing, like this:

dateFormat.setTimeZone(TimeZone.getTimeZone("GMT" ));

And of course, I think it's the recommended practice to run your application server JVM in GMT. That would eliminate the problem entirely. But when you're using Eclipse and Tomcat for development, that's typically not the case.

 

Posted by neil.griffin at 1:01 PM in Entries by Neil Griffin

Wednesday, 3 February 2010

JSF 2.0 Complete Reference, with JSF Portlet Appendix

 

JSF 2.0 Complete Reference with JSF Portlet Appendix

I'm pleased to announce the new JSF 2.0 Complete Reference book by Ed Burns and Chris Schalk, published by McGraw-Hill. During the planning stages, Ed asked me to be a contributing author and help bring the first edition of the book up-to-date with JSF 2.0, and also to write a JSF Portlet Appendix.

As listed in the Table of Contents, Appendix A discusses the following Topics:

  • Overview of Portlet 1.0 and 2.0
    • Portlet Lifecycle
    • Portlet Modes
    • Portlet Window States
    • Portlet Preferences
    • Inter-Portlet Communication
  • JSF Portlet Development
    • JSF Portlet Bridges
    • JSF Portlet View Handlers
    • JSF ExernalContext and the Portlet API
    • JSF and Portlet Preferences
    • JSF and Inter-Portlet Communication
  • ICEfaces Portlet Development
    • ICEfaces Ajax with Partial Submit
    • ICEfaces Direct-to-DOM RenderKit
    • The ice:portlet Tag
    • ICEfaces 1.x Portlet Bridge
    • ICEfaces 1.x D2DFaceletViewHandler
    • ICEfaces 1.x and Portlet Window States
    • ICEfaces Portlets and Concurrent DOM Views
    • ICEfaces 1.x Extended Request Scope
    • ICEfaces Ajax Push and Inter-Portlet Communication
    • ICEfaces Themes and Portal Themes
    • ICEfaces Themes and Liferay Themes
    • ICEfaces Ajax Bridge and Liferay Portal
    • ICEfaces Portlets and Liferay Request Attributes
  • PortletFaces
    • Downloading PortletFaces
    • PortletFacesContext
    • PortletFaces Tags
    • PortletFaces and Portlet Preferences
    • PortletFaces and Expression Language Additions
    • PortletFaces and Localization
    • Liferay Language Portlet Integration
    • Improved Integration Between Liferay and ICEfaces 1.x

This week (Feb 2nd to Feb 5th) Ed Burns & Chris Schalk will be helping to answer questions about the new book at JavaRanch. In addition, JavaRanch will be giving away a free copy of the book.

Finally I'd like to express my gratitude to ICEsoft, Mimacom, Liferay, and Triton for their generous support in making the JSF Portlet Appendix possible.

Posted by neil.griffin at 5:29 AM in Entries by Neil Griffin

Wednesday, 27 January 2010

JSF 2.0 + ICEfaces 2.0 + Portlet 2.0 = The PortetFaces Bridge

UPDATE#1: PortletFaces Bridge webinar took place on Thursday, Feb 11 2010 AD. Click here to view the PDF slideshow.

UPDATE#2: The source code is at Alpha1 status and can be checked out from SVN here:

I'm working on a new project called the PortletFaces Bridge which will enable the use of JSF 2.0 within Portlet 2.0 compliant portals like Liferay 5.x. The bridge implements a subset of the features available in JSR-329. Although the JSR-329 standard defines an API for a JSF 1.2 + Portlet 2.0 bridge, the PortletFaces Bridge is targeting JSF 2.0. Additionally, the bridge will facilitate usage of ICEfaces 2.0 within Liferay Portal.

Project Status as of January 27, 2010 AD:

  • I have a sample JSF 2.0 portlet developed that is using the new PortletFaces Bridge.
  • HTTP GET of portal page: bridge runs the portlet RENDER_PHASE, which runs the JSF lifecycle+renderResponse and the portlet renders fine in the browser.
  • HTTP POST after clicking h:commandButton: bridge runs the portlet ACTION_PHASE, which runs the JSF lifecycle. It then runs the portlet RENDER_PHASE, which runs the JSF renderResponse and the portlet renders fine in the browser.
  • RESOURCES: When using the new JSF 2.0 "resource" mechanism (like for downloading the "jsf.js" JavaScript file), the bridge correctly invokes the portlet RESOURCE_PHASE, which invokes the JSF 2.0 ResourceHandler and the contents of the requested resource are correctly delivered back to the browser.
  • AJAX: After tabbing-out of a field, the JSF 2.0 "jsf.js" JavaScript code correctly invokes the portlet RESOURCE_PHASE, which runs the JSF lifecycle+renderResponse, and correctly applies the DOM updates in the browser. Currently it uses the new JSF 2.0 <f:ajax /> tag to do Ajax requests. BTW I had to fix a problem in Mojarra to make this work -- I'm in contact with the Mojarra team and they're working on fixing it for the upcoming 2.0.3 release.
  • What's left: There's a bunch of little things -- loose ends that need to be coded up. Stuff like:
    • Testing of ICEfaces 2.0 WITHOUT the <f:ajax /> tag
    • Testing of ICEfaces 2.0 components (compatibility components)
    • Testing of ICEfaces 2.0 Ajax Push
    • After navigation-rules fire, need to compute the next JSF viewId to render
    • Detecting portlet mode changes (VIEW MODE, EDIT MODE, HELP MODE)

The goal is to have an Alpha version ready for use in time for the webinar on Thursday, Feb 11 2010 AD. The bridge will be be an open source project and be available for download from the http://www.portletfaces.org website.

 

Posted by neil.griffin at 4:41 PM in Entries by Neil Griffin

Tuesday, 27 October 2009

PortletFaces Project Announcement and Webinar

I'm pleased to announce that the PortletFaces project has now been formally established and can be found here: http://www.portletfaces.org

An ICEsoft+Mimacom webinar has been scheduled for Thursday October 29, 2009:

4PM - 5PM CET
11AM - 12PM EDT
8AM - 9AM PDT

Here's the registration link: https://www1.gotomeeting.com/register/741441337

I'll be conducting the webinar along with Micha Kiener of Mimacom, sponsor of the Edoras Framework.

The goal the PortletFaces project is to make it easier to develop JSF portlets that run within Liferay Portal. The project contains a wealth of features that expose the standard features of the Portlet 2.0 API and vendor-specific features of Liferay in a way that is natural to JSF development. It also provides improved integration between Liferay and ICEfaces 1.x portlets.

The beginnings of PortletFaces can be traced back to a forum post made by community member Joel Kozikowski back in May of 2007. Joel donated his code to Liferay and we began to work on the project together under Liferay incubation. Since then, PortletFaces has been adopted by Mimacom AG and is a sub-project of the edoras framework.

I'd like to personally thank Joel and the other contributors for their valuable additions to PortletFaces:

  • Micha Kiener
  • Atul Patel
  • Ed Shin
  • Stefan Niederhauser

Also my personal thanks to Liferay for sponsoring PortletFaces during incubation, ICEsoft for all the terrific support, and thanks to Mimacom for adopting the project.

Finally, I'd like to thank Triton's Steve Groninga for coming up with the PortletFaces project logo.

Documentation for PortletFaces can be found here: http://www.portletfaces.org/documentation

Posted by neil.griffin at 1:31 PM in Entries by Neil Griffin

Tuesday, 19 May 2009

Conference Talks: Social Networking Portlets with ICEfaces Ajax Push

I have the privilege of speaking about Social Networking Portlets with ICEfaces Ajax Push at the following two conferences:

I am speaking at CommunityOne 2009

Liferay East Coast User Conference

May 21, 2009
Rivet Logic Corporation (Training Center)
1775 Wiehle Avenue, 3rd floor
Reston, VA 20190
Map

CommunityOne West
Here I'll be co-speaking with Ed Burns, who is co-chairman of the JSR 314 (JSF 2.0) Expert Group

June 1-3, 2009
The Moscone Center
San Francisco
Map

This is an open developer conference. Monday 6/1 is free!

The talks will focus on the power and elegance of Liferay + ICEfaces Ajax Push, and how these technologies can be used together to create Social Networking portlets with Liferay Portal.

Social networking is a natural addition to portals, already a meeting place for applications. Diverse systems and users can be brought together for web-based communication and collaboration. When introduced to Ajax Push, Portlets can provide near-real-time communication features, such as presence, chat, and new forms of application-specific interaction.

Here's a screen shot of two portlets I'll be demontrating: ICEfaces Friends, and ICEfaces Chat:

The friends portlet is presence-aware, in that it has an application-scoped bean that listens to users logging-in/out of the portal. When it receives one of those events, ICEfaces Ajax Push will fire a visual effect, alerting the user of the friend's online status. If online, then the chat icon is activated. If the user clicks on the chat icon, then ICEfaces Ajax Push is used to achieve inter-portlet communication with the Chat portlet on the right. A new chat session is created, and users can chat with one another in near-real-time, again thanks to ICEfaces Ajax Push.

One of the things that I love about JSF, is the elegant, clean separation of the Model, View, and Controller concerns of the MVC design pattern. Case in point: Here's the entire XHTML markup for the Chat portlet:.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<f:view xmlns:c="http://java.sun.com/jstl/core"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:ice="http://www.icesoft.com/icefaces/component"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:sn="http://www.liferay.com/jsf/facelets/socialnetworking">
	<ice:portlet styleClass="portlet-content">
		<sn:styling />
		<ice:form>
			<ice:messages />
			<c:set value="#{chatRoomsModel.roomsWithUser}" var="chatRoomsWithUser" />
			<ice:panelTabSet rendered="#{!empty chatRoomsWithUser}" value="#{chatRoomsWithUser}" var="chatRoom">
				<ice:panelTab label="#{chatRoom.name}">
					<ice:panelGroup id="scroller" style="overflow: auto; width: 100%; height: 250px;">
						<ice:dataTable rowClasses="results-row,results-row alt"
								width="100%" value="#{chatRoom.chatMessages}" var="chatMessage">
							<ice:column style="width: 50px;">
								<sn:friend
									portraitStyleClass="avatar" portraitWidth="30px" showJobTitle="false"
									showOnlineStatus="false" user="#{chatMessage.user}" />
							</ice:column>
							<ice:column>
								<ice:outputText value="#{chatMessage.date}">
									<f:convertDateTime pattern="MM/dd/yyyy hh:mm:ss a" />
								</ice:outputText>
								<br />
								<ice:outputText value="#{chatMessage.text}" />
							</ice:column>
						</ice:dataTable>
					</ice:panelGroup>
					<ice:inputText action="#{chatRoomsBacking.addMessage(chatRoom)}" value="#{chatRoomsBacking.messageText}" />
					<ice:commandButton action="#{chatRoomsBacking.addMessage(chatRoom)}" value="#{message['add-message']}" />
				</ice:panelTab>
			</ice:panelTabSet>
		</ice:form>
	</ice:portlet>
</f:view>

 

Also, these portlets make heavy use of Facelets Composite Components, and demonstrate how you can create new JSF components entirely with XHTML markup.

Hope to see you at one of these conferences!

Posted by neil.griffin at 7:29 PM in Entries by Neil Griffin

Thursday, 23 April 2009

Making distinctions between different kinds of JSF managed-beans

JSF has a simple Inversion-of-Control (IoC) container called the JSF Managed Bean Facility (MBF). Although it has a verbose XML syntax, and is not as robust as the Spring BeanFactory, PicoContainer, or the JBoss Microcontainer, the MBF does have the basics of an IoC container, and offers features like dependency injection.

When a POJO is managed by the JSF MBF, it is typically referred to as a managed-bean. But if you're going to create a maintainable JSF webapp/portlet, it is necessary to distinguish between different kinds of managed-beans. This practice will also preserve the clean separation of concerns that JSF provides by implementing the Model-View-Controller (MVC) design pattern:

 

Managed-Bean Type Nickname Typical Scope
Model Managed-Bean model-bean session

Description: This type of managed-bean participates in the "Model" concern of the MVC design pattern. When you see the word "model" -- think DATA. A JSF model-bean should be a POJO that follows the JavaBean design pattern with getters/setters encapsulating properties. The most common use case for a model bean is to be a database entity, or to simply represent a set of rows from the result set of a database query.

Backing Managed-Bean backing-bean request

Description: This type of managed-bean participates in the "View" concern of the MVC design pattern. The purpose of a backing-bean is to support UI logic, and has a 1::1 relationship with a JSF view, or a JSF form in a Facelet composition. Although it typically has JavaBean-style properties with associated getters/setters, these are properties of the View -- not of the underlying application data model. JSF backing-beans may also have JSF actionListener and valueChangeListener methods.

Controller Managed-Bean controller-bean request

Description: This type of managed-bean participates in the "Controller" concern of the MVC design pattern. The purpose of a controller bean is to execute some kind of business logic and return a navigation outcome to the JSF navigation-handler. JSF controller-beans typically have JSF action methods (and not actionListener methods).

Support Managed-Bean support-bean session / application

Description: This type of bean "supports" one or more views in the "View" concern of the MVC design pattern. The typical use case is supplying an ArrayList<SelectItem> to JSF h:selectOneMenu drop-down lists that appear in more than one JSF view. If the data in the dropdown lists is particular to the user, then the bean would be kept in session scope. However, if the data applies to all users (such as a dropdown lists of provinces), then the bean would be kept in application scope, so that it can be cached for all users.

Utility Managed-Bean utility-bean application

Description: This type of bean provides some type of "utility" function to one or more JSF views. A good example of this might be a FileUpload bean that can be reused in multiple web applications.

 

Now... One of the main benefits in making fine distinctions like this is loose coupling. What's that you ask? Well let's first take a look at an example of tight coupling, where MVC concerns can be smashed/confused into a single managed-bean:

 

public class ModelAndBackingAndControllerBean {

	private String fullName; // model-bean property
	private boolean privacyRendered; // backing-bean property

	// model-bean getter
	public String getFullName() {
		return fullName;
	}
	
	// model-bean setter
	public void setFullName(String fullName) {
		this.fullName = fullName;
	}

	// backing-bean getter
	public boolean isPrivacyRendered() {
		return privacyRendered;
	}

	// backing-bean setter
	public void setPrivacyRendered(boolean privacyRendered) {
		this.privacyRendered = privacyRendered;
	}

	// backing-bean actionListener for UI support logic
	public void togglePrivacySection(ActionEvent actionEvent) {
		privacyRendered = !privacyRendered;
	}

	// controller-bean business logic
	public String submit() {
		System.out.println("fullName=" + fullName);
		return "success";
	}
}

The problem here is that the bean would have to be kept in session scope because of the model-bean property. Additionally, what if we wanted to do some unit testing with mock model data? Can't do it. So in order to fix these problems, and to promote loose coupling, we would have three separate Java classes:

public class ModelBean {

	private String fullName;

	public void setFullName(String fullName) {
		this.fullName = fullName;
	}

	public String getFullName() {
		return fullName;
	}
}

public class BackingBean {

	private boolean privacyRendered;

	public void setPrivacyRendered(boolean privacyRendered) {
		this.privacyRendered = privacyRendered;
	}

	public boolean isPrivacyRendered() {
		return privacyRendered;
	}

	public void togglePrivacySection(ActionEvent actionEvent) {
		privacyRendered = !privacyRendered;
	}

}

public class ControllerBean {

	private ModelBean modelBean;
	
	public ModelBean getModelBean() {
		return modelBean;
	}

	public void setModelBean(ModelBean modelBean) {
		// Dependency injected from the JSF managed-bean facility
		this.modelBean = modelBean;
	}

	public String submit() {
    	System.out.println("fullName=" + getModelBean().getFullName());
        return "success";
    }

}

 

Now that the beans are found in different classes, they can all be kept in their appropriate scopes. The model-bean can be kept in session scope, and the backing-bean and controller-bean can be kept in request scope, thus saving memory resources on the server.

Finally, we can use the dependency injection features of the JSF MBF in order to inject the model-bean into the controller-bean. This can be seen in the following WEB-INF/faces-config.xml example, where the #{modelBean} Expression Language (EL) binding is used:

<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
	version="1.2">
	<managed-bean>
		<managed-bean-name>modelBean</managed-bean-name>
		<managed-bean-class>myproject.ModelBean</managed-bean-class>
		<managed-bean-scope>session</managed-bean-scope>
	</managed-bean>
	<managed-bean>
		<managed-bean-name>backingBean</managed-bean-name>
		<managed-bean-class>myproject.BackingBean</managed-bean-class>
		<managed-bean-scope>request</managed-bean-scope>
	</managed-bean>
	<managed-bean>
		<managed-bean-name>controllerBean</managed-bean-name>
		<managed-bean-class>myproject.ControllerBean</managed-bean-class>
		<managed-bean-scope>request</managed-bean-scope>
		<managed-property>
			<property-name>modelBean</property-name>
			<value>#{modelBean}</value>
		</managed-property>
	</managed-bean>
</faces-config>

 

 

Posted by neil.griffin at 2:38 PM in Entries by Neil Griffin

Wednesday, 5 November 2008

Lazy Loading a JSF DataModel for an ICEfaces ice:dataTable

Iterator components like the ICEfaces ice:dataTable have two special attributes: value and var. The value attribute is typically bound to a JSF model-managed-bean, and the var attribute introduces a new variable into the JSF Expression Language (EL) like this:

<ice:dataTable value="#{modelBean.rows}" var="row">
    <ice:column>
        <f:facet name="header">
            <ice:outputText value="#{msgs.firstName}" />
        </f:facet>
        <ice:outputText value=#{row.firstName}" />
    </ice:column>
    ...
</ice:dataTable>

The ModelBean.getRows() method can return a variety of types, but in my experience the most typical one is a generic java.util.List like this:

public List<Row> getRows() {...}

Under the hood, JSF is expecting the value attribute to contain an instance of a JSF DataModel object. In fact, if you don't return a DataModel, JSF will implicitly wrap your return value with a wrapper class, such as the ListDataModel for values of type java.util.List.

Typically, the model bean that contains the data is kept in JSF session scope or ICEfaces extended-request scope. This is fine if you only have 10 or 20 rows in the result set, but what if you have 1,000,000 rows? Obviously there is a scalability concern in such a case, especially since the user is only going to be viewing 10 or 20 rows at a time in the browser.

Unfortunately, the JSF spec does not provide a way of loading data on demand (popularly known as "lazy loading" ). I've seen several posts on how to do this, but I thought it would be nice to develop a persistence-technology-independent solution.

To this end, I wrote an abstract class named LazyDataModel.java that is meant to be subclassed into a concrete implementation. Feel free to download the LazyDataModel.java (zipped) source code.

Here are the three methods you will need to supply in your concrete implementation:

public abstract int getRowsPerPage();

public abstract int countRows();

public abstract List<DTO> findRows(int startRow, int finishRow);

The DTO marker implies that this class is meant to be used at the JSF UI layer of a webapp/portlet, and that it is meant to be used in conjunction with the Data Transfer Object design pattern (formerly known as the Value Object / VO design pattern).

BTW, in order for this to be of benefit to the end user, you'll need to connect an ICEfaces ice:dataPaginator component to the ice:dataTable iterator. That will provide icons for navigation such as first-page, previous-page, next-page, and last-page.

 

Posted by neil.griffin at 3:20 PM in Entries by Neil Griffin

Friday, 3 October 2008

Webinar: Filthy Rich Portlets with ICEfaces and Liferay

Update! An archive of the webinar is now available on ICEfaces .org in both .wmv and quicktime: http://www.icefaces.org/main/resources/webinars.iface (3rd item in the Archive Webinar list)

Also, here is a video+transcript of a similar presentation given at the JSFOne conference: http://java.dzone.com/videos/filthy-rich-portlets

If you missed out on JSFOne 2008, then please attend the webinar that I'll be hosting:

Webinar Title: Filthy Rich Portlets with ICEfaces and Liferay

Webinar Date/Time: Tuesday, October 14, 2008 1:00 PM - 2:00 PM EDT

Webinar Link: https://www1.gotomeeting.com/ojoin/451479046/1859554

Webinar Slides and Demo Downloads:

The sources are meant to be extracted into the "plugins" folder of the Liferay Plugins SDK. Fore more info, download the the Liferay Plugins SDK documentation.

Webinar Overview:

  • Portals and Portlets
  • Liferay Portal
  • JSF Portlets
  • ICEfaces Portlets
  • Standard Inter-Portlet Communication
  • Ajax Push Inter-Portlet Communication
     

Posted by neil.griffin at 4:02 PM in Entries by Neil Griffin