EJB
EJB is deployed in Jar, War, Ear format. In WAR, if the EJB is packaged in jar format, it can be placed in WEB-INF/lib. If EJB classes are to be directly packaged in WAR, they can placed in WEB-INF/classes.
I will create a minimal project here to show a client accessing a Stateless bean (basically a simplified version from quickstart) and code on Github.
1. Create the project:
For this you need a home interface/remote interface and the implementation, as explained here:
1.a Create an interface
import javax.ejb.Remote;
@Remote
public interface SumRemote
{ int add(int a, int b); }
1.b Implement this interface
import javax.ejb.Stateless;
@Stateless
public class Sum implements SumRemote
{ public int add(int a, int b){ return a+b; } }
1.c Create a client (eap 7.1:)
Get the InitialContext:
public static Context getInitialContext() throws NamingException{
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, “org.wildfly.naming.client.WildFlyInitialContextFactory”);
props.put(Context.PROVIDER_URL,”remote+http://localhost:8080“);
final Context context = new InitialContext(props);
return context;
(The port here comes from <socket-binding name=”http” port=”${jboss.http.port:8080}”/>)
And then get the remote – attention that is stateless so the JNDI will be:
The class name we know, is SumRemote, so we can add it diretly, or use the .class.getName(0;
SumRemote remote = (SumRemote) getInitialContext().lookup(“ejb:/EjbSum/Sum!” + SumRemote.class.getName());
OR
AdderImplRemote remote = (AdderImplRemote) getInitialContext().lookup(“ejb:/EjbRemote/Sum!SumRemote”);
2. Export
JBOSS_HOME/modules/system/layers/base/javax/ejb/api/main/jboss-ejb-api_3.2_spec-1.0.1.Final-redhat-1.jar
3. Compile and package:
[fdemeloj@fdemeloj Bean]$ javac Sum*
[fdemeloj@fdemeloj Bean]$ jar -cvf EjbSum.jar .
added manifest
adding: SumRemote.class(in = 194) (out= 163)(deflated 15%)
adding: Sum.class(in = 335) (out= 253)(deflated 24%)
Compile the Client
#export CLASSPATH=/home/fdemeloj/jboss-eap-7.3/bin/client/jboss-client.jar:$CLASSPATH
#javac StandaloneClient.java
4.Deploy
[fdemeloj@fdemeloj Bean]$ cp EjbSum.jar $JBOSS_HOME/standalone/deployments
This is the JNDI:
23:17:47,545 INFO [org.jboss.as.ejb3.deployment] (MSC service thread 1-1) WFLYEJB0473: JNDI bindings for session bean named ‘Sum’ in deployment unit ‘deployment “EjbSum.jar”‘ are as follows:
java:global/EjbSum/Sum!SumRemote
java:app/EjbSum/Sum!SumRemote
java:module/Sum!SumRemote
java:jboss/exported/EjbSum/Sum!SumRemote
ejb:/EjbSum/Sum!SumRemote
java:global/EjbSum/Sum
java:app/EjbSum/Sum
java:module/Sum
5. Test
# java StandaloneClient
Getting the Remote
Apr 19, 2020 2:05:10 AM org.wildfly.naming.client.Version <clinit>
INFO: WildFly Naming version 1.0.11.Final-redhat-00001
Apr 19, 2020 2:05:10 AM org.wildfly.security.Version <clinit>
INFO: ELY00001: WildFly Elytron version 1.10.4.Final-redhat-00001
Apr 19, 2020 2:05:10 AM org.xnio.Xnio <clinit>
INFO: XNIO version 3.7.7.Final-redhat-00001
Apr 19, 2020 2:05:10 AM org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.7.7.Final-redhat-00001
Apr 19, 2020 2:05:10 AM org.jboss.threads.Version <clinit>
INFO: JBoss Threads version 2.3.3.Final-redhat-00001
Apr 19, 2020 2:05:10 AM org.jboss.remoting3.EndpointImpl <clinit>
INFO: JBoss Remoting version 5.0.16.Final-redhat-00001
Apr 19, 2020 2:05:10 AM org.jboss.ejb.client.EJBClient <clinit>
INFO: JBoss EJB Client version 4.0.27.Final-redhat-00001
Got the remote InterfaceProxy for remote EJB StatelessEJBLocator for “/EjbSum/Sum”, view is interface SumRemote, affinity is None
20
The 20 is the answer.
5. Comparing Remote vs Local
When Same deploying in the same JVM use local and when using another JVM use remote:
@Local ~
Call by Reference, the overhead is minimal, since it is the same JVM so the parameters is the same, so the references are the same. As results, no overhead.
@Remote ~
Call by Value, processing overhead, since are different JVM, the location is remote, the parameters will be value. Remote method invocation: marshed parameters then.
There is a overhead, because of the marsheling. So no references, but a copy of the value.
@Local
annotated beans can only be accessed if they are in the same application.
@Remote
annotated beans can be accessed across different applications, residing in different jvms or across application servers.
As pointed here
6. JNDI Reference
ejb:<app>/<moduleName>/<distinctName>/<beanName>!<viewClassName>?stateful
<app>EAR name
<moduleName> name of EJB jar
<distinctName> Optional Name
<beanName> Bean’s class
<ViewClassName> fully qualified class name of the remote interface
7. To extract content from jar file:
jar xf jar-file [archived-file(s)]
8. Get the Environment from the context, it will return what is passed:
System.out.println(context.getEnvironment());
Returns:
{java.naming.factory.initial=org.wildfly.naming.client.WildFlyInitialContextFactory, java.naming.provider.url=remote+http://localhost:8080}
8. References:
For JBoss EAP 7.1:
About EJB
https://www.javaworld.com/article/2071724/ejb-fundamentals-and-session-beans.html
About JNDI: