Module CSC7321—CSN: Middleware and software architecture for Internet distributed applications

Portail informatique

JavaEE Lab 1 — Explanations on the different versions of the stateless bean example

  • Learn more on Maven: multi-module, dependencies, technology-specific plug-ins, reporting, execution of applications, etc.
  • Prepare for the software engineering aspects of the micro-project.


Documentation of maven pom.xml file

The source code of the examples is provided in Maven modules in the examples-ejb.zip archive. Extract the content of the archive. You should then have the following directories:

# e.g. content extracted from the archive EJB-Jakarta-01-hello-stateless EJB-Jakarta-01-hello-stateless-docker EJB-Jakarta-11-hello-stateless-future EJB-Jakarta-21-hello-stateful EJB-Jakarta-31-entity-bean-example EJB-Jakarta-31-entity-bean-example-docker EJB-Jakarta-32-entity-bean-example

The intructions for compiling, executing, etc. the examples are in the README.txt files.

Version in directory EJB-Jakarta-01-hello-stateless

Root/parent module

The root module is declared in the file EJB-Jakarta-01-hello-stateless/pom.xml. The role of the root module is to factor common declarations that are shared by the children modules.

As declared at the begin of the file with the XML tag "<packaging>" with the value "pom", this is a multi-module Maven module. The effect of the command mvn clean install is to install the description of the multiples modules in the local repository:

ls -1 ~/.m2/repository/org/glassfish-samples/ejb-01-hello-stateless-ejb/6.0-SNAPSHOT/ ejb-01-hello-stateless-ejb-6.0-SNAPSHOT.pom maven-metadata-local.xml _remote.repositories

The list of children modules is conventionally specified at the end of the pom.xml file with the XML tag "<modules>". The module "...ejb-bean" contains the code of the bean (server) part and the module "...ejb-client" is for the client that demonstrates the use of the server part.

The "properties" section at the beginning of the POM indicates that we use version 6.1.0 of Glassfish.

The "repositories" section of the POM declares the use of the Checkstyle tool for verifying the quality of the JAVA code. For our CSC teaching units, we propose a default configuration that is included in a module published in a Maven repository: you can visit "TSP CSC Checkstyle configuration, snapshot". For using Checkstyle in Eclipse, please refer to the related section in the page "Trucs et astuces Eclipse" (in French).

The only dependency (section "dependencies") that is common to children modules is JUnit. We use version 4.

The next block of the POM that is called "<build>" is about defining the tools and tools' versions for the construction of the children "ejb" and "jar" modules.

  • The Maven Eclipse configuration specifies that the source code and the Javadoc documentation of the dependency modules are downloaded so that you can have access to all the elements of the libraries that you use in your favorite tools (e.g. Eclipse). This is so when the authors make these artefacts publicly available in their repositories.
  • The JAVA compiler takes into account version 11 of JAVA.
  • The JUnit tests are launched using Surefire.
  • In the Maven Eclipse configuration, we have just declared that the source code and the Javadoc documentation are downloaded. Thus, we similarly build the artefacts for providing the source code and Javadoc documentation. This is the role of the source packaging and the Javadoc packaging configuration.
  • The quality of the JAVA code is systematically checked with Checkstyle when building the children modules.
  • The last plug-in configuration is for specifying the version used for building the Maven Web site of our modules with the command maven site. Have a try.

The next block of the POM, which is called "reporting", declares the plug-ins that are used to generate the Maven Web site of the modules. For instance, the Web site includes the Javadoc documentation, and two reports assessing the quality of the JAVA code using FindBugs and using Checkstyle.

Child module of the stateless bean

This content of the module is in directory ejb-01-hello-stateless-ejb-bean.

In the POM file pom.xml, let us observe that the packaging of the Maven module is "ejb" (neither "pom" nor "jar"). This is so in order to use the plug-in "maven-ejb-plugin" (to be explained below).

In addition, the added dependency indicates that the JAKARTA EE specification API is version 9.

Finally, the "build" block is for adding the JAKARTA EE specific generation of the bean archive with the plug-in "maven-ejb-plugin". The configuration specifies:

  • the name of the archive as used in the command "asadmin deploy ejb-01-hello-stateless-ejb-bean/target/stateless-bean.jar" of the README.txt file;
  • the EJB version (3.2);
  • the generation of an archive that will include the API of the bean (server) and that is going to be used by the client for calling the bean. The API is the interface HelloStateless (cf. the section "clientIncludes"). As a consequence, the maven EJB plug-in generates two archives: file target/stateless-bean.jar and file target/stateless-bean-client.jar.
    • When installed, using the group identifier + the artefact identifier + the version identifier, the two archives are
      ~/.m2/repository/org/glassfish-samples/hello-stateless-ejb/ejb-01-hello-stateless-ejb-bean/6.0-SNAPSHOT/ejb-01-hello-stateless-ejb-bean-6.0-SNAPSHOT.jar
      and
      ~/.m2/repository/org/glassfish-samples/hello-stateless-ejb/ejb-01-hello-stateless-ejb-client/6.0-SNAPSHOT/ejb-01-hello-stateless-ejb-client-6.0-SNAPSHOT.jar, respectively.

