Friday, August 19, 2011

JBoss AS 7.0.1 - Configuring EJB3 Pools

Now that AS 7.0.1 has been released, let's take a look at what new EJB3 features are available. Like I mentioned in my previous post AS 7.0.1 now allows you to configure pools for your stateless session beans and MDBs. Currently we allow configuring the pools at the subsystem level, which means that the pool will be applicable for all the beans deployed on the server. In some upcoming release, we'll allow configuring the pools at individual deployment and individual bean level. Let's, for now, see how the configuration looks like at the subsystem level.

In my previous post I mentioned that AS 7.0.1 has 2 distributions. One which is purely webprofile and the other (named "everything") has additional EE features like support for MDBs. In this post, I'll be using the "Everything" distribution and the JBOSS_HOME/standalone/configurations/standalone-preview.xml for explaining the configurations.

Before we begin with the configurations, for those of you who are new to AS7, let's just see how to start the server using a specific configuration file. First, download the server and the unzip the binary in a folder of your choice. Then from the command prompt, move to the "bin" folder of the installation. Within this folder, you will see a standalone.bat/standalone.sh and domain.bat/domain.sh. We'll be concentrating on the standalone server in this post, but the same applies to the EJB3 subsystem in the domain configurations.

Starting the standalone server

So let's start the server. I'm on a Linux system, so I'll use the standalone.sh file. Those of you on Windows, will have to use standalone.bat.

 jpai@jpai-laptop:bin$ ./standalone.sh  
Within around a couple of seconds, you'll see the server is up and running:

 jpai@jpai-laptop:bin$ ./standalone.sh  
 =========================================================================  
  JBoss Bootstrap Environment  
  JBOSS_HOME: /NotBackedUp/jpai/jboss-as-7.0.1.Final  
  JAVA: /opt/Java/SunJava-6/jdk1.6.0_21//bin/java  
  JAVA_OPTS: -server -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Djboss.modules.system.pkgs=org.jboss.byteman  
 =========================================================================  
 09:30:31,537 INFO [org.jboss.modules] JBoss Modules version 1.0.1.GA  
 09:30:31,765 INFO [org.jboss.msc] JBoss MSC version 1.0.0.GA  
 09:30:31,818 INFO [org.jboss.as] JBoss AS 7.0.1.Final "Zap" starting  
 09:30:32,618 WARN [org.jboss.as] No security realm defined for native management service, all access will be unrestricted.  
 09:30:32,693 INFO [org.jboss.as] creating http management service using network interface (management) port (9990)  
 09:30:32,694 WARN [org.jboss.as] No security realm defined for http management service, all access will be unrestricted.  
 09:30:32,703 INFO [org.jboss.as.logging] Removing bootstrap log handlers  
 09:30:32,720 INFO [org.jboss.as.connector.subsystems.datasources] (Controller Boot Thread) Deploying JDBC-compliant driver class org.h2.Driver (version 1.2)  
 09:30:32,739 INFO [org.jboss.as.clustering.infinispan.subsystem] (Controller Boot Thread) Activating Infinispan subsystem.  
 09:30:32,905 INFO [org.jboss.as.naming] (Controller Boot Thread) Activating Naming Subsystem  
 09:30:32,915 INFO [org.jboss.as.naming] (MSC service thread 1-1) Starting Naming Service  
 09:30:32,918 INFO [org.jboss.as.osgi] (Controller Boot Thread) Activating OSGi Subsystem  
 09:30:32,940 INFO [org.jboss.as.security] (Controller Boot Thread) Activating Security Subsystem  
 09:30:32,957 INFO [org.jboss.remoting] (MSC service thread 1-4) JBoss Remoting version 3.2.0.Beta2  
 09:30:32,968 INFO [org.xnio] (MSC service thread 1-4) XNIO Version 3.0.0.Beta3  
 09:30:32,982 INFO [org.xnio.nio] (MSC service thread 1-4) XNIO NIO Implementation Version 3.0.0.Beta3  
 09:30:33,182 INFO [org.apache.catalina.core.AprLifecycleListener] (MSC service thread 1-4) The Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /opt/Java/SunJava-6/jdk1.6.0_21/jre/lib/i386/server:/opt/Java/SunJava-6/jdk1.6.0_21/jre/lib/i386:/opt/Java/SunJava-6/jdk1.6.0_21/jre/../lib/i386:/usr/java/packages/lib/i386:/lib:/usr/lib  
 09:30:33,203 INFO [org.jboss.as.jmx.JMXConnectorService] (MSC service thread 1-2) Starting remote JMX connector  
 09:30:33,209 INFO [org.jboss.as.remoting] (MSC service thread 1-1) Listening on /127.0.0.1:9999  
 09:30:33,232 INFO [org.jboss.as.ee] (Controller Boot Thread) Activating EE subsystem  
 09:30:33,390 INFO [org.apache.coyote.http11.Http11Protocol] (MSC service thread 1-4) Starting Coyote HTTP/1.1 on http--127.0.0.1-8080  
 09:30:33,512 INFO [org.jboss.as.connector] (MSC service thread 1-1) Starting JCA Subsystem (JBoss IronJacamar 1.0.3.Final)  
 09:30:33,554 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-4) Bound data source [java:jboss/datasources/ExampleDS]  
 09:30:33,919 INFO [org.jboss.as.deployment] (MSC service thread 1-4) Started FileSystemDeploymentService for directory /NotBackedUp/jpai/jboss-as-7.0.1.Final/standalone/deployments  
 09:30:33,931 INFO [org.jboss.as] (Controller Boot Thread) JBoss AS 7.0.1.Final "Zap" started in 2636ms - Started 93 of 148 services (55 services are passive or on-demand)  

