====== Creating ====== Creating EJBs is easy. Simply create a class with the appropriate annotations and deploy it as part of a .war or .jar. ===== Singleton EJB ===== Singletons can be useful, especially when you have big/costly resources (which probably need to be initialized at deployment, not when they are first needed). To do this add the @Singleton annotation to your class. If you want to do some initialization also add the @Startup annotation and a method annotated with @PostConstruct Example @Startup @Singleton @Lock(LockType.WRITE) // If you are unsure if your class is threadsafe, add this to forbid concurrent access. public class RMMMapmatcher implements Mapmatcher { @PostConstruct private void init() { //some initialization stuff } public String doSomething() { return "something"; } } ===== Remotely accessible EJB ===== Please note that 'remote' here does not only necessarily mean "remote server" but rather anything that is not in the same application (and thus has a different classloader / different class visibilities). Generally remote access can be achieved by using the @Remote annotation. However things are bit more complicated when you want to cast the bean to a usable class (JNDI lookup returns java.lang.Object): *1.) create a bean-api.jar which defines the API of the EJB * bean-api.jar should contain the interface of the EJB and all data transfer classes * all data transfer classes need to be Serializable * the bean-api.jar will be a dependency for the EJB implementation and the EJB user * --> the .jar must not contain the actual EJB implementation/annotations, otherwise it will be deployed multiple times (which is probably not what you want) *2.) implement the EJB in a separate .jar or .war and add the appropriate @Remote annotation: @Startup @Singleton @Remote(Mapmatcher.class) // interface from the bean-api.jar public class RMMMapmatcher implements Mapmatcher { // implementation } *3.) implement the JNDI EJB lookup on the client Object o = new InitialContext().lookup("java:global/map-service/RMMMapmatcher"); // JNDI lookup Mapmatcher mm = (Mapmatcher) o; // cast to interface of bean-api.jar // use normally .. ====== Using ====== There are several ways of using the EJB: * When you are inside a container managed class you can just use dependency injection (see [[Java CDI]]). * Anywhere else you can use JNDI to get a reference to to the class: ===== Lookup via JNDI ===== When the EJB is being deployed JBoss shows under which JNDI names it is registered. It should look something like this: 13:01:08,136 INFO [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-1) JNDI bindings for session bean named DefaultTraveltimeService in deployment unit deployment "traveltime-service.war" are as follows: java:global/traveltime-service/DefaultTraveltimeService java:app/traveltime-service/DefaultTraveltimeService java:module/DefaultTraveltimeService Knowing this name, using the EJB is straingtforward: DefaultTraveltimeService s = (DefaultTraveltimeService) new InitialContext().lookup("java:global/traveltime-service/DefaultTraveltimeService"); Note that JBoss registers the EJB under several names which are visible to different contexts: * **java:global** - visible to the whole application server (other .wars and .ejbs) \\ Please note that just being "visible" does not imply that it is actually _usable_ without further steps. Have a look at [[JBoss EJB#Remotely accessible EJB]]. * **java:app** - visible in the same application * **java:module** - visible in the same module see https://docs.jboss.org/author/display/AS71/JNDI+Reference for details ==== Additional Global JNDI names ==== The @EJB anntation can be used to register an EJB under addtional JNDI names: @Stateless @EJB(name = "java:global/MyBean", beanInterface = MyBean.class) public class MyBean { } However comining this technique with @Remote currently breaks the JNDI page in the JBoss 7.1.1 administration console.