1. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 1 Session: Pattern of the
Entity Layer Good ol' DAO & DomainStore The GenericDAO
TransferObject and DataTransferObject Large amounts of data A key
does the trick Adding some data dynamically Tips & Tricks
2. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 2 Objectives Learn about:
Get an idea about the challenges at the entity layer Learn how to
access data in a performant manner Learn how to deal with large
chunks of data
3. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 3 Some orientation
Consumer Consumer Layer Integration Layer Business Process Layer
Services Layer Component Layer OS Layer
4. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 4 ECB Pattern Entity
Control Boundary Based upon Robustness Diagrams
(http://www.agilemodeling.com/artifacts/robustnessDiagram.htm)
Boundary: user interface Control: actual process or activity
Entity: a concept from an enterprise context. Elements are generic
enough to be mapped either to service- oriented or object-oriented
architectures. Boundary Control Entity Adam Bien
5. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 5 Services, components and
patterns Boundary Control Entity DAO & Domain Store Generic DAO
Singleton Service Starter Dual View SOA Facade Lightweight
asynchronous Facade Multichannel Facade TO & DTO Paginator Bean
Locator Multichannel Facade Resource Binder Payload Extractor
Aynchronous Resource Integrator Infrastructure
6. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 6 Module Good ol' DAO
& Domain Store
7. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 7 Do you remember ...
Long, long time ago:
8. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 8 Implementing a DAO For
implementing a DAO, we have to implement the following steps. An
interface which defines methods for various operations related to
the domain object (here: User). Concrete classes which implement
DAO interface (here: H2UserDAO) Factory/Abstract Factory class to
get a reference to DAO object (here: DAOFactory) A DataSource to
establish a connection
9. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 9 Data Access Object (DAO)
Is DAO still needed? Adam Bien quoted: DAO pattern is actually no
more interesting for general data access. JPA comes already with
the EntityManager which provides already generic data access
functionality. The usage cannot be simpler. Anyhow, data access is
crucial, therefore there still might be some place to use it After
some discussion: I would say: it depends. It depends how complex
your application really is. Adam Bien:
http://www.infoq.com/news/2007/09/jpa-dao
10. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 10 Domain Store Purpose:
Pattern mainly used prior to EJB 3.0 / JPA Avoid putting
persistence details in your Business Objects. Not want to use
entity beans Application might be running in a web container.
Object model uses inheritance and complex relationships.
11. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 11 Domain Store UML class
diagram
12. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 12 Why bothering? The
architecture as we know it right now has some disadvantages:
Boilerplate code as you have to have DAOs for each and every domain
class / persistent entity So the MDA people might wrote generators
for CRUD methods (but this is proprietary and only few people might
know how to maintain and enhance it) Maybe you want to take
advantage of a few principles of OO like delegation and
inheritance
13. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 13 Lab Implement
DataAccessObject (not more than 15 min.)
14. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 14 Module The Generic
DAO
15. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 15 GenericDAO The
EntityManager already is an implementation of the DAO Pattern
Dedicated DAOs are exception to the rule as the EntityManager can
be injected into the SLSBs / SFSBs => still a lot of boilerplate
code in the dedicated services (createX, createY, findByA, findByB)
For many services plain CRUD methods plus sophisticated finder
methods might do
16. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 16 GenericDAO UML
Diagram
17. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 17 A common superclass
Might be helpful ... @MappedSuperclass public abstract class
BaseEntity implements Serializable { @Version private long version;
@Id @GeneratedValue(strategy = GenerationType.AUTO) private long
id; @Temporal(TemporalType.DATE) private Date creationDate; public
BaseEntity() { //lazy } public Date getCreationDate() { return
creationDate; } public void setCreationDate(Date creationDate) {
this.creationDate = creationDate; } public long getId() { return
id; } }
18. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 18 The GenericDAO class
Just a SLSB ... @Stateless(mappedName =
"ejb/facade/GenericDAOService") @Remote(GenericDAO.class) public
class GenericDAOBean implements GenericDAO { private static final
Logger log = LoggerFactory.getLogger(GenericDAOBean.class);
@PersistenceContext private EntityManager em; // create, read,
update and delete will follow
19. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 19 Using Generics to
persist or update an instance public T createOrUpdateEntity(T
entity) { // as we have no id yet, it must be freshly brewed if
(entity.getId() == 0) { log.debug("createOrUpdateEntity::create::
{}", entity); this.em.persist(entity); } // if there is an id, we
must have dealt with it before else {
log.debug("createOrUpdateEntity::update:: {}", entity);
this.em.merge(entity); } this.em.flush(); return entity; }
20. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 20 Using Generics find an
instance by key public T findEntityById(Class clazz, long id) {
log.debug("findEntityById:: class= {}, id= {}", clazz, id); return
this.em.find(clazz, id); }
21. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 21 Using Generics to
delete an instance public void deleteEntity(BaseEntity entity) {
log.debug("deleteEntity:: {}", entity); // updating it first ...
entity = (BaseEntity) this.em.merge(entity); // ... then killing it
this.em.remove(entity); }
22. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 22 Using Generics to
invoke a (named) query dynamically public List
findByNamedQuery(Class clazz, String queryName, String[]
paramNames, Object[] values) { TypedQuery query =
this.em.createNamedQuery(queryName, clazz); if (paramNames != null)
{ for (int i = 0; i < paramNames.length; i++) {
query.setParameter(paramNames[i], values[i]); } } List result =
query.getResultList(); log.debug("findByNamedQuery:: result={}",
result); return (List) result; }
23. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 23 Lab Implement
GenericDAO (not more than 15 min.)
24. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 24 Module The
Domain-Specific DAO
25. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 25 Domain-specific DAO A
type-safe DAO operating on a specific domain object Extends the
GenericDAO with domain-specific extensions and additional
functionality (e.g. specific queries with specific return types
=> Transfer Object) In practice, GenericDAO and Domain-specific
DAO are used together
26. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 26 Example Presumed, you
want to get some DataTransferObject, the domain- specific DAO is
the only place you can implement it. Either you implement all other
methods as well or you think about some more sophisticated
architecture. @Stateless(mappedName =
"ejb/facade/UserManagementService")
@Remote(UserManagementService.class) public class
UserManagementServiceBean implements UserManagementService {
@PersistenceContext private EntityManager em; public UserPersonDTO
findUserPersonDTOByCredentials(String user, String pwd) { //public
UserPersonDTO(long userId, long personId, String user, String
firstname) String jpql = "SELECT NEW
de.brockhaus.userMgmt.dto.UserPersonDTO( u.id, p.id, u.user,
p.firstName, p.lastName) FROM User u, Person p WHERE u.user = :user
AND u.password = :pwd)"; Query q = this.em.createQuery(jpql);
q.setParameter("user", user); q.setParameter("pwd", pwd); return
(UserPersonDTO) q.getSingleResult(); }
27. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 27 What about this?
28. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 28 Lab Implement
Domain-specific DAO (not more than 15 min.)
29. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 29 Module TransferObject
& DataTransferObject
30. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 30 The Problem On can say,
the problem with EJB 2.1 is solved by detached entities of EJB 3.x,
why to introduce an new class just to transfer data? Although
Transfer Objects might provide a client- / consumer- specific view
to the persistence layer and might keep the interfaces stable. In a
SOA, exposing the domain layer directly to the consumer would make
further extensions impossible; TO's can hide changes to some degree
(for the price of an additional translation layer).
31. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 31 JPA POJOs might be the
best choice when they play the role of DTOs. Loading: Web
developers building on top of the EJB3 architecture tried to use
objects that were not loaded eagerly, and then the middle layer
developers have to to change the way data load was done.
Performance: A business method using a set of POJOs had as an extra
load the eagerly loaded POJOs, no matter if this business method
needed them or not: if another business method was using one of the
POJOs, then you have to load even if you dont need it. This
overhead can be irrelevant in unit testing, but its relevant in
stressed systems. Robustness: Changes in the ER to OO mapping were
propagated to the web layer, forcing the web development team to
refactor their code to fix the problem.
32. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 32 And now? Don't design
lasagna architectures (dozens of layers with only little beef)
Decoupling is not a sufficient justification for using TOs (as they
are in most cases just duplicates of the original) and therefore
would violate the DRY principle. There are enough cases: Additional
view to the domain model Abstracting von legacy data Enforcements
of eager loading Store TOs in a dedicated subpackage
33. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 33 DTOs: SELECT NEW JPA
allows to create objects on the fly using SELECT NEW The DTO itself
(note the constructor) public class UserPersonDTO implements
Serializable { private long userId; private long personId; private
String user; private String firstname; private String lastname;
public UserPersonDTO(long userId, long personId, String user,
String firstname, String lastname) { ... Adam Bien has named this
as detached DTO strategy
34. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 34 DTO's: SELECT NEW The
SLSB: @Stateless(mappedName = "ejb/facade/UserManagementService")
@Remote(UserManagementService.class) public class
UserManagementServiceBean extends GenericServiceBean implements
UserManagementService { @PersistenceContext private EntityManager
em; private Logger log = LoggerFactory.getLogger(this.getClass());
public UserPersonDTO findUserPersoDTOByCredentials(String user,
String pwd) { //public UserPersonDTO(long userId, long personId,
String user, String firstname) String jpql = "SELECT NEW
de.brockhaus.userMgmt.dto.UserPersonDTO(u.id, p.id, u.user,
p.firstName, p.lastName) FROM User u, Person p WHERE u.user = :user
AND u.password = :pwd)"; Query q = this.em.createQuery(jpql);
q.setParameter("user", user); q.setParameter("pwd", pwd); return
(UserPersonDTO) q.getSingleResult(); }
35. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 35 Table View According to
Adam Bien: SQL Views can be considered either as best practice or
an anti-pattern. It depends on the perspective. Sometimes, however,
it is required to provide an efficient way to iterate over an
excerpt or even a set of related entities, but return a different
view to the client. This can be achieved by: fetching the entities
with EntityManager and merging them together inside a Session Bean
(a Service). This approach is neither fast, nor easy to maintain.
Especially the merging and extraction of entity data is error-prone
and can become quite complex. Another option is the execution of
more complex native SQL- statements and mapping them into existing
entities or TOs. For SQL queries there is no difference between
views and tables, so you can easily map a JPA entity to a view
transparently.
36. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 36 Table View Sample view:
CREATE VIEW UserPersonDTO AS SELECT u.id, u.password, u.user,
u.person_id, p.firstname, p.lastname FROM User u INNER JOIN PERSON
p on u.person_id = p.id
37. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 37 Using the view just
like a normal entity @Entity @Table(name="USERPERSONDTO") public
class UserPersonDTO implements Serializable { @Id @Column(name =
"ID") private long userId; @Column(name="PERSON_ID") private long
personId; private String user; private String firstname; private
String lastname; ...
38. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 38 Table View Although
seen in the light of handling large amount of data, creating a SQL
view and mapping a DTO to it might be helpful in the field of DTO
as well Will be covered in detail later.
39. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 39 DTOs: Builder Pattern
Abstract steps of construction of objects so that different
implementations of these steps can construct different
representations of objects. Separate the construction of a complex
object from its representation. By doing so, the same construction
process can create different representations Joshua Bloch quoted:
The builder pattern is a good choice when designing classes whose
constructors or static factories would have more than a handful of
parameters.
40. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 40 DTOs: Builder Pattern
Outer class, private constructor: public class PersonUserDTO
implements Serializable { private long userId; private long
personId; private String user; private String firstname; private
String lastname; /** * private constructor so no one can invoke *
@param builder */ private PersonUserDTO(PersonUserDTOBuilder
builder) { this.userId = builder.personId; this.userId =
builder.userId; } }
41. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 41 DTOs: Builder Pattern
Inner class /** * static inner builder class */ public static class
PersonUserDTOBuilder{ private long userId; private long personId;
private String user; private String firstname; private String
lastname; public PersonUserDTO build(){ return new
PersonUserDTO(this); } public PersonUserDTOBuilder userId(long
userId){ this.userId = userId; return this; } public
PersonUserDTOBuilder personId(long personId){ this.personId =
personId; return this; } }
42. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 42 DTOs: Builder Pattern
Building: PersonUserDTO dto = new
PersonUserDTO.PersonUserDTOBuilder().personId(1).userId(1).build();
43. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 43 DTOs: Apache BeanUtils
/ Dozer might be an alternative as well but are not within the
scope of this training. You might check here:
http://www.javaranch.com/journal/2003/07/TouringTheCommonsPart1.html
44. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 44 Lab Implement DTO using
SELECT NEW (not more than 15 min.)
45. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 45 Module Large amounts of
data
46. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 46 Dealing with large
amounts of data When to use Displaying / iterating over a large
amount of data Data can't be loaded at once at the client but has
to be cached at the server
47. Copyright by Brockhaus GmbH, alle Rechte reserviert,
unautorisierte Vervielfltigung untersagt 47 The simplest case The
classical Value List Handler pattern is already implemented by JPA
/ the EntityManager. public List findAll(Class clazz, int lowNo,
int maxNo) { TypedQuery