Using a different server configuration file

The standalone.sh command by default uses a configuration file named "standalone.xml" which is present in JBOSS_HOME/standalone/configuration folder. The command also allows you to specify a different configuration file, to start the server. Like I mentioned, earlier, I'll be using the standalone-preview.xml in this post. So let's start the server using the standalone-preview.xml.

 jpai@jpai-laptop:bin$ ./standalone.sh -server-config=standalone-preview.xml  
As you see, we pass the -server-config parameter with standalone-preview.xml as the parameter value. By default, the file is looked for in the JBOSS_HOME/standalone/configuration folder. The server starts up in around 3.5 seconds:

 09:35:59,694 INFO  [org.jboss.as] (Controller Boot Thread) JBoss AS 7.0.1.Final "Zap" started in 3586ms - Started 125 of 184 services (59 services are passive or on-demand)  

EJB3 subsystem configurations

Now that we have seen how to startup the server, let's move on to see the configurations. In the standalone-preview.xml, look for the EJB3 subsystem which looks like this:
 <subsystem xmlns="urn:jboss:domain:ejb3:1.1" >  
      <timer-service>  
           <thread-pool core-threads="1" max-threads="4" />  
           <data-store path="timer-service-data" relative-to="jboss.server.data.dir" />  
      </timer-service>  
      <!-- EJB3 pools -->  
      <pools>  
           <bean-instance-pools>  
                <strict-max-pool name="slsb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5"  
                                     instance-acquisition-timeout-unit="MINUTES"/>  
                <strict-max-pool name="mdb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5"  
                                     instance-acquisition-timeout-unit="MINUTES"/>  
           </bean-instance-pools>  
      </pools>  
      <!-- Default MDB configurations -->  
      <mdb>  
           <resource-adapter-ref resource-adapter-name="hornetq-ra"/>  
           <bean-instance-pool-ref pool-name="mdb-strict-max-pool"/>  
      </mdb>  
      <!-- Session bean configurations -->  
      <session-bean>  
           <stateless>  
                <bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>  
           </stateless>  
      </session-bean>  
 </subsystem>  
This is where the EJB3 subsystem level configurations are present. Let's quickly see what some of those are. The first piece of configuration is for EJB3 timerservices. We won't go into too much details of that in this post.

EJB3 Pools

The next piece of configuration is the "pools":
 <!-- EJB3 pools -->  
 <pools>  
      <bean-instance-pools>  
           <strict-max-pool name="slsb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5"  
                                instance-acquisition-timeout-unit="MINUTES"/>  
           <strict-max-pool name="mdb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5"  
                                instance-acquisition-timeout-unit="MINUTES"/>  
      </bean-instance-pools>  
 </pools>  
This is where you configure the pools used by EJB3. Within the "pools" element, you can configure the bean instance pools using the "bean-instance-pools" element. In AS 7.0.1, we only support "strict-max-pool" as a bean instance pool.

A strict max pool allows you to configure a maximum upper limit for the pool. At runtime, when all the bean instances from the pool are in use and a new bean invocation request comes in, the pool blocks the request till the next bean instance is available or till a timeout (set in instance-acquisition-timeout) is reached. Each pool has a unique name. The configurations above show 2 strict max pools named "slsb-strict-max-pool" and "mdb-strict-max-pool". You can add a new strict max pool in there and set a unique name of your choice to it. You can either edit the xml by hand (when the server is down) to add a new strict max pool or you can use the Command Line Client (CLI) that comes with AS7. We'll see how to use the CLI, later in this post.

Message driven bean configurations

Let's now move to the next configurations in that EJB3 subsystem:
 <!-- Default MDB configurations -->  
 <mdb>  
      <resource-adapter-ref resource-adapter-name="hornetq-ra"/>  
      <bean-instance-pool-ref pool-name="mdb-strict-max-pool"/>  
 </mdb>  