Child module of the client that demonstrates the stateless bean

This content of the module is in directory ejb-01-hello-stateless-ejb-client.

Two dependencies are added in the file pom.xml for the construction of the client:

  • The first one is for the JAKARTA EE specification API. Since it is also present the maven module of the bean (server), it could have been factored in the parent POM;
  • The second dependency is for the API archive generated by the bean module (type=ejb-client).

The new plug-in in the "build" block is for declaring the executable class that can be launched using the Maven "exec" plug-in for starting the client. This plug-in can be used (command "mvn exec:java") instead of using the java command of the README.txt file.

Limitation of this organisation

In this organisation of the stateless bean example, one needs to execute all the many asadmin commands of the scenario proposed in the README.txt file.

Version in directory EJB-Jakarta-01-hello-stateless-docker

This version is the same as EJB-Jakarta-01-hello-stateless but runs entirely in a Docker container. It shows how to create a docker image with glassfish.

Version in directory EJB-Jakarta-11-hello-stateless-future

This version shows an example of the use of the Future mechanism to postpone the delivery of the result of a method.

Each part of the application is in a separate maven module. This represents 3 modules: api (interface of the session bean), bean (implementation of the session bean) and client.

This decomposition is more technical than it may look at first.

Introducing a separate module for the API — server part

A new child module is introduced in the parent POM: ejb-11-hello-stateless-ejb-api. In the POM file of the root module, this new module is declared first in the list of sub-modules so that the server and the client parts are built after the construction of the API module.

The interface HelloStateless is moved from the source code of the bean module (ejb-11-hello-stateless-ejb-bean) to the new ejb-11-hello-stateless-ejb-api module.

Adaptation of the bean module

In the POM of the bean module (ejb-11-hello-stateless-ejb-bean/pom.xml), the first adaptation is to add a dependency upon the API module and to remove the generation of an archive that will include the API (the tag "generateClient" and the section "clientIncludes" are removed from the configuration of the Maven plug-in "maven-ejb-plugin").

Now, we present the rather tricky part, namely the packaging of the bean (server) to be deployed as self-contained archive. For explaining the necessity and the role of the plug-in "maven-dependency-plugin" with the goal "unpack", we propose that you comment all the declaration of the plug-in in the POM file of the bean module. Next, build the multiple modules by executing the command mvn clean install in the root directory of the example. Finally, execute the first commands of the README.txt file. The error message is the following one:

(asadmin start-domain domain1; asadmin deploy ejb-11-hello-stateless-ejb-bean/target/stateless-bean.jar) ... remote failure: Error occurred during deployment: Exception while deploying the app [stateless-bean] : Invalid ejb jar [stateless-bean]: it contains zero ejb. Note: 1. A valid ejb jar requires at least one session, entity (1.x/2.x style), or message-driven bean. 2. EJB3+ entity beans (@Entity) are POJOs and please package them as library jar. 3. If the jar file contains valid EJBs which are annotated with EJB component level annotations (@Stateless, @Stateful, @MessageDriven, @Singleton), please check server.log to see whether the annotations were processed properly.. Please see server.log for more details. Command deploy failed.

The EJB is not complete because the archive of the bean (server) does not contain the byte-code of the interface HelloSession. You can check this with the jar command that analyses the content of the archive:

jar tf ejb-11-hello-stateless-ejb-bean/target/stateless-bean.jar META-INF/MANIFEST.MF META-INF/ enterprise/ enterprise/hello_stateless_ejb/ META-INF/maven/ META-INF/maven/org.glassfish-samples.hello-stateless-ejb/ META-INF/maven/org.glassfish-samples.hello-stateless-ejb/ejb-11-hello-stateless-ejb-bean/ enterprise/hello_stateless_ejb/HelloStatelessBean.class META-INF/maven/org.glassfish-samples.hello-stateless-ejb/ejb-11-hello-stateless-ejb-bean/pom.xml META-INF/maven/org.glassfish-samples.hello-stateless-ejb/ejb-11-hello-stateless-ejb-bean/pom.properties

We now return to the POM of the bean module and uncomment the configuration of maven-dependency-plugin. This plug-in is used with the goal "unpack" to extract the content of the archive of the API module in the target directory structure so that the construction of the archive of the bean module contains the JAVA interface HelloStateless. The unpacking has to be done before the execution of the maven-ejb-plugin plug-in: This is specified so by assigning the phase to the value "process-classes".

What we have just learned is that the bean archives that are deployed into containers must be self-contained (when using the asadmin tools) or the context of the container must be complemented (when using the embedded server in JUnit tests). In fact, when a bean (server) depends upon external libraries provided as Maven modules, we must unpack all the dependencies as explained just before.

