8.5. Invoking Session Beans
8.5.1. Invoke a Session Bean Remotely using JNDI
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.
Warning
Prerequisites
- You must already have a Maven project created ready to use.
- Configuration for the JBoss EAP 6 Maven repository has already been added.
- The session beans that you want to invoke are already deployed.
- The deployed session beans implement remote business interfaces.
- 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. Refer to 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 hostname and JNDI port of the server hosting the session beans.
Procedure 8.8. Add Maven Project Configuration for Remote Invocation of Session Beans
- Add the required project dependenciesThe
pom.xml
for the project must be updated to include the necessary dependencies. - Add the
jboss-ejb-client.properties
fileThe JBoss EJB client API expects to find a file in the root of the project namedjboss-ejb-client.properties
that contains the connection information for the JNDI service. Add this file to thesrc/main/resources/
directory of your project with the following content.# In the following line, set SSL_ENABLED to true for SSL remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false remote.connections=default # Uncomment the following line to set SSL_STARTTLS to true for SSL # remote.connection.default.connect.options.org.xnio.Options.SSL_STARTTLS=true remote.connection.default.host=localhost remote.connection.default.port = 4447 remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false # Add any of the following SASL options if required # remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false # remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT=false # remote.connection.default.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS=JBOSS-LOCAL-USER
Change the host name and port to match your server.4447
is the default port number. For a secure connection, set theSSL_ENABLED
line totrue
and uncomment theSSL_STARTTLS
line. The Remoting interface in the container supports secured and unsecured connections using the same port. - Add dependencies for the remote business interfacesAdd the Maven dependencies to the
pom.xml
for the remote business interfaces of the session beans.<dependency> <groupId>org.jboss.as.quickstarts</groupId> <artifactId>jboss-ejb-remote-server-side</artifactId> <type>ejb-client</type> <version>${project.version}</version> </dependency>
Procedure 8.9. Obtain a Bean Proxy using JNDI and Invoke Methods of the Bean
- Handle checked exceptionsTwo of the methods used in the following code (
InitialContext()
andlookup()
) have a checked exception of typejavax.naming.NamingException
. These method calls must either be enclosed in a try/catch block that catchesNamingException
or in a method that is declared to throwNamingException
. Theejb-remote
quickstart uses the second technique. - Create a JNDI ContextA JNDI Context object provides the mechanism for requesting resources from the server. Create a JNDI context using the following code:
final Hashtable jndiProperties = new Hashtable(); jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); final Context context = new InitialContext(jndiProperties);
The connection properties for the JNDI service are read from thejboss-ejb-client.properties
file. - Use the JNDI Context's lookup() method to obtain a bean proxyInvoke 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.final RemoteCalculator statelessRemoteCalculator = (RemoteCalculator) context.lookup( "ejb:/jboss-ejb-remote-server-side//CalculatorBean!" + RemoteCalculator.class.getName());
Session bean JNDI names are defined using a special syntax. For more information, see Section 8.8.1, “EJB JNDI Naming Reference” . - Invoke methodsNow 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.
8.5.2. About EJB Client Contexts
- A remote client, which runs as a standalone Java application.
- A remote client, which runs within another JBoss EAP 6 instance.
8.5.3. Considerations When Using a Single EJB Context
You must consider your application requirements when using a single EJB client context with standalone remote clients. For more information about the different types of remote clients, refer to: Section 8.5.2, “About EJB Client Contexts” .
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:
public class MyApplication { public static void main(String args[]) { final javax.naming.Context ctxOne = new javax.naming.InitialContext(); final MyBeanInterface beanOne = ctxOne.lookup("ejb:app/module/distinct/bean!interface"); beanOne.doSomething(); ... } }
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 6 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: Section 8.5.1, “Invoke a Session Bean Remotely using JNDI” .
A user application may want to invoke a bean more than once, but connect to the JBoss EAP 6 server using different security credentials. The following is an example of a standalone remote client application that invokes the same bean twice:
public class MyApplication { public static void main(String args[]) { // Use the "foo" security credential connect to the server and invoke this bean instance final javax.naming.Context ctxOne = new javax.naming.InitialContext(); final MyBeanInterface beanOne = ctxOne.lookup("ejb:app/module/distinct/bean!interface"); beanOne.doSomething(); ... // Use the "bar" security credential to connect to the server and invoke this bean instance final javax.naming.Context ctxTwo = new javax.naming.InitialContext(); final MyBeanInterface beanTwo = ctxTwo.lookup("ejb:app/module/distinct/bean!interface"); beanTwo.doSomething(); ... } }
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 Section 8.5.4, “Using Scoped EJB Client Contexts” and Section 8.5.5, “Configure EJBs Using a Scoped EJB Client Context” .
8.5.4. Using Scoped EJB Client Contexts
To invoke an EJB In earlier versions of JBoss EAP 6, you would typically create a JNDI context and pass it the PROVIDER_URL, which would point to the target server. Any invocations done on EJB proxies that were looked up using that JNDI context, would end up on that server. With scoped EJB client contexts, user applications have control over which EJB receiver is used for a specific invocation.
Prior to the introduction of scoped EJB client contexts, the context was typically scoped to the client application. Scoped client contexts now allow the EJB client contexts to be scoped with the JNDI contexts. The following is an example of a standalone remote client application that invokes the same bean twice using a scoped EJB client context:
public class MyApplication { public static void main(String args[]) { // Use the "foo" security credential connect to the server and invoke this bean instance final Properties ejbClientContextPropsOne = getPropsForEJBClientContextOne(): final javax.naming.Context ctxOne = new javax.naming.InitialContext(ejbClientContextPropsOne); final MyBeanInterface beanOne = ctxOne.lookup("ejb:app/module/distinct/bean!interface"); beanOne.doSomething(); ... ctxOne.close(); // Use the "bar" security credential to connect to the server and invoke this bean instance final Properties ejbClientContextPropsTwo = getPropsForEJBClientContextTwo(): final javax.naming.Context ctxTwo = new javax.naming.InitialContext(ejbClientContextPropsTwo); final MyBeanInterface beanTwo = ctxTwo.lookup("ejb:app/module/distinct/bean!interface"); beanTwo.doSomething(); ... ctxTwo.close(); } }
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.
org.jboss.ejb.client.scoped.context
property and aren't 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.
Note
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.
8.5.5. Configure EJBs Using a Scoped EJB Client Context
EJBs can be configured using a map-based scoped context. This is achieved by programmatically populating a Properties
map using the standard properties found in the jboss-ejb-client.properties
, specifying true
for the org.jboss.ejb.client.scoped.context
property, and passing the properties on the InitialContext
creation.
Procedure 8.10. Configure an EJB Using a Map-Based Scoped Context
Set the Properties
Configure the EJB client properties programmatically, specifying the same set of properties that are used in the standardjboss-ejb-client.properties
file. To enable the scoped context, you must specify theorg.jboss.ejb.client.scoped.context
property and set its value totrue
. The following is an example that configures the properties programmatically.// Configure EJB Client properties for the InitialContext Properties ejbClientContextProps = new Properties(); ejbClientContextProps.put(“remote.connections”,”name1”); ejbClientContextProps.put(“remote.connection.name1.host”,”localhost”); ejbClientContextProps.put(“remote.connection.name1.port”,”4447”); // Property to enable scoped EJB client context which will be tied to the JNDI context ejbClientContextProps.put("org.jboss.ejb.client.scoped.context", “true”);
Pass the Properties on the Context Creation
// Create the context using the configured properties InitialContext ic = new InitialContext(ejbClientContextProps); MySLSB bean = ic.lookup("ejb:myapp/ejb//MySLSBBean!" + MySLSB.class.getName());
- 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.
8.5.6. EJB Client Properties
The following tables list properties that can be configured programmatically or in the jboss-ejb-client.properties
file.
The following table lists properties that are valid for the whole library within the same scope.
Property Name | Description |
---|---|
endpoint.name |
Name of the client endpoint. If not set, the default value is
client-endpoint
This can be helpful to distinguish different endpoint settings because the thread name contains this property.
|
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED |
Boolean value that specifies whether the SSL protocol is enabled for all connections.
Warning
Red Hat recommends that you explicitly disable SSL in favor of TLSv1.1 or TLSv1.2 in all affected packages.
|
deployment.node.selector |
The fully qualified name of the implementation of
org.jboss.ejb.client.DeploymentNodeSelector .
This is used to load balance the invocation for the EJBs.
|
invocation.timeout |
The timeout for the EJB handshake or method invocation request/response cycle. The value is in milliseconds.
The invocation of any method throws a
java.util.concurrent.TimeoutException if the execution takes longer than the timeout period. The execution completes and the server is not interrupted.
|
reconnect.tasks.timeout |
The timeout for the background reconnect tasks. The value is in milliseconds.
If a number of connections are down, the next client EJB invocation will use an algorithm to decide if a reconnect is necessary to find the right node.
|
org.jboss.ejb.client.scoped.context |
Boolean value that specifies whether to enable the scoped EJB client context. The default value is
false .
If set to
true , the EJB Client will use the scoped context that is tied to the JNDI context. Otherwise the EJB client context will use the global selector in the JVM to determine the properties used to call the remote EJB and host.
|
The connection properties start with the prefix remote.connection.CONNECTION_NAME
where the CONNECTION_NAME is a local identifier only used to uniquely identify the connection.
Property Name | Description |
---|---|
remote.connections |
A comma-separated list of active
connection-names . Each connection is configured by using this name.
|
|
The host name or IP for the connection.
|
|
The port for the connection. The default value is 4447.
|
|
The user name used to authenticate connection security.
|
|
The password used to authenticate the user.
|
|
The timeout period for the initial connection. After that, the reconnect task will periodically check whether the connection can be established. The value is in milliseconds.
|
|
Fully qualified name of the
CallbackHandler class. It will be used to establish the connection and can not be changed as long as the connection is open.
|
|
Integer value specifying the maximum number of outbound requests. The default is 80.
There is only one connection from the client (JVM) to the server to handle all invocations.
|
|
Boolean value that determines whether credentials must be provided by the client to connect successfully. The default value is
true .
If set to
true , the client must provide credentials. If set to false , invocation is allowed as long as the remoting connector does not request a security realm.
|
|
Disables certain SASL mechanisms used for authenticating during connection creation.
JBOSS-LOCAL-USER means the silent authentication mechanism, used when the client and server are on the same machine, is disabled.
|
|
Boolean value that enables or disables the use of plain text messages during the authentication. If using JAAS, it must be set to false to allow a plain text password.
|
|
Boolean value that specifies whether the SSL protocol is enabled for this connection.
Warning
Red Hat recommends that you explicitly disable SSL in favor of TLSv1.1 or TLSv1.2 in all affected packages.
|
|
Interval to send a heartbeat between client and server to prevent automatic close, for example, in the case of a firewall. The value is in milliseconds.
|
If the initial connection connects to a clustered environment, the topology of the cluster is received automatically and asynchronously. These properties are used to connect to each received member. Each property starts with the prefix remote.cluster.CLUSTER_NAME
where the CLUSTER_NAME refers to the related to the servers Infinispan subsystem configuration.
Property Name | Description |
---|---|
|
The fully qualified name of the implementation of
org.jboss.ejb.client.ClusterNodeSelector .
This class, rather than
org.jboss.ejb.client.DeploymentNodeSelector , is used to load balance EJB invocations in a clustered environment. If the cluster is completely down, the invocation will fail with No ejb receiver available .
|
|
Integer value specifying the maximum number of outbound requests that can be made to the entire cluster.
|
|
Integer value specifying the maximum number of outbound requests that can be made to this specific cluster-node.
|
8.5.7. Remote EJB Data Compression
Note
org.jboss.ejb.client.annotation.CompressionHint
. The hint values specify whether to compress the request, response or request and response. Adding @CompressionHint
defaults to compressResponse=true
and compressRequest=true
.
import org.jboss.ejb.client.annotation.CompressionHint; @CompressionHint(compressResponse = false) public interface ClassLevelRequestCompressionRemoteView { String echo(String msg); }
import org.jboss.ejb.client.annotation.CompressionHint; public interface CompressableDataRemoteView { @CompressionHint(compressResponse = false, compressionLevel = Deflater.BEST_COMPRESSION) String echoWithRequestCompress(String msg); @CompressionHint(compressRequest = false) String echoWithResponseCompress(String msg); @CompressionHint String echoWithRequestAndResponseCompress(String msg); String echoWithNoCompress(String msg); }
compressionLevel
setting shown above can have the following values:
- BEST_COMPRESSION
- BEST_SPEED
- DEFAULT_COMPRESSION
- NO_COMPRESSION
compressionLevel
setting defaults to Deflater.DEFAULT_COMPRESSION
.
@CompressionHint public interface MethodOverrideDataCompressionRemoteView { @CompressionHint(compressRequest = false) String echoWithResponseCompress(final String msg); @CompressionHint(compressResponse = false) String echoWithRequestCompress(final String msg); String echoWithNoExplicitDataCompressionHintOnMethod(String msg); }
org.jboss.ejb.client.view.annotation.scan.enabled
system property is set to true
. This property tells JBoss EJB Client to scan for annotations.