This section configures the MDB with the defaults.

Default resource adapter for MDBs

The "resource-adapter-ref" element specifies the default resource-adapter which will be used by the MDBs. In this example, it shows that we use hornetq-ra as the default RA.

Default bean instance pool for MDBs

The bean-instance-pool-ref acts as a reference to a bean-instance-pool, which will be used as the default pool configuration for all MDBs. In this example, we see that it points to "mdb-strict-max-pool" which we saw in the earlier section was configured as a strict max pool with 20 as the upper limit for the pool. If you want to change the default bean instance pool for MDBs, then just change the pool-name attribute of the bean-instance-pool-ref element to some other bean instance pool that's available. You can either do it by editing the xml directly (when the server is down) or use the CLI to do this (we'll see how that's done, later).

Stateless session bean configurations

Moving on to the next section in the EJB3 configurations, you'll see:
 <!-- Session bean configurations -->  
 <session-bean>  
      <stateless>  
           <bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>  
      </stateless>  
 </session-bean>  
This is where you configure the defaults for the session beans. Like we saw with MDBs, the above configuration shows how we configure the default bean instance pool for the stateless session beans. Here we see that "slsb-strict-max-pool" is used as the default. Just like for MDBs, you can change the default bean instance pool for Stateless session beans by changing the pool-name attribute of the bean-instance-pool-ref element either directly in the xml or via the CLI.

Using the Command Line Client (CLI)

AS7 comes with a powerful command line client. Check the AS7 documentation on CLI for a quick reference. The command line client tool is started using the jboss-admin.sh/jboss-admin.bat scripts that are available in the JBOSS_HOME/bin folder:
 jpai@jpai-laptop:bin$ ./jboss-admin.sh  
On running that script, you will notice the following message which acts you to connect to the server:
 You are disconnected at the moment. Type 'connect' to connect to the server or 'help' for the list of supported commands.  
 [disconnected /]   
The CLI requires a running server to be able to connect. So if you haven't started the server, then start it first (as explained in one of the sections above). Now let's connect to the server through the command line:
 [disconnected /] connect  
 Connected to standalone controller at localhost:9999  
 [standalone@localhost:9999 /]   
So the CLI is now connected to the server which is listening on localhost on port 9999. The CLI can be passed a different hostname and port to connect to, but let's not get into that now.

Once you are connected to the server from the CLI, you can now run operations from the CLI to manage your running server. Let's now see how we can manage the bean instance pool configurations for EJB3 subsystem.

Create a new strict max bean instance pool from the CLI

After you have connected to the server from the CLI, you can create a new strict max bean instance pool as follows:
 [standalone@localhost:9999 /] /subsystem=ejb3/strict-max-bean-instance-pool=new-pool:add  
I would recommend that you read the CLI documentation to understand the command better. But let me just briefly split up the above command and explain what each part does.

An important thing to note is that you don't have to type all of that on the CLI. The CLI provides a very (very) useful tab completion feature! So typing in /subsystem= and pressing the tab will show you the available options.

Understanding the bean instance pool creation command

From the CLI documentation:
An operation request basically consists of three parts: The address, an operation name and an optional set of parameters.

The formal specification for an operation request is:
 [/node-type=node-name (/node-type=node-name)*] : operation-name [( [parameter-name=parameter-value (,parameter-name=parameter-value)*] )]  

In this example, our goal is to create a new strict max bean instance pool. This can be done by issuing a "add" operation. In the command that I posted above, notice the use of ":add" at the end. An operation always starts with a ":" followed by the operation name. So in the example above, we are issuing the ":add" operation.

Now the "add" operation will have to be executed on a particular "resource". i.e. the server has to know what to add and where. This is known as addressing. In order to run an operation, an address needs to be provided (don't confuse this with the hostname/port "address" of the server, that's completely different). In AS7 management terms, the server is made up of manageable "resources" and each resource has a address of its own. For example, each of the subsystems that make up the server configuration can be addressed. To refer to the ejb3 subsystem from the command line client, you use /subsystem=ejb3 (you can use the tab completion).

Let's say our new pool that we are creating is going to be named "new-pool". So ultimately the address at which the "add" operation needs to be carried out would look like:
 /subsystem=ejb3/strict-max-bean-instance-pool=new-pool  
Finally, we will combine the address and the operation and run it from the CLI
 [standalone@localhost:9999 /] /subsystem=ejb3/strict-max-bean-instance-pool=new-pool:add  
A sucessful completion of the operation will show you the following output:
 [standalone@localhost:9999 /] /subsystem=ejb3/strict-max-bean-instance-pool=new-pool:add  
 {"outcome" => "success"}  
All management operations are persisted to the server configuration file. In our case it's the standalone-preview.xml, since that's the one we used to start the server.

