NetBeans Setup of Seam 2.0 Applications for Tomcat 6.0″

< @RequestParameter and @Observer usage | Ajax Magic with DataTables >

Recently I’ve had need to begin developing a new application using Seam. However this time I’ve decided to go lightweight, so the obvious choice was Tomcat 6. I realized that the Seam plugin for NetBeans was limited to project generation for JBoss and so wasn’t an option. I decided to create everything on my own. Thankfully there is an example of the booking application with build scripts for Tomcat 6, Glassfish, WebLogic and WebSphere under jboss-seam-2.0.GA/examples/jpa. So here’s how you can set up yours work on Tomcat 6.

 

First, build the tomcat example by running ant tomcat6, which generates 2 folders – dist-tomcat6 and exploded-archives-tomcat6. With that done, create a library in NetBeans which you’ll add it to your project. I called mine “Seam4Tomcat” and added all the jar files in jpa/exploded-archives-tomcat6/jboss-seam-jpa.war/WEB-INF/lib.

Adding a library

Then create the project itself. Select the “Web Application” project type, specify Tomcat 6 as the target server and JavaEE 5 as the version of JavaEE. Next check Facelets as the framework to be used and create the project. Right click on the project and select “Properties”. Select “Libraries” on the left panel and “Add Library” to add your Seam4Tomcat (or whatever name you gave it) jars to your project. Remember to uncheck the Facelets related libraries provided by the NetBeans facelets support, since they are already in you newly added library.

Add library to project

Since the Seam filter needs to be installed to allow seam integration (as well as other configurations), just copy the contents of jpa/exploded-archives-tomcat6/jboss-seam-jpa.war/WEB-INF/web.xml and paste them in your web.xml file. You may change the <url-pattern> under the “Faces Servlet” servlet mapping to the url you want from the default “*.seam”.

 

Append this to the top of the web.xml file to add the blueSky RichFaces skin to RichFaces components you might use in the application.

 

<context-param>

<param-name>org.ajax4jsf.SKIN</param-name>

<param-value>blueSky</param-value>

</context-param>

 

Note that your faces-config.xml will already contain the reference to the Facelet view handler as well after creating the project.

 

Next, Seam gives you advanced navigation in its pages.xml file compared to JSF’s faces-config.xml file. To use it, just copy the jpa/exploded-archives-tomcat6/jboss-seam-jpa.war/WEB-INF/pages.xml into your WEB-INF folder. Also add the components.xml from the same directory to your WEB-INF folder. This is the most central file to any seam application and must always be there.

 

We’ll need to connect to some database to begin work with. So right-click your project, go to “New” and select “Entity Classes from Database”. We’ll assume no existing datasource and create one from an existing database connection. Drop down the “Data Source” combo box and select “New Data Source”. Enter a jndi name (mine is “jdbc/example”) and select the database connection. Enter the username and password for connecting to that database and your tables will be displayed.

Data source creation

Select the tables you want to generate entities for and click “Next”. You are then given the chance to edit the names of the Entities to be generated as well as specify the package within which they will be kept (mine is “example.entity”). NetBeans can generate named queries for you, but more importantly any JPA project needs a persistence unit. This consists of your entities and an ever so vital persistence.xml or orm.xml file.

 

Generating entities

Click the “Create Persistence Unit” button to create a persistence.xml file. Enter a persistence unit name (note the name you give. It will be used later). Specify your persistence provider – NetBeans comes with TopLink, but for Seam Hibernate is the better persistence provider. Note that I’ve changed the “Data Source” from “jdbc/example” to “java:comp/env/jdbc/example”. This is the fully qualified JNDI name that will be used by the container to resolve the EntityManager resource we’ll be injecting into our code. Since our database tables already exist, we’ll select “None” for “Table Generation Strategy” and click “OK”. We are finished with everything now and will click “Finish” to end the wizard.

View of persistence.xml

The preceding process creates two very important files: context.xml and persistence.xml files. Every resource that would be used in Tomcat should be declared in context.xml as a resource. Here is mine from the process above. You are free to tweak yours as the need may be.

 

