First of all, I'd like to point out the excellent
tutorial by Greg Mally on using EJB3 within Workshop
How to define an EJB3 ?
Well, it's quite easy. According to the specification, you only have to use annotations to define your EJB. For instance, let's take the following EJB :
@Stateless(
name = "PdfRetriever",
mappedName = "ejb/stateless/PdfRetriever",
description = "Gets a PDF file from the server")
@Local ({PdfRetriever.class})
@Remote ({PdfRetrieverRemote.class})
public class PdfRetrieverBean implements PdfRetriever, PdfRetrieverRemote {
[...]
}
For specifying the interfaces (local or remote), you can choose to use only the annotations or the implementation declarations.
The use of annotations is maybe a bit quicker to read, but the implement declaration prevents you from missing an interface method.
I wrote both so that you can make your choice. As for the deployment descriptor, the ejb-jar.xml must have the correct declaration, that is to say :
<ejb-jar
xmlns=http://java.sun.com/xml/ns/javaee
xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
version="3.0">
How to call it with remote interface ?
Here's the code to call the EJB :
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
props.put(Context.PROVIDER_URL, "t3://localhost:8001");
InitialContext ctx = new InitialContext(props);
PdfRetrieverRemote ejb = (PdfRetrieverRemote)ctx.lookup("ejb.stateless.PdfRetriever#sample.ejb.PdfRetrieverRemote");
ejb.getPdfFileFromServer("myFile.pdf");
Be aware that the JNDI name is not exactly the same as entered in the EJB definition ("ejb/stateless/PdfRetriever").
It has been postfixed with a # and the full-qualified name of the Remote interface.
How to call it with local interface ?
Note : "Local" doesn't refer to the same JVM but the same EAR.
The easiest way to call your EJB is through a Servlet thanks to an annotation. As explained above, your servlet must reside in the same EAR as the EJB3 module.
You don't have to use JNDI to reach your EJB, just reference it that way :
@EJBprivate PdfRetriever pdfRetriever;public void myMethod () {
byte[] myPdfFile = pdfRetriever.getPdfFileFromServer("myFile.pdf");
}
Note : Due to lots of messages asking me how to call an EJB3 from a pojo, I will write some details about that, but know that this is not the way it is sensed to be used.
According to the specification, an EJB3 is to be called via an annotation in a Servlet or another EJB. This solution lies on the "
java:comp/env" mechanism.
EJB within a web application
First part : declaring the EJB
Taking the example quoted above, you will have to add an annotation to at least one servlet. Example :
@EJB(beanInterface=sample.ejb.PdfRetriever.class, name = "ejb/PdfRetriever")
public class EjbInvoker extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
This annotation replaces the EJB declaration in the
web.xml file. It makes the EJB available for all the War context. Else you can declare your EJB in the
web.xml :
<ejb-local-ref>
<ejb-ref-name>ejb/PdfRetriever</ejb-ref-name>
<local>sample.ejb.PdfRetriever</local>
</ejb-local-ref>
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd
As you can see, the attributes are different :
Deployment descriptor | Annotation |
local | beanInterface |
ejb-ref-name | name |
Note : With the annotation, the beanInterface attribute expects a class.
Second part : calling the EJB from the POJO
Now the EJB has been made visible within the whole web application, the code to call the EJB from the POJO is quite simple :
InitialContext ctx = new InitialContext();
PdfRetriever ejb = (PdfRetriever) ctx.lookup("java:comp/env/ejb/PdfRetriever");
Note : The lookup has been made on the name specified in "
name" attribute for the annotation and "
ejb-ref-name" for the DD, that is to say "
ejb/PdfRetriever"
You can then manipulate your local EJB.
EJB within an EJB module
The scenario is the same as for the web application, except that the element you've got to add the EJB declaration to is now an EJB and the DD to modify is not the
web.xml but the
ejb-jar.xml