Chapter3_partI
Download
Report
Transcript Chapter3_partI
Chapter 3:
Middleware Services
Overview of 10 important middleware services
and examples in CORBA, RMI, JEE, Web Services and .NET
(During the lesson, it will be indicated which parts are highly
important and which are not important for the exam)
Design of Distributed Software
Overview
Naming Service
Event and Notification Service
Messaging Service
Persistence Service
Transaction Service
Activation Service
Loadbalancing Service
Session Tracking
Security Service
Dynamic Invocation Service
Design of Distributed Software
2
3.1 Naming Service
Design of Distributed Software
Naming Service
1. Naming Service
Definition
Binding Service
Bind Object References to a textual name
Operations:
bind / rebind : registration by server
lookup / resolve : by client
Design of Distributed Software
4
Java RMI : Registry
RMI registry must run on every server computer in the
distributed system.
1. Naming Service
maps names to remote object references.
a name is represented as a string with format:
//computerName:port/objectName
class java.rmi.Naming
public void bind(String name, Remote obj)
public void unbind(String name, Remote obj)
public void rebind(String name, Remote obj)
gives an exception when the name is already bound
when the name is already bound, the object reference is overwritten
public Remote lookup(String name)
public String[ ] list()
returns all names bound in the Registry
Design of Distributed Software
5
JNDI
Java Naming and Directory Interface
Distributed version of RMI registry
1. Naming Service
applications based on Java technology can store and
retrieve named Java objects of any type
JNDI provides methods for performing standard
directory operations,
associating attributes with objects
searching for objects using their attributes
etc.
http://java.sun.com/products/jndi/reference/
codesamples/index.html
http://java.sun.com/products/jndi/tutorial/
Design of Distributed Software
6
1. Naming Service
CORBA Naming Service
Naming
service
1
2
a
client
3
b
server
Registration of Object References
Names are structured in a hierarchy
cfr directories in file system
files and directories can be assigned a “Kind” id
Design of Distributed Software
7
CORBA server
1. Naming Service
Java class with Main method
Creates and initializes the ORB
Creates an instance of Servant class
Registers it to the ORB (through the connect
method)
Gets a reference for the Naming Service
Registers the server to the Naming Service
Waits for incoming client requests
Design of Distributed Software
8
CORBA Naming Service
NamingService implements an interface called
NamingContext
rebind for servers to register the remote object
references of CORBA objects by name (e.g. rebind
(path, Object))
resolve for clients to look them up by name.(e.g.Object =
resolve(path))
The names are structured in a hierarchy,
1. Naming Service
a path is an array of NameComponent (a struct with a
name in it)
the path starts from an initial context provided by
CORBA
Naming Service is available in all CORBA
implementations
Design of Distributed Software
9
Example ShapeListServer
1. Naming Service
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
public class ShapeListServer {
public static void main(String args[]) {
try{
java.util.Properties props = System.getProperties();
ORB orb = ORB.init(args, props);
ShapeListServant shapeRef = new ShapeListServant(orb);
orb.connect(shapeRef);
org.omg.CORBA.Object objRef =
orb.resolve_initial_references("NameService");
NamingContext ncRef = NamingContextHelper.narrow(objRef);
NameComponent nc = new NameComponent("ShapeList", "");
NameComponent path[] = {nc};
ncRef.rebind(path, shapeRef);
orb.run();
} catch (Exception e) { ... }
}
}
Design of Distributed Software
10
Example ShapeListClient
1. Naming Service
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
public class ShapeListClient{
public static void main(String args[]) {
try{
java.util.Properties props = System.getProperties();
ORB orb = ORB.init(args, props);
org.omg.CORBA.Object objRef =
orb.resolve_initial_references("NameService");
NamingContext ncRef = NamingContextHelper.narrow(objRef);
NameComponent nc = new NameComponent("ShapeList", "");
NameComponent path [] = { nc };
ShapeList shapeListRef =
ShapeListHelper.narrow(ncRef.resolve(path));
Shape[] sList = shapeListRef.allShapes();
GraphicalObject g = sList[0].getAllState();
} catch(org.omg.CORBA.SystemException e) {...}
}
Design of Distributed Software
11
Advanced Example (1)
1. Naming Service
NameComponent[] contextName= new NameComponent[1];
contextName[0] = new org.omg.CosNaming.NameComponent();
contextName[0].id = "CORBA_test";
contextName[0].kind = “ODS_course";
// Note on kind: The kind field is used to indicate the type
// of the object. This is to avoid conventions such as that used
// by files (name.type -- e.g. test.ps = postscript etc.)
org.omg.CosNaming.NamingContext testContext;
try {
// Bind the context to root, and assign testContext to it:
testContext = rootContext.bind_new_context(contextName);
}
catch(org.omg.CosNaming.NamingContextPackage.AlreadyBound ex) {
// If the context already exists, this exception will be raised.
// In this case, just resolve the name and assign testContext
// to the object returned:
org.omg.CORBA.Object tmpobj;
tmpobj = rootContext.resolve(contextName);
testContext = NamingContextHelper.narrow(tmpobj);
if (testContext == null) {
System.err.println("Failed to narrow naming context.");
return false;}
} Design of Distributed Software
12
Advanced Example (2)
1. Naming Service
// Bind the object (obj) to testContext, naming it Echo:
org.omg.CosNaming.NameComponent[] objectName=new
org.omg.CosNaming.NameComponent[1];
objectName[0] = new org.omg.CosNaming.NameComponent();
objectName[0].id = "Echo";
objectName[0].kind = "Object";
// Bind obj with name Echo to the testContext:
try {
testContext.bind(objectName,obj);
}
catch(org.omg.CosNaming.NamingContextPackage.AlreadyBound ex) {
testContext.rebind(objectName,obj);
}
// Note: Using rebind() will overwrite any Object previously bound
//
to /CORBA_test.ATLANTIS_tests with obj.
//
Alternatively, bind() can be used, which will raise a
//
CosNaming::NamingContext::AlreadyBound exception if the name
//
supplied is already bound to an object.
Design of Distributed Software
13
1. Naming Service
Running server and client with NS
Start orbd :
Start the Echo server :
UNIX command shell : $ orbd -ORBInitialPort 1050 -ORBInitialHost
nameserverhost &
MS-DOS system prompt : start orbd -ORBInitialPort 1050 -ORBInitialHost
nameserverhost
1050 = port on which Naming Service listens
UNIX command shell :
$ java echoServer -ORBInitialPort 1050 -ORBInitialHost nameserverhost &
MS-DOS system prompt :
start java echoServer -ORBInitialPort 1050 -ORBInitialHost nameserverhost
Result: echoServer ready and waiting ...
Run the client application :
$ java echoClient -ORBInitialPort 1050 -ORBInitialHost localhost
ResuIt: I said, “Hello!“. The Object said, “Hello!"
Design of Distributed Software
14
CORBA Trading Service
1. Naming Service
Trading Service:
Comparable to Naming Service
Allows objects to be located by attribute : directory
service
Database: service types and attributes -> remote object
references
Clients specify :
Constraints on the values of attributes
Preferences for the order in which to receive matching offers
Design of Distributed Software
15
Other Name Services
Web Services
1. Naming Service
URIs are used to locate the web services
DNS (Domain Name Service)
.Net
No distributed directory, but a local directory on each
participating machine
Based on Web Services
Design of Distributed Software
16
3.2 Event and
Notification Service
Design of Distributed Software
Events and Notifications
Method
Call
A
2. Event/Notification Service
data
Method 1
Method 2
Method 3
Client
Event or
Notification
Design of Distributed Software
18
2. Event/Notification Service
Publish - Subscribe paradigm
Object that generates events : publishes the type of
events it will make available
Objects that want to receive notifications: subscribe to
the types that are of interest
(or: register)
Event types : refer to different operations of object
generating events
Objects that represent events = notifications
Asynchronous communication between publishers and
the subscribers
Design of Distributed Software
19
2. Event/Notification Service
Event type
Each
event has attributes:
Name or identifier of generating object
Operation
Parameters
Time
Sequence Number
Subscribing
=
specify event types
criterion about attribute values
Design of Distributed Software
20
2. Event/Notification Service
Architecture for distributed event notification
Event service
subscriber
object of interest
1.
notification
object of interest
2.
object of interest
observer
notification
subscriber
notification
observer
3.
subscriber
notification
Notification : object that contains information about event
Observer : decouple the object of interest from its subscribers
(forwarding, filtering, patterns of events, notification mailbox)
Design of Distributed Software
21
CORBA Event Service
Defines interfaces for:
Suppliers
Consumers
Push (by supplier to consumer)
2. Event/Notification Service
PushConsumer interface {push (...);}
Consumer register their object references
Pull (by consumer from supplier)
PullSupplier interface { pull (...); }
Suppliers register their object references
Design of Distributed Software
22
Event Service (2)
Event Channels
Allow multiple suppliers to communicate with multiple
consumers
Buffer between suppliers and consumers
EventChannel interface
2. Event/Notification Service
implemented by objects in event server
Chains of event channels
Design of Distributed Software
23
Notification Service
2. Event/Notification Service
Extends Event Service with filters
Notifications have datatype ( <-> any )
Event Consumers may use filters
Event Suppliers can discover the events the consumer
are interested in
Event Consumers can discover a set of event types
(subscribe to new event)
Configure properties of Event Channel
Specify events they are interested in
Proxies forward notifications to consumers according to
constraints specified in filters
Reliability, priority of events, required ordering, policy for
discarding stored events
Event type repository
Design of Distributed Software
24
2. Event/Notification Service
Eventing in other technologies
Java RMI / JEE
Web Services
write callbacks
Java Message Service
WS Eventing : W3C draft
defines a protocol for eventing
http://www.w3.org/Submission/WS-Eventing/
.Net Framework
support comparable to JEE
Design of Distributed Software
25
Intermezzo :
EJB : Enterprise Java Beans
I1. Architecture
I2. Types of EJBs
I3. Stateless Session Beans
I4. Stateful Session Beans
Design of Distributed Software
Introduction
I1. Architecture
EJB components
have the remote capabilities of RMI or CORBA
objects
are JavaBeans components :
allow introspection of properties
JavaBeans “design patterns” for component layout
(properties, accessors, modifiers, events, ...)
architecture provides non-functional features
component life cycle management,
transaction processing,
security handling,
persistence
remotability
timer
state management
resource pooling
messaging
Design of Distributed Software
27
Introduction
I1. Architecture
container hosted on application server
java beans interactions mediated by container
interactions :
- with other beans
locally (same container)
remotely (different container)
- with other JEE components (servlets, jsp, ...)
- with client
- with other resources (e.g. database)
EJB
EJB
EJB
EJB-container
Design of Distributed Software
28
I1. Architecture
Architecture
Client
Webserver
Application Server
Database system
Web container
webserver
applet
applet
browser
EJB container
Servlet
JEE client
Web container services
• component life cycle management
• handle communication with
webserver HTTP <-> servlet
• session tracking
Design of Distributed Software
JSP
EJB
EJB container services
• component life cycle management
• transaction service
• security handling
• resource pooling
29
I1. Architecture
Server side architecture
business logic
Web container
EJB container
persistent
application data [POJO]
Persistence
provider
Java EE container
Servlet
JSP
EJB
External
Resource
Entity
Design of Distributed Software
persistent
application data
[RDBMS]
30
Benefits (1)
I1. Architecture
simplify the development of large, distributed
applications.
the EJB container provides system-level services to
enterprise beans,
the bean developer can concentrate on solving
business problems.
the EJB container--not the bean developer--is
responsible for system-level services such as
transaction management and security authorization.
Design of Distributed Software
31
Benefits (2)
the client developer can focus on the presentation
of the client
I1. Architecture
because the beans--and not the clients--contain the
application's business logic,
the clients are thinner (important for clients that run
on small devices)
enterprise beans are portable/reusable components
the application assembler can build new applications
from existing beans.
these applications can run on any compliant J2EE
server.
Design of Distributed Software
32
I1. Architecture
EJB Views
EJBs have two possible views:
The local view
The remote view
Used by local clients (only EJBs in the same container)
Used by remote clients (not limited to EJBs; can include
Servlets, etc.)
Can also be used by clients in the same container
A bean can implement both local and remote views
remote
Design of Distributed Software
EJB
EJB
local
33
The Local View
I1. Architecture
New since EJB 2.0 spec
Parameters are passed by reference
The client and the EJB must reside in the same
container
Much faster than remote view
The client itself must be an EJB
No network latency
No marshalling/unmarshalling
No need to worry about remote exceptions
Design of Distributed Software
34
I1. Architecture
The Local View (cont.)
1. Client looks up a bean object
- using Java Naming and Directory Interface (JNDI)
- using Dependency Injection (DI)
2. Client finds EJB
3. Client uses EJB business methods from the local interface
JNDI service
InitialContext
client
(EJB)
Bean
Instance
EJBLocalObject
EJB container
Design of Distributed Software
35
The Remote View
Based on Java RMI
I1. Architecture
Uses remote interface, stub, and tie (skeleton)
Works with RMI/IIOP (“RMI over IIOP”)
Vendor-specific protocols are also possible
Parameters are passed by value
All parameter and return-value types must be
serializable
Provides location independence and flexibility
API design consideration (method granularity) :
One method that does several related tasks is more
effective than several smaller methods
Design of Distributed Software
36
I1. Architecture
The Remote View (cont.)
Same 3 steps as before, but taken over the network:
JNDI service
InitialContext
client
(EJB)
EJBObject
remote
stub
client container
Design of Distributed Software
Bean
Instance
remote
tie
EJB container
37
Intermezzo
EJB : Enterprise Java Beans
I1. Architecture
I2. Types of EJBs
I3. Stateless Session Beans
I4. Stateful Session Beans
Design of Distributed Software
I2. Types of EJBs
Types of EJBs
EJBs
Session Beans
Message Beans
- session related object
- always associated to
one single client at
most
- types
stateful :
“conversational
state”
stateless
- asynchronous
message handling
- new since J2EE 1.3
synchronous
asynchronous
Design of Distributed Software
Entities
- “real life” object
- mostly associated
to “row in database”
- persistent
- NEW since EJB3.0
[replace (very) complex
EntityBeans]
- NOT managed by
EJB container
39
Session EJBs
A session bean instance is:
I2. Types of EJBs
A non-persistent object
Implements some business logic
(“procedural component”)
Runs on the server
Not shared among multiple clients
Design of Distributed Software
40
Stateful Session EJBs
A stateful session bean maintains a state
cannot be seen by other clients
The state is not persistent
values of its instance variables
also called : conversational state
The state is relevant only for a single client
I2. Types of EJBs
does not survive a server shutdown
when the client removes the bean or terminates, the
session ends and the state disappears
Canonical example: ShoppingCart
Design of Distributed Software
41
Stateless Session EJBs
I2. Types of EJBs
Conceptually, the same as stateful session
EJBs
No state
http-style request – reply interaction
Can have fields, but they are not unique to any client
Basically, it’s an optimization trick:
Since the container knows the bean has no
state, it can:
Use a single bean instance (While each client thinks it
has its own copy)
Destroy/re-instantiate on the fly
Redirect requests to different instances (load
balancing)
Example: CurrencyConversionBean
Design of Distributed Software
42
Entities
I2. Types of EJBs
Object-oriented view of entities stored in persistent
storage
Normally, each entity represents a row in a relational
DB table
Persistence code generated through ORM-tool
(Object-Relational Mapping, e.g. Hibernate, TopLink)
A single instance (on the server) can be accessed by
multiple clients
Unlike stateful session EJBs
Each instance must be uniquely identifiable by means of
a primary key.
Design of Distributed Software
43
Message Driven Beans (MDBs)
process messages asynchronously
messages originate from JMS (Java Messaging Service)-compliant
system
message can be sent by any source
other EJB
other JEE component (e.g. web component)
any other (legacy) component
indirectly accessed by clients
I2. Types of EJBs
no interface, use message instead
similar to stateless session bean
all beans are equivalent (pooling !) – no client specific state
no conversational state maintained
can handle requests from multiple clients
JMS queue
Client
Design of Distributed Software
MDB
44
I2. Types of EJBs
Bean packaging
Bean contents
deployment descriptor (XML) [deploytool]
enterprise bean class (bytecode) [programmer]
interfaces [IDE]
local/remote
helper classes (utilities/exceptions/...)
[programmer]
EJB JAR-file
JEE-application
EJB JAR-file
EAR-file
WAR-file
Design of Distributed Software
deployable units to
application server
45
Deployment descriptor
I2. Types of EJBs
-essentially contains meta-data of application/component
- cumbersome to construct/maintain
- alternative : Annotations
POJO
JEE
component
BUT : deployment descriptor can still override annotations
Design of Distributed Software
46
Naming Conventions
syntax
bean name
<name>Bean
bean class
<name>Bean
remote [component] interface <name>Remote
local [component] interface <name>Local
Design of Distributed Software
I2. Types of EJBs
example
ExampleBean
ExampleBean
ExampleRemote
ExampleLocal
47
Intermezzo
EJB : Enterprise Java Beans
I1. Architecture
I2. Types of EJBs
I3. Stateless Session Beans
I4. Stateful Session Beans
Design of Distributed Software
Session Bean services
I3. Stateless SB
• Thread safe and performant concurrency
(techniques : pooling, session management,
passivation – activation)
• Remoting
• Exposure as Web Service
• Transaction Management
• Security Management
• Timer services (scheduling)
Design of Distributed Software
49
Session Bean in EJB2.0
I3. Stateless SB
public class MyBean implements javax.ejb.SessionBean,BeanInterface {
private javax.ejb.SessionContext context;
public void setSessionContext(javax.ejb.SessionContext aContext) {
context = aContext;
}
// called when created
public void ejbActivate() { }
// called when activated
public void ejbPassivate() {}
// called when passivated
public void ejbRemove() { }
// called when removed from server
public void ejbCreate() { }
// called when created
// business methods
}
• implements the SessionBean + BeanInterface interface
• is public
• is NOT abstract or final
• at least one ejbCreate method
• implements required business methods (component i’face)
• does NOT have a finalize method
Design of Distributed Software
50
Session Bean in EJB3.0
@Stateful
public class MyBean implements BeanInterface {
@Resource SessionContext context;
@PostContruct
// ...
// called
@PostActivate
// ...
// called
@PrePassivate
// ...
// called
@PreDestroy
// ...
// called
I3. Stateless SB
when created
when activated
when passivated
when removed from server
// remote business method
// local business method
• SIMPLE Plain Old Java Object
• WITH annotations ...
}
Design of Distributed Software
51
Session Bean in EJB3.0
Programming Rules
I3. Stateless SB
- Bean MUST implement at least one business interface
- methods must NOT start with “ejb”
- business methods are public, NOT final, NOT static
- @Remote : arguments and return value
MUST implement Serializable
- Class MUST be concrete, NOT final
- MUST have no-arg constructor
(can be default no-arg constructor)
- can subclass other Session Bean, or POJO
BUT : mind “inheritance of annotations”
- @Stateless, @Stateful -> NOT inherited
- lifecycle call back method annotations -> inherited
Design of Distributed Software
52
Session Context
During creation, the EJB instance is handed a
Session Context object
I3. Session EJBs
An instance of javax.ejb.SessionContext
Typically set using DI
@Resource SessionContext context;
The context object contains:
Security-related information
Transaction-related information and methods
getCallerPrinciple, isCallerInRole
getUserTransaction, get/setRollbackOnly
EJB Object-related information
getEJBObject, getEJBLocalObject
The former must be returned instead of this, whenever required
Design of Distributed Software
53
Stateless Session Bean usage
I3. Stateless SB
Client 1
Client 2
Bean Pool
Instance 1
Client 3
Instance 2
Client 4
Design of Distributed Software
EJB container
54
I3. Stateless SB
Session Bean interfaces
SB1
SB2
EJB container
Local interface ( @Local )
Remote interface ( @Remote )
Web Service interface ( @WebService )
Stateless Session Beans ONLY !
Design of Distributed Software
55
Session Bean interfaces
I3. Stateless SB
Interface can ONLY be annotated with 1 SB interface type
NOT allowed :
@WebService
@Remote
public interface MyInterface {
public int f(int i);
}
Allowed :
public interface MyInterface {
public int f(int i);
}
@Remote
public MyRemoteInterface extends MyInterface {}
@WebService
public MyWSInterface extends MyInterface {}
Design of Distributed Software
56
Example : a random bean
I3. Stateless SB
• business methods
• random() : give a random int number between 0 and 10
• random(int n) : idem between 0 and n
package random;
import javax.ejb.Remote;
@Remote
public interface RandomRemote {
public int random();
public int random(int n);
}
Design of Distributed Software
RandomRemote.java
57
Coding the RandomBean
I3. Stateless SB
package random;
import javax.ejb.Stateless;
@Stateless
public class RandomBean implements random.RandomRemote {
public RandomBean() {
}
public int random() {
return random(10);
}
public int random(int n) {
return (int)(Math.random()*n);
}
}
RandomBean.java
Design of Distributed Software
58
EJB-clients
I3. Stateless SB
different types of clients
-container clients (JEE components) -> support !
- app client (client side component)
- other EJB (same container or not)
- web component (JSP/Servlet) (other container)
-[non-container clients (standalone)]
Steps :
1. Client gets reference to EJB (JNDI or not)
2. Invocation of business methods on session bean
3. Client calls remove-method (stateful session beans only)
Design of Distributed Software
61
I2. Session Beans
Coding the AppClient
package randomappclient;
import javax.ejb.EJB;
import random.*;
public class Main {
@EJB
public static RandomRemote r;
public static void main(String[] args) {
System.out.println("Starting appclient ...");
System.out.println(r.random(10000));
}
}
Main.java
INJECTION ONLY DONE FOR
- statics
- in class Main
Design of Distributed Software
64
Client 2 : Standalone Application Client
I3. Stateless SB
Application client separately from enterprise application
typical client code sequence
1. Retrieve InitialContext
Context ctx = new InitialContext();
2. Perform explicit JNDI lookup
(MyRemote) ejbRef=(MyRemote)ctx.lookup(“<BeanName>”)
3. Invoke business methods on bean
ejbREF.method1(par1);
ejbREF.method2();
// ...
USE mappedName (global JNDI names !)
Design of Distributed Software
66
Example : Random Bean
I3. Stateless SB
@Stateless(mappedName="Random")
public class RandomBean implements random.RandomRemote {
public RandomBean() { }
public int random() {
return random(10);
Random Bean
}
public int random(int n) {
return (int)(Math.random()*n);
}
}
package randomappclientjndi;
import javax.ejb.EJB;
import javax.naming.*;
import random.RandomRemote;
public class Main {
public Main() {}
public static void main(String[] args) throws Exception {
System.out.println("Starting appclient ...");
Application
Context ctx = new InitialContext();
RandomRemote r=(RandomRemote)ctx.lookup("Random");
client
for(int i=0;i<10;i++)
System.out.println(r.random(10000));
}
Design of Distributed Software
68
}
Client 3 : Web Client
I3. Stateless SB
Create jsp or servlet
-> WebModule -> New -> JSP or Servlet
Compile web resource
Add to war (IDE or deploytool)
Deploy application
Set context root for web application (default index.jsp)
Browse to indicated URL
(e.g. http://localhost:8080/RandomApp-war/ )
Design of Distributed Software
70
Client 3 : Web Client
I3. Stateless SB
JSP client
index.jsp
<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@ page import="random.*, javax.ejb.*, java.math.*, javax.naming.*,
java.rmi.RemoteException" %>
<%!
private RandomRemote bean = null;
public void jspInit() {
or “Random”
try {
InitialContext ic = new InitialContext();
bean=(RandomRemote)ic.lookup(RandomRemote.class.getName());
} catch (Exception ex) {
System.out.println("Exception caught : "+ ex.getMessage());
}
}
public void jspDestroy() {
bean = null;
}
%>
Design of Distributed Software
71
Client 3 : Web Client
I3. Stateless SB
<html>
<head><title>Random Values</title></head>
<body bgcolor="white">
<h1><b><center>Random Values</center></b></h1>
<hr><p>Enter upperbound:</p>
<form method="get">
<input type="text" name="upper" size="25">
<br><p>
<input type="submit" value="Submit">
<input type="reset" value="Reset">
</form>
<%
String upper = request.getParameter("upper");
if ( upper != null ) {
int n = Integer.parseInt(upper);
%>
<p>
Random value smaller than <%= upper %> : <%= bean.random(n) %>
<%
}
%>
</body>
Design of Distributed Software
</html>
index.jsp 72
Client 3 : Web Client
Servlet client
I3. Stateless SB
automatically generated DI for EJB lookup
(right-click in Servlet body-> Enterprise Resources
-> Call Enterprise Bean-> Select the bean to look up)
RandomServlet.java
private random.RandomRemote lookupRandomBean () {
@EJB
private RandomRemote randomBean;
protected void processRequest(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet RandomServlet</title>");
out.println("</head>");
out.println("<body>");
out.println("A random value < 100 : "+randomBean.random(100));
out.println("</body>");
out.println("</html>");
out.close();
}
// Servlet methods
} Design of Distributed Software
73
EJB :
Enterprise Java Beans I
I1. Architecture
I2. Types of EJBs
I3. Stateless Session Beans
I4. Stateful Session Beans
Design of Distributed Software
Stateful Session Bean usage
I4. Stateful SB
Client 1
Client 2
State 1 Instance 1
State 2 Instance 2
Client 3
State 3 Instance 3
Client 4
State 4 Instance 4
EJB container
Design of Distributed Software
typical usage : multi-step workflows
78
Stateful Session Beans
Programming Rules
I4. Stateful SB
Additional Rules
- @Stateful (instead of @Stateless)
identical (except for name) als @Stateless
- instance variables must be primitive/Serializable
- @Remove for “friendliness”
- provide additional methods (wrt stateless
beans) :
@PostActivate
@PrePassivate
Design of Distributed Software
81
Simple Example : a random bean
I4. Stateful SB
• business methods
• random() : give a random int number between 0 and 10
• random(int n) : idem between 0 and n
• getSum() : get sum of all values produced in this session
• getUser() : get user of this session
• setUser() : set user of this session
Design of Distributed Software
82
I4. Stateful SB
Random State Bean : remote interface
package randomstate;
RandomStateRemote.java
import javax.ejb.Remote;
import javax.ejb.Remove;
@Remote
public interface RandomStateRemote {
int random(int n);
int random();
void setUser(String name);
String getUser();
int getSum();
@Remove
void remove();
}
Design of Distributed Software
83
Random State Bean : Bean Class
package randomstate;
import javax.ejb.Remove;
import javax.ejb.Stateful;
I4. Stateful SB
RandomStateBean.java
@Stateful
public class RandomStateBean implements RandomStateRemote {
private String userName;
private int sum=0;
session related state variables
public RandomStateBean() {}
public int random(int n) {
int r=(int)(n*Math.random());
sum+=r;
return r;
}
public int random() {return random(10);}
public void setUser(String name) {userName=name;}
public String getUser() {return userName;}
public int getSum() {return sum;}
friendly removal
@Remove
public void remove() {userName=null;sum=0;}
}
Design of Distributed Software
84
I4. Stateful SB
Random State Bean : multisession client
Main.java
sample run
package twosessionclient;
import javax.ejb.EJB;
import randomstate.RandomStateRemote;
public class Main {
@EJB
private static RandomStateRemote george;
@EJB
private static RandomStateRemote john;
public Main() {}
1:5 2:8
1:0 2:25
1:6 2:43
1:3 2:34
1:1 2:1
George:15
John:111
public static void main(String[] args) {
george.setUser("George");
john.setUser("John");
for(int i=0;i<5;i++)
System.out.println("1:"+george.random(10)+"\t2:"+john.random(100));
System.out.println(george.getUser()+" : "+george.getSum());
System.out.println(john.getUser()+" : "+john.getSum());
george.remove();
john.remove();
}
}
Design of Distributed Software
85
I4. Stateful SB
J2EE canonical example : CartBean
CartBean.java
package cart;
import java.util.ArrayList;
import javax.ejb.Remove;
import javax.ejb.Stateful;
@Stateful
public class CartBean implements CartRemote {
private String customerName;
private String customerId;
private ArrayList<Book> contents=new ArrayList<Book>();
public CartBean() {}
public void initUser(String person) throws CreateException {
initUser(person,"0");
}
public void initUser(String person, String id) throws CreateException {
if(person==null) throw new CreateException("Null person not allowed.");
else customerName=person;
customerId=id;
}
Design of Distributed Software
86
I4. Stateful SB
J2EE canonical example : CartBean
public void addBook(Book b) {
contents.add(b);
}
public void removeBook(Book b) throws BookException {
if(contents.contains(b)) contents.remove(b);
else throw new BookException("Book not in shopping cart !");
}
public ArrayList<Book> getContents() {
return contents;
}
@Remove
public void remove() {
contents=null;
customerName=null;
customerId=null;
}
}
CartBean.java
Design of Distributed Software
87
Cart Bean : Remote Interface
package cart;
I4. Stateful SB
CartRemote.java
import javax.ejb.Remote;
import javax.ejb.Remove;
@Remote
public interface CartRemote {
void initUser(String person) throws CreateException;
void initUser(String person, String id) throws CreateException;
void addBook(Book b);
void removeBook(Book b) throws BookException;
java.util.ArrayList<cart.Book> getContents();
@Remove
void remove();
}
Design of Distributed Software
88
Cart Bean : Utility Classes
package cart;
I4. Stateful SB
Book.java
import java.io.Serializable;
public class Book implements Serializable {
private String title;
private String author;
public Book(String t,String a) {
title=t;author=a;
}
public String toString() {
return "<"+title+","+author+">";
}
public boolean equals(Object o) {
if(o instanceof Book) {
Book a=(Book)o;
return (((a.author).equals(author))&&((a.title).equals(title)));
} else return false;
}
}
MUST be Serializable !
Design of Distributed Software
89
Cart Bean : Utility Classes
I4. Stateful SB
BookException.java
package cart;
import java.rmi.RemoteException;
public class BookException extends RemoteException{
public BookException(String message) {
super(message);
}
MUST be RemoteException !
}
package cart;
CreatekException.java
import java.rmi.RemoteException;
public class CreateException extends RemoteException{
public CreateException(String message) {
super(message);
}
}
Design of Distributed Software
90
CartBean Client
I4. Stateful SB
Main.java
package shoppingcartclient;
import cart.*;
import java.util.ArrayList;
import javax.ejb.EJB;
public class Main {
@EJB
private static CartRemote shoppingCart;
public Main() {}
public static void main(String[] args) {
try {
shoppingCart.initUser("MyFavouriteUser");
} catch(Exception e) {System.err.print(e);}
shoppingCart.addBook(new Book("The Martian Chronicles","Jane Austin"));
shoppingCart.addBook(new Book("2001 A Space Odyssey","George Lewanski"));
shoppingCart.addBook(new Book("The Left Hand of Darkness","Unknown"));
ArrayList<Book> bookList = new ArrayList<Book>();
bookList = shoppingCart.getContents();
System.out.println(bookList);
try {
shoppingCart.removeBook(new Book("Alice in Wonderland","Lewis Carrol"));
shoppingCart.remove();
} catch(Exception e) {System.out.println(e);}
}
Design of Distributed Software
91
}
3. Messaging Service
1. Messaging concepts
2. Message Driven Beans
Design of Distributed Software
3.1 Messaging concepts
Messaging architecture
supports communication between components/subsystems
• loosely coupled (no interface to conform to)
• asynchronous
-> can be used to couple
“fast” and “slow” subsystems
• JMS also supports synchronous communication
(with timeout)
send message
“deliver”
retrieve
acknowledge
store
send message
acknowledge
message sender
= producer
Message Oriented Middleware [MoM]
= reliable man-in-the-middle
Design of Distributed Software
message receiver
= consumer
93
3.1 Messaging concepts
Messaging models
point-to-point (PTP)
consumer
producer
Queue
consumer
delivered to 1 online consumer with correct destination ID
receiver
publish-subscribe (Topic)
consumer
producer
Design
of Distributed
delivered
to allSoftware
consumers
Topic
subscribed to the topic
consumer
94
JMS-basics
“Java Messaging Service”
= messaging API supported by JEE
- resembles JDBC API
JMS message
message headers
message properties
message body
Design of Distributed Software
3.1 Messaging concepts
common set of (key,value) pairs
- JMSTimestamp
- JMSCorrelationID
- JMSReplyTo
- JMSMessageID
application defined
(key,value) pairs
[String, Object, primitive no char]
message payload
-ObjectMessage
-BytesMessage
-MapMessage
-StreamMessage
-TextMessage
95
3.1 Messaging concepts
JMS programming model
Connection Factory
long-lived logical relation
client-provider
expensive to create
resource hungry
creates
Connection
creates
short-lived logical relation
inexpensive to create
cheap !
Session
creates
Producer
creates
creates
message
Destination
Design of Distributed Software
Consumer
Destination
96
JMS message delivery model
3.1 Messaging concepts
Designed for reliable message communication :
•Use of acknowledgements
•DeliveryMode can be specified to indicate message persistence
•Priority levels can be specified
•Support for transactions (default : auto-commit)
Design of Distributed Software
97
3. Messaging Service
1. Messaging concepts
2. Message Driven Beans
Design of Distributed Software
3.2 MDBs
Message Driven Beans
MDBean Pool
message
destination
Instance 1
Instance 2
Instance 4
client producer 1
Instance 3
EJB container
client producer 2
client producer 3
Design of Distributed Software
Services offered
- safe multithreading and pooling
- simplified coding (wrt native JMS)
99
Message Driven Beans
Programming Rules
3.2 MDBs
Class
- must implement message listener interface
(can be declared by annotation)
- concrete (not absract), non-final
- POJO, not subclass of MDB
- public
Methods
-MUST have no-arg constructor
- no finalizer (use @PreDestroy)
- MUST have message listener methods
(public, NOT static, NOT final)
- NO runtime exceptions (terminates MDB)
Design of Distributed Software
100
@MessageDriven : Listener
3.2 MDBs
@MessageDriven(
name=“MyBean”,
messageListenerInterface=“javax.jms.MessageListener”)
public class MyBeanMDB { ... }
OR
@MessageDriven(name=“MyBean”)
public class MyBeanMDB implements MessageListener {
...
}
OR
use deployment descriptor
Design of Distributed Software
101
@MessageDriven :
ActivationConfigs
3.2 MDBs
allows for system-specific configuration
public @interface ActgivationConfigProperty {
String propertyName();
String propertyValue();
}
Bean listens to Queue
typical usage
find Factory to connect to Queue
@MessageDriven(
name=“MyBean”,
activationConfig= {
@ActivationConfigProperty(propertyName=“destinationType”,
propertyValue=“javax.jms.Queue”),
@ActivationConfigProperty(propertyName=“connectionFactoryJndiName”,
propertyValue=“jms/QueueConnectionFactory”),
@ActivationConfigProperty(propertyName=“destinationName”,
propertyValue=“jms/MyQueue”;
}
Design of Distributed Software
102
)
find Queue to listen to
@MessageDriven :
ActivationConfigs
3.2 MDBs
acknowledgeMode
How should the session acknowledge ?
AUTO_ACKNOWLEDGE
-> rigorous acknowledgement of each message (default)
DUPS_OK_ACKNOWLEDGE
-> lazy acknowledgement (once in case of duplicate messages)
subscriptionDurability (for Topics)
How to handle offline consumers ?
NonDurable
-> offline consumers do not get the message (default)
Durable
-> offline consumers get the message as soon as they get
connected
Design of Distributed Software
103
3.2 MDBs
@MessageDriven :
ActivationConfigs
messageSelector
consumer side filtering of messages
<expression>
operands
literals (Strings, numeric values, booleans, ...)
Identifiers -> message property name or header field
operators
comparison
=, >, >=, <=, <>
Null comparison : IS NULL, IS NOT NULL
true/false comparison : IS [NOT] TRUE,
IS [NOT] FALSE
logical : NOT, AND, OR
Design of Distributed Software
104
3.2 MDBs
MDB lifecycle
Does Not
Exist
0. newInstance()
1. Dependency Injection
2. @PostConstruct
@PreDestroy
onMessage
Ready
@PostConstruct -> setup session with Queue/Topic
@PreDestroy -> Release session
Design of Distributed Software
105
Example: Processing ShipRequests
3.2 MDBs
NetBeans
1. Create EnterpriseProject with Application Client
[JMessageProject]
2. Create Message Driven Bean
Right click on JMessageProject-ejb node
-> New -> Message Driven Bean
EJB-name : ShipRequestMDB
package : ejb
Destination Type : Queue
-> Finish
3. Program onMessage() -method
Design of Distributed Software
106
Example: Processing ShipRequests
package ejb;
3.2 MDBs
ShipRequestMDB.java
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.Message;
JNDI mapped name
import javax.jms.MessageListener;
@MessageDriven(mappedName = "jms/ShipRequestMDB", activationConfig = {
@ActivationConfigProperty(propertyName = "acknowledgeMode",
propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType",
propertyValue = "javax.jms.Queue")
})
public class ShipRequestMDB implements MessageListener {
/** Creates a new instance of ShipRequestMDB */
public ShipRequestMDB() {
listens to JMS messages
}
public void onMessage(Message message) {
}
}
Design of Distributed Software
IDE-generated
107
Example: Processing ShipRequests
3.2 MDBs
ShipRequestMDB.java
package ejb;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.*;
import util.ShipRequest;
@MessageDriven(mappedName = "jms/ShipRequestMDB", activationConfig = {
@ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
})
public class ShipRequestMDB implements MessageListener {
/** Creates a new instance of ShipRequestMDB */
public ShipRequestMDB() {
}
public void onMessage(Message message) {
try {
ObjectMessage oMessage=(ObjectMessage)message;
ShipRequest sRequest=(ShipRequest)oMessage.getObject();
processShipRequest(sRequest);
} catch(JMSException e) {
System.err.println(e);
e.printStackTrace(System.err);
with onMessage
}
}
private void processShipRequest(ShipRequest s) {
System.out.println(s);
}
Design of Distributed Software
}
...
108
Example: Utility Class
package util;
3.2 MDBs
ShipRequest.java
import java.io.Serializable;
public class ShipRequest implements Serializable {
protected String item;
protected String dest;
must be serializable
/** Creates a new instance of ShipRequest */
public ShipRequest(String i,String d) {
item=i;
dest=d;
}
public String toString() {
return "Send item : <"+item+"> to destination : "+dest+".";
}
}
Design of Distributed Software
109
Example : Sending messages
[from appclient]
3.2 MDBs
NetBeans
1. Open Application Client project
[JMessageProject-app-client]
2. Connect to Message Driven Bean
Right click in main() -method
-> Enterprise Resources
-> send JMS message
Project : JMessageProject-ejb
Destination: ShipRequestMDB
Select : Generate Inline Lookup Code
3. Copy util-package (!)
4. Code application logic
Design of Distributed Software
110
Example : Sending messages
[from appclient]
3.2 MDBs
Main.java
package jmessageproject;
import javax.annotation.Resource;
import javax.jms.*;
import javax.naming.NamingException;
public class Main {
@Resource(mappedName = "jms/ShipRequestMDBFactory")
private static ConnectionFactory shipRequestMDBFactory;
@Resource(mappedName = "jms/ShipRequestMDB")
private static Queue shipRequestMDB;
public Main() {
}
public static void main(String[] args) {
// TODO code application logic here
}
inject resources :
administrated JMS objects
Convenience template
method
}
private Message createJMSMessageForShipRequestMDB(Session session, Object messageData)
throws JMSException {
// TODO create and populate message to send
// javax.jms.TextMessage tm = session.createTextMessage();
// tm.setText(messageData.toString());
// return tm;
}
// ...
Design of Distributed Software
111
IDE-generated
Example : Sending messages
[from appclient]
3.2 MDBs
private void sendJMSMessageToShipRequestMDB(Object messageData)
throws NamingException, JMSException {
Connection connection = null;
Session session = null;
Convenience template
try {
method
connection = shipRequestMDBFactory.createConnection();
session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(shipRequestMDB);
messageProducer.send(createJMSMessageForShipRequestMDB(session, messageData));
} finally {
if (session != null) {
session.close();
}
if (connection != null) {
connection.close();
}
}
}
IDE-generated
}
Main.java
Design of Distributed Software
112
Example : Sending messages
[from appclient]
3.2 MDBs
package jmessageproject;
import javax.annotation.Resource;
import javax.jms.*
import javax.naming.NamingException;
import util.ShipRequest;
public class Main {
@Resource(mappedName = "jms/ShipRequestMDBFactory")
private static ConnectionFactory shipRequestMDBFactory;
@Resource(mappedName = "jms/ShipRequestMDB")
private static Queue shipRequestMDB;
public Main() {}
public static void main(String[] args) throws Exception {
Main.java
ShipRequest r=new ShipRequest("Book ","Sunset Boulevard");
try {
sendJMSMessageToShipRequestMDB(r);
}catch(NamingException ne) {
System.err.println(ne);
}catch(JMSException je) {
System.err.println(je);
}
}
Modified ...
// ...
}
Design of Distributed Software
113
Example : Sending messages
[from appclient]
private
static
3.2 MDBs
Message createJMSMessageForShipRequestMDB(Session session,
ShipRequest mData ) throws JMSException {
ObjectMessage oMessage=session.createObjectMessage(mData);
return oMessage;
}
void sendJMSMessageToShipRequestMDB( ShipRequest mData )
throws NamingException, JMSException {
Connection connection = null;
Session session = null;
try {
connection = shipRequestMDBFactory.createConnection();
session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(shipRequestMDB);
messageProducer.send(createJMSMessageForShipRequestMDB(session, mData));
} finally {
if (session != null) {
session.close();
}
if (connection != null) {
connection.close();
}
}
private
static
Modified ...
}
Main.java
}
Design of Distributed Software
114
Sending back info to the client
3.2 MDBs
How to send JMS message from bean -> client ?
-> ConnectionFactory and Destination to be configured by admin
-> deployment descriptor contains info for container to set up
-> resources can be injected by container
appclient container ONLY injects:
- into Main –class
- private static attributes
Set up administrated resources for reply (MDB -> appclient)
ShipReplyConnectionFactory
ShipReplyQueue
Design of Distributed Software
115
Configuring administrated objects
NetBeans
1. Select resource type
File -> New File ...
Select ejb-project node
Categories -> Sun Resources
File Types -> JMS Resource
-> Next
2. Configure JMS resource
JNDIname : jms/<name>
description : Free text
3.2 MDBs
[JMessageProject-ejb]
[jms/ShipReplyConnectionFactory]
[jms/ShipReplyQueue]
[jms.ConnectionFactory]
Select JMS-resource type
[jms.Queue]
-> Next
Enter properties (if needed)
[]
Name : JNDIname, without prefix
[ShipReplyQueue]
-> Finish
Design of Distributed Software
116
MDB code with reply
package ejb;
import
import
import
import
import
import
3.2 MDBs
ShipRequestMDB.java
javax.annotation.Resource;
javax.ejb.ActivationConfigProperty;
javax.ejb.MessageDriven;
javax.jms.*;
javax.naming.NamingException;
util.ShipRequest;
@MessageDriven(mappedName = "jms/ShipRequestMDB", activationConfig =
@ActivationConfigProperty(propertyName = "acknowledgeMode",
propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType",
propertyValue = "javax.jms.Queue")
})
public class ShipRequestMDB implements MessageListener {
{
@Resource(mappedName="jms/ShipReplyConnectionFactory")
private ConnectionFactory shipReplyCF;
@Resource(mappedName="jms/ShipReplyQueue")
private Destination shipReplyQueue;
public ShipRequestMDB() {}
Design of Distributed Software
117
3.2 MDBs
MDB code with reply
public void onMessage(Message message) {
try {
ObjectMessage oMessage=(ObjectMessage)message;
ShipRequest sRequest=(ShipRequest)oMessage.getObject();
processShipRequest(sRequest);
} catch(JMSException e) {
System.err.println(e);
e.printStackTrace(System.err);
}
}
private void processShipRequest(ShipRequest s) {
System.out.println("----------------------------->"+s);
ShipRequestMDB.java
try {
sendJMSMessageToShipReplyQueue(s);
}catch(Exception e) {
System.err.println(e);
}
}
Design of Distributed Software
118
MDB code with reply
3.2 MDBs
private Message createJMSMessageForShipRequestMDB(Session session,ShipRequest mData)
throws JMSException {
ObjectMessage oMessage=session.createObjectMessage(mData);
return oMessage;
}
private void sendJMSMessageToShipReplyQueue(ShipRequest mData)
throws NamingException, JMSException {
Connection connection=null;
Session session=null;
try {
connection = shipReplyCF.createConnection();
session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(shipReplyQueue);
messageProducer.send(createJMSMessageForShipRequestMDB(session, mData));
} finally {
if (session != null) {
session.close();
}
if (connection != null) {
connection.close();
}
}
}
}
Design of Distributed Software
ShipRequestMDB.java119
Client code with reply
package jmessageproject;
import
import
import
import
3.2 MDBs
Main.java
javax.annotation.Resource;
javax.jms.*;
javax.naming.NamingException;
util.ShipRequest;
public class Main {
@Resource(mappedName = "jms/ShipRequestMDBFactory")
private static ConnectionFactory shipRequestMDBFactory;
Sending
Receiving
@Resource(mappedName = "jms/ShipRequestMDB")
private static Queue shipRequestMDB;
@Resource(mappedName="jms/ShipReplyConnectionFactory")
private static ConnectionFactory shipReplyCF;
@Resource(mappedName="jms/ShipReplyQueue")
private static Queue shipReplyQueue;
Listener
private static ReplyListener r=null;
Design of Distributed Software
120
Client code with reply
3.2 MDBs
public Main() {}
public static ConnectionFactory getFactory() {return shipReplyCF;}
public static Queue getQueue() {return shipReplyQueue;}
public static void main(String[] args) throws Exception {
r=new ReplyListener();
try {
r.init();
} catch(Exception e) {
System.err.println(e);
}
Awkward,
but needed ...
Main.java
ShipRequest r=new ShipRequest("Book ","Sunset Boulevard");
try {
sendJMSMessageToShipRequestMDB(r);
}catch(NamingException ne) {
System.err.println(ne);
}catch(JMSException je) {
System.err.println(je);
}
}
Design of Distributed Software
121
Client code with reply
3.2 MDBs
private static Message createJMSMessageForShipRequestMDB(Session session,
ShipRequest mData) throws JMSException {
ObjectMessage oMessage=session.createObjectMessage(mData);
return oMessage;
}
private static void sendJMSMessageToShipRequestMDB(ShipRequest mData)
throws NamingException, JMSException {
Connection connection=null;
Session session=null;
try {
connection = shipRequestMDBFactory.createConnection();
session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(shipRequestMDB);
messageProducer.send(createJMSMessageForShipRequestMDB(session, mData));
} finally {
if (session != null) {
session.close();
}
if (connection != null) {
connection.close();
}
}
}
Main.java
}
Design of Distributed Software
122
3.2 MDBs
Client code with reply
class ReplyListener implements MessageListener {
Connection connection=null;
Session session=null;
public void init() throws Exception {
try {
ConnectionFactory shipReplyCF=Main.getFactory();
Queue shipReplyQueue=Main.getQueue();
connection = shipReplyCF.createConnection();
session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
MessageConsumer messageConsumer = session.createConsumer(shipReplyQueue);
Find admin resources
messageConsumer.setMessageListener(this);
connection.start();
register listener
start listening
}
public void onMessage(Message m) {
System.out.println("Received !!!!");
// code to close session/connection : if(message.equals(stop)) { // ... }
}
Main.java
}
Design of Distributed Software
123
3.4 Persistence
Service
1. Java 5 Entities
2. (Java 1.4 Entity Beans)
3. EJB Design Patterns
Design of Distributed Software
4.1 Entities
JEE Architecture
Client
Webserver
Application Server
Database system
Web container
webserver
applet
applet
browser
EJB container
JEE client
Servlet
JSP
EJB
Design of Distributed Software
Focus of this section:
- Persistence
- Design Patterns
125
Introduction
4.1 Entities
Entity = persistent object
persistent state realised through persistent fields/properties
object/relational annotations used to map to relational data in data
store
Entity class = any Java class but
annotated with @Entity
public/protected no-arg constructor
not final class, no persistent final fields, no final methods
if passed by value, must implement Serializable
persistent instance variables NOT public
Field is persistent, unless annotated @Transient
Primary key annotated with
- simple primary key @Id
- composite primary key @EmbeddedId, @IdClass
Design of Distributed Software
126
Primary Key
4.1 Entities
Primary Key class
must be public
properties public
public default constructor
must implements hashCode() and equals()
must be Serializable
composite primary key : related to
- multiple fields/properties of the entity class
- embeddable class
Same names of fields/properties as in entity class
Design of Distributed Software
127
Managing Entities
4.1 Entities
EntityManager
- find entities
- query entities
- life cycle funtions on entities (create, remove, persist)
PersistentContext
associated to data store
associated to its own EntityManager
Container Managed :
changes in PersistentContext automatically propagated by container
EntityManager obtained by @PersistenceContext annotation
(through injection)
@PersistenceContext
EntityManager theManager;
Design of Distributed Software
128
Building Java 5 Applications with Entities
4.1 Entities
Entity objects = simple Java classes
no longer need to be placed in an EJB module
no longer need to be packaged in an EAR file
(both cfr Java 1.4 Entity Beans)
entity classes can be created directly inside a web
application
Two options:
See next
slides
Option 1 : Start with Entity code
Generate DB tables, columns and DB sync code
based on attributes of entities
Option 2 : Start with DB structure (tables, columns)
Generate Entity code and DB sync code
Design of Distributed Software
129
Building Java 5 Applications with Entities
4.1 Entities
Option 1: Start with Entity code
Example Netbeans 5.5 IDE
Choose File > New Project (Ctrl-Shift-N). Select Web Application
from the Web category and click Next.
Name the project, set the server to the Sun Java System
Application Server, set the Java EE Version to Java EE 5, and click
Next.
Select the JavaServer Faces checkbox and click Finish.
Next Steps:
Creating a Persistence Unit
Creating the Entity Classes
Creating a Web Interface
Running the Project
Design of Distributed Software
130
Creating a Persistence Unit
4.1 Entities
Persistence unit tells the container:
which entity classes are to be managed by the entity
manager,
the datasource used by those entities.
Created by defining its properties in
persistence.xml table generation strategy
Netbeans 5.5 : mostly created using the New
Persistence Unit wizard.
Design of Distributed Software
131
Creating a Persistence Unit
4.1 Entities
Right-click the web application node in the
Projects window and choose New > File/Folder
From the Persistence category, select
Persistence Unit and click Next.
Choose Persistence Provider
E.g. TopLink (Netbeans default).
Provides the libraries for Java Persistence and the
entity manager
Other: Hibernate, etc.
Choose Data Source
E.g. jdbc/sample (Netbeans default).
Used to connect to the database
Specify table generation strategy (default: create)
Design of Distributed Software
132
Creating the Entity Classes
4.1 Entities
Cfr http://www.netbeans.org/kb/55/persistence.html
Animal class:
Pavilion class:
-name
-name
-kind
-weight
1:n
-pavilion
-address
-Collection <Animals>
OneToMany
ManyToOne
Design of Distributed Software
133
Creating the Entity Classes
4.1 Entities
Animal.java
package entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
public String toString() {
return "entity.Animal[id=" + getId() + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Entity
public class Animal implements Serializable {
public String getKind() {
return kind;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name="animalName")
private String name;
private String kind;
private String weight;
@ManyToOne
private Pavilion pavilion;
public void setKind(String kind) {
this.kind = kind;
}
public String getWeight() {
return weight;
}
/** Creates a new instance of Animal */
public Animal() {
}
public void setWeight(String weight) {
this.weight = weight;
}
public Long getId() {
return id;
}
public Pavilion getPavilion() {
return pavilion;
}
public void setId(Long id) {
this.id = id;
}
Design of Distributed Software
public void setPavilion(Pavilion pavilion) {
this.pavilion = pavilion;
}
}
134
Creating the Entity Classes
4.1 Entities
Pavilion.java
package entity;
import java.io.Serializable;
import java.util.Collection;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
public String toString() {
return "entity.Pavilion[id=" + getId() + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Entity
public class Pavilion implements Serializable {
public String getAddress() {
return address;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name="pavilionName")
private String name;
private String address;
@OneToMany(mappedBy="pavilion")
private Collection <Animal> animals;
public void setAddress(String address) {
this.address = address;
}
public Collection<Animal> getAnimals() {
return animals;
}
public Pavilion() {
}
public Long getId() {
return id;
}
public void setAnimals(Collection<Animal> animals) {
this.animals = animals;
}
}
public void setId(Long id) {
this.id = id;
}
Design of Distributed Software
135
Creating a Web Interface
Design of Distributed Software
4.1 Entities
136
Creating a Web Interface
4.1 Entities
Choose File > New. Select JSF Pages from Entity
Class from the Persistence category and click
Next.
In the New JSF Pages from Entity Class wizard,
click Add All to select our two entity classes and
click Next.
Specify the package for the generated classes
and click Finish.
Running the project:
Start the Java DB database by choosing Tools > Java
DB Database > Start Java DB Server.
Right-click the project node and choose Run Project.
Design of Distributed Software
137
4.1 Entities
Building Java 5 Applications with Entities
Option 2: Start from DB structure
Start the Java DB database by choosing Tools > Java DB
Database > Start Java DB Server.
Choose New File (Ctrl-N) to open the New File wizard.
Select Entity Classes from Database from the Persistence
category and click Next.
In the Entity Classes from Database wizard, select the
data source for the database : a list of available tables
appears in the Available Tables pane.
Select the right table from the Available Tables and click
Add. When you click Add, any tables related to the
selected table are also added.
Click Next. The selected table and any related tables are
displayed. If you want to modify the name of the class that
will be generated, you can type the name in the Class
Name field.
Design of Distributed Software
138
Building Java 5 Applications with Entities
4.1 Entities
Option 2:
URL: http://www.netbeans.org/kb/55/customerbook.html (“Comparing Java EE 5 Platform and J2EE
1.4 Platform”)
Shows Use of EntityManager when using entities
Design of Distributed Software
139
Using Entities
In the Source Editor, right-click in the java-file and choose
Persistence > Use Entity Manager to inject the
PersistenceContext in the class.
The IDE adds the following annotation that specifies the
persistence unit. The annotation is added above the class
declaration.
@PersistenceContext(name = "persistence/LogicalName",
unitName = “NamePU")
The IDE also adds the following annotation injecting a
resource for managing transaction boundaries:
4.1 Entities
@Resource private UserTransaction utx;
The IDE generates default code, to be adapted by
programmers
Design of Distributed Software
140
Using Entities
4.1 Entities
public Customer findByID(Integer customerNr) {
Customer customer = null;
try {
Context ctx = (Context) new InitialContext().lookup("java:comp/env");
EntityManager em = (EntityManager) ctx.lookup("persistence/LogicalName");
utx.begin();
customer = em.find(Customer.class, customerNr);
utx.commit();
} catch(Exception e) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE,"exception caught", e);
throw new RuntimeException(e);
}
return customer;
}
Partially generated by IDE,
adapted by programmer
Design of Distributed Software
141
4.1 Entities
Example Object Relational Mapping (ORM)
package ods.ejb;
//The username of this account.
@Column(unique = true, nullable = false)
private String username;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
@NamedQueries(
{
@NamedQuery (
name="findAccountByUsername",
query="SELECT acc FROM Account acc
WHERE acc.username = :username"
)
})
//The password of this account.
@Column(nullable = false)
private String password;
//Indicates if the user (attached to this account) is an
//administrator.
@Column(nullable = false)
private boolean isAdmin;
public Account() {
}
public Account(String username, String password,
boolean isAdmin){
this.username = username;
this.password = password;
this.isAdmin = isAdmin;
}
@Entity
public class Account implements Serializable {
public Long getId() {
return this.id;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
Design of Distributed Software
public void setId(Long id) {
this.id = id;
}
…
}
142
Example Façade Session
package ods.ejb;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
@Stateless
public class AccountFacade implements AccountFacadeLocal {
@PersistenceContext
private EntityManager em;
public Account findByUsername(String username){
try {
Account account = (Account)
em.createNamedQuery("findAccountByUsername")
.setParameter("username", username).getSingleResult();
return account;
} catch (NoResultException e) { }
return null;
}
public void create(Account account) {
em.persist(account);
}
public AccountFacade() {
}
public void edit(Account account) {
em.merge(account);
}
public boolean isValidAccount(String username, String password){
Account account = findByUsername(username);
boolean valid = false;
public void destroy(Account account) {
em.remove(em.merge(account));
If(account != null)
if(account.getPassword().equals(password))
valid = true;
return valid;
}
public Account addAccount(String username,
String password, boolean isAdmin)
throws IllegalArgumentException{
Account existing = findByUsername(username);
if(existing != null)
throw new IllegalArgumentException("username allready exists");
else{
Account account = new Account(username, password, isAdmin);
create(account);
return account;
}
Design of Distributed Software
}
4.1 Entities
}
public Account find(Object pk) {
return (Account) em.find(Account.class, pk);
}
public List findAll() {
return em.createQuery("select object(o) from Account as
o").getResultList();
}
}
143
Entity Lifecycle Management
4.1 Entities
@PrePersist
Marks a method in the entity class as a pre-persist callback (executed before an entity is persisted).
@PostPersist
Marks a method in the entity class as a postpersist callback (executed after an entity is persisted).
@PreUpdate
Marks a method in the entity class as a preupdate callback (executed before entity data is updated in the
database).
@PostUpdate
Marks a method in the entity class as a postupdate callback (executed after entity data is updated in the
database).
@PreRemove
Marks a method in the entity class as a preremove callback (executed before an entity is removed from the
database).
@PostRemove
Marks a method in the entity class as a postremove callback (executed after an entity is removed from the
database).
@PostLoad
Marks a method in the entity class as a postload callback (executed before an entity is loaded from the
database).
Design of Distributed Software
144
3.4 Persistence Service
1. Java 5 Entities
2. (Java 1.4 Entity Beans)
3. EJB Design Patterns
Design of Distributed Software
Introduction
4.2. Java 1.4 Entity Beans
Entity Beans
represents business object in permanent storage
= “row in a database table”
persistent storage mechanism in AS :
relational database
typically
bean class associated to table
bean instances associated to row in table
characteristics
persistent
allow shared access
can be found using primary key
participate in relations with other beans
Design of Distributed Software
146
4.2. Java 1.4 Entity Beans
Shared Access
Multiple clients access same bean
Requirements
safe access (locks)
client isolation
Implemented using Transaction Service
Transaction attributes specified when deploying the
bean
Transaction boundaries added by container
Design of Distributed Software
147
Persistence
Bean survives
-
•
4.2. Java 1.4 Entity Beans
application shutdown
server crashes/restarts/...
Two persistency flavours
-
Bean Managed Persistence :
-
-
code (SQL) for DB access (load/store/updates) written by
programmer
not necessarily portable to other DB
Container Managed Persistence
-
code automatically generated and called
more portable approach
Design of Distributed Software
148
4.2. Java 1.4 Entity Beans
Entity Beans : Life Cycle
Does Not
Exist
1.
2.
3.
business method
ejbLoad
ejbStore
create
ejbCreate
ejbPostCreate
newInstance
setEntityContext
unsetEntityContext
ejbActivate
Ready
Pooled
ejbPassivate
1.
2.
remove
ejbRemove
Design of Distributed Software
no specific identity
all pooled instances are equal
149
Components of an Entity EJBs
4.2. Java 1.4 Entity Beans
Three parts:
Component interface (local and/or remote)
Home interface (local and/or remote)
The bean class
Implements javax.ejb.EntityBean
And a Primary Key class
Can be an existing class
String, Integer, Date, etc.
Can be a new class (e.g., for composite keys)
Must properly override hashCode and equals
Must be serializable
Naming convention: XKey
Design of Distributed Software
150
Home Interface
Life Cycle methods
As with Session Beans, each ejbCreate method is reflected in the
Home interface
In addition, for every ejbCreate method there’s a corresponding
ejbPostCreate method
PostCreate is invoked after the bean has an EJB object, and is
represented in the persistent data storage
Allows you to pass references to the bean to other EJBs
– e.g., relationships
Other lifecycle methods include ejbActivate, ejbPassivate,, and
ejbRemove
Home methods
4.2. Java 1.4 Entity Beans
to be executed on all instances
Finder methods : ejbFindXXX
DB Synchronization methods : ejbLoad, ejbStore
Design of Distributed Software
151
3.4.2 EJB: Java 1.4 Entity
Beans
1. Bean Managed Persistence
2. Container Managed Persistence
Design of Distributed Software
BMP : Activation ...
getting an identity
4.2.1 BMP EJB
pooled -> ready : bean MUST be associated with
business object
done through assigning primary key
in ejbCreate AND ejbActivate :
set primary key value
Bean creation process
Design of Distributed Software
153
Managing Storage
4.2.1 BMP EJB
Assuming each bean represents a row in a
relational table:
The ejbCreate methods should add a row to the
database
The ejbRemove method should remove the row
represented by the bean instance
ejbLoad should assume nothing about the instance
variables mapped to table fields, and reload their
values from the database
You can find the primary key by invoking getPrimaryKey
on the EntityContext reference
ejbStore should update the table row to reflect the
current bean state
Design of Distributed Software
154
Managing Storage
4.2.1 BMP EJB
Conceptually, ejbLoad is called before every business method
So the method is sure to work with up-to-date values from the
database
Likewise, ejbStore is called after every business method
Storing any changes made to the instance variables
As a result, beans can survive container crashes
Serious performance hit
Common practice: maintain a ‘dirty’ flag
Note that according to the spec, the container may invoke ejbLoad
and ejbStore arbitrarily, and does not have to call them
before/after every business method invocation
Design of Distributed Software
155
Activation and Passivation
4.2.1 BMP EJB
Bean instances are managed in a pool
The same bean instance, after created, can be used for different
table rows at different times
Saves instantiation costs
When a bean is returned to the pool (detached from a given row), it
is passivated
When a bean is re-attached to a row, it is activated
Persistent data should not be stored/reloaded during
activation/passivation
Use ejbPassivate/ejbActivate to release/reacquire other
resources
Design of Distributed Software
156
Storage and Activation
Design of Distributed Software
4.2.1 BMP EJB
157
Finder Methods
4.2.1 BMP EJB
Given the home interface, a client can create new entity EJBs using
the various create methods
Remember that each create method in the home interface has
a corresponding ejbCreate and ejbPostCreate method in
the bean class
But what if the client wants to locate existing beans?
The home interface also includes finder methods.
Named findXXX
Must return either java.util.Collection, or the component
interface type
Throws FinderException (and RemoteException for remote
homes)
Always defined: findByPrimaryKey(keytype)
Design of Distributed Software
158
Finder Methods
For each findXXX method in the home interface, a corresponding
ejbFindXXX method must be implemented in the bean class
ejbFindByPrimaryKey is required
Finder methods can find a single record
4.2.1 BMP EJB
This includes ejbFindByPrimaryKey
Value returned must be the primary key of the found record
which is the parameter in ejbFindByPrimaryKey’s case
Throw FinderException if no record was found
Finder methods can find a set of records
Signature must define java.util.Collection as return type
Return a collection of primary keys
Return an empty collection if no records were found
Design of Distributed Software
159
Removing a Row
4.2.1 BMP EJB
The last lifecycle method, ejbRemove, must
include code to remove the row corresponding
to the current bean instance from the persistent
data store
Can throw javax.ejb.RemoveException if
removal failed.
Design of Distributed Software
160
SQL mapping
ejbCreate
ejbRemove
ejbLoad
ejbStore
ejbFindXXX
Design of Distributed Software
4.2.1 BMP EJB
INSERT
DELETE
SELECT
UPDATE
SELECT
161
BMP design: different steps
4.2.1 BMP EJB
1. Database set up
2. Create bean template
3. Database lookup
4. Class attributes and get/set
5. Life cycle methods
ejbCreate, ejbPostCreate, ejbRemove
ejbLoad, ejbStore
ejbActivate, ejbPassivate
finder methods
6. Business methods
7. Home methods
8. Client code
Design of Distributed Software
162
3.4.2 EJB Java 1.4 : Entity
Beans
1. Bean Managed Persistence
2. Container Managed Persistence
Design of Distributed Software
Letting the Container Do the Work
4.2.2 CMP EJB
Entity beans, as defined so far, must include a lot of SQL
statements if they use a database as their data source
SELECT for ejbLoad and finder methods
INSERT for create methods
UPDATE for ejbStore
DELETE for ejbRemove
The work is repetitive, tedious, and error-prone
Why not automate it?
Enter CMP: Container Managed Persistence for Entity EJBs
Design of Distributed Software
164
CMP Entity Beans
4.2.2 CMP EJB
CMP EJBs work just like BMP EJBs
Same lifecycle
However, the mapping between persistent bean attributes and table
columns is defined in a declarative manner.
tell the container which attribute corresponds to which column
the container generates deployment code that handles
loading, finding, deleting, etc.
In the EJB 1.x spec, persistent attributes are simply class
variables.
Starting with EJB 2.0, persistent attributes are not reflected as
class variables
Only defined by getter/setter methods
Allows the container to manage a ‘dirty’ flag automatically,
thus saving needless updates
Design of Distributed Software
165
CMP Beans
4.2.2 CMP EJB
Abstract Schema
part of bean deployment descriptor (declarative)
describes bean persistent state and relationships
referenced by queries written in EJB QL
supply one EJB query for each finder method
Persistent Fields
• persistent bean state
• automatically synchronized at runtime
• no coding of persistent fields, just declare them in the AS
• identified my get/set methods
Design of Distributed Software
166
Bean class
4.2.2 CMP EJB
CMP
BMP
Class definition
abstract
not abstract
DB calls
handled by container
not handled by container
Persistent state
virtual state
instance variables
Access methods for state and relationships
required
none required
findByPrimaryKey
by container
to be coded
findXXX
provide EJB query
to be coded
select methods
handled by container
none
return ejbCreate
none
primary key object
Design of Distributed Software
167
Lifecycle Methods in CMP Entity Beans
4.2.2 CMP EJB
Each CMP entity bean must include the same lifecycle methods as
BMP beans
However, some of the semantics are slightly different:
ejbLoad is called immediately after the data is loaded
Allows you to calculate values for any class variables that
depend on field values
Should not attempt to load the data by itself
ejbStore is called immediately before the data is stored
Does not store the data by itself
ejbRemove is called immediately before the row is removed
Does not actually remove the row by itself
All are normally empty.
Design of Distributed Software
168
Access Methods
4.2.2 CMP EJB
For each persistent attribute A in the bean, there
must be a getA and/or a setA method
The getters and setters are defined in the bean
class as abstract methods
Their actual implementation is included in a
subclass generated by the container.
Implication: the bean class itself is abstract.
Design of Distributed Software
169
Finder Methods in CMP Entity Beans
4.2.2 CMP EJB
Finder methods are defined normally in the home interface
However, no corresponding ejbFindXXX methods are defined in
the bean class
Each finder method is associated (in the deployment descriptor)
with an EJB QL query
The query should return one row (at most) if the finder is
defined to return a single bean
The query should return zero or more rows if the finder is
defined to return a collection
EJB QL is a modified subset of SQL
Design of Distributed Software
170
Select Methods
4.2.2 CMP EJB
Similar to finder methods
can return local/remote interface
queries the DB
EJB QL query associated with every select method
not implemented in the bean class
Different from finder methods
can return persistent state of related bean
not exposed to client -> only invoked by other beans methods
defined in the entity bean class
Design of Distributed Software
171
CMP design: different steps
1.
2.
3.
4.
5.
6.
7.
8.
9.
4.2.2 CMP EJB
Database set up -> idem as BMP
Create bean template
Database lookup
Class attributes : get/set
Life cycle methods
1.
ejbCreate, ejbPostCreate, ejbRemove
2.
ejbLoad, ejbStore
3.
ejbActivate, ejbPassivate
4.
finder methods
Business methods -> idem as BMP
Home methods -> idem as BMP
Facade Session Bean
Client code
-> idem as BMP (actually calls SB !)
Design of Distributed Software
172
3.4 Persistence Service
1. Java 5 Entities
2. (Java 1.4 Entity Beans)
3. EJB Design Patterns
Design of Distributed Software
EJB Design Patterns
Client
4.3 Design Patterns
Proxy pattern
proxy
abstracts the server to the client
Facade
Command pattern
Facade pattern
• session bean
• presents API to clients
• reduce the complexity in the
communication
• decouple client - server
Controller
Entity
Entity
Bean
1
Entity
Bean
1
Entity
Bean
1
Bean 1
Design of Distributed Software
Entity
Entity
Bean
2
Bean 2
Entity
Entity
Bean 3
Entity
Bean 3
Entity
Bean 3
Bean 3
174
The Session Facade Pattern
Used for minimizing
Client/entity bean coupling
Risk of client using unapproved business methods
4.3 Design Patterns
Or using approved business methods in unapproved ways
Network delays
Points of change if high-level business operations are
modified
The idea: create a Session EJB that provides highlevel business methods
Client should only work with the session bean(s)
Entity EJBs provide (possibly only) a local interface
Session EJB accesses entity EJBs locally
Design of Distributed Software
175
The Session Facade Pattern
4.3 Design Patterns
No Facade
Client
Client
Client
Application Server
Design of Distributed Software
176
The Session Facade Pattern
4.3 Design Patterns
With Facade
Client
Client
Client
Application Server
Design of Distributed Software
177
Session Facade Example
Client code without the facade:
4.3 Design Patterns
Find Account home
Find accounts a1, a2 by primary keys k1, k2
a1.setBalance(a1.getBalance() - amount);
a2.setBalance(a2.getBalance() + amount);
Client code with the facade:
Find TransferBean home, create TransferBean t1
t1.transfer(k1, k2, amount);
Design of Distributed Software
178
Resulting Benefits
4.3 Design Patterns
Faster operation
1 JNDI lookup, 1 remote object lookup and 1 remote business method
vs. 1 JNDI lookup, 2 remote object lookups and 4 remote business
methods in the old code
Easier maintenance
If we have two different clients (servlet, application) and we wish to
change the transfer semantics (e.g., add logging), there's only one
place to change
Easier transaction management
can be started at the facade
Increased security
Client can't invoke Account.setBalance directly, since Account
has no remote component interface
Design of Distributed Software
179
Proxy Pattern
4.3 Design Patterns
Class at client side
Abstracts home interface location to the client
Performance benefit : cache home objects
Also called “EJBHomeFactory pattern”
EJBHome
ClientNoProxy
ClientProxy
Design of Distributed Software
Application Server
180
Proxy Pattern
4.3 Design Patterns
Advantages
Proxy can contain JNDI name – Bean class mapping
Can serve as cache for EJBHome objects
Allows cleaner coding style
Design of Distributed Software
181
Command Pattern
Command pattern
4.3 Design Patterns
= Class, transmitted from one object to another
Client constructs commands, facade forwards them to right controller
Example code
public interface BasicCommandInterface{
public String getCommandTarget();
public String getCommandInstruction();
public HashMap getCommandData();
public void setCommandData(String key,Object value);
public void setCommandTarget(String aTarget);
public void setCommandInstruction(String anInstruction);
public execute();
public void getCommandData(HashMap aData);
}
Applications can be modified dynamically
Facade doesn’t need to provide all interface methods
Design of Distributed Software
182
Command Pattern
Command Routing
(could be proxy)
Client
Command Processor
(stateless SB)
4.3 Design Patterns
Controller
(stateful SB)
Commands
• decoupling client – server
• single network transaction
Design of Distributed Software
183
Other Recommended Practices
4.3 Design Patterns
Avoid calling EJB methods directly from JSP
The need to catch remote exceptions would
complicate the JSP code
Avoid hard-coding JNDI properties
Store configuration hashtable values in a file
Avoid hard-coding JNDI resource names
Avoid fine grain data transfers
Design of Distributed Software
184