package study.ejb2.lifecycle.stateful; import javax.ejb.SessionBean; import javax.ejb.SessionContext; /** * An EJB Stateful is created only when a client request one. * There is only one per client. * This class can be only a Statefull bean, because stateless bean's must not * have anything except the no-arg create() method. * Must NOT have a finalize() method. */ public class EjbStatefulBean implements SessionBean { private static final long serialVersionUID = 8339967245339132866L; private SessionContext context; private String specificClientData; private Object someVarNoSerializable; /* Methods of Creation */ /** * In the constructor the bean isn't a really bean (doesn't has the advantages * of be a bean - context, JNDI capabilities), it actually is only a * normal Java object. * We shouldn't do anything because is to early to do EJB's things. * Normally will be always empty, is better wait until the ejbCreate[XXXX]. */ public EjbStatefulBean() { } /** * This method is called after the constructor and before the * ejbCreate[XXXX] method. * * Here we received the SessionContext, here the object is becoming a * really EJB. * * With the SessionContext we can: * - get a reference to home * - get a reference to EJB object * - get security information about the client * - force a transaction to rollback (CMT) * - find out if the transaction has already been set to rollback (CMT) * - get a transaction and call methods on it (BMT) * * But in this method is to early to do something because does not have * a "meaningful transaction context" (where the Container gives us some * authority to do some things). * * We CAN only: * - get a reference to home * - use JNDI environment * * We CANNOT: * - get a reference to EJB object * - get security information about the client * - force a transaction to rollback (CMT) * - find out if the transaction has already been set to rollback (CMT) * - get a transaction and call methods on it (BMT) * - use another bean's methods * - use a resource manager (like a database) (we can ask a connection but * not make a JDBC call on it) * * Usually we will only save the context. * * @see javax.ejb.SessionBean#setSessionContext(javax.ejb.SessionContext) */ public void setSessionContext(SessionContext ctx) { this.context = ctx; // myConnection = dataSource.getConnection(); } /** * This method is called when the client calls the method on * the EJBHome's stub. * * We can have other ejbCreate overloaded or ejbCreateXXXXXX * if we need, but in the home interface must have the * correpondent method. * Every method must be void, public and must not be marked final * or static. * We can declare exceptions if we actually throw one, * but is often a good practice to declare CreateException. * Must not declare RemoteException and must declare only application * exceptions (checked) declared in the home interface. * * Finally we have full bean status (it really is an EJB). * There we should put all initialization. * * We CAN only: * - get a reference to the home object * - get a reference to the EJB object * - get security information about the client * - get a transaction reference and call methods on it (BMT) * - use JNDI environment * - use another bean's methods * - use a resource manager (like a database) * * We CANNOT: * - force a transaction to rollback (CMT) * - find out if the transaction has already been set to rollback (CMT) * */ public void ejbCreate() { System.out.println("Created through ejbCreate() from " + context.getEJBHome()); specificClientData = "New one"; } public void ejbCreate(String someInitial) { System.out.println("Created through ejbCreate(String) from " + context.getEJBHome()); this.specificClientData = someInitial; } public void ejbCreateAnySufix() { System.out.println("Created through ejbCreatAnySufix() from " + context.getEJBHome()); specificClientData = "Created a specific"; } /** * A business method, here we can do everything. * We CAN: * - get a reference to the home object * - get a reference to the EJB object * - get security information about the client * - get a transaction reference and call methods on it (BMT) * - force a transaction to rollback (CMT) * - find out if the transaction has already been set to rollback (CMT) * - use JNDI environment * - use another bean's methods * - use a resource manager (like a database) */ public void doStuff() { System.out.println("Doing stuff: " + specificClientData + " (" + someVarNoSerializable + ")"); } /* Methods of Passivation and Activation */ /** * Used only in a Statefull bean. * This method is called before the bean is passivate by the Container. * In this method we must leave the bean ready for that, we must sure * every non-transient instance variable MUST be a reference to one of * the following: * - a serializable object * - a null value * - a bean's remote or local component or home interface, even if it isn't * serializable (teh Container will take care of) * - a SessionContext, even if it isn't serializable (again the Container will) * - JNDI context or its subcontexts * - an UserTransaction interface * - a resource manager connection factory (like a DataSource) * * We also should release the resources because the Container can kill the * bean when it is in the passivated (when the Container is gonna kill the * bean it won't call the remote() method, thus we will have a leak of * resources). * * The bean will never be passivated while the bean is still in a transaction. * * We CAN do the same thing as the thing we can do in an ejbCreate[XXXX]. * * @see javax.ejb.SessionBean#ejbPassivate() */ public void ejbPassivate() { someVarNoSerializable = null; // we must set null // myConnection = null; } /** * Used only in a Statefull bean. * This method is called after the bean is deserialized and before the * business methoed called by the client run. * We must make sure that all resources needed by the methods are available * again. * * We should also initialize the transient variables because in the * spec does not guarantee that will be set to default values (because * the passivation cannot be a serialization). * * We CAN do the same thing as the thing we can do in an ejbCreate[XXXX]. * * Usually, when the ejbPassivate() is empty this also will be. * @see javax.ejb.SessionBean#ejbActivate() */ public void ejbActivate() { // reacquire the resources someVarNoSerializable = new Object(); // myConnection = dataSource.getConnection(); // we not have to restore the DataSource because it's one // of the things on the Container's "approved list" (it's a // resource manager factory, and the Container is required to // passivate it) } /** * We should release all resources used by the bean. * Is called before the Container kill the bean when: * - Client calls remove() on EJBObject's stub * - Client calls remote() on EJBHome's stub passing either the EJB's handler * or Primary Key * - The bean times out (only if it's on an active) * Isn't called when: * - Container crash * - The bean throws a runtime exception * * We CAN do the same thing as the thing we can do in an ejbCreate[XXXX]. * * @see javax.ejb.SessionBean#ejbRemove() */ public void ejbRemove() { specificClientData = null; someVarNoSerializable = null; // release the resources // myConnection.close(); // dataSource = null; } }