* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download Chapter 20: Entity Beans and Persistence
Survey
Document related concepts
Entity–attribute–value model wikipedia , lookup
Data analysis wikipedia , lookup
Concurrency control wikipedia , lookup
Expense and cost recovery system (ECRS) wikipedia , lookup
Information privacy law wikipedia , lookup
Forecasting wikipedia , lookup
Relational model wikipedia , lookup
Business intelligence wikipedia , lookup
Open data in the United Kingdom wikipedia , lookup
Data vault modeling wikipedia , lookup
3D optical data storage wikipedia , lookup
Clusterpoint wikipedia , lookup
Transcript
Entity Beans and Persistence • Entity Enterprise JavaBeans REPRESENT entity objects in an analysis model – Real World Concepts • Customers • Products – Abstractions • Process • Customer Purchases Representation • Session Beans – Can access the data that Entity Beans can access – Cannot provide an object-oriented representation of that data • WHY? – Why can't you have a 'customer' or 'product' session bean, like you can with entity beans? The Problem of State • Entity Beans – State is SHARED, TRANSACTIONAL • Session Beans – State is PRIVATE, CONVERSATIONAL • Problem: – If attempting to use a Session Bean to represent an object, how is the STATE made available to clients of the that bean? Transactions • Atomic • More details, – Success of failure as a group see Chapter 21, page 1031 Consistent – Database state not compromised by success or failure • Isolated – System activities isolated from each other • Durable – A committed transactions is reflected in the store Transactional State • "Roughly speaking, transactional state is the data you store in the persistent store. Multiple clients can read and modify this data without conflict. If the application server crashes or is restarted, the data is still available in the data store." (p. 909) Conversational State • "Conversational state is the data cached in the application variables, either on the client or the server. This is private data that isn't accessible by other clients. If the conversational state isn't turned into transactional state, it can disappear when a component of the application disappears" (p. 909) Beans, Beans, Everywhere • Entity Bean – Logically a single point of access for data -any client will access the data through the entity bean • Session Bean – Can only be accessed by a single client -multiple clients will require multiple session beans Goals • Compare and Contrast using an entity bean and a session bean • Compare and contrast entity beans whose persistence mechanism is container managed and those whose are managed by the bean developer (bean managed) Session Beans -- Why not? • How might we try to get a session bean to play the same role as an entity bean? • In other words, let's try to build an entity bean out of session bean parts. • Let's create a bean that is intended to provide an O-O representation of a particular customer -- data will be accessed as properties of the Customer object » Code snippet, see p. 968 of text. Stateful Session Bean public class Customer implements SessionBean{ public int customerID; public String customerName The session bean's public String customerAddr; state public String city public String state; public String postalCode; public void ejbCreate(String customerID){ this.customerID = customerID; } public void setCustomerName(String customerName){ this.customerName = customerName; } // .. . . Similar Methods . . . public void saveStateToDatabase(){ // . . . SQL Code . . . } public void loadStateFromDatabase(){ // . . . SQL Code } // . . . Lifecycle methods . . . } Using Stateful Session Beans • What is the sessions bean's state? – The customer data for a particular customer • name, address, etc. • The state is loaded from the database by one method • The state is saved to the database by another method Isn't This Approach Gonna Be Messy?? • Problem – When do methods for loading and saving the state to the database get called? – Is the client code to have calls to these methods, like bookends around the business logic? » Less than desireable!! • Solution eNTiTy bEanZ!! – Entity Beans, of course. • EBs have special callbacks that help the container manage their state automatically Not so fast, Bucko!!! • Session beans can duplicate these special container-managed-state callbacks by implementing – javax.ejb.SessionSynchronization » Tell me more! SessionSynchronization Interface • Provides to Session Beans optional callbacks that the container will use to notify the bean . . . • When the transaction begins • When the transation is about end • These transation boundaries are the place to synchronize object state with the database! • A little code, please . . . » (see page 969) public class Customer implements SessionBean, SessionSynchronization{ // . . . public void afterBegin() { loadStateFromDatabase(); // EXCELLENT!! } public void afterCompletion(boolean commit) { // if commit is false, ROLL BACK } public void beforeCompletion() { // called only if no roll back saveStateToDatabase(); // EXCELLENT!! } } • As you can see . . . – The bean is notified by the container that the transaction has begun, and then the bean can call loadStateFromDatabase() – Similarly, when the transaction is about to end, the container notifies the bean, and then the bean can call saveStateToDatabase() SESSION BEANS ALL THE WAY!! • It looks like Session Beans provide us will all the functionality we need . . . • We can handle STATE -- NO problem. » Err, excuse me . . . Let the chanting begin . . . SESSION BEANS!! SESSION BEANS!! SESSION BEANS!! The crowd goes wild!! In Case You Forgot... • . . . this "perfectly adequate" representation of a customer entity using only a SESSION BEAN . . . – IT AINT SO ADEQUATE!!! • CUZ – This SB represents the state of a single client only -- HELLO!?!?!?! » Ooops!! Whaaat… How… ?? I'm So Confused! • What's Missing? • Understanding of . . . – the limitation of using "private, conversational state to represent shared data" • Consider the Case . . . – in which we have two session beans within one transaction that need to access customer data Let's Process an Order!! • We need to change the . . . – customer's ship-to address – the customer's available credit • These activities will be performed by two stateless session beans called . . . – "manage preferences" – "manage acounts" As a part of their work, both beans must . . . • Alter data managed by the Customer object • Create a stateful session bean to represent the customer, using the create() method to associate the customer ID with the bean • Invoke the appropriate business method • setCustomerPreferences(CustomerPref erencesView preferences) • setAvailableCredit(double availableCredit) As the business methods are invoked . . . • Each Customer bean is enlisted into the transaction • afterBegin() is called on each bean – the state data is loaded – GULP!! We now have two (count 'em, TWO) copies of the same state data. Each copy is accessible only by its client. » I have a feeling this isn't going to be good First Dilemma • What do we do with the Customer beans? • Remember – They have state, and are consuming resources . .. Possible Solutions That Turn Out to be STUPID • Remove the Bean!! – illegal – stateful sessions beans cannot be removed in the middle of a transaction • Have Application Server Remove the Bean!! – Requires a time-out -- performance problems Contrast with EJBs • EJBs are Shared Objects – the instantiation and destruction are handled directly by the container – as the entity beans don't belong to any one client, the client is not responsible for removing them from the container • Life Cycle Methods – EJBs • refer to the underlying storage mechanism (like a database) – SBs • refer to the EJB in the container Other Problems • Using Stateful session beans to represent a Customer objects has two other problems • Because SBs represent private, conversational data, and not shared transactional data -– copies of data can become unsynchronized – copies can become stale Inconsistent State Results • When the transaction is about to commit – container calls beforeCompletion() on the two customer beans (undefined order) – the first updates the data in the database . . . – when the second performs its update . . . » the database will be left in an inconsistent state! Contrast with EJB • EJBs are SHARED objects – As far as clients are concerned • there is only ONE bean which they are all accessing – the changes from one client in a transaction . . . • will be reflected in an access by a different client – . . . therefore, kept in a consistent state How About Using a Stateless SB? • Stateless SB? Couple of Issues – SB being reference by the client, cannot be associated with an identity (e.g., primary key), BECAUSE it cannot remember that identity from method call to method call • SO, we'd have to pass the identity to each method – No ability to cache • SO, any information needed must be read in, and any updates must be written immediately. EVERY method that accesses state must do this. Code Follows • Taking the previous two points into consideration . . . » see page 971ff public class Customer implements SessionBean{ public void setCustomerName(String customerID, String customerName){ Connection con = null; try { con = getConnection(); PreparedStatement statement = con.prepareStatement("Update…"); statement.setString(1,customerName); statement.setString(2, customerID); int updated = statement.executeUpdate(); if (updated != 1){ throw new EJBException("Customer not found."); } } catch (SQLException sqle) { throw new EJBException(sqle); } finally { try { if (con != null) { con.close(); } }catch (Exception e) {} } } public String getCustomerName(String customerID){ Connection con = null; try { con = getConnection(); PreparedStatement statement = con.prepareStatement("SELECT Name FROM Customer WHERE id=?"); statement.setString(1, customerID); ResultSet resultSet = statement.executeQuery(); if (!resultSet.next()) { throw new EJBException("Customer not found."); } return resultSet.getString(1); } catch (SQLException sqle) { throw new EJBException(sqle); } finally { try { if (con != null){ con.close(); } }catch (Exception e) () } } // . . . } This code has none of the fatal flaws of the stateful version • The client does not need to worry about the removal of the SB – Calling remove() does not produce an error • Since each operation on a stateless session bean is automatic • Data cannot become unsynchronized and inconsistent – no private caches – database can manage concurrent accesses So, Then . . . EJBs Obsolete? • Notice that this code is "painful" – Embedding SQL directly in your Java is tedious and error prone. • This approach is not providing an O-O view of your data – really it's just providing a function library – the stateless session customer bean has only functionality; it does NOT have data, nor identity Benefits of EJBs • Container callbacks to manage caching within a transaction • Support for concurrent access • Maintaining a cache between transactions • Providing all the persistence management code » WOW!! Cool!! Container vs Bean Managed Persistence • The EJB container can manage the process of saving and restoring the state of your entity beans » This is known as CMP, contain-managed persistence • The bean developer can control the bean's persistence » This is known as BMP, bean-managed persistence Container vs Bean Managed Persistence • Deciding on WHICH form of persistence . . . – CMP – BMP • . . . is one of the most important implementation decisions » What is clear is that persistence is NOT appropriate for business logic programmers Container vs Bean Managed Persistence • SQL Code? – Moving the state of the Java object back and forth from a database? • • • • This is a common manifestation of persistence Time consuming Tedious ERROR prone Container vs Bean Managed Persistence • EJB Framework . . . – Moves persistence issues to the EJB container • So! – CMP must be the way to GO!! » Well not always . . . Container vs Bean Managed Persistence • Although every EJB-1.1 compliant container MUST provide CMP . . . – the specification does not indicate HOW this support is to be provided • The fact is that . . . – The container need not provide ANY support for mapping your entity bean's state to columns in a database – It COULD use Java serialization to write the whole bean state to one column and still be complient! » Gee, that's not what I wanted . . . Container vs Bean Managed Persistence • BUT . . . – Such theoretical cases don't exist in REAL LIFE – According to your author, "Every single application server with EJB support of which I am away . . . has some support for mapping your objects to the fields in a relational database" (974) • STILL . . . – You MUST determine whether the EJB container has the level of CMP support YOU need – If it does, use it » Like, DUH!! the boost in productivity is potentially very large, as well as, perhaps, application performance! Container vs Bean Managed Persistence • Please note: – EJB 2.0 containers can be depended on to manage mappings between multiple tables and entity relationships – It may be that even the portion of the container responsible for performing these mappings (the persistence manager) will be portable across EJB 2.0 containers Container vs Bean Managed Persistence • If you MUST use BMP . . . – Seek THEARPY and use PROZAC – Trying finding another container! » Even after reading this chapter!! – Use a third-party object/relational mapping tool – Change your design – Write you own data-access code SportsBean Lab • See page 975-978 • A simple application that allows us to talk about persistence using either CMP or BMP » Take a look for details -- most of them ought to become apparent as we discuss the callbacks, etc. C.R.U.D. Callbacks • • • • Create Read Update Delete Create • When a client calls create() for an entity bean . . . – state data is inserted into the corresponding data store • this is transactional data that is accessible from multiple clients • When a client calls create() for a stateful SB – the EJB container creates a private, nontransactional store of data in the applications server's temporary storeage Create "When you call create() on a session bean's home interface, you are creating an instance of that session bean, whereas when you call create() on an entity bean's home interface, you are actually inserting a record in the database." (979) Create() • There can be multiple forms of create() defined in the bean's home interface – These methods may take different parameters, which correspond to the bean's state at time of creation – The parameters must have enough information to initialize the primary key of the entity • ALL create methods MUST – return the bean's remote interface » So that, when the client programmer calls create() on the home interface, they'll have a reference to that bean on which the business methods may be called. Create() • All the create() methods must throw … – java.rml.RemoteException » because they can be remote methods – javax.ejb.CreateException » used to indicate an application-level problem during attempted creation -- like illegal parameters passed to create() • Code coming up » See page 979 package sportBean.cmp; import javax.ejb.*; import java.rmi.RemoteException; import java.util.Collection; public interface SportTeamHome extends EJBHome { SportTeam create(String sport, String nickName) throws RemoteException, CreateException; SportTeam create(String sport,String nickName, String ownerName, String franchisePlayer) throws RemoteException, CreateException; • Each one of these forms of the create() method, defined in the bean's home interface . . . – MUST have two matching methods in the bean's implementation class • The two methods for each create() in the home interface . . . – MUST be named . . . • ejbCreate()<<< returns the PK • ejbPostCreate() <<< returns void – They MUST . . . • have the same parameters in the same order as the create() method • be declared public – They must NOT . . . • be final or static Point of Confusion • Why . . . – ejbCreate() and ejbPostCreate() » BOTH are REQUIRED! • Generally – All the work will be done in ejbCreate(), leaving ejbPostCreate() empty • So what gives??? Point of Confusion • You are not allowed to pass "this" as a parameter to a remote method; – You must always the remote interface instead • BUT – the REMOTE INTERFACE for the bean is NOT available UNTIL ejbCreate() returns – SO, • if you need you need the remote interface during the creation of the EJB component . . . » . . . you be . . . outta luck! – Enter ejbPostCreate() » TO SAVE THE DAY!! Point of Confusion • The same situation exists with the PK in CMP – Because the container creates the key • If the primary key is needed . . . – that work needs to be done in ejbPostCreate() CMB Stuff • In a CMB, – the parameters that are passed in by the client will be used to initialize the entity bean's state • Although, the return type of ejbCreate() is the same as the PK, – the bean developer should return null » the container will ignore the returned value anyway BMP Stuff • In a BMP, the bean must insert its state into the underlying data store – For a relational database – this means writing an SQL INSERT statement • The bean developer – should use the data to initialize the state variables of the bean – should construct an instance of the PK and return it CMP Stuff • Code follows » It's the CMP version of the sports team entity bean's creation callbacks » Full code is found on p. 980-1 package sportBean.cmp; . . . public class SportTeamEJB implements EntityBean{ . . . public SportTeamPK ejbCreate(String sport,String nickname) throws CreateException { this.sport = sport; this.nickName = nickName; ownerName = null; franchisePlayer = null; return null; } public void ejbPostCreate(String key, String relatedData) {} public SportTeamPK ejbCreate(String sport,String nickname, String ownerName,String franchisePlayer) throws javax.ejb.CreateException { this.sport = sport; this.nickName = nickName; ownerName = null; franchisePlayer = null; return null; } public void (ejbPostCreate(String sport, String nickName, String ownerName, String franchisePlayer){} BMP Stuff • The same sports team entity bean – with bean-managed persistence • Has two basic differences – the ejbCreate() methods have JDBC and SQL code to insert a record into the database – the method returns an instance of a primary key, rather than null » See pages 981-3 Read -- ejbLoad() • The ejbLoad() callback method – corresponds (roughtly) to the 'read' functionality of entity beans • The entity loads the database – in correspondence to the container's ejbLoad() call Read -- ejbLoad() • With CMP – the EJB container will take care of transferring the entity's state from the database to the entity's instance variables » That means I can leave ejbLoad() blank!! » BUT you may want to do some postprocessing, too! Read -- ejbLoad() • With BMP – the bean programmer will write their data access code . . . » JDBC and SQL code – . . . in ejbLoad() to transfer the entity's state to instance variables Read -- ejbLoad() • Technically ejbLoad() doesn't tell the bean that it must actually load data • it just tells the bean that it must re-synchornize its state with the underlying data store • In fact, – the bean's persistence implementation may choose to defer loading the state until that state is acutally used ejbLoad() and CMP • The role of ejbLoad() in CMP is to process the data after it has been loaded from the database – Usually, the data will not need any processing, and ejbLoad() will be empty – But it may be the case that some changes are necessary » See page 984 for an example ejbLoad() and BMP • Here the role of ejbLoad() is to notify the bean that it must invalidate the current cached state and prepare for business method invocations – Practically, this mean replacing the state by loading it from the database • For this you'll need the PK – by the time that ejbLoad() is called, the PK is associated with the entity and is available from its context. – You'll have to add the interfaces and methods on page 984-5 Interface public EJBObject getEJBObject() throws IllegalStateException; pubic Object getPrimaryKey() throws IllegalStateException; For BMP public void setEntityContent(EntityContext ctx) { this.ctx = ctx; } public void unsetEntityContext() { ctx = null; } For CMP public void setEntityContext(EntityContext ctx) {} public void unsetEntityContext() {} ejbLoad() -- BMP version • see page 985-6 for the BMP version of ejbLoad() • Note is made of how the saved EntityContext is used to retrieve the primary key SportTeamPK primaryKey = (SportTeamPK) ctx.getPrimary Key(); Update -- ejbStore() • For a bean with CMP – ejbStore() is called directly before the container writes the bean state to the database – this gives an opportunity to pre-process the bean's data to ensreu that it is in an appropriate state for persistent storage » Typically though this method will be left empty Update -- ejbStore() • For a bean with BMP, the programmer is responsible for providing in this method, the logic that will transfer the bean's state to the underlying data store. » For a relational database this most likely means JDBC code and SQL statements Update -- ejbStore() • NOTE (p. 986) – "With ejbLoad(), the bean has the option to defer the actual loading of state until it was used. There is not such option with ejbStore(). Any modifications to the object's state must be written to the data store immediately." ejbStore() for BMP • Next slide shows the ejbStore for a bean with BMP » see page 986-7 of text for complete listing public void ejbStore() { Connection con = null; try { con = getConnection(); PreparedStatement statement = con.prepareStatement("UPDATE . . ."); statement.setString(1, ownderName); statement.setString(2, francisePlayer); . . . if (statement.executeUpdate() !=1){ throw new EJBException("Failed to save..."); } statement.close(); }catch (SQLException sqle) { throw new EJBException(sqle); } finally { try { if (con != null) { con.close(); } }catch (SQLException sqle) {} } } ejbStore() for CMP • Next slide shows the ejbStore for a bean with CMP » see page 987 of text for complete listing public void ejbStore() {} Delete -- Remove()? • When a client calls remove() on an entity bean – data is deleted from the corresponding data store • This is in contrast to calling remove on a stateful session bean – the EJB container discards the session bean instance in the application server's temporary storage -- be sure to call remove() when done, or else the EJB container will waste resources » this is probably a good thing to know! Delete -- Remove()? • Note – "You should not call remove() on an entity bean unless you want to delete that record. The EJB container will manage the entity bean's instance in the container" (p. 987). Delete -- ejbRemove() • For a bean with CMP – Can usually be left blank » I'm beginning to see a pattern here! – However, the programmer may want to to do somethings (such as updating related data, or notifying other systems) before the entity's object representation is removed from the database, and here's the chance to do it. • Code follows » p 987 ejbRemove() for CMP public void ejbRemove() {} ejbRemove() for BMP • Code follows, see page 987-8 public void ejbRemove() throws javax.ejb.RemoveException{ Connection con = null; try { con = getConnection(); PreparedStatement statement = con.prepareStatement("DELETE FROM SPORTSTEAMS …"); statement.setString1, sport); statement.setString2, nickName); if (statement.executeUpdate() != 1){ throw new EJBException("Failed…"); } statement.close(); } catch (SQLException sqle){ throw new EJBException(sqle); } finally { try { if (con !=null) { con.close(); } }catch (SQLException sqle) () } } BMP vs CMP Callbacks • BMP – callbacks are responsible for solving the entire problems of synchronizing the state with the underlying data store for creates, reads, updates, and deletes. • CMP – with the exception of ejbCreate(), the callbacks are for fine tuning, and can be left empty CMP Callbacks public String ejbCreate(String key, String relatedData) { this.key = key; this.relatedData = relatedData; } public void ejbPostCreate(String key, String related data) {} public void ejbLoad() {} public void ejbRemove() {} public void ejbStore() {} Deployment Descriptor • They type of persistence . . . – bean managed – container managed • . . . is specified in the XML deployment descriptor for the EJB • The <persistence-type> element of the DD will be one of – <persistence-type>Bean</persistence-type> – <persistence-type>Container</persistencetype> Deployment Descriptor • If the bean's persistence is CM, the fields that are persisted must also be specified in the deployment descriptor • Each entry in the DD has the name of the field in the class (and also a description, optionally) • Examples follows » see page 989 Specifying Persistence Fields <cmp-field> <field-name>sport</field-name> <description>basketball</description> </cmp-field> <cmp-field> <field-name>nickName</field-name> <cmp-field> Specifying Persistence Fields • "All the container-managed fields listed in the DD must be declared public, and must not be transient in the bean class. They must be serializable, primitive types, or references to other EJBs. In a bean with container-managed persistence, all the persistence code must be left to the container" (p. 989) Specifying Persistence Fields • The complete deployment descriptor for the CMP version of the bean is on page 989-90 • The complete deployment descriptor for the BMP version of the bean is on page 990. Caching • A secondary copy of data typically made for reasons of performance or convenience. – The instance variables in your EB that represent the object's persistent state are actually a cache of the data in the permanent store. • The cache suffers from the problem of – getting out if synch with the permanent store Caching • With BOTH BMP and CMP it is the combined responsibility of . . . – . . . the EJB container . . . – . . . and the underlying data store . . . • . . . to manage the synchronization • The EJB container calls ejbLoad() and ejbStore() at those times that it thinks appropriate to keep the local cache in synch Caching • The bean programmer does not need to be concerned with exactly when the container will call ejbLoad() and ejbStore() • Still, it's nice to know some common stratigies used by EJB containers First Case • Two methods called in the same transaction – After the first method is called the container has the option of called ejbload() and ejbstore() – More typically, the container will wait until the second method is finished – So basically, the container will call ejbLoad() and ejbStore() on the transaction boundaries Second Case • Two methods in different transactions – Again in this case the container calls ejbLoad() and ejbSave() on the transaction boundaries – This must be the case because between transactions some other process could have modified the data • Two exceptions – If all accesses to the data go through the EJB container, then ejbLoad() doesn't have to be called -- cache and store are in synch – If the application does not require the absolutely freshest data -- not applicable in a banking scheme, but perhaps in an e-commerce application 5-minute old data is okay Finder Methods • Every entity bean MUST declare – findByPrimaryKey() – For CMP, the implementation will be provided by the EJB container • However when the EJB is deployed, additional information needs to be specified – in what is currently an application-server-specific format about how the finder should behave Finder Methods • For BMP, the developer must provide the implementation • The return type – One result -- an instance of the PK for that entity – Zero or more results -- Collection or Enumeration Finder Methods • Note – You don't have access to state related instance variables in the implementation of finder methods -- NOR any other identity specific information » Chart on page 997 may be helpful • See code on page 994-5 for implementation of finder methods for BMP Activation/ Passivation • For EBs ejbActivate() – provides notification that the enity bean has been associated with an identity, and is now ready for ejbLoad() to be called prior to busness method invocation • For EBs ejbPassivate() – provides notification that the entity bean is being dissassociated • For the most part, these methods can be empty » see page 996 Lifecycle • The diagram on page 997 summarizes the information about container callbacks for entity beans. » Enjoy!! THE END