Sunday, March 02, 2008

Netbeans Visual JSF: Woodstock DropDown component using Calendar and Date objects

In this example, I will create a Netbeans Visual JSF Web Application using Woodstock DropDown components which use calendar and date objects. There will be some basic AJAX and validation.

Using Netbeans 6.0.1, create a new web application and select visual jsf as a framework.



This should create a visual web application.

Open the source packages directory from the Project window and click on the SessionBean1.java file. This class represents items which should be stored in the session which we want available between page views. Add the following properties to the bottom of the file:

private GregorianCalendar startCalendar;
private GregorianCalendar endCalendar;
private Date startDate;
private Date endDate;

public GregorianCalendar getEndCalendar() {
return endCalendar;
}

public void setEndCalendar(GregorianCalendar endCalendar) {
this.endCalendar = endCalendar;
}

public Date getEndDate() {
return endDate;
}

public void setEndDate(Date endDate) {
this.endDate = endDate;
}

public GregorianCalendar getStartCalendar() {
return startCalendar;
}

public void setStartCalendar(GregorianCalendar startCalendar) {
this.startCalendar = startCalendar;
}

public Date getStartDate() {
return startDate;
}

public void setStartDate(Date startDate) {
this.startDate = startDate;
}
After adding these component, right click on the page and fix imports. These properties will persist our values when we submit our page.

Next go back to the page and add 4 DropDown List and 4 StaticText components to the page from the palette. Add a DateTimeConverter and a CalendarConverter to the page. Right click on the staticText components and bind to data. Select bind to object and select startCalendar, on the next staticText field select endCalendar. Repeat for the remaining two staticText using start and end dates. After completing this select each component, and in the properties select the appropriate converter to be applied.





At this point we need to add a little Java to the backing bean. Add the following code to the page:



public Option[] getCalendars() {
ArrayList<Option> l = new ArrayList<Option>();
ArrayList<GregorianCalendar> calendars = new ArrayList<GregorianCalendar>();
GregorianCalendar gc = (GregorianCalendar) GregorianCalendar.getInstance();
gc.setTime(new Date());
gc.setTimeZone(TimeZone.getTimeZone("EST5EDT"));
gc.set(GregorianCalendar.HOUR_OF_DAY, 0);
gc.set(GregorianCalendar.MINUTE, 0);
gc.set(GregorianCalendar.SECOND, 0);
gc.set(GregorianCalendar.MILLISECOND, 0);
for (int i = 0; i < 24; i++) {
for (int j = 0; j < 60; j += 15) {
GregorianCalendar clone = (GregorianCalendar) gc.clone();
clone.set(GregorianCalendar.HOUR_OF_DAY, i);
clone.set(GregorianCalendar.MINUTE, j);
calendars.add(clone);
}
}
gc.set(GregorianCalendar.HOUR_OF_DAY, 24);
calendars.add(gc);
Collections.sort(calendars);
for (GregorianCalendar c : calendars) {
Option option = new Option();
option.setLabel(String.format("%02d", c.get(GregorianCalendar.HOUR_OF_DAY)) + ":" + String.format("%02d", c.get(GregorianCalendar.MINUTE)));
option.setValue(c);
l.add(option);
}
return l.toArray(new Option[l.size()]);
}

public Option[] getDates() {
ArrayList<Option> l = new ArrayList<Option>();
GregorianCalendar gc = (GregorianCalendar) GregorianCalendar.getInstance();
gc.setTime(new Date());
gc.setTimeZone(TimeZone.getTimeZone("EST5EDT"));
gc.set(GregorianCalendar.HOUR_OF_DAY, 0);
gc.set(GregorianCalendar.MINUTE, 0);
gc.set(GregorianCalendar.SECOND, 0);
gc.set(GregorianCalendar.MILLISECOND, 0);
for (int i = 0; i < 24; i++) {
for (int j = 0; j < 60; j += 15) {
GregorianCalendar clone = (GregorianCalendar) gc.clone();
clone.set(GregorianCalendar.HOUR_OF_DAY, i);
clone.set(GregorianCalendar.MINUTE, j);
Option option = new Option();
option.setLabel(String.format("%02d", clone.get(GregorianCalendar.HOUR_OF_DAY)) + ":" + String.format("%02d", clone.get(GregorianCalendar.MINUTE)));
option.setValue(clone.getTime());
l.add(option);
}
}
gc.set(GregorianCalendar.HOUR_OF_DAY, 24);
l.add(new Option(gc.getTime(), String.format("%02d", gc.get(GregorianCalendar.HOUR_OF_DAY)) + ":" + String.format("%02d", gc.get(GregorianCalendar.MINUTE))));
return l.toArray(new Option[l.size()]);
}