<Context path=”/example”>

<Resource auth=”Container” driverClassName=”com.mysql.jdbc.Driver”

maxActive=”20″ maxIdle=”10″ maxWait=”-1″

name=”jdbc/example” password=”” type=”javax.sql.DataSource”

url=”jdbc:mysql://localhost:3306/knust” username=”edem”/>

</Context>

 

Here is my persistence.xml file as well. Note that I have changed the transaction-type to “RESOURCE_LOCAL” from “JTA”. However Seam provides JTA support for our application and therefore the <jta-data-source> declaration instead of <non-jta-data-source>. These must be exactly as it is here or your application will DEFINITELY give you errors.

 

 

<persistence-unit name=”exampleDatabase” transaction-type=”RESOURCE_LOCAL”>

<provider>org.hibernate.ejb.HibernatePersistence</provider>

<jta-data-source>java:comp/env/jdbc/example</jta-data-source>

<properties/>

</persistence-unit>

</persistence>

 

Now go back to your components.xml file. If you did copy the one from the exploded jpa example, you should have the following declaration in this file.

 

<core:manager conversation-timeout=”120000″

concurrent-request-timeout=”500″

conversation-id-parameter=”cid”/>

 

<transaction:entity-transaction entity-manager=”#{em}”/>

 

<persistence:entity-manager-factory name=”bookingDatabase”/>

 

<persistence:managed-persistence-context name=”em”

auto-create=”true”

entity-manager-factory=”#{bookingDatabase}”/>

 

<security:identity authenticate-method=”#{authenticator.authenticate}”/>

 

First things first. Replace all instances of “bookingDatabase” with the name of your persistence unit (I told you to take note of that – mine is “exampleDatabase”). Secondly, by giving the name “em” to all references to EntityManager and managed persistence contexts, it means that your code can only inject the EntityManager under the same name like so

 

@In EntityManager em

 

If you use a different name to inject it don’t say I didn’t tell you about the errors you’ll be getting. Alternatively you could change it to “entityManager” or whatever, just make sure that you use the same name as declared in components.xml throughout your code.

 

The last but often most forgotten thing that needs to be added is a seam.properties file. I can recount the number of times I’ve had nightmarish debugging sessions when a fresh application I’d just created to display Seam to someone didn’t work because of this file. In NetBeans, just right-click the project, select “New” and the “Properties file”. Call it “seam” and do not put it in any package (which puts it in default).

 

 

With all this done, you are good to go developing for Tomcat 6 using Seam. NetBeans offers some level of incremental deployment to Tomcat, detecting if Java classes have changed and redeploying the application. However, since NetBeans remotely deploy web applications to Tomcat, Tomcat will be reading from your project folder directly to deploy the application. This means that some changes like changes made to your facelets page will immediately appear on your web-browser. Just save the changes you make to a facelet, refresh your web browser and boom! For me that is enough. Tomcat deploys quickly and so redeploying when a Java class changes is not that painful.

 

Here’s an application I created to display this process to a mate. It’s got all the configurations files, some entities and Seam components to get you started.

 

Advertisements

Using @RequestParameter and @Observer events model in Seam

<Simple DataTable Example | Seam on Tomcat >

One good thing that Seam adds to JSF is the ability to use GET requests to retrieve data. The JSF spec decided to make every request a post, and this makes it difficult to bookmark pages or fetch pages directly from entering a url along with some parameters.

Well see how this problem is solved in Seam using a simple annotation: @RequestParameter. This annotation allows us to pass a request parameter to our Seam component. Its value is injected before any method is called, guaranteeing us that the request paremeter will be available to us to make use of in our code. A look at our previous example shows us that departmens belong to specific faculties. This means we will need to pass the particular faculty whose departments we want to see on our departmentList.xhtml page displaying departments. Here’s the code that does it in our departmentListing Seam component:

@Stateful

@Name(“departmentListing”)

@Scope(ScopeType.SESSION)

