EJB project division

I have an EJB project, to do the system deployment the project needs to be divided into 3.

  • the database on a machine
  • the user Interface on another host
  • and the EJB (services) in another

Except that the system is all developed in ejb, the ear package is in the following form.

  • EAR
    • EJB
    • WAR

Until I understand I should leave the WAR package on one of the host, and the EJB running on another, but how do I break the project this way? We are using JBOSS EAP 6.3 on both servers, the database separation part is already done.

Author: João, 2015-06-11

1 answers

Since your doubt is general regarding the process of this physical separation of the components of your architecture, I will try to cover as much as possible.

The form I show here is not the only one that exists, it is just one that I consider organized and that I adopt with JavaEE when a distributed architecture similar to your need is used.

Well, considering that it uses maven and also its current structure, I imagine that it has three projects:

  • a project com package ejb Where Are Your Local interfaces and other things like DAO s, etc. It will undergo little change
  • a project with package war, with dependency of the package ejb;
  • a project with package ear, with dependence on the other two (package ejb e package war) and being modules of your EAR.

If this is not the scenario you are using, correct me to consider a correction in the answer.

That said, Let's go to a way to do this separation. I will put the steps and show you how you can do this separation in your project.

1. Using local and remote interfaces

The first step is to analyze your current project in search of what will be made available by remote interfaces or not. There are several ways to do this, many people usually provide a single remote interface for everyone the services. I don't particularly like it, I find it an unorganized way when you have a single remote interface, even because it loses a little the semantics of the thing.

Chances are you'll need a cool refactoring in your project so you don't have duplicate things and more importantly, don't remotely expose what you don't need to expose.

2. Project modules

For the project structure, I will consider that you have a projects, let's call it root-project. This root-project will have the following modules:

  • project4remote: this project will contain only remote interfaces, no implementation the package will be ejb and it has no dependency on other modules of your application.

An example of a remote interface is basically annotated with @Remote and you say how you want the result to be serialized, it would be like this:

import javax.ejb.Remote;

@Remote
public interface RemoteInterface { }
  • project4local: This basically your project with package ejb, changing only that it should implement the remote interfaces, the package remains as ejb and obviously has dependency on project4remote.

I imagine you already have local interfaces, but in case you don't, it's just something noted like @Local, something like this:

import javax.ejb.Local;

@Local
public interface LocalInterface { }

In its implementation can be the same implementation of the remote interface, i.e. something like this:

import javax.ejb.Stateless;

@Stateless(name = "yourServiceBean")
public class LocalRemoteImpl implements LocalInterface, RemoteInterface { }
  • project4web: this web project, of your projects will depend only on project4remote because it will need such interfaces to consume the services that are in the container.
  • project4ear: this is the project that will group what will be installed in the container JEE, so it will have dependency for the projects. An example configuration could be this:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.brunocesar</groupId>
    <version>0.0.1-SNAPSHOT</version>
    <artifactId>root-project</artifactId>
    <packaging>pom</packaging>

    <build>
        <finalName>${project.artifactId}</finalName>
        <defaultGoal>clean install</defaultGoal>
        <pluginManagement>
            <plugins>
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>2.6</version>
                    <configuration>
                        <failOnMissingWebXml>false</failOnMissingWebXml>
                    </configuration>
                </plugin>
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>2.7</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

    <modules>
        <module>project4ear</module>
        <module>project4local</module>
        <module>project4remote</module>
        <module>project4web</module>
    </modules>
</project>

3. How to do lookup of your interfaces remote?

Since you are apparently not using anything that makes this lookup for you, I will show you just how you can do it "on hand". In summary it is something like this:

final InputStream fis = SuaClasse.class.getResourceAsStream("/ejb-client.properties")

final Properties props = new Properties();
props.load(is);

final InitialContext ic = new InitialContext(props);

final SuaInterfaceRemota interface = (SuaInterfaceRemota) ic.lookup("nome:/doRecurso/PublicadoNaJNDI");
interface.seuMetodo(args);

I suggest looking at how interfaces are being published, there are always several ways to access them through JNDI. I don't remember what it's like in the case of JBoss, so take a look at the log to be able to do the lookup correctly.

For client properties, see here and also the gifts here, in case you need if any of those that were not put in the example. An example configuration would be this:

java.naming.factory.url.pkgs=org.jboss.ejb.client.naming

remote.connections=${remote.connections}
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

remote.connection.${remote.connections}.host=${remote.connection.host}
remote.connection.${remote.connections}.port=${remote.connection.port}
remote.connection.${remote.connections}.username=${remote.connection.username}
remote.connection.${remote.connections}.password=${remote.connection.password}

Where remote.connections is the identification of the connection, such as default.

Obs.. I took these parameters from a project that I have already configured, if you do not use property replacement from maven in your build, just change.

 3
Author: Bruno César, 2015-06-20 22:37:31