Java EE 7
When you deploy an EJB to the application server, it makes a record of them via JNDI - called a binding - with the following data:
java:global/[<application-name>]/<module-name>/<bean-name>!<fully-qualified-bean-interface-name>
Where:
- application-name: is the name of the application. Only necessary if an EAR has been deployed . It is deduced by:
- the name of the EAR
- the value of
<display></display>
of file application.xml
within META-INF
.
- module-name: is the name of the module to which the bean belongs (.jar, .war files) without the extension. This can be overwritten in
ejb-jar.xml
.
- bean-name: indicates the simple name of the bean.
- fully-qualified-bean-interface-name: indicates the qualified name (with everything and package) of the bean or of the interface (in case it is a remote EJB).
This structure was imposed from the EJB 3.1 specification and you can use it in Java EE 7+. Prior to this, each vendor had its own JNDI structure, not allowing fully portable applications.
There are also two more types of JNDI:
-
java:module/ejbName!fullEjbInterfaceName
: used when the remote EJB is in the same module.
-
java:app/moduleName/ejbName!fullEjbInterfaceName
: used when the remote EJB is in another module but in the same application.
Creating remote EJBs without status
To create a remote EJB it is enough to create an interface and a class that implements it and that, in addition, referenced to the interface by means of the annotation @Remote
.
public class CalculadoraRemote {
public int sumar(int n1, int n2);
public int restar(int n1, int n2);
public int multiplicar(int n1, int n2);
public double dividir(int n1, int n2);
}
@Remote(CalculadoraRemote.class);
public class CalcuadoraBean implements CalculadoraRemote {
// métodos
}
When we deploy this, the JNDI will be:
java:global/Calculadora/calculadoraejbs/CalculadoraBean!pe.mitsugami.ejb.CalculadoraRemote
Doing lookup of remote EJBs
To do a lookup
of an EJB, we will do it by means of the properties of the JNDI:
- application-name: Only necessary if an EAR has been deployed .
- module-name: the same, the name of the jar that contains the / the EJB.
- bean-name: the same
- fully-qualified-bean-interface-name: the same
Non-JavaEE Components
final Map<String, String> propiedadesJndi = new HashTable<>();
propiedadesJndi.put(Context.URL_PGK_PREFIXES, "org.jboss.client.naming");
final Context contexto = new InitialContext(propiedadesJndi);
// propiedades JNDI
String appName = ""; // o el nombre del EAR en caso hayas desplegado un EAR
String moduleName = "calcuadoraejbs";
String beanName = CalculadoraBean.class.getSimpleName();
String fullyBeanName = CalculadoraBean.class.getName();
// procedemos con la búsqueda
CalculadoraRemote calculadora = (CalculadoraRemote) contexto.lookup("java:global/"+appName+"/"+beanName+"!"+fullyBeanName);
Java EE components
For Java EE components, we can take advantage of the @EJB
annotation to inject the remote EJB dependency.
@EJB
private CalculadoraRemote calculadora;
This will work if you only have one implementation of CalculadoraRemote
, if you have more it will not work because you will have a problem of ambiguous dependencies . This is solved by means of the attribute name
of Stateless|Stateful|Singleton
:
@Stateless(name = "calculadoraCientifica")
@Remote(CalculadoraRemote.class)
public class CalculadoraCientifica implements CalculadoraRemote { }
@Stateless(name = "calculadoraSimple")
@Remote(CalculadoraRemote.class)
public class CalculadoraSimple implements CalculadoraRemote { }
And we inject:
@EJB(name = "calculadoraCientifica")
private CalculadoraRemote calculadora;
You can also inject a remote EJB by specifying the JNDI name explicitly by means of the lookup
attribute of the% @EJB
.
@EJB(lookup = "java:global/calculadoraejbs/CalculadoraBean!pe.mitsugami.ejb.CalculadoraRemote")
private CalculadoraRemote calculadora;