750 likes | 769 Views
Tal Cohen tal@forum2.org. Enterprise Java Beans (part I). Outline of Part I. What are Enterprise Java Beans Types of EJBs EJB Views Creating and Working with Session EJBs Components of a Session EJB Lifecycle and lifecycle methods Sample code Creating and Working with Entity EJBs
E N D
Tal Cohen tal@forum2.org Enterprise Java Beans (part I)
Outline of Part I • What are Enterprise Java Beans • Types of EJBs • EJB Views • Creating and Working with Session EJBs • Components of a Session EJB • Lifecycle and lifecycle methods • Sample code • Creating and Working with Entity EJBs • Components of an Entity EJB • Lifecycle and lifecycle methods • Sample code
EJB Design Goals • A standards-based component model. • Common services • Multithreading • Transaction management • Resource management • e.g., connection pooling • Persistence management • Security services • Distribution and scalability • “Throw money at it” solution • Unrelated to (non-Enterprise) JavaBeans • Except that both are component models.
Session EJBs • A session bean instance is: • A non-persistent object • Implements some business logic • Runs on the server • Not shared among multiple clients
Stateful Session EJBs • A stateful session bean maintains a state • The state is relevant only for a single client • Cannot be seen by other clients • The state is not persistent • Expires after a certain timeout • Canonical example: Shopping cart
Stateless Session EJBs • Conceptually, the same as stateful session EJBs • No state • 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) • Client does not care on which server the bean is stored • And migration is cheap, since there’s no data to move around • Example: Currency conversion bean
Message-Driven EJBs • New in EJB 2.0 standard • Built on top of JMS • Each instance is an asynchronous message consumer • Have no client visibility
Entity EJBs • Object-oriented view of entities stored in persistent storage • Normally, each instance represents a row in a relational DB table • Persistence code can be written manually (bean-managed persistence, BMP) or automatically (container-managed persistence, CMP) • A single bean 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.
CMP Entity EJBs • Container is responsible for saving the persistent state • You specify the container-managed attributes • In EJB 2.0, they do not appear as actual class variables • Persistence is independent of the data source • The mapping can be applied to other DBs • Makes the beans very portable • Several additional benefits • Container can manage caching, locking strategies • Can only be used with data sources supported by JDBC 2.0
BMP Entity EJBs • The bean writer must provide code for storing/restoring persistent state • Less adaptable • Can exploit any persistence framework • Not limited to databases • Manual tuning can result in performance benefits • At the price of portability and hard work
EJB Views • Session and entity EJBs have two possible views: • The local view • Used by local clients (only EJBs in the same container) • Includes a local Home interface and a local component interface • The remote view • Used by remote clients (not limited to EJBs; can include Servlets, etc.) • Can also be used by clients in the same container • Includes remote Home and component interfaces • A bean an implement both local and remote views • Message-drive beans have no views
The Home and Component Interfaces • The component interface allows access to the EJB object • Defines the business methods callable by the client • Extends javax.ejb.EJBObject or EJBLocalObject • The home interface provides bean management facilities • Factory and lifecycle services • Create, remove and find EJB instances • ‘Static’ methods: the home interface can include services (methods) that are not specific to a particular bean instance • For entity EJBs only • Extends javax.ejb.EJBHome or EJBLocalHome
The Local View • New in EJB 2.0 spec • Parameters are passed by reference • The client and the EJB must reside in the same container • The client itself must be an EJB • Much faster than remote view • No network latency • No marshalling/unmarshalling • No need to worry about remote exceptions • The expectation is that Entity EJBs will mostly be accessed through the local view • Using the Session Facade pattern
The Local View (cont.) • 1. Client looks up a bean home object using JNDI • 2. Client creates or finds EJB • 3. Client uses EJB business methods from the local interface
The Remote View • Based on Java RMI • 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 • APIs should be coarsely-grained • One method that does several related tasks is more effective than several smaller methods
The Remote View (cont.) • Same 3 steps as before, but taken over the network:
Sample Usage: EJBs in a Banking Environment JDBC (over TCP/IP?) RMI/IIOP Web server (running servlets, JSPs) Acts as EJB client EJBserver Database/legacyserver HTTP RMI/IIOP Bank clerk, running a Java app (using Swing, etc.) that acts as an EJB client Home user Runs Internet Browser
Sample Usage: Details • Web server, terminal programs both act as EJB clients • Do not have to know about DB structure • DB can be changed, upgraded etc. • Have an object-oriented abstraction of the DB information • Can invoke remote operations • Including high-level operations using Session EJBs • Each client has a different access level/privileges • Home user cannot do some things that a bank clerk can • Decreased load on web server, bank terminals • EJB server can be the same machine as the DB server • Alternatively, it can be a whole cluster of machines • EJBs provide and maintain the model; clients manage view/control
Components of a Session EJB • To define session EJB X, you must create three classes: • The remote (local) component interface, called X (or XLocal) • Extends EJBObject (or EJBLocalObject) • (All extended types are from javax.ejb) • The home interface, called XHome (or XLocalHome) • Extends EJBHome (or EJBLocalHome) • The bean class itself, called XBean • Extends SessionBean • Should implement java.io.Serializable (for stateful beans) • Implements business methods from the component interface • Implements lifecycle methods (ejbXXX) • The class names are (strong) conventions
Lifecycle Methods • Lifecycle methods are defined in the XBean class • They are named ejbXXX • ejbCreate, ejbActivate, etc. plus setSessionContext • No other method name should begin with ‘ejb’ • Some lifecycle methods also appear in the XHome interface • For session beans, only the create methods appear in the home interface • In the home interface, the ‘ejb’ prefix is not used • i.e., method should be named ‘create’ • Lifecycle methods are invoked by the container when changing state during the bean’s life
ejbCreate Methods in Stateful Session Beans • A stateful session bean can contain several ejbCreate methods • The methods can have zero or more parameters • They can be called be ejbCreate(...) or ejbCreateXXX(...), for more descriptive names • e.g., ejbCreateByName(String name) • Must be public void • Should throw javax.ejb.CreateException if creation fails for whatever reason (invalid arguments, etc.) • Must be reflected in the XHome interface (local or remote) by a method with identical parameters, that is called ‘create’ or ‘createXXX’ • Returns the bean component interface type (X) • For remote homes, throws java.rmi.RemoteException • e.g., public X createByName(String name) throws ...
ejbCreate Methods in Stateless Session Beans • For stateless session beans, there can be only one ejbCreate method • Called ‘ejbCreate’ • Accepts zero parameters • Reflected normally in the home interface
The Birth of a New Session Bean • 1. Client obtains home interface via JNDI lookup • 2. Client calls home.create(...) • 3. EJB object, session context and EJB instance are created in the container • 4. EJB instance is provided with the session context • 5. Corresponding variant of ejbCreate is invoked on EJB instance • 6. create method returns a stub that the client can use.
The EJB Session Context • During creation, the EJB instance is handed a Session Context object • An instance of javax.ejb.SessionContext • setSessionContext should keep a copy of the context in a field • The context object contains: • Security-related information • getCallerPrinciple, isCallerInRole • Transaction-related information and methods • getUserTransaction, get/setRollbackOnly • Home-related information • getEJBHome, getEJBLocalHome • EJB Object-related information • getEJBObject, getEJBLocalObject • The former must be returned instead of this, whenever required
The EJB Session Context (cont.) • WSAD generates all EJBs with: • SessionContext field • setSessionContext method that stores the provided context in this field • getSessionContext method
Activation and Passivation • During the bean’s lifecycle, the container may decide to passivate it • Normally done to free up memory and other resources • Bean is notified immediately before passivation by lifecycle method ejbPassivate() • In this method, the bean should: • Release any resources it might be holding • Open files, database connections, etc. • Nullify fields that should not be serialized (cache, etc.) • If the bean is referenced by client while passivated, the container activates it. • Bean is notified by ejbActivate() immediately after de-serialization • Its chance to restore all field values, resources, etc.
One Last Lifecycle Method • ejbRemove() is called before the container destroys a bean instance • Should release all resources • Normally empty.
The Lifecycle of Stateless Session EJBs • Session EJBs have no state, so activation and passivation are meaningless • The container simply destroys instances when low on memory, and creates new ones as needed • Still, ejbActivate and ejbPassivate must be implemented in XBean (as empty methods) • The resulting lifecycle diagram is somewhat simplified:
Business and Utility Methods • Other than lifecycle method, the bean class can include business methods • Business methods are those that appear in the remote (or local) component interface • i.e., can be invoked by clients • Utility methods are those that do not appear in the component interface • Cannot be invoked by clients -- even if defined as public methods • There are some limitations on business methods • All parameters and return types must be serializable • Must not return ‘this’ • etc.
Sample code: Stateless Session Bean (1/4) • The component interface: public interface CurrencyConverter extends javax.ejb.EJBObject { public double convertUsdToNis(double usd) throws java.rmi.RemoteException; } • Code in green was automatically generated by WSAD • Code in dark green was automatically generated upon request • Request for “promoting” the convertUsdToNis method
Sample code: Stateless Session Bean (2/4) • The home interface: public interface CurrencyConverterHome extends javax.ejb.EJBHome { public CurrencyConverter create() throws javax.ejb.CreateException, java.rmi.RemoteException; } • Entirely auto-generated • All auto-generated comments were removed
Sample code: Stateless Session Bean (3/4) • The bean class itself: public class CurrencyConverterBean implements javax.ejb.SessionBean { private static final double NIS_PER_USD = 4.6; private SessionContext mySessionCtx; public SessionContext getSessionContext() { return mySessionCtx; } public void setSessionContext(SessionContext ctx) { mySessionCtx = ctx; } (more...)
Sample code: Stateless Session Bean (4/4) public void ejbCreate() throws CreateException {} public void ejbActivate() {} public void ejbPassivate() {} public void ejbRemove() {} public double convertUsdToNis(double usd) { return usd * NIS_PER_USD; } } • In such simple cases, one has to implement only the business logic. • Sadly, it isn’t always so...
Session Bean Deployment Descriptors • EJBs are distributed in JAR (“Java Archive”) files • Each JAR contains a Deployment Descriptor, listing details for every EJB it contains • Sample XML fragment for a single EJB from a JAR file: <session id="CurrencyConverter"> <ejb-name>CurrencyConverter</ejb-name> <home>demo.j2ee.CurrencyConverterHome</home> <remote>demo.j2ee.CurrencyConverter</remote> <ejb-class>demo.j2ee.CurrencyConverterBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> </session>
Session Bean Deployment Descriptors (cont.) • For stateful session beans: <session-type>Stateful</session-type> • The deployment descriptor is normally generated by WSAD • If you need to change it, you can edit the XML or use a GUI
Components of an Entity EJBs • As per Session EJBs: • 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
Entity Bean Lifecycle Does not exist Pooled newInstance() setEntityContext() ejbRemove() or ejbPassivate() unset- EntityContext() ejbLoad() business method ejbStore() ejbCreate() or ejbActivate() Ready
The Bean Pool • The EJB container maintains a pool of available beans • Pooled beans are not associated with any specific row • When a bean becomes ready, it is provided with an identity • Possibly its own previous identity (if it was passivated) • Possibly a different one • When a bean instance is required, the container will pick a bean from the pool rather than create a new instance
The Bean’s Start and End of Life • setEntityContext is called only once • Even if the identity changes; the context object will be modified by the container • unsetEntityContext is called only once • When the instance is removed from memory • Use this pair for initializing/finalizing fields that do not depend on the bean’s identity • e.g., finding a connection pool via JNDI • Use ejbCreate/ejbActivate and ejbRemove/ejbPassivate to initialize fields that do depend on the bean’s identity
Lifecycle 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, ejbLoad, ejbStore, ejbFindXXX and ejbRemove • The exact semantics vary between container-managed and bean-managed persistence
Lifecycle Methods in BMP Entity EJBs • The bean creation sequence:
Managing Storage in BMP EJBs • 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 • If you’re using JDBC to connect to the data source, use connection pooling
The role of ejbLoad and ejbStore in BMP EJBs • 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
Activation and Passivation • Bean instances are managed in a pool • Like we said, 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 • Persistence data should not be stored/reloaded during activation/passivation • Use ejbPassivate/ejbActivate to release/reacquire other resources