Note: Fix the imports, make sure that you choose import com.sun.webui.jsf.model.Option as the item to be imported.

Save and clean and build the application. This will refresh the framework so we can bind the new methods to our dropDown Lists.

Go back to the Design view. Click on the first two dropdown lists and bind them to the Page1.calendar items. Click on the next two items and bind them to the dates.


Next go to the properties and set the converters on the dropdown lists as appropriate. CalendarConverter on the first two dropdown lists and DateTimeConverter to the remaining dropdowns.

Next set the selected value to the appropriate property on the SessionBean1 Data Bean. startCalendar for dropDown1 and endCalendar for the second dropdown. Repeat for the date dropdowns. Add an appropriate label for each dropdown. I named them the same as the SessionBean1 property to be bound to.

Add a button and call it submit. Your example should look like this.


Next deploy the application and confirm that it works.

Next we will add some AJAX to the dropdown items. On dropDown1 add the following to the onChange event listed under the properties:
$('form1:dropDown1').submit(), $('form1:staticText1').refresh();
Repeat on the other dropdown components, but change the tags to point to the appropriate dropDown and staticText items.

Next, click on the calendarConverter1 component and change its properties: to

dateStyle: full
timeStyle: full
timeZone:EST5EDT
type: both
Repeat the process for the dateTimeConverter1.

We will now add a validator to dropDown2 which should be the endCalendar bound component. On the properties select validate under Events. Use the default handler listed. It should be dropDown2_validate


Go to Java source and navigate to the dropDown2_validate() method. Add the following code:


public void dropDown2_validate(FacesContext context, UIComponent component, Object value) {
GregorianCalendar end = (GregorianCalendar) value;
// dropDown1 is an AJAX component so the value on the backend is updated.
GregorianCalendar start = (GregorianCalendar) dropDown1.getValue();
if (start != null) {
if (end.compareTo(start) < 0) {
throw new ValidatorException(new FacesMessage("End Time must be greater than start time."));
}
}
}
Note: You need to ensure that you have both the start and end dropDown components. If they have different names, you will need to adjust the logic above to the appropriate dropDown component ids.

Your page should look something like this when you are done.



Redeploy the application. Check to see if the staticText fields update when you change values on the dropDown lists.



The submission should fail if the endCalendar is before the startCalendar.

I hope you enjoyed this brief tutorial. The files for the application are located here: CalendarDateDropDownExample.zip

Postscript: I asked for some folks at Sun to take a look at the page. They gave me some cool and interesting criticism of the tutorial.

One item that was not clear was that there are Woodstock components for calendars and schedulers. This is really an example of using a dropDown component with java.util.Calendar and java.util.Date.

It was suggested that I should use one or the other, but not both. Since this example is done, I will not change it. I will keep this in mind for future tutorials. The criticism was that it essentially was a duplication of effort and does not clearly state the case. I agree.

Additional Notes:


The project was developed using Netbeans 6.0/6.0.1 and Visual JSF (Project Woodstock 4.1.1). The latest version of Netbeans (6.1) includes Project Woodstock 4.2.

Project Woodstock has undergone a tremendous amount of changes from 4.1.1. This includes removing Prototype (JavaScript framework) and using a custom version of Dojo toolkit. The AJAX in this application depends on Prototype. You will need to install prototype in the project by adding a jar to the libraries. Here is prototype-1.5.0.jar.

Saturday, March 01, 2008

JPA and Web Examples using Project Woodstock and Netbeans

I was looking at some of the examples from the Netbeans site and trying to find a basic example to demonstrate. After looking at the examples I found on the web, I thought I would create a quick example myself.

First I created a project in Netbeans. I picked Java Library. Then I selected create entity classes from database and used the sample JavaDB database that comes with Netbeans. It prompted me to create the persistence.xml and I accepted the defaults.

Next I created a Web project in Netbeans. During the project creation wizard, I selected Visual JSF to include the JSF and Woodstock libraries.

Next I clicked on the properties for the project and added my library to the project.

Next I created a created a new persistence.xml file. After it was created, I modified it so that it would include the specific entity classes that I created in the library project.

Note: This is required otherwise the entity classes will not be detected.


Next I added this code snippet to SessionBean1

This fetches my data so that I can display it later in a table.

Next I compile the project (no deployment yet). This refreshes the beans so that I can manipulate them visually.

Next I create a table on Page1 from the palette. I right click the table and select binding and point it from the DefaultTableProvider to customers in the SessionBean.

Now I deploy it. Poof the magic is complete.

The link to my example Netbeans 6.5.1 project on Bitbucket: SamplePersistenceWeb

Popular Posts