| Title: Simple Stateful Example |
| <a name="SimpleStatefulExample-Overview"></a> |
| # Overview |
| |
| {span:style=float: right; margin-left: 20px;} |
| {html} |
| |
| <object width="400" height="250"><param name="movie" |
| value="http://www.youtube.com/v/9JqxbfzsWOQ?fs=1&hl=en_US&rel=0"></param><param |
| name="allowFullScreen" value="true"></param><param name="allowscriptaccess" |
| value="always"></param><embed |
| src="http://www.youtube.com/v/9JqxbfzsWOQ?fs=1&hl=en_US&rel=0" |
| type="application/x-shockwave-flash" allowscriptaccess="always" |
| allowfullscreen="true" width="400" height="250"></embed></object> |
| |
| {html} |
| {span} |
| {div} |
| |
| This example shows how to create a Stateful session EJB using annotations. |
| |
| A Stateful session bean is a session bean whose instances can maintain the |
| conversational state with the client. The conversational state of the |
| stateful session bean, which describes the conversation between a specific |
| client and a session bean, is contained in the fields of the stateful |
| session bean. |
| |
| Simply put, when you create a stateful bean an actual instance is created |
| by the container and *dedicated* to you and only you. Every call you make |
| will go to your instance. Further, your instance will not be shared with |
| anyone unless you give them a reference to your stateful bean. The |
| instance will last until you remove it or until it times-out and is removed |
| by the container. |
| |
| With EJB 3.0, it's now possible to write stateful session bean without |
| specifying a deployment descriptor; you basically have to write just a |
| remote or local business interface, which is a plain-old-java-interface, |
| annotated with the @Remote or @Local annotation the stateful session bean |
| implementation, a plain-old-java-object which implements the remote or the |
| local business interface and is annotated with the @Stateful annotation |
| |
| _This example is the "simple-stateful" example located in the [openejb-examples.zip](openejb:download.html) |
| available on the [download page](http://tomee.apache.org/downloads.html)._ |
| |
| |
| |
| {div} |
| {div:style=clear:both;}{div} |
| |
| <a name="SimpleStatefulExample-TheCode"></a> |
| # The Code |
| |
| In this example we develop a simple counter stateful session EJB. Every |
| stateful session bean implementation must be annotated using the annotation |
| *@Stateful* or marked that way in the ejb-jar.xml file. |
| |
| <a name="SimpleStatefulExample-Bean"></a> |
| ## Bean |
| |
| {snippet:id=code|url=openejb3/examples/simple-stateful/src/main/java/org/superbiz/counter/CounterImpl.java|lang=java} |
| |
| In EJB 3.0 session beans do not need to implement the javax.ejb.SessionBean |
| interface. You can simply annotate it as @Stateful if you want it to be a |
| stateful session bean. |
| |
| Users of EJB 2.x may notice the bean actually implements the business |
| interfaces! In the prior version of EJB implementing the remote interface |
| (which derives from javax.ejb.EJBObject) in your bean was just not allowed. |
| Now there is no javax.ejb.EJBObject requirement, so implementing the |
| business interfaces is standard practice for EJB 3.0. |
| |
| <a name="SimpleStatefulExample-Localbusinessinterface"></a> |
| ## Local business interface |
| |
| {snippet:id=code|url=openejb3/examples/simple-stateful/src/main/java/org/superbiz/counter/CounterLocal.java|lang=java} |
| |
| Local interfaces in EJB are *pass-by-reference* interfaces. Meaning that |
| *normal java semantics* are used for passing arguments, return values and |
| exceptions. A business local interface can be any plain java interface. |
| There are no restrictions on the method arguments, return types, or throws |
| clauses. |
| |
| Unless specified otherwise, every interface your bean implements (and it's |
| parent class implements and so on) is considered to be a local business |
| interface. You can use the *@Local* annotation to explicitly state that an |
| interface is a local interface, but this is not required. |
| |
| You'll notice that in EJB 3.0 the Local Business Interface of a stateless |
| session bean does not need to extend from javax.ejb.EJBLocalObject and does |
| not need a javax.ejb.EJBLocalHome interface as they did in EJB 2.x and |
| prior. Per the vocabulary of the EJB spec, interfaces that implement |
| javax.ejb.EJBLocalObject or javax.ejb.EJBLocalHome are considered Component |
| Interfaces and the plain java interface above is considered a Business |
| Interface. |
| |
| <a name="SimpleStatefulExample-Remotebusinessinterface"></a> |
| ## Remote business interface |
| |
| {snippet:id=code|url=openejb3/examples/simple-stateful/src/main/java/org/superbiz/counter/CounterRemote.java|lang=java} |
| |
| Remote interfaces are *pass-by-value* interfaces. Meaning that all method |
| parameters, return values, and exceptions are *serialized* on every call. |
| The result is that you get a copy of the original object and not the |
| original object. The advantage is of course that Remote interfaces can be |
| used to invoke an EJB across a network in a client-server fashion. There |
| are no restrictions on the Remote interface itself, but there are on the |
| data passed in and out of the remote interface. The *values* passed into a |
| method or returned from a method of a Remote interface *must be |
| serializable*. It is fine for the method signature to be, for example, |
| "public Object myMethod(Object myParam)" as long as the *value* passed in |
| and returned implements *java.io.Serializable*. |
| |
| As stated above, the Remote Business Interface of a bean can be any plain |
| old interface. It does not need to extend javax.ejb.EJBObject, it does not |
| need a javax.ejb.EJBHome, the methods do not need to throw |
| javax.rmi.RemoteException, and the bean class *can* implement it! |
| |
| At minimum the interface must be annotated with *@Remote* either in the |
| interface itself or in the bean class, or the interface must be declared |
| via <business-remote> in the ejb-jar.xml. |
| |
| <a name="SimpleStatefulExample-Writingaunittestfortheexample"></a> |
| # Writing a unit test for the example |
| |
| Writing an unit test for the stateful session EJB is quite simple. We need |
| just to write a setup method to create and initialize the InitialContext, |
| and then write our test methods |
| |
| <a name="SimpleStatefulExample-setUp"></a> |
| #### setUp |
| |
| {snippet:id=setup|url=openejb3/examples/simple-stateful/src/test/java/org/superbiz/counter/CounterImplTest.java|lang=java} |
| |
| <a name="SimpleStatefulExample-Testthelocalbusinessinterface"></a> |
| #### Test the local business interface |
| |
| {snippet:id=local|url=openejb3/examples/simple-stateful/src/test/java/org/superbiz/counter/CounterImplTest.java|lang=java} |
| |
| <a name="SimpleStatefulExample-Testtheremotebusinessinterface"></a> |
| #### Test the remote business interface |
| |
| {snippet:id=remote|url=openejb3/examples/simple-stateful/src/test/java/org/superbiz/counter/CounterImplTest.java|lang=java} |
| |
| {info:title=JNDI Names} |
| Note that JNDI names for Java SE clients are not standardized by the EJB |
| spec. This is unfortunate and something being addressed in EJB 3.1. The |
| default schema that OpenEJB uses is ejbName + interfaceType (i.e. Local, |
| Remote, LocalHome, RemoteHome), so in our example "CounterImpl" + "Local" |
| and "CounterImpl" + "Remote". You can in fact change this default to be |
| absolutely [anything you want](jndi-names.html) |
| including interface class name, ejb class name, and more. |
| {info} |
| |
| <a name="SimpleStatefulExample-Running"></a> |
| # Running |
| |
| Running the example is fairly simple. In the "simple-stateful" directory |
| of the [examples zip](openejb:download.html) |
| , just run: |
| |
| $ mvn clean install |
| |
| Which should create output like the following. |
| |
| |
| ------------------------------------------------------- |
| T E S T S |
| ------------------------------------------------------- |
| Running org.superbiz.counter.CounterImplTest |
| Apache OpenEJB 3.0 build: 20080408-04:13 |
| http://tomee.apache.org/ |
| INFO - openejb.home = |
| /Users/dblevins/work/openejb-3.0/examples/simple-stateful |
| INFO - openejb.base = |
| /Users/dblevins/work/openejb-3.0/examples/simple-stateful |
| INFO - Configuring Service(id=Default Security Service, |
| type=SecurityService, provider-id=Default Security Service) |
| INFO - Configuring Service(id=Default Transaction Manager, |
| type=TransactionManager, provider-id=Default Transaction Manager) |
| INFO - Configuring Service(id=Default JDK 1.3 ProxyFactory, |
| type=ProxyFactory, provider-id=Default JDK 1.3 ProxyFactory) |
| INFO - Found EjbModule in classpath: |
| /Users/dblevins/work/openejb-3.0/examples/simple-stateful/target/classes |
| INFO - Configuring app: |
| /Users/dblevins/work/openejb-3.0/examples/simple-stateful/target/classes |
| INFO - Configuring Service(id=Default Stateful Container, type=Container, |
| provider-id=Default Stateful Container) |
| INFO - Auto-creating a container for bean CounterImpl: |
| Container(type=STATEFUL, id=Default Stateful Container) |
| INFO - Loaded Module: |
| /Users/dblevins/work/openejb-3.0/examples/simple-stateful/target/classes |
| INFO - Assembling app: |
| /Users/dblevins/work/openejb-3.0/examples/simple-stateful/target/classes |
| INFO - Jndi(name=CounterImplLocal) --> Ejb(deployment-id=CounterImpl) |
| INFO - Jndi(name=CounterImplRemote) --> Ejb(deployment-id=CounterImpl) |
| INFO - Created Ejb(deployment-id=CounterImpl, ejb-name=CounterImpl, |
| container=Default Stateful Container) |
| INFO - Deployed |
| Application(path=/Users/dblevins/work/openejb-3.0/examples/simple-stateful/target/classes) |
| Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.698 sec |
| |
| Results : |
| |
| Tests run: 2, Failures: 0, Errors: 0, Skipped: 0 |
| |
| |
| |