Red Hat JBoss Enterprise Application Platform-7.0-Developing EJB Applications-en-US
Red Hat JBoss Enterprise Application Platform-7.0-Developing EJB Applications-en-US
Platform 7.0
For Use with Red Hat JBoss Enterprise Application Platform 7.0
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons
Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is
available at
http://creativecommons.org/licenses/by-sa/3.0/
. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must
provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert,
Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, JBoss, OpenShift, Fedora, the Infinity
logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other
countries.
Linux ® is the registered trademark of Linus Torvalds in the United States and other countries.
XFS ® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States
and/or other countries.
MySQL ® is a registered trademark of MySQL AB in the United States, the European Union and
other countries.
Node.js ® is an official trademark of Joyent. Red Hat Software Collections is not formally related to
or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack ® Word Mark and OpenStack logo are either registered trademarks/service marks
or trademarks/service marks of the OpenStack Foundation, in the United States and other countries
and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or
sponsored by the OpenStack Foundation, or the OpenStack community.
Abstract
This document provides information for developers and administrators who want to develop and
deploy EJB applications with JBoss EAP 7.0.
Table of Contents
Table of Contents
.CHAPTER
. . . . . . . . .1.. .INTRODUCTION
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5. . . . . . . . . .
1.1. OVERVIEW OF ENTERPRISE JAVABEANS 5
1.2. EJB 3.2 FEATURE SET 5
1.3. ENTERPRISE BEANS 6
1.3.1. Writing Enterprise Beans 6
1.4. ENTERPRISE BEAN BUSINESS INTERFACES 6
EJB Local Business Interfaces 6
EJB Remote Business Interfaces 6
EJB No-interface Beans 6
.CHAPTER
. . . . . . . . .2.. .CREATING
. . . . . . . . . .ENTERPRISE
. . . . . . . . . . . .BEAN
. . . . . PROJECTS
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7. . . . . . . . . .
2.1. CREATE AN EJB ARCHIVE PROJECT USING RED HAT JBOSS DEVELOPER STUDIO 7
Prerequisites 7
Create an EJB Project in Red Hat JBoss Developer Studio 7
2.2. CREATE AN EJB ARCHIVE PROJECT IN MAVEN 11
Prerequisites 11
Create an EJB Archive project in Maven 11
2.3. CREATE AN EAR PROJECT CONTAINING AN EJB PROJECT 12
Prerequisites 12
Create an EAR Project containing an EJB Project 12
2.4. ADD A DEPLOYMENT DESCRIPTOR TO AN EJB PROJECT 15
Prerequisites 15
Add a Deployment Descriptor to an EJB Project 15
. . . . . . . . . .3.. .SESSION
CHAPTER . . . . . . . . BEANS
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .17
...........
3.1. SESSION BEANS 17
3.2. STATELESS SESSION BEANS 17
3.3. STATEFUL SESSION BEANS 17
3.4. SINGLETON SESSION BEANS 17
3.5. ADD SESSION BEANS TO A PROJECT IN RED HAT JBOSS DEVELOPER STUDIO 17
Prerequisites 17
Add Session Beans to a Project in Red Hat JBoss Developer Studio 17
.CHAPTER
. . . . . . . . .4.. .MESSAGE-DRIVEN
. . . . . . . . . . . . . . . . .BEANS
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .20
...........
4.1. MESSAGE-DRIVEN BEANS 20
4.2. MESSAGE-DRIVEN BEANS CONTROLLED DELIVERY 20
4.2.1. Delivery Active 20
Configuring Delivery Active in the jboss-ejb3.xml File 20
Configuring Delivery Active Using Annotations 21
Configuring Delivery Active Using the Management CLI 21
View the MDB Delivery Active Status 22
4.2.2. Delivery Groups 22
Configuring Delivery Group in the jboss-ejb3.xml File 22
Configuring Delivery Group Using the Management CLI 22
4.2.3. Clustered Singleton MDBs 22
Identify an MDB as a Clustered Singleton 23
4.3. CREATE A JMS-BASED MESSAGE-DRIVEN BEAN IN RED HAT JBOSS DEVELOPER STUDIO 23
Prerequisites 23
Add a JMS-based Message-Driven Bean in Red Hat JBoss Developer Studio 24
4.4. SPECIFYING A RESOURCE ADAPTER IN JBOSS-EJB3.XML FOR AN MDB 25
4.5. ENABLE EJB AND MDB PROPERTY SUBSTITUTION IN AN APPLICATION 26
4.5.1. Configure the Server to Enable Property Substitution 26
1
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
.CHAPTER
. . . . . . . . .5.. .INVOKING
. . . . . . . . . SESSION
. . . . . . . . .BEANS
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .36
...........
5.1. INVOKE A SESSION BEAN REMOTELY USING JNDI 36
5.2. ABOUT EJB CLIENT CONTEXTS 38
5.3. CONSIDERATIONS WHEN USING A SINGLE EJB CONTEXT 39
5.4. TRANSACTION BEHAVIOR OF EJB INVOCATIONS 40
EJB Remoting Call 40
Internet Inter-ORB Protocol (IIOP) Remote Call 43
5.5. EXAMPLE EJB INVOCATION FROM A REMOTE SERVER INSTANCE 45
5.5.1. Configuring the Client Server 46
5.5.2. Adding jboss-ejb-client.xml to Client Application 48
5.5.3. Invoking the Bean 49
5.5.4. Deploying the Client Application 49
5.6. USING SCOPED EJB CLIENT CONTEXTS 49
5.6.1. Configure EJBs Using a Scoped EJB Client Context 51
Configure an EJB Using a Map-Based Scoped Context 51
5.7. EJB CLIENT PROPERTIES 52
5.8. REMOTE EJB DATA COMPRESSION 56
5.9. EJB CLIENT REMOTING INTEROPERABILITY 57
Default Connector 58
5.10. CONFIGURE IIOP FOR REMOTE EJB CALLS 58
Enabling IIOP 58
Create an EJB That Communicates Using IIOP 59
. . . . . . . . . .6.. .EJB
CHAPTER . . . .APPLICATION
. . . . . . . . . . . . SECURITY
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .62
...........
6.1. SECURITY IDENTITY 62
6.1.1. About EJB Security Identity 62
6.1.2. Set the Security Identity of an EJB 62
6.2. EJB METHOD PERMISSIONS 63
6.2.1. About EJB Method Permissions 63
6.2.2. Use EJB Method Permissions 63
6.3. EJB SECURITY ANNOTATIONS 66
6.3.1. About EJB Security Annotations 66
6.3.2. Use EJB Security Annotations 66
6.4. REMOTE ACCESS TO EJBS 67
6.4.1. Use Security Realms with Remote EJB Clients 67
6.4.2. Add a New Security Realm 68
6.4.3. Add a User to a Security Realm 69
6.4.4. Relationship Between Security Domains and Security Realms 69
6.4.5. About Remote EJB Access Using SSL Encryption 69
. . . . . . . . . .7.. .CONTAINER
CHAPTER . . . . . . . . . . .AND
. . . . CLIENT
. . . . . . . INTERCEPTORS
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .71
...........
7.1. ABOUT CONTAINER INTERCEPTORS 71
Positioning of the Container Interceptor in the Interceptor Chain 71
Differences Between the Container Interceptor and the Java EE Interceptor API 71
7.2. CREATE A CONTAINER INTERCEPTOR CLASS 71
2
Table of Contents
. . . . . . . . . .8.. .CLUSTERED
CHAPTER . . . . . . . . . . . ENTERPRISE
. . . . . . . . . . . . JAVABEANS
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .79
...........
8.1. ABOUT CLUSTERED ENTERPRISE JAVABEANS (EJBS) 79
8.2. DEPLOYING CLUSTERED EJBS 79
8.3. FAILOVER FOR CLUSTERED EJBS 80
8.4. REMOTE STANDALONE CLIENTS 80
8.5. CLUSTER TOPOLOGY COMMUNICATION 80
8.6. REMOTE CLIENTS ON ANOTHER INSTANCE 81
8.7. STANDALONE AND IN-SERVER CLIENT CONFIGURATION 81
8.8. IMPLEMENTING A CUSTOM LOAD BALANCING POLICY FOR EJB CALLS 83
Configuring the jboss-ejb-client.properties File 85
Using EJB Client API 86
Configuring the jboss-ejb-client.xml File 86
.APPENDIX
. . . . . . . . . A.
. . .REFERENCE
. . . . . . . . . . . MATERIAL
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .88
...........
A.1. EJB JNDI NAMING REFERENCE 88
A.2. EJB REFERENCE RESOLUTION 88
A.3. PROJECT DEPENDENCIES FOR REMOTE EJB CLIENTS 89
A.4. JBOSS-EJB3.XML DEPLOYMENT DESCRIPTOR REFERENCE 90
A.5. CONFIGURE AN EJB THREAD POOL 92
Configure an EJB Thread Pool Using the Management Console 93
Configure an EJB Thread Pool Using the Management CLI 93
3
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
4
CHAPTER 1. INTRODUCTION
CHAPTER 1. INTRODUCTION
EJB 3.2 provides two profiles: full and lite. JBoss EAP 7 implements the full profile for applications built
using the EJB 3.2 specifications.
Session beans
Message-driven beans
No-interface views
Local interfaces
Remote interfaces
AutoClosable interface
Timer service
Asynchronous calls
Interceptors
RMI/IIOP interoperability
Transaction support
Security
Embeddable API
5
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
An enterprise bean can also define any number of business interfaces. Business interfaces provide
greater control over which of the bean’s methods are available to clients and can also allow access to
clients running in remote JVMs.
There are three types of Enterprise beans: Session beans, Message-driven beans and Entity beans.
NOTE
Business interfaces can be declared as local or remote interfaces, but not both.
A remote client is any client running in a different JVM and can include desktop applications as well as
web applications, services and enterprise beans deployed to a different application server.
Local clients can access the methods exposed by a remote business interface.
A session bean that implements a business interface can also be written to expose a no-interface view.
6
CHAPTER 2. CREATING ENTERPRISE BEAN PROJECTS
Prerequisites
A server and server runtime for JBoss EAP has been configured in JBoss Developer Studio.
b. When the New Project wizard appears, select EJB/EJB Project and click Next.
7
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
Project name: The name of the project that appears in Red Hat JBoss Developer Studio,
and also the default filename for the deployed JAR file.
Project location: The directory where the project files will be saved. The default is a
directory in the current workspace.
Target Runtime: This is the server runtime used for the project. This will need to be set to
the same JBoss EAP runtime used by the server that you will be deploying to.
EJB module version: This is the version of the EJB specification that your enterprise beans
will comply with. Red Hat recommends using 3.2.
8
CHAPTER 2. CREATING ENTERPRISE BEAN PROJECTS
Configuration: This allows you to adjust the supported features in your project. Use the
default configuration for your selected runtime.
Click Next to continue.
3. The Java project configuration screen allows you to add directories containing Java source files
and specify the directory for the output of the build.
Leave this configuration unchanged and click Next.
4. In the EJB Module settings screen, check Generate ejb-jar.xml deployment descriptor if a
deployment descriptor is required. The deployment descriptor is optional in EJB 3.2 and can be
added later if required.
Click Finish and the project is created and will be displayed in the Project Explorer.
5. To add the project to the server for deployment, right-click on the target server in the Server tab
and choose Add and Remove.
9
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
In the Add and Remove dialog, select the resource to deploy from the Available column and
click the Add button. The resource will be moved to the Configured column. Click Finish to
close the dialog.
You now have an EJB Project in Red Hat JBoss Developer Studio that can build and deploy to the
specified server.
10
CHAPTER 2. CREATING ENTERPRISE BEAN PROJECTS
WARNING
If no enterprise beans are added to the project then Red Hat JBoss Developer
Studio will display the warning stating An EJB module must contain one or more
enterprise beans. This warning will disappear once one or more enterprise beans
have been added to the project.
Prerequisites
1. Create the Maven project: An EJB project can be created using Maven’s archetype system and
the ejb-javaee7 archetype. To do this run the mvn command with parameters as shown:
mvn archetype:generate -
DarchetypeGroupId=org.codehaus.mojo.archetypes -
DarchetypeArtifactId=ejb-javaee7
Maven will prompt you for the groupId, artifactId, version and package for your project.
11
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
2. Add your enterprise beans: Write your enterprise beans and add them to the project under the
src/main/java directory in the appropriate sub-directory for the bean’s package.
3. Build the project: To build the project, run the mvn package command in the same directory
as the pom.xml file. This will compile the Java classes and package the JAR file. The built JAR
file is named -.jar and is placed in the target/ directory.
You now have a Maven project that builds and packages a JAR file. This project can contain enterprise
beans and the JAR file can be deployed to an application server.
Prerequisites
A server and server runtime for JBoss EAP have been set up.
b. When the New Project wizard appears, select Java EE/Enterprise Application Project
and click Next.
12
CHAPTER 2. CREATING ENTERPRISE BEAN PROJECTS
Project name: The name of the project that appears in Red Hat JBoss Developer Studio,
and also the default filename for the deployed EAR file.
Project location: The directory where the project files will be saved. The default is a
directory in the current workspace.
Target Runtime: This is the server runtime used for the project. This will need to be set to
the same JBoss EAP runtime used by the server that you will be deploying to.
EAR version: This is the version of the Java Enterprise Edition specification that your
project will comply with. Red Hat recommends using Java EE 7.
13
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
Configuration: This allows you to adjust the supported features in your project. Use the
default configuration for your selected runtime.
Click Next to continue.
3. Add a new EJB Module: New modules can be added from the Enterprise Application page of
the wizard. To add a new EJB Project as a module follow the steps below:
a. Add new EJB Module: Click New Module, uncheck Create Default Modules checkbox,
select the Enterprise Java Bean and click Next. The New EJB Project wizard appears.
b. Create EJB Project: New EJB Project wizard is the same as the wizard used to create new
standalone EJB Projects and is described in Create an EJB Archive Project Using Red Hat
JBoss Developer Studio.
The minimal details required to create the project are:
Project name
Target Runtime
Configuration
All the other steps of the wizard are optional. Click Finish to complete creating the EJB
Project.
The newly created EJB project is listed in the Java EE module dependencies and the
checkbox is checked.
5. Click Finish: Two new projects will appear: the EJB project and the EAR project.
6. Add Build Artifact to Server for Deployment: Open the Add and Remove dialog by right-
clicking in the Servers tab on the server you want to deploy the built artifact to in the server tab
and then select Add and Remove.
Select the EAR resource to deploy from the Available column and click the Add button. The
resource will be moved to the Configured column. Click Finish to close the dialog.
14
CHAPTER 2. CREATING ENTERPRISE BEAN PROJECTS
You now have an Enterprise Application Project with a member EJB Project. This will build and deploy to
the specified server as a single EAR deployment containing an EJB subdeployment.
Prerequisites
You have a EJB Project in Red Hat JBoss Developer Studio to which you want to add an EJB
deployment descriptor.
15
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
1. Open the Project: Open the project in Red Hat JBoss Developer Studio.
2. Add Deployment Descriptor: Right-click on the Deployment Descriptor folder in the project
view and select Generate Deployment Descriptor tab.
16
CHAPTER 3. SESSION BEANS
Singleton beans provide the smallest memory footprint of all the session bean types but must be
designed as thread-safe. EJB 3.2 provides container-managed concurrency (CMC) to allow developers
to implement thread safe singleton beans easily. However singleton beans can also be written using
traditional multi-threaded code (bean-managed concurrency or BMC) if CMC does not provide enough
flexibility.
Prerequisites
You have a EJB or Dynamic Web Project in Red Hat JBoss Developer Studio to which you want
to add one or more session beans.
1. Open the Project: Open the project in Red Hat JBoss Developer Studio.
17
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
2. Open the Create EJB 3.x Session Bean wizard: To open the Create EJB 3.x Session Bean
wizard, navigate to the File menu, select New and then select Session Bean (EJB 3.x).
Source folder: This is the folder that the Java source files will be created in. This should not
usually need to be changed.
Class name: Specify the name of the class that will be the session bean.
Superclass: The session bean class can inherit from a superclass. Specify that here if your
session has a superclass.
State type: Specify the state type of the session bean: stateless, stateful or singleton.
18
CHAPTER 3. SESSION BEANS
Click Next.
4. Session Bean Specific Information: You can enter in additional information here to further
customize the session bean. It is not required to change any of the information here.
Items that you can change are:
Bean name
Mapped name
You can also specify EJB 2.x Home and Component interfaces if required
5. Finish: Click Finish and the new session bean will be created and added to the project. The files
for any new business interfaces will also be created if they were specified.
Figure 3.2. New Session Bean in Red Hat JBoss Developer Studio
19
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
With an MDB, Java EE applications process messages asynchronously. An MDB functions as a JMS or
JCA message listener. The messages can be sent by a Java EE component, for example an application
client, or another enterprise bean, or by a non-Java EE application.
Delivery Active
Delivery Groups
You can configure the active attribute of the delivery-group using XML or annotations, and you
can change its value after deployment using the management CLI. By default, the active attribute is
activated and delivery of messages occurs as soon as the MDB is deployed.
20
CHAPTER 4. MESSAGE-DRIVEN BEANS
</d:delivery>
</assembly-descriptor>
</jboss:ejb-jar>
If you want to apply the active value to all MDBs in your application, you can use a wildcard * in place of
the ejb-name.
If you use Maven to build your project, make sure you add the following dependency to the pom.xml file
of your project:
<dependency>
<groupId>org.jboss.ejb3</groupId>
<artifactId>jboss-ejb3-ext-api</artifactId>
<version>2.2.0.Final</version>
</dependency>
cd deployment=jboss-helloworld-mdb.war/subsystem=ejb3/message-
driven-bean=HelloWorldQueueMDB
:stop-delivery
:start-delivery
21
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
1. Choose Deployments and select the deployed MDB application. Click on View.
Result
You see the status as Delivery active: true or Delivery active: false.
You can add a delivery group to the ejb3 subsystem using either the XML configuration or the
management CLI.
<delivery>
<ejb-name>MdbName<ejb-name>
<delivery-group>passive</delivery-group>
</delivery>
On the server side, delivery-groups can be enabled by having their active attribute set to true, or
disabled by having their active attribute set to false, as shown in the example below:
<delivery-groups>
<delivery-group name="group" active="true"/>
</delivery-groups>
./subsystem=ejb3/mdb-delivery-group=group:add
./subsystem=ejb3/mdb-delivery-group=group:remove
./subsystem=ejb3/mdb-delivery-group=group:write-
attribute(name=active,value=true)
When you set the delivery active in the jboss-ejb3.xml file or using the annotation, it persists on
server restart. However, when you use the management CLI to stop or start the delivery, it does not
persist on server restart.
22
CHAPTER 4. MESSAGE-DRIVEN BEANS
IMPORTANT
This feature is provided as Technology Preview only. It is not supported for use in a
production environment, and it may be subject to significant future changes. See
Technology Preview Features Support Scope on the Red Hat Customer Portal for
information about the support scope for Technology Preview features.
When an MDB is identified as a clustered singleton and is deployed in a cluster, only one node is active.
This node can consume messages serially. When the server node fails, the active node from the
clustered singleton MDBs starts consuming the messages.
<jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="urn:clustering:1.1"
xmlns:d="urn:delivery:1.1"
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee
http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
version="3.1"
impl-version="2.0">
<c:clustering>
<ejb-name>HelloWorldQueueMDB</ejb-name>
<c:clustered-singleton>true</c:clustered-singleton>
</c:clustering>
</jboss:ejb-jar>
NOTE
You have to activate the delivery-group in the entire cluster, specifically, in all nodes
of the cluster, because you do not know which node of the cluster is chosen to be the
singleton master. If the server chooses a node to be singleton master, and that
node does not have the required delivery-group activated, no node in the cluster
receives the messages.
Prerequisites
You must have an existing project open in Red Hat JBoss Developer Studio.
23
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
You must know the name and type of the JMS destination that the bean will be listening to.
Support for Java Messaging Service (JMS) must be enabled in the JBoss EAP configuration to
which this bean will be deployed.
1. Open the Create EJB 3.x Message-Driven Bean Wizard: Go to File → New → Other. Select
EJB/Message-Driven Bean (EJB 3.x) and click the Next button.
2. Specify class file destination details: There are three sets of details to specify for the bean
class here: Project, Java class, and message destination.
Project:
If multiple projects exist in the Workspace, ensure that the correct one is selected in the
Project menu.
The folder where the source file for the new bean will be created is ejbModule under
the selected project’s directory. Only change this if you have a specific requirement.
Java Class:
24
CHAPTER 4. MESSAGE-DRIVEN BEANS
It is not necessary to supply a Superclass unless the business logic of your application
requires it.
Message Destination:
These are the details you must supply for a JMS-based Message-Driven Bean:
Destination name, which is the queue or topic name that contains the messages
that the bean will respond to.
3. Enter Message-Driven Bean specific information: The default values here are suitable for a
JMS-based Message-Driven bean using Container-managed transactions.
Change the Transaction type to Bean if the Bean will use Bean-managed transactions.
Change the Bean name if a different bean name than the class name is required.
The JMS Message Listener interface will already be listed. You do not need to add or
remove any interfaces unless they are specific to your application’s business logic.
Result
The Message-Driven Bean is created with stub methods for the default constructor and the
onMessage() method. A Red Hat JBoss Developer Studio editor window opens with the corresponding
file.
To specify a resource adapter in jboss-ejb3.xml for an MDB, use the following example.
<jboss xmlns="http://www.jboss.com/xml/ns/javaee"
xmlns:jee="http://java.sun.com/xml/ns/javaee"
xmlns:mdb="urn:resource-adapter-binding">
<jee:assembly-descriptor>
<mdb:resource-adapter-binding>
<jee:ejb-name>MyMDB</jee:ejb-name>
<mdb:resource-adapter-name>MyResourceAdapter.rar</mdb:resource-
adapter-name>
</mdb:resource-adapter-binding>
</jee:assembly-descriptor>
</jboss>
25
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
For a resource adapter located in an EAR, you must use the following syntax for <mdb:resource-
adapter-name>:
<mdb:resource-adapter-
name>OtherDeployment.ear#MyResourceAdapter.rar</mdb:resource-
adapter-name>
For a resource adapter that is in the same EAR as the MDB, you can omit the EAR name:
<mdb:resource-adapter-name>#MyResourceAdapter.rar</mdb:resource-
adapter-name>
You must enable property substitution in the JBoss EAP server configuration file.
You must define the system properties in the server configuration file or pass them as
arguments when you start the JBoss EAP server.
You must modify the application code to use the substitution variables.
The following examples demonstrate how to modify the helloworld-mdb quickstart that ships with
JBoss EAP to use property substitution. See the helloworld-mdb-propertysubstitution
quickstart for the completed working example.
2. Navigate to the JBoss EAP install directory and start the server with the full profile.
$ EAP_HOME/bin/standalone.sh -c standalone-full.xml
NOTE
26
CHAPTER 4. MESSAGE-DRIVEN BEANS
$ EAP_HOME/bin/jboss-cli.sh --connect
NOTE
/subsystem=ee:write-attribute(name=annotation-property-
replacement,value=true)
5. Review the changes to the JBoss EAP server configuration file. The ee subsystem should now
contain the following XML.
<subsystem xmlns="urn:jboss:domain:ee:4.0">
...
<annotation-property-replacement>true</annotation-property-
replacement>
...
</subsystem>
2. Use the following command syntax to configure a system property in the JBoss EAP server.
/system-property=PROPERTY_NAME:add(value=PROPERTY_VALUE)
/system-
property=property.helloworldmdb.queue:add(value=java:/queue/HELLOWOR
LDMDBPropQueue)
27
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
/system-
property=property.helloworldmdb.topic:add(value=java:/topic/HELLOWOR
LDMDBPropTopic)
/system-
property=property.connection.factory:add(value=java:/ConnectionFacto
ry)
3. Review the changes to the JBoss EAP server configuration file. The following system properties
should now appear in the after the <extensions>.
<system-properties>
<property name="property.helloworldmdb.queue"
value="java:/queue/HELLOWORLDMDBPropQueue"/>
<property name="property.helloworldmdb.topic"
value="java:/topic/HELLOWORLDMDBPropTopic"/>
<property name="property.connection.factory"
value="java:/ConnectionFactory"/>
</system-properties>
If you prefer, you can instead pass the arguments on the command line when you start the JBoss EAP
server in the form of -DPROPERTY_NAME=PROPERTY_VALUE. The following is an example of how to
pass the arguments for the system properties defined in the previous section.
EAP_HOME/bin/standalone.sh -c standalone-full.xml -
Dproperty.helloworldmdb.queue=java:/queue/HELLOWORLDMDBPropQueue -
Dproperty.helloworldmdb.topic=java:/topic/HELLOWORLDMDBPropTopic -
Dproperty.connection.factory=java:/ConnectionFactory
4.5.3. Modify the Application Code to Use the System Property Substitutions
Replace the hard-coded @ActivationConfigProperty and @Resource annotation values with
substitutions for the newly defined system properties. The following are examples of how to change the
helloworld-mdb quickstart to use the newly defined system property substitutions.
28
CHAPTER 4. MESSAGE-DRIVEN BEANS
/**
* Definition of the two JMS destinations used by the quickstart
* (one queue and one topic).
*/
@JMSDestinationDefinitions(
value = {
@JMSDestinationDefinition(
name = "java:/${property.helloworldmdb.queue}",
interfaceName = "javax.jms.Queue",
destinationName = "HelloWorldMDBQueue"
),
@JMSDestinationDefinition(
name = "java:/${property.helloworldmdb.topic}",
interfaceName = "javax.jms.Topic",
destinationName = "HelloWorldMDBTopic"
)
})
/**
* <p>
* A simple servlet 3 as client that sends several messages to a
queue or a topic.
* </p>
*
* <p>
* The servlet is registered and mapped to
/HelloWorldMDBServletClient using the {@linkplain WebServlet
* @HttpServlet}.
* </p>
*
* @author Serge Pagop ([email protected])
*
*/
@WebServlet("/HelloWorldMDBServletClient")
public class HelloWorldMDBServletClient extends HttpServlet {
29
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
8314035702649252239L;
@Inject
private JMSContext context;
@Resource(lookup = "${property.helloworldmdb.queue}")
private Queue queue;
@Resource(lookup = "${property.helloworldmdb.topic}")
private Topic topic;
4. Modify the activemq-jms.xml file to use the system property substitution values.
5. Deploy the application. The application now uses the values specified by the system properties
for the @Resource and @ActivationConfigProperty property values.
@Target(value={})
@Retention(value=RUNTIME)
public @interface ActivationConfigProperty
{
String propertyName();
String propertyValue();
}
30
CHAPTER 4. MESSAGE-DRIVEN BEANS
@MessageDriven(name="MyMDBName",
activationConfig =
{
@ActivationConfigProperty(propertyName="destinationLookup",propertyValue="
queueA"),
@ActivationConfigProperty(propertyName =
"destinationType",propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "acknowledgeMode",
propertyValue = "Auto-acknowledge"),
})
Example ejb-jar.xml
31
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
<activation-config-property-value>Auto-
acknowledge</activation-config-property-value>
</activation-config-property>
</activation-config>
</message-driven>
<enterprise-beans>
</jboss:ejb-jar>
Name Description
destinationLookup The JNDI name of the queue or topic. This is a mandatory value.
acknowledgeMode The type of acknowledgement when not using transacted JMS. Valid values
are Auto-acknowledge or Dups-ok-acknowledge. This is not a
mandatory value.
subscriptionDurabili Whether topic subscriptions are durable. Valid values are Durable or
ty NonDurable. This is not a mandatory value.
subscriptionName The subscription name of the topic subscription. This is not a mandatory
value.
32
CHAPTER 4. MESSAGE-DRIVEN BEANS
Name Description
destination Using this property with useJNDI=true has the same meaning as
destinationLookup. Using it with useJNDI=false , the destination
is not looked up, but it is instantiated. You can use this property instead of
destinationLookup. This is not a mandatory value.
user The user for the JMS connection. This is not a mandatory value.
password The password for the JMS connection. This is not a mandatory value.
transactionTimeout The transaction timeout for the session in milliseconds. This is not a
mandatory value.
jndiParams The JNDI parameters to use in the connection. Parameters are defined as
name=value pairs separated by ;
setupAttempts Number of attempts to set up a JMS connection. It is possible that the MDB
is deployed before the JMS resources are available. In that case, the
resource adapter will try to set up several times until the resources are
available. This applies only to inbound connections.
33
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
Name Description
package org.jboss.as.quickstarts.mdb;
import javax.annotation.Resource;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.inject.Inject;
import javax.jms.JMSContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Queue;
@Inject
private JMSContext jmsContext;
@Resource(lookup = "java:/queue/ResponseDefault")
private Queue defaultDestination;
/**
* @see MessageListener#onMessage(Message)
*/
public void onMessage(Message rcvMessage) {
try {
Message response =
jmsContext.createTextMessage("Response for message " +
rcvMessage.getJMSMessageID());
if (rcvMessage.getJMSReplyTo() != null) {
jmsContext.createProducer().send(rcvMessage.getJMSReplyTo(),
34
CHAPTER 4. MESSAGE-DRIVEN BEANS
response);
} else {
jmsContext.createProducer().send(defaultDestination, response);
}
} catch (JMSException e) {
throw new RuntimeException(e);
}
}
}
In the example above, after the MDB receives the message, it replies to either the destination
specified in JMSReplyTo or the destination which is bound to the JNDI name
java:/queue/ResponseDefault.
@MessageDriven(name="MyMDBName",
activationConfig =
{
@ActivationConfigProperty(propertyName =
"destinationType",propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName =
"destinationLookup", propertyValue = "queueA"),
@ActivationConfigProperty(propertyName =
"rebalanceConnections", propertyValue = "true")
}
)
35
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
The ejb-remote quickstart contains working Maven projects that demonstrate this functionality. The
quickstart contains projects for both the session beans to deploy and the remote client. The code
samples below are taken from the remote client project.
This task assumes that the session beans do not require authentication.
WARNING
Red Hat recommends that SSLv2, SSLv3, and TLSv1.0 be explicitly disabled in
favor of TLSv1.1 or TLSv1.2 in all affected packages.
Prerequisites
Configuration for the JBoss EAP Maven repository has already been added.
The session beans that you want to invoke are already deployed.
The remote business interfaces of the session beans are available as a Maven dependency. If
the remote business interfaces are only available as a JAR file then it is recommended to add
the JAR to your Maven repository as an artifact. See the Maven documentation for the
install:install-file goal for directions, http://maven.apache.org/plugins/maven-install-
plugin/usage.html
You need to know the host name and JNDI port of the server hosting the session beans.
To invoke a session bean from a remote client you must first configure the project correctly.
36
CHAPTER 5. INVOKING SESSION BEANS
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLE
D=false
remote.connections=default
remote.connection.default.host=localhost
remote.connection.default.port = 8080
remote.connection.default.connect.options.org.xnio.Options.SASL_POLI
CY_NOANONYMOUS=false
#remote.connection.default.connect.options.org.xnio.Options.SSL_STAR
TTLS=true
Change the host name and port to match your server. The default port number is 8080. For a
secure connection, set the SSL_ENABLED line to true and uncomment the SSL_STARTTLS line.
The Remoting interface in the container supports secured and unsecured connections using the
same port.
<dependency>
<groupId>org.jboss.quickstarts.eap</groupId>
<artifactId>jboss-ejb-remote-server-side</artifactId>
<type>ejb-client</type>
<version>${project.version}</version>
</dependency>
After the project is configured correctly, you can add the code to access and invoke the session
beans.
Obtain a Bean Proxy using JNDI and Invoke Methods of the Bean
The connection properties for the JNDI service are read from the jboss-ejb-
client.properties file.
37
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
Invoke the lookup() method of the bean proxy and pass it the JNDI name of the session bean
you require. This will return an object that must be cast to the type of the remote business
interface that contains the methods you want to invoke.
Session bean JNDI names are defined using a special syntax. For more information, see EJB
JNDI Naming Reference.
4. Invoke methods: Now that you have a proxy bean object you can invoke any of the methods
contained in the remote business interface.
int a = 204;
int b = 340;
System.out.println("Adding " + a + " and " + b + " via the remote
stateless calculator deployed on the server");
int sum = statelessRemoteCalculator.add(a, b);
System.out.println("Remote calculator returned sum = " + sum);
The proxy bean passes the method invocation request to the session bean on the server, where
it is executed. The result is returned to the proxy bean which then returns it to the caller. The
communication between the proxy bean and the remote session bean is transparent to the caller.
You should now be able to configure a Maven project to support invoking session beans on a remote
server and write the code invoke the session beans' methods using a proxy bean retrieved from the
server using JNDI.
Depending on the type of remote client, from an EJB client API point of view, there can potentially be
more than one EJBClientContext within a JVM.
While standalone applications typically have a single EJBClientContext that may be backed by any
number of EJB receivers, this isn’t mandatory. If a standalone application has more than one
EJBClientContext, an EJB client context selector is responsible for returning the appropriate context.
In case of remote clients that run within another JBoss EAP instance, each deployed application will
have a corresponding EJB client context. Whenever that application invokes another EJB, the
38
CHAPTER 5. INVOKING SESSION BEANS
corresponding EJB client context is used to find the correct EJB receiver, which then handles the
invocation.
Typical Process for a Remote Standalone Client with a Single EJB Client Context
A remote standalone client typically has just one EJB client context backed by any number of EJB
receivers. The following is an example of a standalone remote client application:
Remote client JNDI lookups are usually backed by a jboss-ejb-client.properties file, which is
used to set up the EJB client context and the EJB receivers. This configuration also includes the security
credentials, which are then used to create the EJB receiver that connects to the JBoss EAP server.
When the above code is invoked, the EJB client API looks for the EJB client context, which is then used
to select the EJB receiver that will receive and process the EJB invocation request. In this case, there is
just the single EJB client context, so that context is used by the above code to invoke the bean. The
procedure to invoke a session bean remotely using JNDI is described in greater detail here: Invoke a
Session Bean Remotely using JNDI.
39
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
javax.naming.InitialContext();
final MyBeanInterface beanTwo =
ctxTwo.lookup("ejb:app/module/distinct/bean!interface");
beanTwo.doSomething();
...
}
}
In this case, the application wants to connect to the same server instance to invoke the EJB hosted on
that server, but wants to use two different credentials while connecting to the server. Because the client
application has a single EJB client context, which can have only one EJB receiver for each server
instance, this means the above code uses just one credential to connect to the server and the code does
not execute as the application expects it to.
Solution
Scoped EJB client contexts offer a solution to this issue. They provide a way to have more control over
the EJB client contexts and their associated JNDI contexts, which are typically used for EJB invocations.
For more information about scoped EJB client contexts, refer to Using Scoped EJB Client Contexts and
Configure EJBs Using a Scoped EJB Client Context.
NOTE
JBoss EAP does not require Java Transaction Services (JTS) for transaction propagation
on server-to-server EJB invocations if both servers are JBoss EAP. JBoss EJB client API
library handles it itself.
The following code example shows an EJB client that holds a reference to the InitialContext object.
This code example was taken from the ejb-multi-server quickstart that ships with JBoss EAP.
package org.jboss.as.quickstarts.ejb.multi.server;
40
CHAPTER 5. INVOKING SESSION BEANS
import java.util.Date;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.jboss.as.quickstarts.ejb.multi.server.app.MainApp;
import org.jboss.ejb.client.ContextSelector;
import org.jboss.ejb.client.EJBClientConfiguration;
import org.jboss.ejb.client.EJBClientContext;
import org.jboss.ejb.client.PropertiesBasedEJBClientConfiguration;
import org.jboss.ejb.client.remoting.ConfigBasedEJBClientContextSelector;
/**
* @param args no args needed
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// suppress output of client messages
Logger.getLogger("org.jboss").setLevel(Level.OFF);
Logger.getLogger("org.xnio").setLevel(Level.OFF);
p.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABL
ED", "false");
p.put("remote.connections", "one");
p.put("remote.connection.one.port", "8080");
p.put("remote.connection.one.host", "localhost");
p.put("remote.connection.one.username", "quickuser");
p.put("remote.connection.one.password", "quick-123");
EJBClientConfiguration cc = new
PropertiesBasedEJBClientConfiguration(p);
ContextSelector<EJBClientContext> selector = new
ConfigBasedEJBClientContextSelector(cc);
EJBClientContext.setSelector(selector);
41
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
NOTE
import org.jboss.ejb.client.EJBClient;
import javax.transaction.UserTransaction;
...
Context context = null;
UserTransaction tx = null;
try {
Properties props = new Properties();
// REMEMBER: there must be a jboss-ejb-client.properties with the
// connection parameter in the client's classpath
props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
context = new InitialContext(props);
System.out.println("\n\tGot initial Context: "+context);
tx = EJBClient.getUserTransaction("yourServerName");
System.out.println("UserTransaction = "+tx.getStatus());
tx.begin();
// do some work
...
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally{
if(context != null) {
context.close();
}
}
42
CHAPTER 5. INVOKING SESSION BEANS
NOTE
To get UserTransaction reference on the client side; start your server with the
following system property -Djboss.node.name=yourServerName and then use it on
client side as following:
tx = EJBClient.getUserTransaction("yourServerName");
Replace "yourServerName" with the name of your server. If a user transaction is started
on a node all invocations are sticky on the node and the node must have all the needed
EJBs. It is not possible to use UserTransaction with remote-naming protocol and
scoped-context.
To enable IIOP you must have the iiop-openjdk subsystem installed and the <iiop/> element
present in the ejb3 subsystem configuration. The standalone-full.xml configuration that comes
with the distribution has both of these enabled.
For a bean to be reachable by IIOP remote call, it needs to use EJB 2 and home interface with
narrowing. More details on IIOP remote invocation can be seen at Configure IIOP for Remote EJB Calls.
NOTE
The major differences between IIOP remote call and EJB remoting call are:
When a client intends to invoke an EJB bean via IIOP remote call to start
transaction on client side, the JTS transaction implementation has to be used. On
the other hand, if a client intends to invoke an EJB bean via EJB remoting call,
the JTA transaction implementation has to be used.
For EJB invocation via IIOP remote call, the transaction is created on client and
propagated via call to the server. Whereas, for EJB invocation via EJB remoting
call, the transaction is looked up on the server and is managed on the client side.
To enable JTS transactions on the server, you must change the transactions attribute from value
spec to full in the iiop-openjdk subsystem and set the jts attribute in the transactions
subsystem to true. You can accomplish this by using the following management CLI commands.
/subsystem=iiop-openjdk/:write-attribute(name=transactions,value=full)
/subsystem=transactions/:write-attribute(name=jts,value=true)
IMPORTANT
For the client to successfully invoke an EJB transaction using an IIOP call, we need to add
the client-side dependency on org.wildfly:wildfly-iiop-openjdk.
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
43
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
import javax.rmi.PortableRemoteObject;
import com.arjuna.ats.arjuna.recovery.RecoveryManager;
import com.arjuna.ats.internal.jts.ORBManager;
import com.arjuna.ats.internal.jts.context.ContextPropagationManager;
import com.arjuna.ats.jts.OTSManager;
import com.sun.corba.se.impl.orbutil.ORBConstants;
import com.arjuna.orbportability.ORB;
import com.arjuna.orbportability.OA;
// Set orb to be initialized on client and being able to start ORB txn
Properties properties = new Properties();
properties.setProperty(ORBConstants.PERSISTENT_SERVER_PORT_PROPERTY,
"15151");
properties.setProperty(ORBConstants.ORB_SERVER_ID_PROPERTY, "1");
OA oa = OA.getRootOA(orb);
org.omg.PortableServer.POA rootPOA =
org.omg.PortableServer.POAHelper.narrow(sunOrb.resolve_initial_references(
"RootPOA"));
oa.setPOA(rootPOA);
oa.initOA();
ORBManager.setORB(orb);
ORBManager.setPOA(oa);
44
CHAPTER 5. INVOKING SESSION BEANS
// Bean lookup
final Object iiopObj =
context.lookup(IIOPBeanMandatory.class.getSimpleName());
final IIOPBeanHome beanHome = (IIOPBeanHome)
PortableRemoteObject.narrow(iiopObj, IIOPBeanHome.class);
final IIOPRemote bean = beanHome.create();
For more information, see Configuring Transactions in the JBoss EAP Configuration Guide.
Following example demonstrates how to invoke EJBs deployed on a JBoss EAP server instance from
another remote JBoss EAP server instance. For ease of reference, let us use the following aliases:
Client server: the server from which the EJB invocation happens.
Prerequisites
Configure the user with required credentials on the destination server. See Adding a
Management User in the JBoss EAP Configuration Guide for details.
./standalone.sh -server-config=standalone-full.xml
Deploy the application. See Deploying Applications in the JBoss EAP Configuration Guide for
details.
45
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
NOTE
Each of your server instances must have a unique jboss.node.name system property.
You can set this value by passing it to the startup script:
./standalone.sh -server-config=standalone-full.xml -
Djboss.node.name=<add appropriate value here>
/standalone.sh -server-config=standalone-full.xml -
Djboss.socket.binding.port-offset=100
2. Create a security realm on the client server to communicate with a secure destination server.
The client server must provide the user credentials to the destination server. To achieve this,
you need to create a security realm on the client server, which will pass the user information
provided for the user that was added to the destination server.
You must use a security realm which stores a base64-encoded password and then passes on
these credentials when asked for. You need to create the base64 encoded version of the
password that was provided for the user created initially for the destination server. You may use
OpenSSL to generate base64-encoded passwords at the command line.
Here the password in plain text - password - is piped into the OpenSSL digest function then
piped into another OpenSSL function to convert into base64-encoded format. You can now use
base64-encoded password in the security realm that you configure on the client server.
3. Run the following management CLI commands to create a security realm for the base64-
encoded password:
/core-service=management/security-realm=ejb-security-realm:add()
/core-service=management/security-realm=ejb-security-realm/server-
identity=secret:add(value=<base64-encoded password>)
You may notice that the management CLI shows the message "process-state" ⇒
"reload-required", so you must restart the server before this change can be used.
On successful invocation of this command, the following configuration will be created in the
<management> section of standalone.xml:
<management>
<security-realms>
...
<security-realm name="ejb-security-realm">
46
CHAPTER 5. INVOKING SESSION BEANS
<server-identities>
<secret value=<base64-encoded password>/>
</server-identities>
</security-realm>
</security-realms>
...
The code snippet above creates a security realm named ejb-security-realm with the
base64-encoded password.
4. Create an outbound-socket-binding on the client server. You must now create an outbound-
socket-binding that points to the destination server’s host and port.
/socket-binding-group=standard-sockets/remote-destination-outbound-
socket-binding=remote-ejb:add(host=localhost, port=8080)
When this command is run successfully, you will see that the standalone-full.xml was
updated with the following outbound-socket-binding in the socket-binding-group:
/subsystem=remoting/remote-outbound-connection=remote-ejb-
connection:add(outbound-socket-binding-ref=remote-ejb,
protocol=http-remoting, security-realm=ejb-security-realm,
username=ejb)
This step creates an outbound connection on the client server to the remote destination server
47
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
and sets up the username to the user who is allowed to communicate with that destination
server. It also sets up the security realm to a pre-configured security realm capable of passing
along the user credentials (in this case the password). This way when a connection has to be
established from the client server to the destination server, the connection creation logic will
have the necessary security credentials to pass along and set up a successful secure
connection.
Let us run the following two operations to set some default connection creation options for the
outbound connection:
/subsystem=remoting/remote-outbound-connection=remote-ejb-
connection/property=SASL_POLICY_NOANONYMOUS:add(value=false)
/subsystem=remoting/remote-outbound-connection=remote-ejb-
connection/property=SSL_ENABLED:add(value=false)
Ultimately, upon successful invocation of this command, the following configuration will be
created in the remoting subsystem:
<subsystem xmlns="urn:jboss:domain:remoting:1.1">
...
<outbound-connections>
<remote-outbound-connection name="remote-ejb-connection"
outbound-socket-binding-ref="remote-ejb" protocol="http-remoting"
security-realm="ejb-security-realm" username="ejb">
<properties>
<property name="SASL_POLICY_NOANONYMOUS"
value="false"/>
<property name="SSL_ENABLED" value="false"/>
</properties>
</remote-outbound-connection>
</outbound-connections>
</subsystem>
This completes our configuration on the client server. Our next step is to deploy the application
on the client server which will invoke the bean deployed on the destination server.
<jboss-ejb-client xmlns="urn:jboss:ejb-client:1.0">
<client-context>
<ejb-receivers>
<remoting-ejb-receiver outbound-connection-ref="remote-ejb-
connection"/>
</ejb-receivers>
</client-context>
</jboss-ejb-client>
Notice that we have configured the EJB client context for this application to use a remoting-ejb-
receiver that points to the remote-outbound-connection named remote-ejb-connection,
which we had created earlier. This links the EJB client context to use the remote-ejb-connection
pointing to the EJB remoting connector on the destination server.
48
CHAPTER 5. INVOKING SESSION BEANS
import javax.naming.Context;
import java.util.Hashtable;
import javax.naming.InitialContext;
…
public void invokeOnBean() {
try {
final Hashtable props = new Hashtable();
// setup the ejb: namespace URL factory
props.put(Context.URL_PKG_PREFIXES,
"org.jboss.ejb.client.naming");
// create the InitialContext
final Context context = new
javax.naming.InitialContext(props);
// Lookup the Greeter bean using the ejb: namespace syntax
which is explained here
https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+c
lient+using+JNDI
final Greeter bean = (Greeter) context.lookup("ejb:" +
"myapp" + "/" + "myejb" + "/" + "" + "/" + "GreeterBean" + "!" +
org.myapp.ejb.Greeter.class.getName());
// invoke on the bean
final String greeting = bean.greet("Tom");
System.out.println("Received greeting: " + greeting);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
The code above will invoke the bean deployed on the destination server and return the result.
See Deploying Applications in the JBoss EAP Configuration Guide for details.
49
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
To use the scoped EJB client context, you configure EJB client properties programmatically and pass the
properties on context creation. The properties are the same set of properties that are used in the
standard jboss-ejb-client.properties file. To scope the EJB client context to the JNDI context,
you must also specify the org.jboss.ejb.client.scoped.context property and set its value to
true. This property notifies the EJB client API that it must create an EJB client context, which is backed
by EJB receivers, and that the created context is then scoped or visible only to the JNDI context that
created it. Any EJB proxies looked up or invoked using this JNDI context will only know of the EJB client
context associated with this JNDI context. Other JNDI contexts used by the application to lookup and
invoke EJBs will not know about the other scoped EJB client contexts.
JNDI contexts that do not pass the org.jboss.ejb.client.scoped.context property and are not
scoped to an EJB client context will use the default behavior, which is to use the existing EJB client
context that is typically tied to the entire application.
Scoped EJB client contexts provide user applications with the flexibility that was associated with the JNP
based JNDI invocations in previous versions of JBoss EAP. It provides user applications with more
control over which JNDI context communicates to which server and how it connects to that server.
50
CHAPTER 5. INVOKING SESSION BEANS
NOTE
With the scoped context, the underlying resources are no longer handled by the container
or the API, so you must close the InitialContext when it is no longer needed. When
the InitialContext is closed, the resources are released immediately. The proxies
that are bound to it are no longer valid and any invocation will throw an Exception. Failure
to close the InitialContext may result in resource and performance issues.
The benefit of using a scoped context is that it allows you to configure access without directly referencing
the EJB or importing JBoss classes. It also provides a way to configure and load balance a host at
runtime in a multithreaded environment.
51
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
Contexts generated by lookup EJB proxies are bound by this scoped context and use only the relevant
connection parameters. This makes it possible to create different contexts to access data within a client
application or to independently access servers using different logins.
In the client, both the scoped InitialContext and the scoped proxy are passed to threads, allowing
each thread to work with the given context. It is also possible to pass the proxy to multiple threads that
can use it concurrently.
The scoped context EJB proxy is serialized on the remote call and then deserialized on the server. When
it is deserialized, the scoped context information is removed and it returns to its default state. If the
deserialized proxy is used on the remote server, because it no longer has the scoped context that was
used when it was created, this can result in an EJBCLIENT000025 error or possibly call an unwanted
target by using the EJB name.
52
CHAPTER 5. INVOKING SESSION BEANS
WARNING
53
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
54
CHAPTER 5. INVOKING SESSION BEANS
WARNING
55
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
NOTE
Compression currently can only be specified by annotations on the EJB interface which
should be on the client and server side. There is not currently an XML equivalent to
specify compression hints.
The annotation can be specified at the interface level to apply to all methods in the EJB’s interface such
as:
import org.jboss.ejb.client.annotation.CompressionHint;
@CompressionHint(compressResponse = false)
public interface ClassLevelRequestCompressionRemoteView {
String echo(String msg);
}
Or the annotation can be applied to specific methods in the EJB’s interface such as:
import org.jboss.ejb.client.annotation.CompressionHint;
56
CHAPTER 5. INVOKING SESSION BEANS
@CompressionHint(compressRequest = false)
String echoWithResponseCompress(String msg);
@CompressionHint
String echoWithRequestAndResponseCompress(String msg);
The compressionLevel setting shown above can have the following values:
BEST_COMPRESSION
BEST_SPEED
DEFAULT_COMPRESSION
NO_COMPRESSION
@CompressionHint
public interface MethodOverrideDataCompressionRemoteView {
@CompressionHint(compressRequest = false)
String echoWithResponseCompress(final String msg);
@CompressionHint(compressResponse = false)
String echoWithRequestCompress(final String msg);
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=fals
e
remote.connections=default
remote.connection.default.host=localhost
57
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
remote.connection.default.port=8080
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOA
NONYMOUS=false
Default Connector
The default connector is http-remoting.
If a client application uses the EJB client library from JBoss EAP 6 and wants to connect to a
JBoss EAP 7 server, the server must be configured to expose a remoting connector on a port
other than 8080. The client must then connect using that newly configured connector.
A client application that uses the EJB client library from JBoss EAP 7 and wants to connect to a
JBoss EAP 6 server must be aware that the server instance does not use the http-remoting
connector and instead uses a remoting connector. This is achieved by defining a new client-
side connection property.
remote.connection.default.protocol=remote
NOTE
EJB remote calls are supported for JBoss EAP 7 with JBoss EAP 6 only.
Besides EJB client remoting interoperability, you can connect to legacy clients using the following
options:
Configure the ORB for JTS Transactions in the JBoss EAP Configuration Guide.
The <iiop> element is used to enable IIOP, CORBA, invocation of EJBs. The presence of this element
means that the iiop-openjdk subsystem is installed. The <iiop> element includes the following two
attributes:
enable-by-default: If this is true, then all the EJBs with EJB 2.x home interfaces are
exposed through IIOP. Otherwise they must be explicitly enabled through jboss-ejb3.xml.
use-qualified-name: If this is true, then the EJBs are bound to the CORBA naming context
with a binding name that contains the application and modules name of the deployment, such as
myear/myejbjar/MyBean. If this is false, then the default binding name is simply the bean
name.
IMPORTANT
IIOP calls can be done only with EJB 2 beans. EJB 3 beans are not supported by IIOP in
JBoss EAP 7.0.
Enabling IIOP
To enable IIOP you must have the IIOP OpenJDK ORB subsystem installed, and the <iiop/> element
present in the ejb3 subsystem configuration. The standalone-full.xml configuration that comes
with the distribution has both of these enabled.
58
CHAPTER 5. INVOKING SESSION BEANS
<subsystem xmlns="urn:jboss:domain:iiop-openjdk:1.0">
Use the following management CLI command to access and update the iiop-openjdk subsystem.
/subsystem=iiop-openjdk
The IIOP element takes two attributes that control the default behavior of the server.
<subsystem xmlns="urn:jboss:domain:ejb3:1.2">
...
<iiop enable-by-default="false" use-qualified-name="false"/>
...
</subsystem>
The following management CLI command adds the <iiop> element under the ejb3 subsystem:
/subsystem=ejb3/service=iiop:add(enable-by-default=false, use-qualified-
name=false)
@Remote(IIOPRemote.class)
@RemoteHome(IIOPBeanHome.class)
@Stateless
public class IIOPBean {
public String sayHello() throws RemoteException {
return "hello";
}
}
2. Create a home implementation, which has a mandatory method create(). This method is
called by the client to obtain proxy of remote interface to invoke business methods:
4. Introduce the bean for remote call by creating a descriptor file jboss-ejb3.xml in META-INF:
59
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
xmlns:iiop="urn:iiop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance"
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee
http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd
http://java.sun.com/xml/ns/javaee
http://www.jboss.org/j2ee/schema/jboss-ejb3-spec-2_0.xsd
urn:iiop jboss-ejb-iiop_1_0.xsd"
version="3.1"
impl-version="2.0">
<assembly-descriptor>
<iiop:iiop>
<ejb-name>*</ejb-name>
</iiop:iiop>
</assembly-descriptor>
</jboss:ejb-jar>
NOTE
The packed beans along with the descriptor in the JAR file is now ready to be
deployed to the JBoss EAP container.
System.setProperty("com.sun.CORBA.ORBUseDynamicStub", "true");
final Properties props = new Properties();
props.put(Context.PROVIDER_URL,
"corbaloc::localhost:3528/JBoss/Naming/root");
props.setProperty(Context.URL_PKG_PREFIXES,
"org.jboss.iiop.naming:org.jboss.naming.client");
props.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.cosnaming.CNCtxFactory");
props.put(Context.OBJECT_FACTORIES,
"org.jboss.tm.iiop.client.IIOPClientUserTransactionObjectFactory");
NOTE
The client will need to have the wildfly iiop openjdk library added to its
class path. The client might also need to add the org.wildfly:wildfly-
iiop-openjdk artifact as Maven dependency.
6. Use the context lookup to narrow the reference to the IIOPBeanHome home interface. Then call
the home interface create() method to access the remote interface, which allows you to call
its methods:
try {
Context context = new InitialContext(props);
60
CHAPTER 5. INVOKING SESSION BEANS
61
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
By default, the EJB uses its own caller identity. The identity can alternatively be set to a specific security
role. Using specific security roles is useful when you want to construct a segmented security model - for
example, restricting access to a set of components to internal EJBs only.
Example: Set the security identity of an EJB to be the same as its caller
This example sets the security identity for method invocations made by an EJB to be the same as the
current caller’s identity. This behavior is the default if you do not specify a <security-identity> element
declaration.
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>ASessionBean</ejb-name>
<!-- ... -->
<security-identity>
<use-caller-identity/>
</security-identity>
</session>
<!-- ... -->
</enterprise-beans>
</ejb-jar>
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>RunAsBean</ejb-name>
<!-- ... -->
<security-identity>
<run-as>
<description>A private internal role</description>
<role-name>InternalRole</role-name>
</run-as>
</security-identity>
62
CHAPTER 6. EJB APPLICATION SECURITY
</session>
</enterprise-beans>
<!-- ... -->
</ejb-jar>
By default, when you use <run-as>, a principal named anonymous is assigned to outgoing calls. To
assign a different principal, uses the <run-as-principal>.
<session>
<ejb-name>RunAsBean</ejb-name>
<security-identity>
<run-as-principal>internal</run-as-principal>
</security-identity>
</session>
NOTE
You can also use the <run-as> and <run-as-principal> elements inside a servlet
element.
The EJB <method-permission> element declaration specifies the roles that can invoke the interface
methods of the EJB. You can specify permissions for the following combinations:
Overview
The <method-permission> element defines the logical roles that are allowed to access the EJB
methods defined by <method> elements. Several examples demonstrate the syntax of the xml. Multiple
method permission statements may be present, and they have a cumulative effect. The <method-
permission> element is a child of the <assembly-descriptor> element of the <ejb-jar>
descriptor.
The XML syntax is an alternative to using annotations for EJB method permissions.
<method-permission>
<description>The employee and temp-employee roles may access any method
of the EmployeeService bean </description>
<role-name>employee</role-name>
63
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
<role-name>temp-employee</role-name>
<method>
<ejb-name>EmployeeService</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
Example: Allow roles to access only specific methods of an EJB, and limiting which
method parameters can be passed
<method-permission>
<description>The employee role may access the findByPrimaryKey,
getEmployeeInfo, and the updateEmployeeInfo(String) method of
the AcmePayroll bean </description>
<role-name>employee</role-name>
<method>
<ejb-name>AcmePayroll</ejb-name>
<method-name>findByPrimaryKey</method-name>
</method>
<method>
<ejb-name>AcmePayroll</ejb-name>
<method-name>getEmployeeInfo</method-name>
</method>
<method>
<ejb-name>AcmePayroll</ejb-name>
<method-name>updateEmployeeInfo</method-name>
<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</method>
</method-permission>
<method-permission>
<description>Any authenticated user may access any method of the
EmployeeServiceHelp bean</description>
<unchecked/>
<method>
<ejb-name>EmployeeServiceHelp</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<exclude-list>
<description>No fireTheCTO methods of the EmployeeFiring bean may be
used in this deployment</description>
<method>
<ejb-name>EmployeeFiring</ejb-name>
64
CHAPTER 6. EJB APPLICATION SECURITY
<method-name>fireTheCTO</method-name>
</method>
</exclude-list>
<ejb-jar>
<assembly-descriptor>
<method-permission>
<description>The employee and temp-employee roles may access
any
method of the EmployeeService bean </description>
<role-name>employee</role-name>
<role-name>temp-employee</role-name>
<method>
<ejb-name>EmployeeService</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<method-permission>
<description>The employee role may access the
findByPrimaryKey,
getEmployeeInfo, and the updateEmployeeInfo(String) method
of
the AcmePayroll bean </description>
<role-name>employee</role-name>
<method>
<ejb-name>AcmePayroll</ejb-name>
<method-name>findByPrimaryKey</method-name>
</method>
<method>
<ejb-name>AcmePayroll</ejb-name>
<method-name>getEmployeeInfo</method-name>
</method>
<method>
<ejb-name>AcmePayroll</ejb-name>
<method-name>updateEmployeeInfo</method-name>
<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</method>
</method-permission>
<method-permission>
<description>The admin role may access any method of the
EmployeeServiceAdmin bean </description>
<role-name>admin</role-name>
<method>
<ejb-name>EmployeeServiceAdmin</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<method-permission>
<description>Any authenticated user may access any method of
the
EmployeeServiceHelp bean</description>
65
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
<unchecked/>
<method>
<ejb-name>EmployeeServiceHelp</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<exclude-list>
<description>No fireTheCTO methods of the EmployeeFiring bean
may be
used in this deployment</description>
<method>
<ejb-name>EmployeeFiring</ejb-name>
<method-name>fireTheCTO</method-name>
</method>
</exclude-list>
</assembly-descriptor>
</ejb-jar>
EJBs use security annotations to pass information about security to the deployer. These include:
@DeclareRoles
Declares which roles are available.
@RunAs
Configures the propagated security identity of a component.
Overview
You can use either XML descriptors or annotations to control which security roles are able to call
methods in your Enterprise JavaBeans (EJBs). For information on using XML descriptors, refer to Use
EJB Method Permissions.
Any method values explicitly specified in the deployment descriptor override annotation values. If a
method value is not specified in the deployment descriptor, those values set using annotations are used.
The overriding granularity is on a per-method basis.
@DeclareRoles
Use @DeclareRoles to define which security roles to check permissions against. If no
@DeclareRoles is present, the list is built automatically from the @RolesAllowed annotation. For
information about configuring roles, refer to the Java EE 7 Tutorial Specifying Authorized Users by
Declaring Security Roles.
@RolesAllowed, @PermitAll, @DenyAll
Use @RolesAllowed to list which roles are allowed to access a method or methods. Use
66
CHAPTER 6. EJB APPLICATION SECURITY
@PermitAll or @DenyAll to either permit or deny all roles from using a method or methods. For
information about configuring annotation method permissions, refer to the Java EE 7 Tutorial
Specifying Authorized Users by Declaring Security Roles .
@RunAs
Use @RunAs to specify a role a method uses when making calls from the annotated method. For
information about configuring propagated security identities using annotations, refer to the Java EE 7
Tutorial section 49.2.3, Propagating a Security Identity (Run-As).
@Stateless
@RolesAllowed({"admin"})
@SecurityDomain("other")
public class WelcomeEJB implements Welcome {
@PermitAll
public String WelcomeEveryone(String msg) {
return "Welcome to " + msg;
}
@RunAs("tempemployee")
public String GoodBye(String msg) {
return "Goodbye, " + msg;
}
public String GoodbyeAdmin(String msg) {
return "See you later, " + msg;
}
}
In this code, all roles can access method WelcomeEveryone. The GoodBye method uses the
tempemployee role when making calls. Only the admin role can access method GoodbyeAdmin, and
any other methods with no security annotation.
To authenticate a specific username/password pair that exists in a security realm against an EJB, follow
these steps:
remote.connection.default.username=appuser
remote.connection.default.password=apppassword
Create a custom Remoting connector on the domain or standalone server, which uses your new
security realm.
67
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
Deploy your EJB to the server group which is configured to use the profile with the custom
Remoting connector, or to your standalone server if you are not using a managed domain.
/host=master/core-service=management/security-
realm=MyDomainRealm:add()
/core-service=management/security-realm=MyDomainRealm:add()
4. Create the references to the properties file which will store information about the new role:
Run the following command to create a pointer to the myfile.properties file, which will
contain the properties pertaining to the new role.
NOTE
The properties file will not be created by the included add-user.sh and add-
user.bat scripts. It must be created externally.
/host=master/core-service=management/security-
realm=MyDomainRealm/authentication=properties:add(path=myfile.proper
ties)
/core-service=management/security-
realm=MyDomainRealm/authentication=properties:add(path=myfile.proper
ties)
68
CHAPTER 6. EJB APPLICATION SECURITY
Your new security realm is created. When you add users and roles to this new realm, the information will
be stored in a separate file from the default security realms. You can manage this new file using your
own applications or procedures.
NOTE
When using the add-user.sh script to add a user to a non-default file, other than
application-users.properties, you have to pass it the argument --user-
properties myfile.properties otherwise it will try to use application-
users.properties.
2. Choose whether to add a management user or application user. For this procedure, type b to
add an application user.
3. Choose the realm the user will be added to. By default, the only available realm is
ApplicationRealm. If you have added a custom realm, you may add the user to that instead.
4. Type the username, password, and roles, when prompted. Type the desired username,
password, and optional roles when prompted. Verify your choice by typing yes, or type no to
cancel the changes. The changes are written to each of the properties files for the security
realm.
IMPORTANT
For EJBs to be secured by security realms, they have to use a security domain which is
configured to retrieve user credentials from the security realm. This means that the
domain needs to contain the Remoting and RealmDirect login modules. Assigning a
security domain is done by the @SecurityDomain annotation, which can be applied on
an EJB.
The other security domain retrieves the user and password data from the underlying security realm.
This security domain is the default one if there is no @SecurityDomain annotation on the EJB but the
EJB contains any of the other security-related annotations to be considered secured.
The underlying http-remoting connector, which is used by the client to establish a connection,
decides which security realm is used. For more information on http-remoting connector, see
About the Remoting Subsystem in the JBoss EAP Configuration Guide.
The security realm of the default connector can be changed this way:
/subsystem=remoting/http-connector=http-remoting-connector:write-
attribute(name=security-realm,value=MyDomainRealm)
69
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
By default, the network traffic for Remote Method Invocation (RMI) of EJB2 and EJB3 Beans is not
encrypted. In instances where encryption is required, Secure Sockets Layer (SSL) can be utilized so that
the connection between the client and server is encrypted. Using SSL also has the added benefit of
allowing the network traffic to traverse some firewalls, depending on the firewall configuration.
WARNING
Red Hat recommends that SSLv2, SSLv3, and TLSv1.0 be explicitly disabled in
favor of TLSv1.1 or TLSv1.2 in all affected packages.
70
CHAPTER 7. CONTAINER AND CLIENT INTERCEPTORS
Differences Between the Container Interceptor and the Java EE Interceptor API
Although container interceptors are modeled to be similar to Java EE interceptors, there are some
differences in the semantics of the API. For example, it is illegal for container interceptors to invoke the
javax.interceptor.InvocationContext.getTarget() method because these interceptors are
invoked long before the EJB components are set up or instantiated.
The following is an example of a container interceptor class that marks the iAmAround method for
invocation:
For an example of how to configure a jboss-ejb3.xml descriptor file to use a container interceptor
class, see Configure a Container Interceptor.
71
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
c. Use the <interceptor-binding> elements to bind the container interceptor to the EJBs.
The interceptors can be bound in any of the following ways:
Bind the interceptor to all the EJBs in the deployment using the * wildcard.
Bind the interceptor at the individual bean level using the specific EJB name.
Bind the interceptor at the specific method level for the EJBs.
NOTE
These elements are configured using the EJB 3.2 XSD in the same way
it is done for Java EE interceptors.
3. Review the following descriptor file for examples of the above elements.
<jboss xmlns="http://www.jboss.com/xml/ns/javaee"
xmlns:jee="http://java.sun.com/xml/ns/javaee"
xmlns:ci ="urn:container-interceptors:1.0">
<jee:assembly-descriptor>
<ci:container-interceptors>
<!-- Default interceptor -->
<jee:interceptor-binding>
<ejb-name>*</ejb-name>
<interceptor-
class>org.jboss.as.test.integration.ejb.container.interceptor.Contai
nerInterceptorOne</interceptor-class>
</jee:interceptor-binding>
<!-- Class level container-interceptor -->
<jee:interceptor-binding>
<ejb-name>AnotherFlowTrackingBean</ejb-name>
<interceptor-
class>org.jboss.as.test.integration.ejb.container.interceptor.ClassL
evelContainerInterceptor</interceptor-class>
</jee:interceptor-binding>
<!-- Method specific container-interceptor -->
<jee:interceptor-binding>
<ejb-name>AnotherFlowTrackingBean</ejb-name>
<interceptor-
class>org.jboss.as.test.integration.ejb.container.interceptor.Method
SpecificContainerInterceptor</interceptor-class>
<method>
72
CHAPTER 7. CONTAINER AND CLIENT INTERCEPTORS
<method-
name>echoWithMethodSpecificContainerInterceptor</method-name>
</method>
</jee:interceptor-binding>
<!-- container interceptors in a specific order -->
<jee:interceptor-binding>
<ejb-name>AnotherFlowTrackingBean</ejb-name>
<interceptor-order>
<interceptor-
class>org.jboss.as.test.integration.ejb.container.interceptor.ClassL
evelContainerInterceptor</interceptor-class>
<interceptor-
class>org.jboss.as.test.integration.ejb.container.interceptor.Method
SpecificContainerInterceptor</interceptor-class>
<interceptor-
class>org.jboss.as.test.integration.ejb.container.interceptor.Contai
nerInterceptorOne</interceptor-class>
</interceptor-order>
<method>
<method-
name>echoInSpecificOrderOfContainerInterceptors</method-name>
</method>
</jee:interceptor-binding>
</ci:container-interceptors>
</jee:assembly-descriptor>
</jboss>
Interceptors created and configured on the server-side are referred to as container interceptors.
Interceptors created and configured on the client-side are referred to as client interceptors. To change
the identity of a secured connection, you must create and configure the following three components.
Client Interceptor
Container Interceptor
JAAS LoginModule
The abridged code examples that follow are taken from the ejb-security-interceptors quickstart
that ships with JBoss EAP. This quickstart is a simple Maven project that provides a working example of
how to switch identities on an existing connection.
73
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
if (currentPrincipal != null) {
Map<String, Object> contextData =
context.getContextData();
contextData.put(ServerSecurityInterceptor.DELEGATED_USER_KEY,
currentPrincipal.getName());
}
context.sendRequest();
}
74
CHAPTER 7. CONTAINER AND CLIENT INTERCEPTORS
@AroundInvoke
public Object aroundInvoke(final InvocationContext
invocationContext) throws Exception {
Principal desiredUser = null;
UserPrincipal connectionUser = null;
Collection<Principal> connectionPrincipals =
SecurityActions.getConnectionPrincipals();
if (connectionPrincipals != null) {
for (Principal current : connectionPrincipals) {
if (current instanceof UserPrincipal) {
connectionUser = (UserPrincipal) current;
break;
}
}
} else {
throw new IllegalStateException("Delegation user
requested but no user on connection found.");
}
}
75
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
return invocationContext.proceed();
} finally {
// switch back to original context
if (stateCache != null) {
SecurityActions.popIdentity(stateCache);;
}
}
}
@SuppressWarnings("unchecked")
@Override
public boolean login() throws LoginException {
if (super.login() == true) {
log.debug("super.login()==true");
return true;
}
try {
callbackHandler.handle(new Callback[] { ncb, ocb });
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
// If the CallbackHandler can not handle the required
callbacks then no chance.
return false;
}
if (delegationAcceptable(name, (OuterUserCredential)
credential)) {
identity = new SimplePrincipal(name);
if (getUseFirstPass()) {
76
CHAPTER 7. CONTAINER AND CLIENT INTERCEPTORS
NOTE
77
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
This file is expected to contain a separate line for each fully qualified class name of the EJB
client interceptor implementation.
The EJB client interceptor classes must be available in the class path.
EJB client interceptors that are added using the service loader mechanism are added in the order they
are found in the class path and are added to the end of the client interceptor chain. The ejb-
security-interceptors quickstart that ships with Red Hat JBoss Enterprise Application Platform
uses this approach.
78
CHAPTER 8. CLUSTERED ENTERPRISE JAVABEANS
For information on singletons, see HA Singleton Service in the JBoss EAP Development Guide
./standalone.sh -server-config=standalone-ha.xml
Obviously, to be able to see the benefits of clustering, you’ll need more than one instance of the server.
So let’s start another server with HA capabilities. That another instance of the server can either be on the
same machine or on some other machine. If it’s on the same machine, you will need to take care of two
things -
Make sure that each of the server instances have a unique jboss.node.name system
property.
You can do that by passing the following two system properties to the startup command:
./standalone.sh -server-config=standalone-ha.xml -
Djboss.socket.binding.port-offset=<offset of your choice> -
Djboss.node.name=<unique node name>
Follow whichever approach you feel comfortable with for deploying the EJB deployment to this instance
too.
WARNING
Now that you have deployed an application with clustered EJBs on both the instances, the EJBs are now
capable of making use of the clustering features.
79
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
NOTE
Starting JBoss EAP 7, if JBoss EAP is started using an HA profile, the state of your
SFSBs will be replicated. You no longer need to use the @Clustered annotation to
enable clustering behavior.
Disabling this behavior is achievable on a per-EJB basis by annotating your bean using
@Stateful(passivationCapable=false), which is new to the EJB 3.2 specification;
or globally, via the ejb3 subsystem.
The remote client has to list only one of the servers with the clustering capability. This server will act as
the starting point for cluster topology communication between the client and the clustered nodes.
Note that you have to configure the ejb cluster in the jboss-ejb-client.properties configuration
file:
remote.clusters=ejb
remote.cluster.ejb.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOU
S=false
remote.cluster.ejb.connect.options.org.xnio.Options.SSL_ENABLED=false
In case of stateful clustered EJBs, the invocation flow happens in two steps.
1. Creation of a session for the stateful bean, which happens when you do a JNDI lookup for that
bean.
The lookup for the stateful bean, internally, triggers a synchronous session creation request from the
client to the server. In this case, the session creation request goes to server X because it was configured
80
CHAPTER 8. CLUSTERED ENTERPRISE JAVABEANS
in the jboss-ejb-client.properties file. Since server X is clustered, it will return a session id and
send back an affinity of that session. In case of clustered servers, the affinity is equal to the name of the
cluster to which the stateful bean belongs on the server side. For non-clustered beans, the affinity is the
node name on which the session was created. This affinity will help the EJB client to route the
invocations on the proxy, as appropriate, to either a node within a cluster for clustered beans, or to a
specific node for non-clustered beans. While this session creation request is going on, server X will also
send back an asynchronous message that contains the cluster topology. The JBoss EJB client
implementation will record this topology information and use it later for connection creation to nodes
within the cluster and routing invocations to those nodes, when required.
To understand how failover works, consider the same example of server X being the starting point and a
client application looking up a stateful bean and invoking it. During these invocations, the client side
collects the cluster topology information from the server. Assuming that for some reason server X goes
down and the client application subsequently invokes on the proxy. The JBoss EJB client implementation
at this stage must be aware of the affinity, and in this case it is the cluster affinity. From the cluster
topology information that the client has, it knows that the cluster has two nodes, server X and server Y.
When the invocation arrives, the client notices that server X is down, so it uses a selector to fetch a
suitable node from the cluster nodes. When the selector returns a node from the cluster nodes, the JBoss
EJB client implementation creates a connection to that node, if the connection was not already created
earlier, and creates an EJB receiver out of it. Since in this example, the only other node in the cluster is
server Y, the selector will return server Y as the node and the JBoss EJB client implementation will use it
to create an EJB receiver out of it and use this receiver to pass on the invocation on the proxy.
Effectively, the invocation has now failed over to a different node within the cluster.
In the following example, there are three servers involved. Servers X and Y both belong to a cluster and
have clustered EJBs deployed on them. There is another server instance server C, which may or may
not have clustering capability. Server C acts as a client on which there is a deployment that wants to
invoke the clustered beans deployed on servers X and Y and achieve failover.
The configurations are done in the jboss-ejb-client.xml file, which points to a remote outbound
connection to the other server. The configuration in the jboss-ejb-client.xml file is in the
deployment of server C because server C is the client. The client configuration need not point to all the
clustered nodes, but just to one of them. This will act as a starting point for the communication.
In this case, a remote outbound connection is created from server C to server X and then server X is
used as the starting point for the communication. Similar to the case of remote standalone clients, when
the application on server C looks up a stateful bean, a session creation request is sent to server X that
returns a session id and the cluster affinity for it. Server X also sends back an asynchronous message to
server C containing the cluster topology. This topology information includes the node information of
server Y, because server Y belongs to the cluster along with server X. Subsequent invocations on the
proxy will be routed appropriately to the nodes in the cluster. If server X goes down, as explained earlier,
a different node from the cluster will be selected and the invocation will be forwarded to that node.
Both remote standalone clients as well as remote clients on another JBoss EAP instance act similarly in
terms of failover.
81
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
NOTE
An EJB client is any program that uses an EJB on a remote server. A client is in-server
when the EJB client calling the remote server is itself running inside of a server. In other
words, a JBoss EAP instance calling out to another JBoss EAP instance would be
considered an in-server client.
This example shows the additional cluster configuration required for a standalone EJB client.
remote.clusters=ejb
remote.cluster.ejb.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOU
S=false
remote.cluster.ejb.connect.options.org.xnio.Options.SSL_ENABLED=false
remote.cluster.ejb.username=test
remote.cluster.ejb.password=password
<jboss-ejb-client xmlns:xsi="urn:jboss:ejb-client:1.2"
xsi:noNamespaceSchemaLocation="jboss-ejb-client_1_2.xsd">
<client-context>
<ejb-receivers>
<!-- this is the connection to access the app-one -->
<remoting-ejb-receiver outbound-connection-ref="remote-ejb-
connection-1" />
<!-- this is the connection to access the app-two -->
<remoting-ejb-receiver outbound-connection-ref="remote-ejb-
connection-2" />
</ejb-receivers>
<clusters>
<!-- cluster of remote-ejb-connection-1 -->
<cluster name="ejb" security-realm="ejb-security-realm-1"
username="quickuser1">
<connection-creation-options>
<property name="org.xnio.Options.SSL_ENABLED" value="false" />
<property name="org.xnio.Options.SASL_POLICY_NOANONYMOUS"
value="false" />
</connection-creation-options>
</cluster>
</clusters>
</client-context>
</jboss-ejb-client>
For more information about remote-outbound-connection, see About the Remoting Subsystem in the
JBoss EAP Configuration Guide.
82
CHAPTER 8. CLUSTERED ENTERPRISE JAVABEANS
NOTE
For a secure connection you need to add the credentials to cluster configuration in order
to avoid an authentication exception.
You can implement AllClusterNodeSelector for EJB calls. The node selection behavior of
AllClusterNodeSelector is similar to default selector except that AllClusterNodeSelector
uses all available cluster nodes even in case of a large cluster (number of nodes > 20). If an unconnected
cluster node is returned, it is opened automatically. The following example shows
AllClusterNodeSelector implementation:
package org.jboss.as.quickstarts.ejb.clients.selector;
import java.util.Arrays;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.ejb.client.ClusterNodeSelector;
public class AllClusterNodeSelector implements ClusterNodeSelector {
private static final Logger LOGGER =
Logger.getLogger(AllClusterNodeSelector.class.getName());
@Override
public String selectNode(final String clusterName, final String[]
connectedNodes, final String[] availableNodes) {
if(LOGGER.isLoggable(Level.FINER)) {
LOGGER.finer("INSTANCE "+this+ " : cluster:"+clusterName+"
connected:"+Arrays.deepToString(connectedNodes)+"
available:"+Arrays.deepToString(availableNodes));
}
if (availableNodes.length == 1) {
return availableNodes[0];
}
final Random random = new Random();
final int randomSelection = random.nextInt(availableNodes.length);
return availableNodes[randomSelection];
}
You can also implement the SimpleLoadFactorNodeSelector for EJB calls. Load balancing in
SimpleLoadFactorNodeSelector happens based on a load factor. The load factor (2/3/4) is
calculated based on the names of nodes (A/B/C) irrespective of the load on each node. The following
example shows SimpleLoadFactorNodeSelector implementation:
package org.jboss.as.quickstarts.ejb.clients.selector;
83
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.ejb.client.DeploymentNodeSelector;
public class SimpleLoadFactorNodeSelector implements
DeploymentNodeSelector {
private static final Logger LOGGER =
Logger.getLogger(SimpleLoadFactorNodeSelector.class.getName());
private final Map<String, List<String>[]> nodes = new HashMap<String,
List<String>[]>();
private final Map<String, Integer> cursor = new HashMap<String, Integer>
();
@SuppressWarnings("unchecked")
private void checkNodeNames(String[] eligibleNodes, String key) {
if(!nodes.containsKey(key) || nodes.get(key)[0].size() !=
eligibleNodes.length || !nodes.get(key)
[0].containsAll(Arrays.asList(eligibleNodes))) {
// must be synchronized as the client might call it concurrent
synchronized (nodes) {
if(!nodes.containsKey(key) || nodes.get(key)[0].size() !=
eligibleNodes.length || !nodes.get(key)
[0].containsAll(Arrays.asList(eligibleNodes))) {
ArrayList<String> nodeList = new ArrayList<String>();
nodeList.addAll(Arrays.asList(eligibleNodes));
84
CHAPTER 8. CLUSTERED ENTERPRISE JAVABEANS
});
}
}
}
}
private synchronized String nextNode(String key) {
Integer c = cursor.get(key);
List<String> nodeList = nodes.get(key)[1];
return node;
}
@Override
public String selectNode(String[] eligibleNodes, String appName, String
moduleName, String distinctName) {
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.finer("INSTANCE " + this + " : nodes:" +
Arrays.deepToString(eligibleNodes) + " appName:" + appName + "
moduleName:" + moduleName
+ " distinctName:" + distinctName);
}
checkNodeNames(eligibleNodes, key);
return nextNode(key);
}
}
remote.clusters=ejb
remote.cluster.ejb.clusternode.selector=org.jboss.as.quickstarts.ejb.clien
ts.selector.AllClusterNodeSelector
remote.cluster.ejb.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOU
S=false
remote.cluster.ejb.connect.options.org.xnio.Options.SSL_ENABLED=false
remote.cluster.ejb.username=test
remote.cluster.ejb.password=password
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=fals
85
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
e
remote.connections=one,two
remote.connection.one.host=localhost
remote.connection.one.port = 8080
remote.connection.one.connect.options.org.xnio.Options.SASL_POLICY_NOANONY
MOUS=false
remote.connection.one.username=user
remote.connection.one.password=user123
remote.connection.two.host=localhost
remote.connection.two.port = 8180
remote.connection.two.connect.options.org.xnio.Options.SASL_POLICY_NOANONY
MOUS=false
p.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABL
ED", "false");
p.put("remote.connections", "one,two");
p.put("remote.connection.one.port", "8080");
p.put("remote.connection.one.host", "localhost");
p.put("remote.connection.two.port", "8180");
p.put("remote.connection.two.host", "localhost");
p = new Properties();
p.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
InitialContext context = new InitialContext(p);
<jboss-ejb-client xmlns:xsi="urn:jboss:ejb-client:1.2"
xsi:noNamespaceSchemaLocation="jboss-ejb-client_1_2.xsd">
<client-context deployment-node-
selector="org.jboss.ejb.client.DeploymentNodeSelector">
86
CHAPTER 8. CLUSTERED ENTERPRISE JAVABEANS
<ejb-receivers>
<!-- This is the connection to access the application. -->
<remoting-ejb-receiver outbound-connection-ref="remote-ejb-
connection-1" />
</ejb-receivers>
<!-- Specify the cluster configurations applicable for this client
context -->
<clusters>
<!-- Configure the cluster of remote-ejb-connection-1. -->
<cluster name="ejb" security-realm="ejb-security-realm-1"
username="test" cluster-node-
selector="org.jboss.as.quickstarts.ejb.clients.selector.AllClusterNodeSele
ctor">
<connection-creation-options>
<property name="org.xnio.Options.SSL_ENABLED" value="false" />
<property name="org.xnio.Options.SASL_POLICY_NOANONYMOUS"
value="false" />
</connection-creation-options>
</cluster>
</clusters>
</client-context>
</jboss-ejb-client>
To use the above configuration with security, you will need to add ejb-security-realm-1 to client-
server configuration. The following example shows the CLI commands for adding security realm (ejb-
security-realm-1) the value is the base64 encoded password for the user "test":
core-service=management/security-realm=ejb-security-realm-1:add()
core-service=management/security-realm=ejb-security-realm-1/server-
identity=secret:add(value=cXVpY2sxMjMr)
If the load balancing policy should be used for server to server communication, the class can be
packaged together with the application or as a module. This class is configured in the jboss-ejb-
client settings file located in the META-INF directory of the top-level EAR archive. The following
example uses RoundRobinNodeSelector as the deployment node selector.
<jboss-ejb-client xmlns="urn:jboss:ejb-client:1.2">
<client-context deployment-node-
selector="org.jboss.example.RoundRobinNodeSelector">
<ejb-receivers>
<remoting-ejb-receiver outbound-connection-ref="..."/>
</ejb-receivers>
...
</client-context>
</jboss-ejb-client>
NOTE
If you are running a standalone server, use the start option -Djboss.node.name= or
the server configuration file standalone.xml to configure the server name. Ensure that
the server name is unique. If you are running a managed domain, the host controller
automatically validates that the names are unique.
87
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
ejb:<appName>/<moduleName>/<distinctName>/<beanName>!<viewClassName>?
stateful
<appName>: If the session bean’s JAR file has been deployed within an enterprise archive
(EAR) then the appName is the name of the respective EAR. By default, the name of an EAR is
its filename without the .ear suffix. The application name can be overridden in its
application.xml file. If the session bean is not deployed in an EAR, then leave the appName
blank.
<moduleName>: The moduleName is the name of the JAR file in which the session bean is
deployed. The default name of the JAR file is its filename without the .jar suffix. The module
name can be overridden in the JAR’s ejb-jar.xml file.
<distinctName>: JBoss EAP allows each deployment to specify an optional distinct name. If
the deployment does not have a distinct name, then leave the distinctName blank.
<beanName>: The beanName is the simple class name of the session bean to be invoked.
<viewClassName>: The viewClassName is the fully qualified class name of the remote
interface. This includes the package name of the interface.
?stateful: The ?stateful suffix is required when the JNDI name refers to a stateful session
bean. It is not included for other bean types.
ejb:/hello/HelloBean!org.jboss.example.Hello?stateful"
The @EJB annotation also has a mappedName() attribute. The specification leaves this as
vendor specific metadata, but JBoss EAP recognizes mappedName() as the global JNDI
name of the EJB you are referencing. If you have specified a mappedName(), then all other
attributes are ignored and this global JNDI name is used for binding.
@EJB
ProcessPayment myEjbref;
88
APPENDIX A. REFERENCE MATERIAL
The EJB jar of the referencing bean is searched for an EJB with the interface used in the
@EJB injection. If there are more than one EJB that publishes same business interface,
then an exception is thrown. If there is only one bean with that interface then that one is
used.
Search the EAR for EJBs that publish that interface. If there are duplicates, then an
exception is thrown. Otherwise the matching bean is returned.
Search globally in JBoss EAP runtime for an EJB of that interface. Again, if duplicates
are found, an exception is thrown.
NOTE
The artifactId versions are subject to change. Refer to the JBoss EAP Maven
Repository for the latest versions.
GroupID ArtifactID
org.jboss.bom jboss-eap-javaee7
org.jboss.spec.javax.transaction jboss-transaction-api_1.2_spec
org.jboss.spec.javax.ejb jboss-ejb-api_3.2_spec
org.jboss.eap wildfly-ejb-client-bom
The jboss-eap-javaee7 "Bill of Materials" (BOM) packages the correct version of many of the
artifacts commonly required by a JBoss EAP application. The BOM dependency is specified in the
<dependencyManagement> section of the pom.xml with the scope of import.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.bom</groupId>
<artifactId>jboss-eap-javaee7</artifactId>
<version>${version.jboss.bom.eap}</version>
89
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
The remaining dependencies are specified in the <dependencies> section of the pom.xml file with a
scope of runtime.
<dependencies>
<!-- Include the EJB client JARs -->
<dependency>
<groupId>org.jboss.eap</groupId>
<artifactId>wildfly-ejb-client-bom</artifactId>
<type>pom</type>
<scope>compile</scope>
</dependency>
</dependencies>
The ejb-remote quickstart that ships with JBoss EAP provides a complete working example of remote
EJB client application. See the client/pom.xml file located in root directory of that quickstart for a
complete example of dependency configuration for remote session bean invocation.
The format is similar to ejb-jar.xml, using some of the same namespaces and providing some other
additional namespaces. The contents of jboss-ejb3.xml are merged with the contents of ejb-
jar.xml, with the jboss-ejb3.xml items taking precedence.
This document only covers the additional non-standard namespaces used by jboss-ejb3.xml. Refer
to http://java.sun.com/xml/ns/javaee/ for documentation on the standard namespaces.
xmlns:c="urn:clustering:1.0"
90
APPENDIX A. REFERENCE MATERIAL
This allows you to mark EJB’s as clustered. It is the deployment descriptor equivalent to
@org.jboss.ejb3.annotation.Clustered.
<c:clustering>
<ejb-name>DDBasedClusteredSFSB</ejb-name>
<c:clustered>true</c:clustered>
</c:clustering>
xmlns:s="urn:security"
This allows you to set the security-domain and the run-as-principal for an EJB.
<s:security>
<ejb-name>*</ejb-name>
<s:security-domain>myDomain</s:security-domain>
<s:run-as-principal>myPrincipal</s:run-as-principal>
</s:security>
xmlns:r="urn:resource-adapter-binding"
This allows you to set the resource adapter for a Message-Driven Bean.
<r:resource-adapter-binding>
<ejb-name>*</ejb-name>
<r:resource-adapter-name>myResourceAdapter</r:resource-adapter-name>
</r:resource-adapter-binding>
xmlns:u="urn:iiop"
xmlns:p="urn:ejb-pool:1.0"
This allows you to select the pool that is used by the included stateless session beans or Message-
Driven Beans. Pools are defined in the server configuration.
<p:pool>
<ejb-name>*</ejb-name>
<p:bean-instance-pool-ref>my-pool</p:bean-instance-pool-ref>
</p:pool>
91
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
xmlns:c="urn:ejb-cache:1.0"
This allows you to select the cache that is used by the included stateful session beans. Caches are
defined in the server configuration.
<c:cache>
<ejb-name>*</ejb-name>
<c:cache-ref>my-cache</c:cache-ref>
</c:cache>
NOTE
There are known issues with the jboss-ejb3-spec-2_0.xsd file that may result in
schema validation errors. You can ignore these errors. For more information, see
https://bugzilla.redhat.com/show_bug.cgi?id=1192591.
92
APPENDIX A. REFERENCE MATERIAL
7. Click Save.
/subsystem=ejb3/thread-pool=THREADPOOLNAME:add(max-threads=MAXSIZE)
Replace THREADPOOLNAME with the required name for the thread pool.
Use the read-resource operation to confirm the creation of the bean pool:
/subsystem=ejb3/thread-pool=THREADPOOLNAME:read-resource
To reconfigure all the services in the ejb3 subsystem to use a new thread pool, use the following
commands:
/subsystem=ejb3/thread-pool=bigger:add(max-threads=100)
/subsystem=ejb3/service=async:write-attribute(name=thread-pool-name,
value="bigger")
/subsystem=ejb3/service=remote:write-attribute(name=thread-pool-name,
value="bigger")
/subsystem=ejb3/service=timer-service:write-attribute(name=thread-pool-
name, value="bigger")
reload
<subsystem xmlns="urn:jboss:domain:ejb3:4.0">
...
<async thread-pool-name="bigger"/>
...
<timer-service thread-pool-name="bigger" default-data-store="default-
file-store">
...
<remote connector-ref="http-remoting-connector" thread-pool-
name="bigger"/>
...
<thread-pools>
<thread-pool name="default">
93
Red Hat JBoss Enterprise Application Platform 7.0 Developing EJB Applications
<max-threads count="10"/>
<keepalive-time time="100" unit="milliseconds"/>
</thread-pool>
<thread-pool name="bigger">
<max-threads count="100"/>
</thread-pool>
</thread-pools>
...
NOTE
94