Starting with JBoss Seam (using seam-gen)
Published by peter October 18th, 2007 in jboss, seam.After two JSF-free years (I didn't really enjoy myfaces at that time) I decided to get my head around Seam and JSF. My next project will consist of rebuilding a Delphi application to a multiuser Seam application; so let's have a look at where we are!
Introduction
First of all, before I get flamed, Seam is not JSF. Seam supports JSF as a view technology. Seam defines a uniform component model for all business logic in your application. A Seam component may be stateful, with the state associated with any one of several well-defined contexts, including the long-running, persistent, business process context and the conversation context, which is preserved across multiple web requests in a user interaction.
There is no distinction between presentation tier components and business logic components in Seam. You can layer your application according to whatever architecture you devise, rather than being forced to shoehorn your application logic into an "unnatural layering" scheme forced upon you by whatever combination of frameworks you're using today.
The position of Seam in the stack is therefor depicted as follows:
The Seam documentation states:
It turns out that the combination of Seam, JSF and EJB3 is the simplest way to write a complex web application in Java. You won't believe how little code is required!
With my previous Grails experiments I highly doubt it; but we'll see!
Installing and setting up
We'll be running with the latest version of Seam, which is at this point 2.0.0.CR2. To do this we'll need JBoss AS and Seam:
It took me some time to actually find the needed downloads on the JBoss site; the navigation of the different JBoss sites isn't really intuitive. And somehow I think 200M to just get started (no IDE included!) is just nuts; 'back in the days' I used to download entire operating systems which where far smaller!
After unpacking we need to setup Seam:
- Configure the location of your fresh JBoss installation in the build.properties file:
CODE:
-
#Fri Oct 05 09:27:11 CDT 2007
-
mavenized=true
-
build.properties=/Users/peter/JavaApplications/jboss/
-
- On Linux/OsX make sure that the Seam command is executable (chmod a+x seam)
- Run "./seam setup" which will ask you about 20 questions (you can view what I did here, just too verbose to put it inline) about your environment.
- Create your project ./seam create-project
Now, if you start JBoss and deploy you application by run "./seam explode" or "./seam deploy"; which builds and deploys your project. The create project also creates the necessities to import the generated code in eclipse.
Creating the model
For my presentation at Finalists' Battle of the Geeks 2007 I created a simple model to manage "Geek Battles", evenings where developers present their pet projects and the audience can vote and decide how is their favorite. We'll use a part of this model now:
Seam-gen offers a crude generator to create the needed boilerplate code for the needed entities. Let's run it for both domain objects (for brevity I've only copied the part of the first run here):
-
bash>./seam new-entity
-
Buildfile: build.xml
-
-
init:
-
-
init-properties:
-
[echo] /Users/peter/JavaApplications/jboss/
-
-
validate-workspace:
-
validate-project:
-
entity-input:
-
[input] Enter the entity class name
-
Battle
-
-
...
This actually creates a working Seam/JSF application with CRUD (create-read-update-delete) screens for the created entities. Nice! The generated entities contain 3 attributes: id, version and name.
Let's add our attributes and associations:
Battle.java
-
...
-
private Date date;
-
private List<Presentation> presentations;
-
-
@Temporal(TemporalType.DATE)
-
public Date getDate() {
-
return date;
-
}
-
-
public void setDate(Date date) { this.date = date; }
-
-
@OneToMany(mappedBy = "battle")
-
public List<Presentation> getPresentations() {
-
return presentations;
-
}
-
-
public void setPresentations(List<Presentation> presentations) { this.presentations = presentations; }
-
...
Presentation.java
-
...
-
private Battle battle;
-
@ManyToOne
-
public Battle getBattle() {
-
return battle;
-
}
-
-
public void setBattle(Battle battle) { this.battle = battle; }
-
...
The view
First lets create the input for the date property of the Battle. We'll use the calendar widget from richfaces. Just under the form input for the name property we add the following:
-
<s:decorate id="dateDecoration" template="layout/edit.xhtml">
-
<ui:define name="label">Date</ui:define>
-
<rich:calendar value="#{battleHome.instance.date}"
-
datePattern="yyyy-MM-dd" />
-
</s:decorate>
The result is a nice calendar widget which automatically binds to the date attribute of the Battle instance we're currently editing:
battle.xhtml
Setting up a widget to select to Battle to which a presentation belongs didn't prove to be more complex:
presentation.xhtml
-
<s:decorate id="battleDecoration" template="layout/edit.xhtml">
-
<ui:define name="label">Battle</ui:define>
-
<h:selectOneMenu value="#{presentationHome.instance.battle}">
-
<s:selectItems value="#{battleList.resultList}" var="battle" label="#{battle.name}" />
-
<s:convertEntity />
-
</h:selectOneMenu>
-
</s:decorate>
Note the use of the <s:convertEntity /> tag, it took me quite a bit of browsing the examples to figure that one out; it takes care of binding the property as an entity. The result of the above is a nice select box containing all availlable battles to select from:
And the interface wouldn't be complete if we didn't add a list of all presentations in a Battle to the battle.xhtml view:
-
<rich:simpleTogglePanel switchType="client" label="Presentations"
-
opened="false" rendered="#{not empty battleHome.instance.presentations}">
-
<f:facet name="header">Presentations</f:facet>
-
<h:dataTable id="presentationList" var="presentation"
-
value="#{battleHome.instance.presentations}"
-
rendered="#{not empty battleHome.instance.presentations}">
-
<h:column>
-
<f:facet name="header">Name</f:facet>
-
#{presentation.name}
-
</h:column>
-
</h:dataTable>
-
</rich:simpleTogglePanel>
As you can see I used the Richfaces simpleTogglePanel to show the related presentations in nice panel:
Conclusion
Although I've only barely scratched the surface of Seam I must say that, apart from the overly complex installation/setup and scattered documentation, Seam is in fact quite nice. I only had to write some code to add the missing attributes to my model, which is what, 10 lines? And the JSF stuff isn't to bad either; there is actually some documentation now!
I'm actually looking forward to be using Seam on my next project!




















I agree that getting started with seam-gen the first time is way too complex. It's obviously a function our primitive scripting environment (ant) and the need to be able to configure a wide variety of project options from the command-line. I think RHDS/JBossTools is the better way to go. The IDE support there can walk you through the setup process wizard-style and make the whole process very simple. It's not perfect, and it won't solve everyone's needs, but I think it will be the better option for most people. We should have Seam 2 support in JBossTools when we release Seam 2. (or shortly thereafter)