Tel Map

Blog

EJB Remoting with Wildfly

In Java Enterprise, the EJB (Enterprise Java Bean) technology is often used to create a service layer of a J2EE application running in an application Server (like Glassfish or Wildfly). While accessing these EJB instance is relatively easy from inside the same application (using  @Inject  or  @EJB  annotations for automatic dependency injection), it is sometimes also required to call some methods on the EJBs from outside the application server.

The JavaEE standard provides the „EJB remoting“ functionality to do so. In this article I want to show how to access an EJB running in a Wildfly application server from a standalone Java application.

All code examples are also available on our Github page: https://github.com/illucIT/remote-ejb-example

Prerequisites

In this article I will use the JavaEE7 standard, with the following software versions:

Project Layout

To demonstrate the communication between the two processes, we will need two projects. One of them will be running inside the application server (I will call it ejb-remote-server from now on) and the other one will run as Java standalone application (ejb-remote-client).

Server Project

For the project ejb-remote-server you can just create a new maven project. Add the maven EJB plugin and set the project packaging to „ejb“, so it can be deployed to the application server later. For a minimal EJB example, you can import the pom „org.jboss.spec:jboss-javaee-7.0:1.0.0.Final“ in your dependency management and then add the dependency „org.jboss.spec.javax.ejb:jboss-ejb-api_3.2_spec“ as provided.

Here is an example how your pom.xml could look like:

Now for testing purposes, create a simple EJB with interface and implementation.

Important: Make sure, your EJB has a remote interface, annotated with @Remote . If you also need a local interface for it (e.g. to inject it into other beans via CDI) you should consider adding another ( @Local ) interface view for your EJB.

Remote Interface (src/main/java/com/illucit/ejbremote/server/ExampleService.java):

Implementation (src/main/java/com/illucit/ejbremote/server/ExampleServiceImpl.java):

As a next step, we need to define the module name of the deployed project. Per default the application server names the deployment after the provided JAR or WAR file.

In order to configure the module name, you can create a file „ejb-jar.xml“ in your META-INF directory to tell the application server the correct module name:

src/main/resources/META-INF/ejb-jar.xml:

Finally you should be able to build your project with  mvn clear compile package  and deploy the generated JAR file to the application server (e.g. via the management interface).

Client Project

Next we can create the client project. I will also use maven to add the dependencies required for the EJB remoting.

First of all, you have to add the classes (at least the remote interfaces and all linked classes) of your own EJB project to your client project. This can be done by a simple maven dependency with the type „ejb“.

Furthermore the maven artifacts „org.jboss.spec:jboss-javaee-7.0:1.0.0.Final“ and „org.wildfly:wildfly-ejb-client-bom:8.1.0.Final“ have to be added to the dependency management as imports, so maven knowns the artifact versions. Then you can add the required APIs for the EJB client remoting (see code below). Most of the dependencies can be added as „runtime“ depedency, as they are not required during compile time.

Your pom.xml could look like this (Note that the exec-maven-plugin is only used to run the application afterwards via maven):

In order to test the EJB client connection, first create a new class (e.g. src/main/java/com/illucit/ejbremote/EjbRemoteClient.java) with a main-Method. Then you can add the code to create a connection to your EJB and call methods on it.

Step 1: Create EJB naming context

First of all, you need a JNDI context. The context factory is provided in the maven artifact „org.jboss:jboss-remote-naming“ and will create a JNDI context that is able to resolve „ejb“ URLs into proxies to the remote application server process.

Define connection host and port according to your application server. The port is the same that you use for normal HTTP traffic.

The following function creates a JNDI context for EJB remoting.

With the parameter  Context.INITIAL_CONTEXT_FACTORY  you define the factory class. With  Context.URL_PKG_PREFIXES  you can define a package to scan for additional naming context. You need this to parse the ejb:  prefix we will use later. The parameter org.jboss.ejb.client.scoped.context = false will tell the context to read the connection parameters (like connection host and port) from the provided map instead of an additional classpath configuration file. This is especially helpful, if you want to create a JAR bundle which should be able to connect to different hosts, so you can’t hard-code it in the classpath. The parameter  Context.PROVIDER_URL  will define the connection scheme and should start with http-remoting:// .

Step 2: Get EJB URL

