java – EJB Project Division

Question:

I have an EJB project, to implement the system 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

But the system is all developed in ejb, the EAR package is in the following way.

  • EAR
    • EJB
    • WAR

As far as I understand I should leave the WAR package on one of the hosts, 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.

Answer:

As 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 way I show you here is not the only one that exists, it's just one that I consider organized and that I adopt with JavaEE when a distributed architecture similar to your needs is used.

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

  • a project with ejb package where your local interfaces and other things like DAO s, etc. are. It will undergo little change
  • a project with package war , with a dependency on package ejb ;
  • a project with package ear , with dependency on the other two ( package ejb and 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 look at a way to make this separation. I'll put the steps and show you how you can do this separation in your project.

1. Use of local and remote interfaces

The first step to be done 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 all services. I don't particularly like it, I think it's not very organized when you have a single remote interface, because it loses a little of the semantics of the thing.

Chances are, you'll need legal refactoring in your project so you don't have duplicates and more importantly, don't remotely expose what you don't need to expose.

2. Project Modules

For the project structure, I'm going to assume you have a project pooler, let's call it root-project . This root-project will have the following modules:

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

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

import javax.ejb.Remote;

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

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

import javax.ejb.Local;

@Local
public interface LocalInterface { }

In its implementation it can be the same implementation as the remote interface, that is, something like this:

import javax.ejb.Stateless;

@Stateless(name = "yourServiceBean")
public class LocalRemoteImpl implements LocalInterface, RemoteInterface { }
  • project4web : this is the web project, your projects will only depend 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 JEE container, 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 lookup your remote interfaces?

Since you apparently aren't wearing anything that does this lookup for you, I'm just going to show you how you can do it "by hand". In a nutshell it goes 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 observing how interfaces are being published, there are always several ways to access them through JNDI. I don't remember what it's like with JBoss, so take a look at the log to be able to do the lookup correctly.

For the client properties, see here and also those present here , in case you need any of the ones that were not included 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 connection ID, such as default .

Note . I got these parameters from a project I've already configured, if you don't use maven property replacement in your build, just change it.

Scroll to Top