This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
jboss_ejb [2013/12/23 13:54] hkoller [Remotely accessible EJB] |
jboss_ejb [2013/12/23 14:01] (current) hkoller [Lookup via JNDI] |
||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== 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 | ||
+ | |||
+ | <code java> | ||
+ | @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"; | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | ===== 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: | ||
+ | <code java> | ||
+ | |||
+ | @Startup | ||
+ | @Singleton | ||
+ | @Remote(Mapmatcher.class) // interface from the bean-api.jar | ||
+ | public class RMMMapmatcher implements Mapmatcher { | ||
+ | // implementation | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | *3.) implement the JNDI EJB lookup on the client | ||
+ | <code java> | ||
+ | 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 .. | ||
+ | </code> | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ====== 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: | ||
+ | |||
+ | <code> | ||
+ | 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 | ||
+ | </code> | ||
+ | |||
+ | Knowing this name, using the EJB is straingtforward: | ||
+ | |||
+ | <code java> | ||
+ | DefaultTraveltimeService s = (DefaultTraveltimeService) new InitialContext().lookup("java:global/traveltime-service/DefaultTraveltimeService"); | ||
+ | </code> | ||
+ | |||
+ | 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: | ||
+ | |||
+ | <code java> | ||
+ | @Stateless | ||
+ | @EJB(name = "java:global/MyBean", beanInterface = MyBean.class) | ||
+ | public class MyBean | ||
+ | { | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | However comining this technique with @Remote currently breaks the JNDI page in the JBoss 7.1.1 administration console. | ||
+ | |||
+ | |||