public class DepartmentListBean implements DepartmentList {

@PersistenceContext(type=PersistenceContextType.EXTENDED)

EntityManager em;

@DataModel

List<Department> departments;

@DataModelSelection

private Department department;

@In FacesMessages facesMessages;

@RequestParameter

Integer facId;

@Out(required=false,scope=ScopeType.SESSION)

Faculty faculty;

@Factory(“departments”)

@Observer(“univseam.event.DepartmentChanged”)

public void departmentList() {

//select if a faculty id has been passed to us

if(facId != null){

try {

faculty = (Faculty) em.createQuery(“Select f from Faculty f where f.id=:id”).

setParameter(“id”, facId).getSingleResult();

} catch (NoResultException exception) {

facesMessages.add(“Non-existent faculty passed!”);

return;

}

}

//if the faculty is not null then select its departments

if (faculty != null) {

departments = em.createQuery(“Select d from Department d where d.faculty=:faculty”).

setParameter(“faculty”, faculty).getResultList();

return;

}

facesMessages.add(“No departments under this faculty yet”);

}

Our list of departments is as shown below.

old dept list

The “facId” is a request parameter passed from the page displaying the list of faculties. The method departmentList() is annotated with @Factory(“departments”), which forces Seam to load up the list of departments into the “departments” ArrayList. Seam guarantees that the faculty id will be properly converted to an Integer and placed in the facId variable before we initialize our list of departments, enabling us to first select the particular faculty and pass it to the query to load the departments. Outjecting the faculty object to the Session context is necessary to this discuss and we’ll see why soon.

But how was the request parameter passed? Well, the simple <f:param> tag in JSF allows use to do that. Take a look at this portion of the facultyList.xhtml facelet.

<h:column>

<f:facet name=”header”>Action</f:facet>

<s:link value=”Departments” view=”/departmentList.xhtml”>

<f:param name=”facId” value=”#{faculty.id}”/>

</s:link>

</h:column>

With the use of an <s:link> we are able to append the faculty id to our URL under the name facId and seam binds to that name using the RequestParameter.

Not only is RequestParemeter useful in searching, but can also be very helpful in determining if an entity is being edited or a new one being created. Here we are with a list of departments. We want to use the same page to edit as we do for new department creation. RequestParameter to the rescue.

@Stateful

@Name(“departmentManager”)

public class DepartmentManagerBean implements DepartmentManager {

@In

EntityManager entityManager;

@In

FacesMessages facesMessages;

@In

Faculty faculty;

@Out(required=false)

private Department department;

@RequestParameter(“depId”)

Integer depId;

public void createDepartment() {

//if the department already exists, then allow an edit

if(depId != null){

try {

this.department = (Department) entityManager.createQuery(“Select d from Department d where d.id=:id”).setParameter(“id”, depId).getSingleResult();

} catch (NoResultException noResultException) {

facesMessages.add(“Invalid department”);

}

facesMessages.add(“Editing a department”);

return ;

}

//else instantiate a new department entity

this.department = new Department();

this.department.setFaculty(faculty);

facesMessages.add(“Creating a new department”);

return;

}

Passing the department id enables us to find out if a department like this exists already, in which case we load up that department for editing. If not we create a new department instance, passing it the faculty to which it belongs (which we injected from the previously outjected instance).

Look at how this is done in the departmentList.xhtml facelet.


<h:column>

<f:facet name=”header”>Action</f:facet>

<s:link id=”edit” value=”Edit”

view=”/department.xhtml” action=”#{departmentManager.createDepartment}” propagation=”begin”>

<f:param name=”depId” value=”#{department.id}”/>

</s:link>

</h:column>

The page for modifying/creating a new department is below

new department creation

Again this appends the department id as depId to the URL, and Seam makes it available to our departmentManager to use before the createDepartment method is called. Through this the department.xhtml facelet can be used both for creation and editing of department entities.

I’ve also been looking at alternative ways of automatically refreshing a list when a new element has been added to it in the database. Since @Factory is called only if the referred to object is null, we need another way to reload the list of departments and add the new department as well. Seam has an event mechanism based on the Observer pattern. This allows me to raise events, and all observers of that event immediately get notified of it. After populating the fields of a department I call saveDepartment, which saves my entity to the database. I then raise my own pretentious event: “univseam.event.DepartmentChanged”.

@End

public String saveDepartment() {

if(department.getId()!= null){

entityManager.merge(department);

facesMessages.add(“Department updated!”);

}else{

entityManager.persist(department);

facesMessages.add(“New department added!”);

}

Events.instance().raiseEvent(“univseam.event.DepartmentChanged”);

return “success”;

}

Notice that the factory method that initializes the list of departments (displayed previously) is also annotated with @Observer(“univseam.event.DepartmentChanged”). This time the facId will be null, but faculty is still in session scope, so we are able to reload the list of departments as if it’s nobody’s business.

Updated list of depts

Seam events enable applications to be very stateful, updating themselves when changes happen on the fly. Combining it with request parameters even makes it more fun to do.


Added on 8th April 2008:
Here is the updated link to the source for this tutorial

Annoying NetBeans 6.0 Facelets Support Issue on Tomcat

Yesterday i got a call from a good friend of mine who has been dipping his fingers into JSF a bit. He’d decided to jump ship to using JSF on XHTML files, a technology known as Facelets. So he goes to download NetBeans 6.0 Facelets support plugin and installs it.

After developing a simple facelets page, he decides to deploy it to Tomcat 6.0.14 only to get BIG FAT class loader exceptions. What better way to treat a sceptic who is just getting into the game of web development in Java. These are the kind of things that can be so annoying about doing something in Java. Being a Seam advocate and user, I didn’t immediately realise what could have been the problem, since my Seam applications run fine using the jars from Seam.

After doodling around and making some changes to jars that came with the Facelets support, i just decided to ditch the jars from Facelets support and use my own. I picked the jars that come with Seam and VOILA! Problem solved. Makes me wonder if the guys who developed the plugin didn’t try to deploy it themselves AT LEAST to Tomcat before putting it out there. Anyways i just felt like putting up the solution to this simple but very annoying problem here for the sake of those who might try an introduction to Facelets.

Note that i got these jars from the JBoss Seam 2.0.GA’s lib folder. I can’t tell you where u can get them individually but downloading seam altogether will give you a change to start playing around with it if you haven’t started already.

Simply create a new Library in NetBeans by going to Tools->Libraries. I gave mine the name Facelets4Tomcat. Here are the jar files you need.

