ecb: the entity layer

Download ECB: The Entity Layer

If you can't read please download the document

Upload: mbohnen

Post on 12-Aug-2015

59 views

Category:

Software


4 download

TRANSCRIPT

  1. 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. 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. 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. 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. 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. 6. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfltigung untersagt 6 Module Good ol' DAO & Domain Store
  7. 7. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfltigung untersagt 7 Do you remember ... Long, long time ago:
  8. 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. 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. 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. 11. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfltigung untersagt 11 Domain Store UML class diagram
  12. 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. 13. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfltigung untersagt 13 Lab Implement DataAccessObject (not more than 15 min.)
  14. 14. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfltigung untersagt 14 Module The Generic DAO
  15. 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. 16. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfltigung untersagt 16 GenericDAO UML Diagram
  17. 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. 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. 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. 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. 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. 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. 23. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfltigung untersagt 23 Lab Implement GenericDAO (not more than 15 min.)
  24. 24. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfltigung untersagt 24 Module The Domain-Specific DAO
  25. 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. 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. 27. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfltigung untersagt 27 What about this?
  28. 28. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfltigung untersagt 28 Lab Implement Domain-specific DAO (not more than 15 min.)
  29. 29. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfltigung untersagt 29 Module TransferObject & DataTransferObject
  30. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 44. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfltigung untersagt 44 Lab Implement DTO using SELECT NEW (not more than 15 min.)
  45. 45. Copyright by Brockhaus GmbH, alle Rechte reserviert, unautorisierte Vervielfltigung untersagt 45 Module Large amounts of data
  46. 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. 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