| Title: Simple Stateless Example |
| <a name="SimpleStatelessExample-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/aLx2jta96xU?fs=1&hl=en_US"></param><param |
| name="allowFullScreen" value="true"></param><param name="allowscriptaccess" |
| value="always"></param><embed |
| src="http://www.youtube.com/v/aLx2jta96xU?fs=1&hl=en_US" |
| 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 Stateless session EJB using annotations. |
| As stated in the "JSR 220: Enterprise JavaBeansTM,Version 3.0 - EJB Core |
| Contracts and Requirements", |
| |
| {panel} |
| "Stateless session beans are session beans whose instances have no |
| conversational state. This means that all bean instances are equivalent |
| when they are not involved in servicing a client-invoked method. The term |
| 'stateless' signifies that an instance has no state for a specific client." |
| {panel} |
| |
| What this means is quite simply that stateless beans are *shared*. They do |
| in fact have state as you can assign values to the variables, etc. in the |
| bean instance. The only catch is there are a *pool* of identical instances |
| and you are not guaranteed to get the exact same instance on every call. |
| For each call, you get whatever instance happens to be available. This is |
| identical to checking out a book from the library or renting a movie from |
| the video store. You are essentially checking out or renting a new bean |
| instance on each method call. |
| |
| With EJB 3.0, it's now possible to write stateless 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 stateless session bean |
| implementation, a plain-old-java-object which implements the remote or the |
| local business interface and is annotated with the @Stateless annotation |
| |
| _This example is the "simple-stateless" example located in the [openejb-examples.zip](openejb:download.html) |
| available on the download page._ |
| |
| {div} |
| {div:style=clear:both;}{div} |
| |
| <a name="SimpleStatelessExample-TheCode"></a> |
| # The Code |
| |
| In this example we develop a simple EJB 3 Stateless session EJB. Every |
| stateless session bean implementation must be annotated using the |
| annotation *@Stateless* or marked that way in the ejb-jar.xml file. |
| |
| Our Stateless bean has 2 business interfaces: CalculatorRemote, a remote |
| business interface, and CalculatorLocal, a local business interface. A |
| minimum of one business interface is required. |
| |
| <a name="SimpleStatelessExample-Bean"></a> |
| ## Bean |
| |
| {snippet:id=code|url=openejb3/examples/simple-stateless/src/main/java/org/superbiz/calculator/CalculatorImpl.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 @Stateless if you want it to be a |
| stateless 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="SimpleStatelessExample-Localbusinessinterface"></a> |
| ## Local business interface |
| |
| {snippet:id=code|url=openejb3/examples/simple-stateless/src/main/java/org/superbiz/calculator/CalculatorLocal.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="SimpleStatelessExample-Remotebusinessinterface"></a> |
| ## Remote business interface |
| |
| {snippet:id=code|url=openejb3/examples/simple-stateless/src/main/java/org/superbiz/calculator/CalculatorRemote.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="SimpleStatelessExample-Writingaunittestfortheexample"></a> |
| # Writing a unit test for the example |
| |
| Writing an unit test for the stateless 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="SimpleStatelessExample-setUp"></a> |
| ## setUp |
| |
| {snippet:id=setup|url=openejb3/examples/simple-stateless/src/test/java/org/superbiz/calculator/CalculatorTest.java|lang=java} |
| |
| <a name="SimpleStatelessExample-Testthelocalbusinessinterface"></a> |
| ## Test the local business interface |
| |
| {snippet:id=local|url=openejb3/examples/simple-stateless/src/test/java/org/superbiz/calculator/CalculatorTest.java|lang=java} |
| |
| <a name="SimpleStatelessExample-Testtheremotebusinessinterface"></a> |
| ## Test the remote business interface |
| |
| {snippet:id=remote|url=openejb3/examples/simple-stateless/src/test/java/org/superbiz/calculator/CalculatorTest.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 "CalculatorImpl" + |
| "Local" and "CalculatorImpl" + "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="SimpleStatelessExample-Running"></a> |
| # Running |
| |
| Running the example is fairly simple. In the "simple-stateless" 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.calculator.CalculatorTest |
| Apache OpenEJB 3.0 build: 20080408-04:13 |
| http://openejb.apache.org/ |
| INFO - openejb.home = |
| /Users/dblevins/work/openejb-3.0/examples/simple-stateless |
| INFO - openejb.base = |
| /Users/dblevins/work/openejb-3.0/examples/simple-stateless |
| 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-stateless/target/classes |
| INFO - Configuring app: |
| /Users/dblevins/work/openejb-3.0/examples/simple-stateless/target/classes |
| INFO - Configuring Service(id=Default Stateless Container, type=Container, |
| provider-id=Default Stateless Container) |
| INFO - Auto-creating a container for bean CalculatorImpl: |
| Container(type=STATELESS, id=Default Stateless Container) |
| INFO - Loaded Module: |
| /Users/dblevins/work/openejb-3.0/examples/simple-stateless/target/classes |
| INFO - Assembling app: |
| /Users/dblevins/work/openejb-3.0/examples/simple-stateless/target/classes |
| INFO - Jndi(name=CalculatorImplLocal) --> Ejb(deployment-id=CalculatorImpl) |
| INFO - Jndi(name=CalculatorImplRemote) --> |
| Ejb(deployment-id=CalculatorImpl) |
| INFO - Created Ejb(deployment-id=CalculatorImpl, ejb-name=CalculatorImpl, |
| container=Default Stateless Container) |
| INFO - Deployed |
| Application(path=/Users/dblevins/work/openejb-3.0/examples/simple-stateless/target/classes) |
| Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.845 sec |
| |
| Results : |
| |
| Tests run: 2, Failures: 0, Errors: 0, Skipped: 0 |
| |
| |