In order to connect to your EJB, you will need an URL you can feed into the context. The URL Wildfly recognizes is of the following format:

  •  The  ${appName}  variable is the application name of your deployment. If you used no EAR file but a simple JAR or WAR deployment (like in this example), the application name will be empty
  • ${moduleName}  is the name we set for our deployment earlier, so it is „ejb-remote-example“ (as defined in ejb-jar.xml)
  • The  ${beanName}  variable is the simple name of the implementation class of the EJB, so in our example it is „ExampleServiceImpl“
  • ${remoteView}  denotes the fully-qualified interface name of the remote interface (here it is „com.illucit.ejbremote.server.ExampleService“)

This constitutes the full EJB URL:

 

Step 3: Create EJB proxy

In order to create a proxy for your EJB, you can use the following method (using generics for the remote interface type):

The first parameter is your created JNDI context from Step 1, the ejbUrl is the one from Step 2 and the third parameter is the class of the remote interface of the EJB.

Step 4: Call EJB Methods

As a last step, you can combine your results from steps 1-3 and create an actual proxy of your EJB. The connection is not created instantly, but when you first call a method on the returned proxy the connection will be established.

Please note, that the objects transferred to your EJB as parameters (and return values) are value-types and are serialized in the process. So only send and expect values and don’t send transient objects (like open database connections, streams etc.)

 

In order to run your code, you can use the „exec-maven-plugin“ shown in the pom.xml. You only need to add the class containing your main-Method as „configuration/mainClass“ and call the maven command:

01.04.2015 |
Schlagwörter: , , , ,

6 Antworten auf „EJB Remoting with Wildfly“

  1. Rodrigo Silva

    hello, i’m new on EJB but not on JSF, JSP and others java technologies, i’m asking myself here, why the hell EJB is so complicated to generate a client? it’s useless if you need the server classes/code to do a client, because you need expose your code, so what’s the point? or EJB is deprecated and is a must-avoid technology nowadays? Thanks in advance!

    1. Christian Simon Post Autor

      Hi Rodrigo,

      Good question!
      I suppose the EJB technology is generally rather heavy-weighted as you always require an Java Application Server (or more precise, an EJB container) to run those enterprise beans, and also you call the methods on your bean reference directly. In contrast, API specifications like REST or SOAP don’t need any imports of interface classes, but instead they use other mechanics (like the WSDL format in SOAP) to specify the communication between the client and the server. A positive aspect of the EJB behaviour is that you don’t need to define any serialization by yourself, as it is completely handled by the EJB architechture (as long as your parameter types are serializable and don’t contain any transient data like open connections etc.)

      If you really need to run the EJB container on another machine or in another JVM than the EJB client, you only need the bean interfaces, not the implementation classes, however. So I would recommend that you program your client code against the interface of your EJBs, put those interfaces in another utility project, both imported by the client and the server, and then include the EJB implementation classes only in the server project.

      Additionally, I suggest that you use EJB for remote calls only in projects where you control both the server and the client side. If you need to provide a public API of your project for any third parties, I would rather facilitate a RESTful Web API instead of exposing your EJBs.

      I hope that was helpful for you!

      Best regards,
      Christian

      1. Rodrigo Silva

        I would always use as you said, JAX-WS / JAX-RS and not EJB, because is simpler! however, soon I will need work with EJB due some legacy systems in my company, that’s why I asked you. Thank you a lot for your explanation, and helpful post!

  2. abhinav

    dear sir good after noon i am new in EJB.i have installed glassfish server but when i create new connection factory in JMS resurce glassfish4 server give error class java.lang.RuntimeException or this same error i got when i create new data source so please hemp me how to fix this error

    or i have installed wildfly server 9 but i am unable to see JMS option in admin consol in browser

    can you give me one simple example of MDB in wildfly server or glassfish server

    i am using JDK1.8

    1. Christian Simon Post Autor

      Hi,
      I probably should have mentioned above that the example is for (stateless) session beans.
      In my understanding Message-Driven Beans work a bit differently, as you don’t call the methods of a proxy object directly, but rather send message objects to a message queue. So the connection with the JNDI Context will most likely stay the same, but instead of generating a proxy from the context with the „ejb:“ prefix, you need to get the message factory and the queue.

  3. Rahul

    Hi Christian, Thanks for the example, very helpful. I have a query, in above example you have added dependency of server project in child project pom.XML. Is there a ways by which I don’t have add dependency in XML file and at run time I get my server EJB reference while running child class methods.
    Thanking you in advance.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert