Introduction
The previous
section setup the Eclipse project,
namely:
- A default page
- An error page
- A Welcome page
- Internationalization (supports english and french)
In this section the process of registratering is written.
The source code is available in a zip archive here.
The registration
page allows a new user to register their details to become
a member of MyCV. The entity EJB's and the session EJB are written
here, along with their supporting classes and files. The web application,
in the next chapter , makes use of
the EJB's written in this chapter.
The database used in this section was created in the installation
tests.
Entity EJB's
The database currently has two tables: Person and
Address. The EJB's are created in Eclipse. In Eclipse it
is very easy to create a bean: All the private members are entered,
then by right clicking on the code inside the class, the popup
menu option "Generate Getters and Setters" is selected. This
generates the methods to get and set the field values.
The Address entity is shown below. The primary key
is annotated as @Id
@GeneratedValue to specify that the database engine generates the primary key value.
package com.j3ltd.server.entities;
import java.io.Serializable;
import javax.persistence.*;
@Entity
public class Address implements Serializable {
private int id;
private String line1;
private String line2;
private String line3;
private String line4;
private String postcode;
private String country;
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLine1() {
return line1;
}
public void setLine1(String line1) {
this.line1 = line1;
}
public String getLine2() {
return line2;
}
public void setLine2(String line2) {
this.line2 = line2;
}
public String getLine3() {
return line3;
}
public void setLine3(String line3) {
this.line3 = line3;
}
public String getLine4() {
return line4;
}
public void setLine4(String line4) {
this.line4 = line4;
}
public String getPostcode() {
return postcode;
}
public void setPostcode(String postcode) {
this.postcode = postcode;
}
}
The Person entity is shown below. The primary key is annotated, as
done for the Address entity. A relationship is annotated, to
specify that a person entity has one address, using the addressId
database field in the table Person. This allows the Person EJB
to have a member of the type Address. The EJB server handles
the task of going to the Address table to get or change the data.
The cascade type for the Address is set to CascadeType.ALL,
this should ensure that when a Person record is deleted, the
corresponding Address record is also deleted.
package com.j3ltd.server.entities;
import java.io.Serializable;
import javax.persistence.*;
@Entity
public class Person implements Serializable {
private int id;
private String email;
private String password;
private String firstName;
private String lastName;
private String title;
private String gender;
private java.util.Date dateOfBirth;
private String suffix;
private String daytimePhone;
private String eveningPhone;
private String webSite;
private String maritalStatus;
private Address address;
private String localeLanguage;
private String localeCountry;
public String getLocaleCountry() {
return localeCountry;
}
public void setLocaleCountry(String localeCountry) {
this.localeCountry = localeCountry;
}
public String getLocaleLanguage() {
return localeLanguage;
}
public void setLocaleLanguage(String localeLanguage) {
this.localeLanguage = localeLanguage;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="addressId",
referencedColumnName="id")
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public java.util.Date getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(java.util.Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public String getDaytimePhone() {
return daytimePhone;
}
public void setDaytimePhone(String daytimePhone) {
this.daytimePhone = daytimePhone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getEveningPhone() {
return eveningPhone;
}
public void setEveningPhone(String eveningPhone) {
this.eveningPhone = eveningPhone;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getMaritalStatus() {
return maritalStatus;
}
public void setMaritalStatus(String maritalStatus) {
this.maritalStatus = maritalStatus;
}
public String getSuffix() {
return suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getWebSite() {
return webSite;
}
public void setWebSite(String webSite) {
this.webSite = webSite;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Stateless Session EJB
A stateless session EJB is coded, it is through
this EJB that the web application accesses the entities.
package com.j3ltd.server.session;
import javax.ejb.*;
import com.j3ltd.server.entities.*;
import javax.persistence.*;
import com.j3ltd.server.sessionremote.*;
import com.j3ltd.server.Exceptions.*;
@Stateless
public class EntityFacadeBean implements EntityFacade {
@PersistenceContext(unitName="shoestringPU") EntityManager em;
public Person getPerson(String email) {
Person entity = null;
try {
Query query = em.createQuery("SELECT p FROM Person p WHERE p.email = ?1");
query.setParameter(1, email);
entity = (Person) query.getSingleResult();
}
catch (NoResultException noneFound) {
// if not found, just return null
}
return entity;
}
/**
* Perform last minute validation, then if OK save
* entities (Person and Address in Person)
* @param toCreate person record to persist
* @return person record just created, with the
* primary key set to that just insrted.
* @throws PersonEntityExistsException if email given exists
* @throws PersonPasswordException if password is < 6 characters long
* @throws PersonEmailException if email is blank or null
*/
public Person createPerson(Person toCreate)
throws PersonEntityExistsException, PersonPasswordException,
PersonEmailException {
String email = toCreate.getEmail();
if (email == null || email.trim().length() == 0) {
throw new PersonEmailException("Length is zero");
}
String password = toCreate.getPassword();
if (password == null || password.length() < 6) {
throw new PersonPasswordException("Length is less than 6");
}
if (getPerson(email) != null) {
throw new PersonEntityExistsException(
"Person record already exists with an email of " +
toCreate.getEmail());
}
em.persist(toCreate);
return toCreate;
}
}
The class has two methods. The first is to find a Person record
using the email value. The other method is used to create a
new Person record. The Person table has defined a UNIQUE index on the email field.
CreatePerson() throws a PersonEntityExistsException if
a person with the email already exists. PersonEmailException is
thrown, if the email is blank or null. PersonPasswoprdException is
thrown, if the password is too short. At the time of writing, the EJB specification
mentions EntityExistsException, but it does not seem to be documented, and the
release of JBoss used does not have it, hence the need to define our own PersonEntityExistsException.
The application exceptions are defined
as follows:
PersonEntityExistsException:
package com.j3ltd.server.exceptions;
/**
* Currently the javadocs on EntityExistsException do not exist
* in the JEE5 beta sdk docs. When it appears, this exception
* will be removed, and all references replaced by
* EntityExistsException.
*/
public class PersonEntityExistsException extends Exception {
public PersonEntityExistsException(String message) {
super(message);
}
}
PersonEmailException:
package com.j3ltd.server.exceptions;
public class PersonEmailException extends Exception {
public PersonEmailException(String message) {
super(message);
}
}
PersonPasswordException:
package com.j3ltd.server.exceptions;
public class PersonPasswordException extends Exception {
public PersonPasswordException(String message) {
super(message);
}
}
The session ejb has a remote interface defined as follows:
package com.j3ltd.server.sessionremote;
import javax.ejb.*;
import com.j3ltd.server.entities.*;
import com.j3ltd.server.exceptions.PersonEmailException;
import com.j3ltd.server.exceptions.PersonEntityExistsException;
import com.j3ltd.server.exceptions.PersonPasswordException;
@Remote
public interface EntityFacade {
public Person createPerson(Person toCreate)
throws PersonEntityExistsException,
PersonPasswordException,
PersonEmailException;
public Person getPerson(String email);
}
Persistence XML File
The persistence unit that the session EJB uses is defined
in a file called persistence.xml, which is in the "src" folder:
<?xml version="1.0" encoding="UTF-8"?>
<persistence>
<persistence-unit name="shoestringPU">>
<jta-data-source>java:/ShoestringDS</jta-data-source>
<properties>
<property name="hibernate.dialect"
value="org.hibernate.dialect.MySQLDialect"/>
</properties>
</persistence-unit>
</persistence>
Packaging The EJB's
At this point, all the EJB code for the registration process
is complete. The packaging configuration is updated within Eclipse as follows.
The project properties dialog is selected, the "Packaging
Configurations" tab is selected and the "Add..." button is pressed:
The archive name entered
is "MyCV.jar", "OK" is pressed.
The archive is right clicked, and "Add Folder" is selected
from the popup menu.
The project bin folder com/j3ltd/server is selected. The
"includes" field has **.*.class to select all the java classes in the server
folder. The prefix entered is com/j3ltd/server, so that the correct Java package
tree is created.
The archive is right clicked and "Add File" is selected
from the popup menu. The project source file jndi.properties is added. Then
the project file persistence.xml is added with a prefix of "META-INF". The
packaging configuration should look like the screenshot below:
This completes the EJB's and supporting files. The next
step is to update the web application with a new JSF page, and some supporting
code.
|