Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
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