JBoss Seam, JSF,Oracle and EJB3 Hello World
In this first post I shall show you how to setup a simple “Hello World” type application using JSF , JBoss Seam and EJB3, I shall also be persisting data to an Oracle 9i database.
This post is not a introduction to Seam post there are many sources out there which provide a far clearer introduction to Seam than I can provide, This article is simply meant as a guide to getting Seam up and running. I initially had problems getting the basic demos up and running and found myself attempting to tie together multiple forum posts, blogs and tutorials to get a complete end to end setup working.
If you do require a Introduction to Seam I suggest the JBoss Seam manual
Or Micheal Yuan and Thomas Heutes book JBoss Seam: Simplicity and Power Beyond Java EE
Environment Setup:
I am using IntelliJ 8 as my IDE
Java JDK 1.5.0_09
I am running JBoss version 4.2.3 GA JBoss download page
with Seam version 2.1.0 SP1 Seam download page
I am also running a Oracle 9i server and using TOAD as a schema browser.
1. Extract JBoss, my JBoss is located at C:\JBoss-4.2.3.GA
2. Create a new project, In your IDE of choice create a new project called JSFExample. C:\JSFExample
3. Create the following directory structure: ignore the various properties files just now we will come back to them.
4. Setup your classpath the following jar files are required to get this example to work, almost all of these are found in the Seam 2.1.0 SP1 lib directory, with the exception of javaee.jar which is part of IntelliJ and ojdbc14.jar which is required in order to connect to an Oracle database. This can be downloaded from the Oracle site at Oracle download page
5. For simplicity’s sake copy these files with the exception of javaee.jar to the lib directory of your JBoss C:\JBoss-4.2.3.GA\server\default\lib and to the supportingJars directory for our project C:\JSFExample\supportingJars.
6. Start the JBoss server and make sure it starts successfully.
Database setup
In this example we will be entering information for some users, persisting this data to the database and returning a list of all users on successful submit. So create the following table in your database:
CREATE TABLE USERS ( ID INTEGER NOT NULL, NAME VARCHAR2(256 BYTE) NOT NULL, PHONENUMBER VARCHAR2(16 BYTE), ADDRESS VARCHAR2(256 BYTE), CITY VARCHAR2(256 BYTE), EMAIL VARCHAR2(256 BYTE), AGE VARCHAR2 (3 BYTE) )
OK so its not the best table in the world it but it serves our purpose for now, we also need a sequence to use with our primary key ID,
CREATE SEQUENCE USERS_S START WITH 1
Coding – Server,
[UPDATE]Due to problems with the plugin thing I use to show code XML files tend to get a bit messed up and well, broken. I have uploaded the source to http://jdick.co.uk/blog/code/JSFExample.zip None of the supporting jars are in this zip for bandwidth reasons you still have to go and get them yourself[/UPDATE]
Users.java
So now we are almost finished setup lets get some code down. Start by creating a entity bean called Users in beans.com.jsf
package com.jsf;
import static org.jboss.seam.ScopeType.SESSION;
import java.io.Serializable;
import javax.persistence.*;
import org.hibernate.validator.Length;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
@Entity
@Name("userdetails")
@Table(name = "USERS")
@Scope(SESSION)
@SequenceGenerator(name = "USER_SEQUENCE_GENERATOR", sequenceName = "USERS_S")
public class Users implements Serializable {
public Users() {
}
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USER_SEQUENCE_GENERATOR")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(nullable = false)
@Length(min = 5, max = 25)
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Column(nullable = false)
@Length(min = 1, max = 3)
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Column(nullable = false)
@Length(min = 5, max = 15)
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Column(nullable = false)
@Length(min = 5, max = 30)
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Column(nullable = false)
@Length(min = 5, max = 30)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(nullable = false)
@Length(min = 5, max = 13)
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
private int id;
private String name;
private String phoneNumber;
private String address;
private String city;
private String email;
private String age;
}
note the name of the bean is “userdetails” this will be important later.
UserControllerBean.java
Next we need a session bean to carry out our operations. This could be a normal backing bean but I use EJB3 so a session bean it is, in this case a stateless session bean.
package com.jsf;
import javax.ejb.*;
import javax.persistence.*;
import java.util.List;
import org.jboss.seam.annotations.*;
import org.jboss.seam.annotations.datamodel.DataModel;
@Stateless
@Name("userBean")
@Local(value = Controller.class)
public class UserControllerBean implements Controller {
@In
private Users userdetails;
@PersistenceContext
private EntityManager em;
@DataModel
private List items = null;
public void count(String count) {
}
public String count() {
em.merge(userdetails);
return "/registered.seam";
}
@Factory("items")
public void getItems() {
List list = em.createQuery(FIND_ALL).getResultList();
items = list;
}
public static final String FIND_ALL = "SELECT userreturn FROM Users userreturn";
}
Controller.java
The last class we need is the Controller Interface so we can call the session bean from our web client.
package com.jsf;
import javax.ejb.Local;
@Local
public interface Controller {
public String count();
public void count(String count);
public void getItems();
}
Coding – Front End
In the web/resources directory create the following files
index.html
<html> <head> <meta http-equiv="Refresh" content="0; URL=register.seam"> </meta></head> </html>
register.xhtml
< ?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">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<title>Register New User</title>
</head>
<f :view>
<h :form>
<s :validateAll>
<h :panelGrid columns="2">
Name: <h :inputText value="#{userdetails.name}" required="true"/>
Address: <h :inputText value="#{userdetails.address}" required="true"/>
City: <h :inputText value="#{userdetails.city}" required="true"/>
Email: <h :inputText value="#{userdetails.email}" required="true"/>
Phone Number: <h :inputText value="#{userdetails.phoneNumber}" required="true"/>
Age <h :inputText value="#{userdetails.age}" required="true"/>
</h>
</s>
<h :messages/>
<h :commandButton value="Register" action="#{userBean.count}"/>
</h>
</f>
</html>
Note that the value of the inputs is referred to as #{userdetails.name} the “userdetails” is the name of our entity bean and it is important that these match, when I was attempting to learn Seam I found quite a few examples which used a generic “user” variable everywhere with out pointing out the importance of this naming. Yes it may Seam obvious now but I’ve never been very good at picking up the obvious.
registered.xhtml
< ?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">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<title>Successfully Registered New User</title>
</head>
<body>
<h :dataTable var="userreturn" value="#{items}" rendered="#{items.rowCount>0}" id="ResultsTable" >
</h><h :column>
<f :facet name="header">
<h
utputText value="Name"/>
</f>
<h
utputText value="#{userreturn.name}"/>
</h>
<h :column>
<f :facet name="header">
<h
utputText value="Address"/>
</f>
<h
utputText value="#{userreturn.address}"/>
</h>
<h :column>
<f :facet name="header">
<h
utputText value="Phone Number"/>
</f>
<h
utputText value="#{userreturn.phoneNumber}"/>
</h>
<h :column>
<f :facet name="header">
<h
utputText value="City"/>
</f>
<h
utputText value="#{userreturn.city}"/>
</h>
<h :column>
<f :facet name="header">
<h
utputText value="Email"/>
</f>
<h
utputText value="#{userreturn.email}"/>
</h>
<h :column>
<f :facet name="header">
<h
utputText value="Age"/>
</f>
<h
utputText value="#{userreturn.age}"/>
</h>
</body>
</html>
Another thing to note is if you are calling a method on the entity bean you miss out the prefix get/set so you use, “userdetails.name” and not “userdetails.setName” however if you are calling a method on the session bean you use the full method name as it is in the interface.
Config
OK so thats the code written but we still need to put all the various config files in place to get everything talking.
beans/META-INF
create the following files:
ejb-jar.xml
<ejb -jar 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/ejb-jar_3_0.xsd" version="3.0"> <interceptors> <interceptor> </interceptor><interceptor -class>org.jboss.seam.ejb.SeamInterceptor</interceptor> </interceptors> <assembly -descriptor> <interceptor -binding> <ejb -name>*</ejb> </interceptor><interceptor -class>org.jboss.seam.ejb.SeamInterceptor</interceptor> </assembly> </ejb>
persistance.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"> </persistence><persistence -unit name="jsf"> <provider> org.hibernate.ejb.HibernatePersistence </provider> <jta -data-source> java:/OracleDS </jta> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle9Dialect"/> <property name="hibernate.hbm2ddl.auto" value="none"/> </properties> </persistence>
This persistance.xml is one specifically for a use with a standalone Oracle it will not overwrite any existing tables nor will it create any tables which do not all ready exist
In the root of beans create a file called Seam.properties this file is empty and is only needed in order to let the application know Seam is being used.
JSFExample/META-INF
application.xml
< ?xml version="1.0" encoding="UTF-8"?> <application 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/application_5.xsd" version="5"> <display -name>MyApp</display> <module id="EJB"> <ejb>jsf.jar</ejb> </module> <module id="Web"> <web> </web><web -uri>jsf.war</web> <context -root>web</context> </module> </application>
and ejb-jar.xml the is the same code as shown above
web/WEB_INF
components.xml
< ?xml version="1.0" encoding="UTF-8"?>
<components xmlns="http://jboss.com/products/seam/components"
xmlns:core="http://jboss.com/products/seam/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.1.xsd
http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.1.xsd">
<core :init jndi-pattern="jsf/#{ejbName}/local"/>
</components>
faces-config.xml
< ?xml version="1.0" encoding="UTF-8"?> <faces -config version="1.2" 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"> <!-- Facelets support --> <application> <view -handler>com.sun.facelets.FaceletViewHandler</view> </application> </faces>
web.xml
< ?xml version="1.0" encoding="UTF-8"?> <web -app version="2.5" 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-app_2_5.xsd"> <!-- Seam --> <listener> </listener><listener -class>org.jboss.seam.servlet.SeamListener</listener> <context -param> <param -name>javax.faces.DEFAULT_SUFFIX</param> <param -value>.xhtml</param> </context> <servlet> </servlet><servlet -name>Faces Servlet</servlet> <servlet -class>javax.faces.webapp.FacesServlet</servlet> <load -on-startup>1</load> <servlet -mapping> </servlet><servlet -name>Faces Servlet</servlet> <url -pattern>*.seam</url> <session -config> </session><session -timeout>10</session> </web>
Build script
The following is the build.xml and build.properties I have used for this example and It should work for you providing you have ANT installed and you have followed the same directory structure I have, with my project in C:\JSFExample and my JBoss in C:\JBoss-4.2.3.GA
build.xml
< ?xml version="1.0"?>
<project default="deployDevelopmentEar">
<property environment="env"/>
<property file="build.properties"/>
<path id="compile.classpath">
<pathelement location="${servlet.api.jar}"/>
<pathelement location="${jsp.api.jar}"/>
<pathelement location="${el.api.jar}"/>
<pathelement location="${jsf.api.jar}"/>
<pathelement location="${lib.dir}/jboss-seam.jar"/>
</path>
<target name="clean">
<delete dir="${dest.dir}"/>
<mkdir dir="${dest.dir}"/><code>
</code></target>
<target name="compileAll" depends="clean">
<javac compiler="modern" source="1.5" destdir="${dest.dir}">
<classpath refid="compile.classpath"/>
<src path="${web_module.src}"/>
<src path="${libs_modules.src}"/>
</javac>
</target>
<target name="createBeansJar" depends="clean">
<mkdir dir="${dest.dir}/beans"/>
<javac compiler="modern" source="1.5" destdir="${dest.dir}/beans">
<classpath location="${lib.dir}/jsf-api.jar"/>
<classpath location="${lib.dir}/jboss-seam.jar"/>
<classpath location="${lib.dir}/javaee.jar"/>
<classpath location="${lib.dir}/hibernate3.jar"/>
<classpath location="${lib.dir}/hibernate-annotations.jar"/>
<src path="${beans_module.src}"/>
</javac>
<copy file="${beans_module.src}/seam.properties" todir="${dest.dir}/beans"/>
<jar destfile="${dest.dir}/jsf.jar" basedir="${dest.dir}/beans">
<metainf dir="${beans_module.src}/META-INF">
<include name="**/*.*"/>
</metainf>
</jar>
</target>
<target name="createDeployBeansJar">
<mkdir dir="${dest.dir}/beans"/>
<javac compiler="modern" source="1.5" destdir="${dest.dir}/beans">
<classpath location="${lib.dir}/javaee.jar"/>
<src path="${beans_module.src}"/>
</javac>
<jar destfile="${dest.dir}/jsf.jar" basedir="${dest.dir}/beans">
<metainf dir="${beans_module.src}/META-INF">
<include name="**/*.*"/>
</metainf>
</jar>
<copy file="${dest.dir}/jsf.jar" todir="${jboss.deploy.dir}"/>
</target>
<target name="createWebWar" depends="createBeansJar">
<mkdir dir="${dest.dir}/web"/>
<war destfile="${dest.dir}/jsf.war" webxml="${web_module.src}/../WEB-INF/web.xml">
<fileset dir="${web_module.src}/../resources"/>
<webinf dir="${web_module.src}/../WEB-INF">
<include name="**/*.*"/>
<exclude name="**/web.xml"/>
</webinf>
<metainf dir="${web_module.src}/../META-INF">
<include name="**/*.*"/>
</metainf>
<lib dir="${lib.dir}">
<include name="jboss-seam-ui.jar"/>
<include name="jsf-facelets.jar"/>
<include name="commons-beanutils.jar"/>
</lib>
</war>
</target>
<target name="createEar" depends="createWebWar">
<copy file="${lib.dir}/jboss-seam.jar" todir="${dest.dir}"/>
<copy file="${lib.dir}/jboss-el.jar" todir="${dest.dir}"/>
<ear destfile="${dest.dir}/jsf.ear" appxml="META-INF/application.xml">
<fileset dir="${dest.dir}" includes="*.jar, *.war"/>
</ear>
</target>
<target name="deployDevelopmentEar" depends="createEar">
<copy file="${dest.dir}/jsf.ear" todir="${jboss.deploy.dir}"/>
</target>
</project>
build.properties
web_module.src=web/src
beans_module.src=beans
libs_modules.src=libs/src
dest.dir=dest
results=results
lib.dir=C:/JSFExample/supportingJars
jboss.deploy.dir=C:/jboss-4.2.3.GA/server/default/deploy
jboss.lib.dir=C:/jboss-4.2.3.GA/server/default
servlet.api.jar=C:/jboss-4.2.3.GA/server/default/lib/servlet-api.jar
jsp.api.jar=C:/jboss-4.2.3.GA/server/default/lib/jsp-api.jar
el.api.jar=C:/jboss-4.2.3.GA/server/default/lib/el-api.jar
jsf.api.jar=${lib.dir}/jsf-api.jar
jsf.lib.dir=${jsf.dir}/lib
jstl.lib.dir=${tomcat.dir}/lib
jsf.libs=jsf-api.jar,jsf-impl.jar
jstl.libs=jstl.jar,standard.jar
Run the build script. It should run successfully and copy a file called jsf.ear to your JBoss deploy directory.
While In this directory we need to create a datasource so we can connect to the database.
Create the following file and call it Oracle-ds.xml
Oracle-ds.xml
< ?xml version="1.0" encoding="UTF-8"?> <datasources> <local -tx-datasource> <jndi -name>OracleDS</jndi> <connection -url>jdbc:oracle:thin:@[URL]</connection> <driver -class>oracle.jdbc.driver.OracleDriver</driver> <user -name>[USER]</user> <password>[PASSWORD]</password> <exception -sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter </exception> <metadata> <type -mapping>Oracle9i</type> </metadata> </local> </datasources>
replace [USER] with the username for your database, [PASSWORD] with the password and [URL] with the correct database URL.
Testing
Once complete we are good to go.
Start the JBoss and navigate to http://localhost:8080/web
you should see
fill in the details and press the button and you will see the results table:
This concludes this example I hope it helps you. This is the first time I have attempted to write a tutorial like this so please let me know if it was helpful, constructive criticism’s is also welcome.




