java ee based 3-tier system design recommendations (using...
TRANSCRIPT
Recommendations
Java EE Capabilities
& Restrictions
Software Design
Principles
Requirement Specification (use cases)
3-tier System Design Recommendationsbased on Java EE
Java EE based System Design Recommendations 2
3-tier Multilayer Reference Architecture based on Java EE
Java EE based System Design Recommendations 3
Application Server
Presentation: JSF
Business Logic: EJB + CDI
Data Access: EJB + JPA
DBMS
Tables/Triggers/Stored procedures
Client
Browser Internet
Java EE Practical Questions How many EJB components there should be?
How granular EJB components should be?
What type (stateless/stateful) EJB components should have?
What type of Persistence Context should be used?
How many EJB components should use a single web page?
Should we create a separate EJB component for each web page?
Java EE based System Design Recommendations 4
Restriction Example: Data Access Tier (Java EE and .NET) EntityManager is not thread-safe
.Net EntityFramework ObjectContext is not thread-safe too1
One entity cannot be managed/shared by two EntityManagers
The same holds for .Net ObjectContext
One relationship cannot be managed/shared by two EntityManagers
The same holds for .Net ObjectContext
But all Web Applications ARE multi-threaded
1 Entity Framework FAQ: ObjectContext
Java EE based System Design Recommendations 5
Restriction Example: Data Access Tier (Java EE and .NET) You'll have problems, if in your system:
Two EntityManagers try to access one and the same Entity object: For example, one EntityManager has loaded an entity, other tries to
update it
One end of relationship between two entities is being managed by one EntityManager, other – by different EntityManager For example: list of students is loaded by one EntityManager, but
courses are being assigned to students by different EntityManager
Problems of these kinds occur when JSF pages belonging to a single use case use different EJB components Approach “each JSF page must have dedicated EJB
component” is problematic
Java EE based System Design Recommendations 6
Java EE Capabilities @Stateless/@Stateful – many instances,
thread/memory/transaction management
@Singleton – one instance, transaction management
@RequestScoped, … , @ApplicationScoped – life-cycle management
@TransactionAttribute – transaction management
@PersistenceContext: PersistenContextType – short-term or long-term data
cache
SynchronizationType – automatic or manual flushing to DB
@Version – optimistic locking
… many others
Java EE based System Design Recommendations 7
2. Use Case Controller: Request Type Use Case - Annotations For stateful systems (state is being managed on server):
@Named
@Stateful
@RequestScoped
@PersistenceContext(type=EXTENDED, synchronization=SYNCHRONIZED)
For REST type systems (no state management on server):
@Named
@Stateless
Use default @PersistenceContext (transactional and synchronized)
Java EE based System Design Recommendations 8
2. Use Case Controller: Conversation Type Use Case - Annotations For stateful systems (state is being managed on server):
@Named
@ConversationScoped
@Stateful
@PersistenceContext(type=EXTENDED, synchronization=UNSYNCHRONIZED)
For REST type systems (no state management on server):
Not applicable, because conversation must be managed on client side!
Annotations the same as for request type use case
Java EE based System Design Recommendations 10
3. Apply Design Principles:SoC and Cohesion with CDI + EJB
Use Case Controller – one per use case: Orchestrates the execution of sunny day/rainy day scenarios
Centralizes Persistence Context (cache) and Transaction management
=> Stateful Component (CDI + EJB)
Localizable functional requirements: => Service (Stateless) Components (CDI + EJB)
Cross-cutting functional requirements: Not-impacting cross-cut functionality (Observer Pattern):
=> Event-listening Components (CDI + EJB)
Impacting cross-cut functionality (Decorator Pattern): => CDI Decorators
Cross-cutting non-functional requirements (Interceptor Pattern): => CDI Interceptors
Java EE based System Design Recommendations 13
3. Apply Design Principles: Asynchronous Communication (EJB) EJB (and CDI 2.0) provide means for asynchronous
communication:
@Asynchronouspublic Future<String> longComputation() { ... }
Java EE based System Design Recommendations 14
3. Apply Design Principles:Java EE Capabilities/Restrictions Obey these rules:
Resulting business component tree must satisfy rules of Persistence Context propagation (see next slide)
For Service Components:
do not annotate them with @Named to prevent them to be used directly from web pages
prefer @Stateless with transactional unsynchronized@PersistenceContext
Java EE based System Design Recommendations 15
Client Comp1
Comp2 Comp5
Comp3 Comp4 Comp6
R
R
R RN
RN
R
R – RequiredRN – RequiresNew
Transaction and Persistence Context
Transaction and Persistence Context
3. Persistence Context Propagation
Java EE based System Design Recommendations 16
3. Persistence context propagation rules (1) Let k1 and k2 be EJB component instances; k1 injects k2
(with the help of @EJB or @Inject)
If both components have declared @PersistenceContext: Transactional → Transactional , propagates
Transactional → Extended , error
Extended → Transactional , propagates
Extended →newExtended , inherits k1 injects k2 with the help of @Inject and k2 is a newly born
instance
Extended →old Extended , error k1 injects k2 with the help of @Inject, but k2 was born long before k1 and already has its own EntityManager object
Java EE based System Design Recommendations 17
3. Persistence context propagation rules (2) Let k1 and k2 be EJB component instances, k1 injects k2
(with the help of @EJB or @Inject)
If both components have declared @PersistenceContext: Unsynchronized → Unsynchronized , propagates
Synchronized → Synchronized , propagates
Synchronized → Unsynchronized , propagates
Unsynchronized → Synchronized , error
Java EE based System Design Recommendations 18
Example 1: Request Type Use Case@Named @RequestScoped @Stateful public class UseCaseController {
@PersistenceContext(type=EXTENDED,synchronization=SYNCHRONIZED)
private EntityManager em;
@Injectprivate Service1 service1;@Injectprivate Service2 service2;
public String formProcessingMethod() {service1.someMethod(); // em gets propagatedservice2.someMethod(); // em gets propagated
}}
Java EE based System Design Recommendations 20
Example 1: Service Component@Statelesspublic class Service1 {
@Injectprivate StudentCRUD studentCRUD;
public void someMethod(...) {...studentCRUD.createStudent(s);...
}}
Java EE based System Design Recommendations 21
Example 1: Data Access Component@Statelesspublic class StudentCRUD {
@PersistenceContext(type=TRANSACTIONAL,synchronization=UNSYNCHRONIZED)
private EntityManager em;
public void createStrudent(Student s) {em.persist(s);
}}
This is an example of reusable Data Access Component: It may be reused in other use case implementations
no matter the type of use case!
In case of accidental direct use by web tier client – no changes to DB would be done! It may be protected from such a use by using transaction
attribute MANDATORYJava EE based System Design Recommendations 22
Example 2: Conversation Use Case
Java EE based System Design Recommendations 23
Use Case – Register New Student
Steps:1. Fill student fom
2. fill study journal form
3. confirm entered data
4. observe outcomes: success or failure
This is just an example: actually this use-case could be implemented with fewer steps.
Example 2 – Use Case Controller (1)@Named @ConversationScoped @Stateful public class RegisterNewStudentController {
@PersistenceContext(type=PersistenceContextType.EXTENDED, synchronization=SynchronizationType.UNSYNCHRONIZED)
private EntityManager em;
@Injectprivate Conversation conversation;
//--- State being manipulated during the conversation // student and course are bound to HTML forms. private Student student = new Student();public Student getStudent() { return student; }
private Course course = new Course();public Course getCourse() { return course; }
//--- END of state...
Java EE based System Design Recommendations 24
Example 2 – Use Case Controller (2)public void createStudent() {
conversation.begin();
em.persist(student); // changes are not flushed to DB!
}
public void createCourse() {
em.persist(course); // changes are not flushed!
}
public void end() {
try {
course.getStudentList().add(student);
student.getCourseList().add(course);
em.flush(); // try to catch DB problems
em.joinTransaction();
conversation.end();
} catch (OptimisticLockException ole) {
// handle optimistic locking conflicts
}
}}Java EE based System Design Recommendations 25
Example 2 - Discussion This is just an example: relationships can be managed in any
step of the conversation You are allowed to call:
em.persist(…); em.merge(…); em.remove(…); em.refresh(…); em.find(…) and em.createQuery(…);changes to entities are being recorded within the cache of EntityManager, and are flushed to the database as soon as em.joinTransaction() is called.
But you cannot call (TransactionRequiredException): em.flush(…); em.lock(…);
Java EE based System Design Recommendations 26
Example 3: Conversation Use-Case with Several Components
Java EE based System Design Recommendations 27
Example 3: Use Case Controller@Named @ConversationScoped @Stateful public class RegisterNewStudentController {@PersistenceContext(type=PersistenceContextType.EXTENDED,
synchronization=SynchronizationType.UNSYNCHRONIZED)private EntityManager em;@Injectprivate Conversation conversation;
private Student student = new Student();public Student getStudent() { return student; }
private Course course = new Course();public Course getCourse() { return course; }
@Inject private StudentCRUD studentCRUD; // service component
public void createStudent() {
conversation.begin();
studentCRUD.persistStudent(student);
}
... Java EE based System Design Recommendations 28