  • commons-beanutils.jar
  • commons-collections.jar
  • commons-digester.jar
  • commons-logging.jar
  • jboss-el.jar
  • jsf-api.jar
  • jsf-facelets.jar
  • jsf-impl.jar

This goes into your web.xml file.

<context-param>
<param-name>com.sun.faces.validateXml</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>facelets.SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>forward.jsp</welcome-file>
</welcome-file-list>

If you want to add the Ajaxified RichFaces components then add the following from the same Seam lib folder.

  • richfaces-api.jar
  • richfaces-ui.jar
  • richfaces-impl.jar

And add these to the top of your web.xml file

<filter>
<display-name>RichFaces Filter</display-name>
<filter-name>richfaces</filter-name>
<filter-class>org.ajax4jsf.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>richfaces</filter-name>
<url-pattern>*.jsf</url-pattern>
</filter-mapping>
<context-param>
<param-name>org.ajax4jsf.SKIN</param-name>
<param-value>classic</param-value>
</context-param>

You may use a different skin if you want. Check out the documentation for details

You may then add the library you created to your project by right clicking your web project and selecting “Properties”. At Libraries, click “Add Library” and selected the library you just created. Make sure that the check box is enabled or else it will not put the jar files in the right location i.e. WEB-INF/lib.

Oh, and MAKE SURE that the Facelets support libraries are unchecked, or else you’ll be back to square 1.

Happy Faceleting.