After running that operation, you can now open the standalone-preview.xml in a text editor and notice that a new strict max bean instance pool, named "new-pool" has been added to the "bean-instance-pools":
 <pools>  
      <bean-instance-pools>  
           <strict-max-pool name="slsb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>  
           <strict-max-pool name="mdb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>  
           <strict-max-pool name="new-pool"/>  
      </bean-instance-pools>  
 </pools>  
The max-pool-size and the other attributes haven't been set and the default values will be used. That's because while running the operation, we did not specify any values for those attributes. Let's now try issuing a command to create one more pool (named "take2") with some specific attribute values. The command will now look like:
 [standalone@localhost:9999 /] /subsystem=ejb3/strict-max-bean-instance-pool=take2:add(max-pool-size=15,timeout=2)  
So the command above is similar to the previous one, except that the name of the pool is "take2" and we have additional specified a max-pool-size of 15 and a timeout of 2 and let the timeout-unit be the default. Note that you can use tab completion while writing that command. On running that command, you'll see the following output:
 [standalone@localhost:9999 /] /subsystem=ejb3/strict-max-bean-instance-pool=take2:add(max-pool-size=15,timeout=2)  
 {"outcome" => "success"}  
The standalone-preview.xml will now look like:
 <pools>  
      <bean-instance-pools>  
           <strict-max-pool name="slsb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>  
           <strict-max-pool name="mdb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>  
           <strict-max-pool name="new-pool"/>  
           <strict-max-pool name="take2" max-pool-size="15" instance-acquisition-timeout="2"/>  
      </bean-instance-pools>  
 </pools>  
Notice the "take2" pool which has the max-pool-size and instance-acquisition-timeout values set to whatever we specified on the CLI.

So that's how you create a new bean instance pool from the CLI.

Setting/changing the default bean instance pool used by the MDBs and the SLSBs

In the previous section we saw how to create a new bean instance pool. Now if we want this new pool to be our default pool configuration for MDBs and/or SLSBs, then we can use the CLI to do that.

Let's first see how it's done for MDBs:
 [standalone@localhost:9999 /] /subsystem=ejb3:write-attribute(name=default-mdb-instance-pool, value=take2)  
So we are issuing a "write-attribute" operation on the /subsystem=ejb3 address to write the attribute named "default-mdb-instance-pool" with a value "take2". Effectively, this command is going to change the default MDB bean instance pool from "mdb-strict-max-pool" (remember, we saw this in the standalone-preview.xml earlier, in the bean-instance-pool-ref section of the MDB) to the "take2" pool that we create a few steps back. Running this command will show you the following output
 [standalone@localhost:9999 /] /subsystem=ejb3:write-attribute(name=default-mdb-instance-pool, value=take2)  
 {"outcome" => "success"}  
If you open the standalone-preview.xml in a text editor, you'll now notice that the changes have been done - the MDB configuration now uses "take2" as the default pool configuration for all MDBs (henceforth).
 <mdb>  
      <resource-adapter-ref resource-adapter-name="hornetq-ra"/>  
      <bean-instance-pool-ref pool-name="take2"/>  
 </mdb>  
We can do the same for Stateless session bean configuration too. The command is:
 [standalone@localhost:9999 /] /subsystem=ejb3:write-attribute(name=default-slsb-instance-pool, value=new-pool)  
 {"outcome" => "success"}  
Here we set the default-slsb-instance-pool to the "new-pool" that we created earlier. The standalone-preview.xml file will now look like:
 <session-bean>  
      <stateless>  
           <bean-instance-pool-ref pool-name="new-pool"/>  
      </stateless>  
 </session-bean>  
So that's it! We have now used the CLI to configure/manage our EJB3 pools.

Disabling pooling for MDBs and Stateless Session Beans

We also allow pooling to be disabled for MDBs and SLSBs. However, it's not always recommended since it can have performance impacts. If as a developer, you know that your beans aren't too heavy during construction (i.e. nothing in constructor and nothing in @PostConstruct), then it sometimes help to disable pooling for the beans. Currently the only way to do this, is by removing the <bean-instance-pool-ref> element from the <mdb> and/or <stateless> elements in the EJB3 subsystem configuration. We don't currently have a way to do this via the CLI nor do we have a way to specify this at per deployment or per bean level.

So, if you know disabling the pooling benefits you, then that's how you can disable it.

Summary

I hadn't thought that this blog would get this lengthy. But since most of this is new in AS7, it was worth writing this up. So, in this blog we saw how and where the EJB3 bean instance pools are configured, how to create new bean instance pools, how to change the default bean instance pools for MDBs and Stateless session beans. We also saw how all of this can be done using the CLI in AS7.

I plan to write some more blog posts in the upcoming days, to explain some other features of AS7 and/or EJB3 in AS7. If you have any questions or run into issues, please visit us in our user forums.



No comments: