Table of Contents
Javaee Layers
Source: EBJ Design Pattern
- Presentation: JSF, JScript…
- Application: UI workflow, Validation, Servlet, Userbean..
- Service: biz logic (EJB Session Bean)
- Domain: domain logic, EntityBeans.
- Persistence: DB, ORM.
Dev process
- Domain
- Persistence
- Service
- Client –> last.
Packaging Server
Data (Persistence layer)
DAO, SLSB
Controller (Application)
Backing Beans for JSFview.
Model (domain layer)
JPA Models, Entity Beans.
Service
EJB Beans.
Util-qualifier (Persistence)
Specifies Injection points for the EM.
Packaging Client
View (Presentation)
=== Rest (WS) ===
Preparing data Model
- Design Entity Relationship using Dia…
- Use workbench to generate Model and SQL Schemas.
Entities & Session Facade
Member Entity
package de.td.inhanoi.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.validation.constraints.Digits;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;
@Entity
@XmlRootElement
@Table(uniqueConstraints = @UniqueConstraint(columnNames = "email"))
public class Member implements Serializable {
/** Default value included to remove warning. Remove or modify at will. **/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private Long id;
@NotNull
@Size(min = 1, max = 25)
@Pattern(regexp = "[A-Za-z ]*", message = "must contain only letters and spaces")
private String name;
@NotNull
@NotEmpty
@Email
private String email;
@NotNull
@Size(min = 10, max = 12)
@Digits(fraction = 0, integer = 12)
@Column(name = "phone_number")
private String phoneNumber;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
Managed Beans & JSF
package de.td.inhanoi.controller;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.ejb.Stateful;
import javax.enterprise.event.Event;
import javax.enterprise.inject.Model;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import de.td.inhanoi.model.Member;
// The @Stateful annotation eliminates the need for manual transaction demarcation
@Stateful
// The @Model stereotype is a convenience mechanism to make this a request-scoped bean that has an
// EL name
// Read more about the @Model stereotype in this FAQ:
// http://sfwk.org/Documentation/WhatIsThePurposeOfTheModelAnnotation
@Model
public class MemberRegistration {
@Inject
private Logger log;
@Inject
private EntityManager em;
@Inject
private Event<Member> memberEventSrc;
private Member newMember;
@Produces
@Named
public Member getNewMember() {
return newMember;
}
public void register() throws Exception {
log.info("Registering " + newMember.getName());
em.persist(newMember);
memberEventSrc.fire(newMember);
initNewMember();
}
@PostConstruct
public void initNewMember() {
newMember = new Member();
}
}
Data Service
MemberListProducer.java
package de.td.inhanoi.data;
import de.td.inhanoi.model.Member;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.event.Observes;
import javax.enterprise.event.Reception;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
@RequestScoped
public class MemberListProducer {
@Inject
private EntityManager em;
private List<Member> members;
// @Named provides access the return value via the EL variable name "members" in the UI (e.g.,
// Facelets or JSP view)
@Produces
@Named
public List<Member> getMembers() {
return members;
}
public void onMemberListChanged(@Observes(notifyObserver = Reception.IF_EXISTS) final Member member) {
retrieveAllMembersOrderedByName();
}
@PostConstruct
public void retrieveAllMembersOrderedByName() {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Member> criteria = cb.createQuery(Member.class);
Root<Member> member = criteria.from(Member.class);
// Swap criteria statements if you would like to try out type-safe criteria queries, a new
// feature in JPA 2.0
// criteria.select(member).orderBy(cb.asc(member.get(Member_.name)));
criteria.select(member).orderBy(cb.asc(member.get("name")));
members = em.createQuery(criteria).getResultList();
}
}
Util-Qualifier
package de.td.inhanoi.util;
import java.util.logging.Logger;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
/**
* This class uses CDI to alias Java EE resources, such as the persistence context, to CDI beans
*
* <p>
* Example injection on a managed bean field:
* </p>
*
* <pre>
* @Inject
* private EntityManager em;
* </pre>
*/
public class Resources {
// use @SuppressWarnings to tell IDE to ignore warnings about field not being referenced directly
@SuppressWarnings("unused")
@Produces
@PersistenceContext
private EntityManager em;
@Produces
public Logger produceLog(InjectionPoint injectionPoint) {
return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
}
}
Books - Refs
http://www.amazon.com/dp/1430219548/?tag=stackoverfl08-20
http://www.adam-bien.com/roller/abien/entry/simplest_possible_jsf_2_ejb