Chapter 5. Jakarta Enterprise Beans subsystem tuning JBoss EAP can cache Jakarta Enterprise Beans to save initialization time. This is accomplished using bean pools. There are two different bean pools that can be tuned in JBoss EAP: bean instance pools and bean thread pools. Appropriate bean pool sizes depend on your environment and applications. It is recommended that you experiment with different bean pool sizes and perform stress testing in a development environment that emulates your expected real-world conditions. 5.1. Bean instance pools Bean instance pools are used for Stateless Session Beans (SLSBs) and Message Driven Beans (MDBs). By default, SLSBs use the instance pool default-slsb-instance-pool , and MDBs use the instance pool default-mdb-instance-pool . The size of a bean instance pool limits the number of instances of a particular enterprise bean that can be created at one time. If the pool for a particular enterprise bean is full, the client will block and wait for an instance to become available. If a client does not get an instance within the time set in the pool's timeout attributes, an exception is thrown. The size of a bean instance pool is configured using either derive-size or max-pool-size . The derive-size attribute allows you to configure the pool size using one of the following values: from-worker-pools , which indicates that the maximum pool size is derived from the size of the total threads for all worker pools configured on the system. from-cpu-count , which indicates that the maximum pool size is derived from the total number of processors available on the system. Note that this is not necessarily a 1:1 mapping, and might be augmented by other factors. If derive-size is undefined, then the value of max-pool-size is used for the size of the bean instance pool. Note The derive-size attribute overrides any value specified in max-pool-size . derive-size must be undefined for the max-pool-size value to take effect. You can configure an enterprise bean to use a specific instance pool. This allows for finer control of the instances available to each enterprise bean type. 5.1.1. Creating a bean instance pool This section shows you how to create a new bean instance pool using the management CLI. You can also configure bean instance pools using the management console by navigating to the Jakarta Enterprise Beans subsystem from the Configuration tab, and then selecting the Bean Pool tab. To create a new instance pool, use one of the following commands: To create a bean instance pool with a derived maximum pool size: The following example creates a bean instance pool named my_derived_pool with a maximum size derived from the CPU count, and a timeout of 2 minutes: To create a bean instance pool with an explicit maximum pool size: The following example creates a bean instance pool named my_pool with a maximum of 30 instances and a timeout of 30 seconds: 5.1.2. Specifying the instance pool a bean should use You can set a specific instance pool that a particular bean will use either by using the @org.jboss.ejb3.annotation.Pool annotation, or by modifying the jboss-ejb3.xml deployment descriptor of the bean. 5.1.3. Disabling the default bean instance pool The default bean instance pool can be disabled, which results in an enterprise bean not using any instance pool by default. Instead, a new enterprise bean instance is created when a thread needs to invoke a method on an enterprise bean. This might be useful if you do not want any limit on the number of enterprise bean instances that are created. To disable the default bean instance pool, use the following management CLI command: Note 5.2. Bean thread pools By default, a bean thread pool named default is used for asynchronous enterprise bean calls and enterprise bean timers. Note From JBoss EAP 7 onward, remote enterprise bean requests are handled in the worker defined in the io subsystem by default. If required, you can configure each of these enterprise bean services to use a different bean thread pool. This can be useful if you want finer control of each service's access to a bean thread pool. When determining an appropriate thread pool size, consider how many concurrent requests you expect will be processed at once. 5.2.1. Creating a bean thread pool This section shows you how to create a new bean thread pool using the management CLI. You can also configure bean thread pools using the management console by navigating to the Jakarta Enterprise Beans subsystem from the Configuration tab and selecting Container Thread Pool in the left menu. To create a new thread pool, use the following command: The following example creates a bean thread pool named my_thread_pool with a maximum of 30 threads: 5.2.2. Configuring enterprise bean services to use a specific bean thread pool The enterprise bean asynchronous invocation service and timer service can each be configured to use a specific bean thread pool. By default, both these services use the default bean thread pool. This section shows you how to configure the above enterprise bean services to use a specific bean thread pool using the management CLI. You can also configure these services using the management console by navigating to the Enterprise Bean subsystem from the Configuration tab, selecting the Services tab, and choosing the appropriate service. To configure an enterprise bean service to use a specific bean thread pool, use the following command: Replace SERVICE_NAME with the an enterprise bean service you want to configure: async for the enterprise bean asynchronous invocation service timer-service for the enterprise bean timer service The following example sets the enterprise bean async service to use the bean thread pool named my_thread_pool : 5.3. Runtime deployment information for beans You can add runtime deployment information to your beans for performance monitoring. For details about the available runtime data, see the ejb3 subsystem in the JBoss EAP management model. An application can include the runtime data as annotations in the bean code or in the deployment descriptor. An application can use both options. Additional resources For more information about available runtime data, see the ejb3 subsystem in the JBoss EAP management model . 5.3.1. Command line options for retrieving runtime data from Jakarta enterprise beans Runtime data from Jakarta Enterprise Beans is available from the management CLI so you can evaluate the performance of your Jakarta Enterprise Beans. The command to retrieve runtime data for all types of beans uses the following pattern: Replace <deployment_name> with the name of the deployment .jar file for which to retrieve runtime data. Replace <bean_type> with the type of the bean for which to retrieve runtime data. The following options are valid for this placeholder: stateless-session-bean stateful-session-bean singleton-bean message-driven-bean Replace <bean_name> with the name of the bean for which you to retrieve runtime data. The system delivers the result to stdout formatted as JavaScript Object Notation (JSON) data. Example command to retrieve runtime data for a singleton bean named ManagedSingletonBean deployed in a file named ejb-management.jar Example output runtime data for the singleton bean Example command to retrieve runtime data for a message-driven bean named NoTimerMDB deployed in a file named ejb-management.jar Example output for the message-driven bean 5.4. Exceptions that indicate an enterprise bean subsystem tuning might be required The Stateless Jakarta Enterprise Beans instance pool is not large enough or the timeout is too low The enterprise bean thread pool is not large enough, or an enterprise bean is taking longer to process than the invocation timeout 5.4.1. Default global timeout values for stateful session beans In the ejb3 subsystem, you can configure a default global timeout value for all stateful session beans (SFSBs) that are deployed on your server instance by using the default-stateful-bean-session-timeout attribute. With the default-stateful-bean-session-timeout attribute, you can use the following management CLI operations on the ejb3 subsystem: The read-attribute operation in the management CLI to view the current global timeout value for the attribute. The write-attribute operation to configure the attribute by using the management CLI. Attribute behavior varies according to the server mode. For example: When running in the standalone server, the configured value gets applied to all SFSBs deployed on the application server. When running a server in a managed domain, all SFSBs that are deployed on server instances within server groups receive concurrent timeout values. Note When you change the global timeout value for the attribute, the updated settings only apply to new deployments. You must reload the server to apply the new settings to current deployments. By default, the attribute value is set at -1 , which means that deployed SFSBs are configured to never time out. However, you can configure two of the following types of valid values for the attribute: When you set the attribute value to 0 , the attribute immediately marks eligible SFSBs for removal by the ejb container. When you set the attribute value greater than 0 , the SFSBs remain idle for the specified time in milliseconds before the ejb container removes the eligible SFSBs. Note You can still use the pre-existing @StatefulTimeout annotation or the stateful-timeout element, which is located in the ejb-jar.xml deployment descriptor, to configure the timeout value for an SFSB. However, setting such a configuration overrides the default global timeout value to the SFSB. Two methods exist for verifying a new value you set for the attribute: Use the read-attribute operation in the management CLI. Examine the ejb3 subsystem section of the server's configuration file. Additional resources For more information about viewing the current global timeout value for an attribute, see Display an Attribute Value in the Management CLI guide . For more information about updating the current global timeout value for an attribute, see Update an Attribute in the Management CLI guide .