Dear sir Jordan Dick
Thanks for writting a very good article.This certainly helps to understand the various files required and the directory structure.I would like to know whether hibernate.cfg.xml is required or not.I have tried to run the build but i fail.always I get error content is not allowed in prolog. henc I can’t test the program.Please give the details for running the build file.otherwise this article is only literature for us.Expecting your early reply.
Yours
bhaskar
@Bhaskar joshi
Hi Bhaskar,
Thanks for taking the time to comment glad you found this post of some use.
To answer your questions no hibernate.cfg.xml is not required if you are going to use an Oracle database.
And the error message you are seeing is because there is rogue whitespace in the build.xml this was caused by my code displaying plugin not working correctly.
However I have uploaded all the source code in a zip file you can download it here I hope this helps you to get your build to work.
JD
Dear sir Jordan Dick
Thanks for the prompt reply.and suggestions. I tried to run build file,but I get following errors
1. package javax.ejb does not exist
2. package javax.persistence does not exist
3. package org.jboss.seam.annotations does not exist
4. package org.jboss.seam.annotations.datamodel does not exist
5. package org.jboss.seam does not exist
6. package org.hibernate.validator does not exist
Some symbols also not found
I have used Oracle 10g and orcl as schema.
All the above packages are imported in java Files.
Please give the location of the JSFExample.ipr,JSFExample.jws,JSFExample.iml files Should I prepare these blank files in notepad.One more request regarding the Directory structure in your article the subdirectory is com.jsf in beans.but in your zip file the subdirectory is only com.Please guide.
This is an exclent article which gives all the details.I have tried jboss-seamm seam setup,and seam generate as per other artcles with mysql database,but i could not get the results.I don’t the reason.please guide
bhaskar joshi
HI bhaskar
You seem to be missing serveral jar files from your classpath.
in my screenshot I show a list of all the jar files which you need in order to get the example to work.
most of them are included in the Jboss Seam zip file from http://www.seamframework.org/Download
you can ignore JSFExample.ipr,JSFExample.jws,JSFExample.iml these files where generated by my IDE, I use IntelliJ Idea 8 which needs these files you do not require them to make the project work in another IDE.
The file structure on my zip file is beans/com/jsf please recheck you havent made a mistake there, I have double checked it and the example code in the zip is the same as the example in the article.
Thanks,
JD
Excellent article. I run the build successfully/. Jsf.ear and Oracle-ds.xml are copied to the server/default/deploy.and started to JBOss-4.2.3.GA server,but it does not start properly. I used oracle 10g(102010) and ORCL schema database.
MBEANS THAT ARE THE ROOT CAUSE OF THE PROBLEM —
ObjectName: jboss.jca:name=OracleDS,service=DataSourceBinding
State: NOTYETINSTALLED
Depends On Me:
persistence.units:ear=jsf.ear,jar=jsf.jar,unitName=jsf
ObjectName: jboss.jca:service=DataSourceBinding,name=DefaultDS
State: NOTYETINSTALLED
ERROR [URLDeploymentScanner] Incomplete Deployment listing:
— Incompletely deployed packages —
org.jboss.deployment.DeploymentInfo@f58ac230 { url=file:/D:/jboss-4.2.3.GA/server/default/deploy/Oracle-ds.xml }
deployer: org.jboss.deployment.XSLSubDeployer@ebaf12
status: null
state: FAILED
watch: file:/D:/jboss-4.2.3.GA/server/default/deploy/Oracle-ds.xml
altDD: null
@naik lawoo
Hi Naik, Thanks for stopping by.
Are you still having problems?
I’ll try and give you some more help, can you please post a full stack trace or email it to jordan@jdick.co.uk.
Hey. Two things:
1. Good post. Thanks for the time and effort.
2. If you still haven’t worked out a way to display XML code properly and you’re using SyntaxHighlighter (as I believe you do), you may want to try using it in conjunction with java2html tool or to manually replace all instances of “” with the appropriate HTML code.
@veggen
Hi Veggen, thanks for taking the time to read it. hope you found some use.
Also thanks for the suggestion on how to fix my XML. I had actually forgotten it was broken.
Cheers
Jordan
Hi Jordan,
When I tried to access the .xhtml files the not able to compile instead they are opened in the browser (as a download) with source.
Can you please let me know what is the problem? and solution for this problem?
Regards,
Varun Tamiri
@Varun
Sorry for the delay in the reply, is this still a problem?
the xhtml files are rendered on the server if you try to open the file contained in the zip it will show as just the source because the seam tags have not been converted into a renderable format yet.
that is why when you view a seam page you view it as .seam not