Client module

In the source code of the client part, the dependency is changed from a dependency with "type=ejb-client" to a regular dependency upon the new API Maven module.

 

Version in directory EJB-Jakarta-21-hello-stateful

This version implements a stateful session bean instead of a stateless one as in example EJB-Jakarta-01-hello-stateless, with 3 Maven modules for api, bean and client.

Version in directory EJB-Jakarta-31-entity-bean-example

This version implements a full application with session and entity beans. Each part of the application is in a separate maven module, as in the 2 previous examples. This represents 4 modules for api (interface of the session bean), bean (implementation of the session bean), entity (implementation of the 2 entity beans) and client.

Introducing a separate module for the API — server part

A child module for the api is declared in the parent POM: ejb-31-entity-bean-example-api. In the POM file of the root module, this module is declared first in the list of sub-modules so that the server and the client parts are built after the construction of the API module.

The interface HelloStateless is moved from the source code of the bean module (ejb-31-entity-bean-example-bean) to the new ejb-31-entity-bean-example-api module.

Adaptation of the bean module

In the POM of the bean module (ejb-31-entity-bean-example-bean/pom.xml), the first adaptation is to add a dependency upon the API module and to remove the generation of an archive that will include the API (the tag "generateClient" and the section "clientIncludes" are removed from the configuration of the Maven plug-in "maven-ejb-plugin").

Now, we present the rather tricky part, namely the packaging of the bean (server) to be deployed as self-contained archive. For explaining the necessity and the role of the plug-in "maven-dependency-plugin" with the goal "unpack", we propose that you comment all the declaration of the plug-in in the POM file of the bean module. Next, build the multiple modules by executing the command mvn clean install in the root directory of the example. Finally, execute the first commands of the README.txt file. The error message is the following one:

asadmin start-domain domain1; asadmin deploy ejb-31-entity-bean-example-bean/target/entity-bean.jar ... remote failure: Error occurred during deployment: Exception while deploying the app [entity-bean] : Invalid ejb jar [entity-bean]: it contains zero ejb. Note: 1. A valid ejb jar requires at least one session, entity (1.x/2.x style), or message-driven bean. 2. EJB3+ entity beans (@Entity) are POJOs and please package them as library jar. 3. If the jar file contains valid EJBs which are annotated with EJB component level annotations (@Stateless, @Stateful, @MessageDriven, @Singleton), please check server.log to see whether the annotations were processed properly.. Please see server.log for more details. Command deploy failed.

The EJB is not complete because the archive of the bean (server) does not contain the byte-code of the interface HelloSession. You can check this with the jar command that analyses the content of the archive:

jar tf ./ejb-31-entity-bean-example-bean/target/entity-bean.jar META-INF/MANIFEST.MF META-INF/ enterprise/ enterprise/entity_bean_ejb/ META-INF/maven/ META-INF/maven/org.glassfish-samples.entity-bean-example/ META-INF/maven/org.glassfish-samples.entity-bean-example/ejb-31-entity-bean-example-bean/ META-INF/persistence.xml enterprise/entity_bean_ejb/HelloStatelessBean.class META-INF/maven/org.glassfish-samples.entity-bean-example/ejb-31-entity-bean-example-bean/pom.xml META-INF/maven/org.glassfish-samples.entity-bean-example/ejb-31-entity-bean-example-bean/pom.properties

We now return to the POM of the bean module and uncomment the configuration of maven-dependency-plugin. This plug-in is used with the goal "unpack" to extract the content of the archive of the API module in the target directory structure so that the construction of the archive of the bean module contains the JAVA interface HelloStateless. The unpacking has to be done before the execution of the maven-ejb-plugin plug-in: This is specified so by assigning the phase to the value "process-classes".

What we have just learned is that the bean archives that are deployed into containers must be self-contained (when using the asadmin tools) or the context of the container must be complemented (when using the embedded server in JUnit tests). In fact, when a bean (server) depends upon external libraries provided as Maven modules, we must unpack all the dependencies as explained just before.

Client module

In the source code of the client part, the dependency is changed from a dependency with "type=ejb-client" to a regular dependency upon the new API Maven module.

 

This is the Maven organisation that we really do advise for your developments during the micro-project. But, since this is not the simplest one, this organisation is not mandatory. In conclusion, adapt the Maven organisation of your solution to your Maven technical skills, and keep discovering and experimenting with Maven.

Version in directory EJB-Jakarta-31-entity-bean-example-docker

This version is the same as EJB-Jakarta-31-entity-bean-example but runs entirely in a Docker container.

Version in directory EJB-Jakarta-32-entity-bean-example

This version implements a full application with session and entity beans. The only difference with EJB-Jakarta-31-entity-bean-example is the automatic generation of the IDs of the entity beans, that is delegated to the database management system. This requires to use the @GeneratedValue annotation in the implementation of each entity bean but simplifies the manipulation of these entities in the session bean.