Commands:
/subsystem=ejb3/strict-max-bean-instance-pool= POOL_NAME :add(derive-size= DERIVE_OPTION ,timeout-unit= TIMEOUT_UNIT ,timeout= TIMEOUT_VALUE )
/subsystem=ejb3/strict-max-bean-instance-pool=my_derived_pool:add(derive-size=from-cpu-count,timeout-unit=MINUTES,timeout=2)
/subsystem=ejb3/strict-max-bean-instance-pool= POOL_NAME :add(max-pool-size= POOL_SIZE ,timeout-unit= TIMEOUT_UNIT ,timeout= TIMEOUT_VALUE )
/subsystem=ejb3/strict-max-bean-instance-pool=my_pool:add(max-pool-size=30,timeout-unit=SECONDS,timeout=30)
/subsystem=ejb3:undefine-attribute(name=default-slsb-instance-pool)
If a bean is configured to use a particular bean instance pool, disabling the default instance pool does not affect the pool that the bean uses.
/subsystem=ejb3/thread-pool= POOL_NAME :add(max-threads= MAX_THREADS )
/subsystem=ejb3/thread-pool=my_thread_pool:add(max-threads=30)
/subsystem=ejb3/service= SERVICE_NAME :write-attribute(name=thread-pool-name,value= THREAD_POOL_NAME )
/subsystem=ejb3/service=async:write-attribute(name=thread-pool-name,value=my_thread_pool)
/deployment=<deployment_name>/subsystem=ejb3/<bean_type>=<bean_name>:read-resource(include-runtime)
/deployment=ejb-management.jar/subsystem=ejb3/singleton-bean=ManagedSingletonBean:read-resource(include-runtime)
{ "outcome" => "success", "result" => { "async-methods" => ["void async(int, int)"], "business-local" => ["sample.ManagedSingletonBean"], "business-remote" => ["sample.BusinessInterface"], "component-class-name" => "sample.ManagedSingletonBean", "concurrency-management-type" => undefined, "declared-roles" => [ "Role3", "Role2", "Role1" ], "depends-on" => undefined, "execution-time" => 156L, "init-on-startup" => false, "invocations" => 3L, "jndi-names" => [ "java:module/ManagedSingletonBean!sample.ManagedSingletonBean", "java:global/ejb-management/ManagedSingletonBean!sample.ManagedSingletonBean", "java:app/ejb-management/ManagedSingletonBean!sample.ManagedSingletonBean", "java:app/ejb-management/ManagedSingletonBean!sample.BusinessInterface", "java:global/ejb-management/ManagedSingletonBean!sample.BusinessInterface", "java:module/ManagedSingletonBean!sample.BusinessInterface" ], "methods" => {"doIt" => { "execution-time" => 156L, "invocations" => 3L, "wait-time" => 0L }}, "peak-concurrent-invocations" => 1L, "run-as-role" => "Role3", "security-domain" => "other", "timeout-method" => "public void sample.ManagedSingletonBean.timeout(javax.ejb.Timer)", "timers" => [{ "time-remaining" => 4304279L, "next-timeout" => 1577768415000L, "calendar-timer" => true, "persistent" => false, "info" => "timer1", "schedule" => { "year" => "*", "month" => "*", "day-of-month" => "*", "day-of-week" => "*", "hour" => "0", "minute" => "0", "second" => "15", "timezone" => undefined, "start" => undefined, "end" => undefined } }], "transaction-type" => "CONTAINER", "wait-time" => 0L, "service" => {"timer-service" => undefined} } }
/deployment=ejb-management.jar/subsystem=ejb3/message-driven-bean=NoTimerMDB:read-resource(include-runtime)
{ "outcome" => "success", "result" => { "activation-config" => [ ("destination" => "java:/queue/NoTimerMDB-queue"), ("destinationType" => "javax.jms.Queue"), ("acknowledgeMode" => "Auto-acknowledge") ], "component-class-name" => "sample.NoTimerMDB", "declared-roles" => [ "Role3", "Role2", "Role1" ], "delivery-active" => true, "execution-time" => 0L, "invocations" => 0L, "message-destination-link" => "queue/NoTimerMDB-queue", "message-destination-type" => "javax.jms.Queue", "messaging-type" => "javax.jms.MessageListener", "methods" => {}, "peak-concurrent-invocations" => 0L, "pool-available-count" => 16, "pool-create-count" => 0, "pool-current-size" => 0, "pool-max-size" => 16, "pool-name" => "mdb-strict-max-pool", "pool-remove-count" => 0, "run-as-role" => "Role3", "security-domain" => "other", "timeout-method" => undefined, "timers" => [], "transaction-type" => "CONTAINER", "wait-time" => 0L, "service" => undefined } }
javax.ejb.EJBException: JBAS014516: Failed to acquire a permit within 20 SECONDS at org.jboss.as.ejb3.pool.strictmax.StrictMaxPool.get(StrictMaxPool.java:109)
java.util.concurrent.TimeoutException: No invocation response received in 300000 milliseconds