Sun GlassFish Enterprise Server v2.1.1 Developer's Guide

Part III Using Services and APIs

Chapter 15 Using the JDBC API for Database Access

This chapter describes how to use the JavaTM Database Connectivity (JDBCTM) API for database access with the Sun GlassFish Enterprise Server. This chapter also provides high level JDBC implementation instructions for servlets and EJB components using the Enterprise Server. If the JDK version 1.6 is used, the Enterprise Server supports the JDBC 4.0 API, which encompasses the JDBC 3.0 API and the JDBC 2.0 Optional Package API.

The JDBC specifications are available at http://java.sun.com/products/jdbc/download.html.

A useful JDBC tutorial is located at http://java.sun.com/docs/books/tutorial/jdbc/index.html.


Note –

The Enterprise Server does not support connection pooling or transactions for an application’s database access if it does not use standard Java EE DataSource objects.


This chapter discusses the following topics:

General Steps for Creating a JDBC Resource

To prepare a JDBC resource for use in Java EE applications deployed to the Enterprise Server, perform the following tasks:

For information about how to configure some specific JDBC drivers, see Configurations for Specific JDBC Drivers in Sun GlassFish Enterprise Server v2.1.1 Administration Guide.

Integrating the JDBC Driver

To use JDBC features, you must choose a JDBC driver to work with the Enterprise Server, then you must set up the driver. This section covers these topics:

Supported Database Drivers

Supported JDBC drivers are those that have been fully tested by Sun. For a list of the JDBC drivers currently supported by the Enterprise Server, see the Sun GlassFish Enterprise Server v2.1.1 Release Notes. For configurations of supported and other drivers, see Configurations for Specific JDBC Drivers in Sun GlassFish Enterprise Server v2.1.1 Administration Guide.


Note –

Because the drivers and databases supported by the Enterprise Server are constantly being updated, and because database vendors continue to upgrade their products, always check with Sun technical support for the latest database support information.


Making the JDBC Driver JAR Files Accessible

To integrate the JDBC driver into a Enterprise Server domain, copy the JAR files into the domain-dir/lib directory, then restart the server. This makes classes accessible to all applications or modules deployed on servers that share the same configuration. For more information about Enterprise Server class loaders, see Chapter 2, Class Loaders.

Creating a Connection Pool

When you create a connection pool that uses JDBC technology (a JDBC connection pool) in the Enterprise Server, you can define many of the characteristics of your database connections.

You can create a JDBC connection pool in one of these ways:

For a complete description of JDBC connection pool features, see the Sun GlassFish Enterprise Server v2.1.1 Administration Guide

Testing a JDBC Connection Pool

You can test a JDBC connection pool for usability in one of these ways:

Both these commands fail and display an error message unless they successfully connect to the connection pool.

For information about how to tune a connection pool, see the Sun GlassFish Enterprise Server v2.1.1 Performance Tuning Guide.

Creating a JDBC Resource

A JDBC resource, also called a data source, lets you make connections to a database using getConnection(). Create a JDBC resource in one of these ways:

Creating Applications That Use the JDBC API

An application that uses the JDBC API is an application that looks up and connects to one or more databases. This section covers these topics:

Sharing Connections

When multiple connections acquired by an application use the same JDBC resource, the connection pool provides connection sharing within the same transaction scope. For example, suppose Bean A starts a transaction and obtains a connection, then calls a method in Bean B. If Bean B acquires a connection to the same JDBC resource with the same sign-on information, and if Bean A completes the transaction, the connection can be shared.

Connections obtained through a resource are shared only if the resource reference declared by the Java EE component allows it to be shareable. This is specified in a component’s deployment descriptor by setting the res-sharing-scope element to Shareable for the particular resource reference. To turn off connection sharing, set res-sharing-scope to Unshareable.

For general information about connections and JDBC URLs, see Chapter 3, JDBC Resources, in Sun GlassFish Enterprise Server v2.1.1 Administration Guide.

Obtaining a Physical Connection From a Wrapped Connection

The DataSource implementation in the Enterprise Server provides a getConnection method that retrieves the JDBC driver’s SQLConnection from the Enterprise Server’s Connection wrapper. The method signature is as follows:

public java.sql.Connection getConnection(java.sql.Connection con) 
throws java.sql.SQLException

For example:

InitialContext ctx = new InitialContext();
com.sun.appserv.jdbc.DataSource ds = (com.sun.appserv.jdbc.DataSource) 
   ctx.lookup("jdbc/MyBase");
Connection con = ds.getConnection();
Connection drivercon = ds.getConnection(con);
// Do db operations.
// Do not close driver connection.
con.close(); // return wrapped connection to pool.

Marking Bad Connections

The DataSource implementation in the Enterprise Server provides a markConnectionAsBad method. A marked bad connection is removed from its connection pool when it is closed. The method signature is as follows:

public void markConnectionAsBad(java.sql.Connection con)

For example:

com.sun.appserv.jdbc.DataSource ds=
   (com.sun.appserv.jdbc.DataSource)context.lookup("dataSource");
Connection con = ds.getConnection();
Statement stmt = null;
try{
   stmt = con.createStatement();
   stmt.executeUpdate("Update");
}
catch (BadConnectionException e){
   dataSource.markConnectionAsBad(con) //marking it as bad for removal
}
finally{
   stmt.close();	
   con.close(); //Connection will be destroyed during close.
}

Using Non-Transactional Connections

You can specify a non-transactional database connection in any of these ways:

Typically, a connection is enlisted in the context of the transaction in which a getConnection call is invoked. However, a non-transactional connection is not enlisted in a transaction context even if a transaction is in progress.

The main advantage of using non-transactional connections is that the overhead incurred in enlisting and delisting connections in transaction contexts is avoided. However, use such connections carefully. For example, if a non-transactional connection is used to query the database while a transaction is in progress that modifies the database, the query retrieves the unmodified data in the database. This is because the in-progress transaction hasn’t committed. For another example, if a non-transactional connection modifies the database and a transaction that is running simultaneously rolls back, the changes made by the non-transactional connection are not rolled back.

Here is a typical use case for a non-transactional connection: a component that is updating a database in a transaction context spanning over several iterations of a loop can refresh cached data by using a non-transactional connection to read data before the transaction commits.

Using JDBC Transaction Isolation Levels

For general information about transactions, see Chapter 16, Using the Transaction Service and Chapter 12, Transactions, in Sun GlassFish Enterprise Server v2.1.1 Administration Guide. For information about last agent optimization, which can improve performance, see Transaction Scope.

Not all database vendors support all transaction isolation levels available in the JDBC API. The Enterprise Server permits specifying any isolation level your database supports. The following table defines transaction isolation levels.

Table 15–1 Transaction Isolation Levels

Transaction Isolation Level  

Description  

TRANSACTION_READ_UNCOMMITTED

Dirty reads, non-repeatable reads, and phantom reads can occur. 

TRANSACTION_READ_COMMITTED

Dirty reads are prevented; non-repeatable reads and phantom reads can occur. 

TRANSACTION_REPEATABLE_READ

Dirty reads and non-repeatable reads are prevented; phantom reads can occur. 

TRANSACTION_SERIALIZABLE

Dirty reads, non-repeatable reads and phantom reads are prevented. 

Note that you cannot call setTransactionIsolation() during a transaction.

You can set the default transaction isolation level for a JDBC connection pool. For details, see Creating a Connection Pool.

To verify that a level is supported by your database management system, test your database programmatically using the supportsTransactionIsolationLevel() method in java.sql.DatabaseMetaData, as shown in the following example:

InitialContext ctx = new InitialContext();
DataSource ds = (DataSource)
ctx.lookup("jdbc/MyBase");
Connection con = ds.getConnection();
DatabaseMetaData dbmd = con.getMetaData();
if (dbmd.supportsTransactionIsolationLevel(TRANSACTION_SERIALIZABLE)
{ Connection.setTransactionIsolation(TRANSACTION_SERIALIZABLE); }

For more information about these isolation levels and what they mean, see the JDBC API specification.


Note –

Applications that change the isolation level on a pooled connection programmatically risk polluting the pool, which can lead to errors.


Allowing Non-Component Callers

You can allow non-Java-EE components, such as servlet filters, lifecycle modules, and third party persistence managers, to use this JDBC connection pool. The returned connection is automatically enlisted with the transaction context obtained from the transaction manager. Standard Java EE components can also use such pools. Connections obtained by non-component callers are not automatically closed at the end of a transaction by the container. They must be explicitly closed by the caller.

You can enable non-component callers in the following ways:

Restrictions and Optimizations

This section discusses restrictions and performance optimizations that affect using the JDBC API.

Disabling Stored Procedure Creation on Sybase

By default, DataDirect and Sun GlassFish JDBC drivers for Sybase databases create a stored procedure for each parameterized PreparedStatement. On the Enterprise Server, exceptions are thrown when primary key identity generation is attempted. To disable the creation of these stored procedures, set the property PrepareMethod=direct.

Chapter 16 Using the Transaction Service

The Java EE platform provides several abstractions that simplify development of dependable transaction processing for applications. This chapter discusses Java EE transactions and transaction support in the Sun GlassFish Enterprise Server.

This chapter contains the following sections:

For more information about the JavaTM Transaction API (JTA) and Java Transaction Service (JTS), see Chapter 12, Transactions, in Sun GlassFish Enterprise Server v2.1.1 Administration Guide and the following sites: http://java.sun.com/products/jta/ and http://java.sun.com/products/jts/.

You might also want to read “Chapter 35: Transactions” in the Java EE 5 Tutorial.

Transaction Resource Managers

There are three types of transaction resource managers:

For details about how transaction resource managers, the transaction service, and applications interact, see Chapter 12, Transactions, in Sun GlassFish Enterprise Server v2.1.1 Administration Guide.

Transaction Scope

A local transaction involves only one non-XA resource and requires that all participating application components execute within one process. Local transaction optimization is specific to the resource manager and is transparent to the Java EE application.

In the Enterprise Server, a JDBC resource is non-XA if it meets any of the following criteria:

A transaction remains local if the following conditions remain true:

Transactions that involve multiple resources or multiple participant processes are distributed or global transactions. A global transaction can involve one non-XA resource if last agent optimization is enabled. Otherwise, all resourced must be XA. The use-last-agent-optimization property is set to true by default. For details about how to set this property, see Configuring the Transaction Service.

If only one XA resource is used in a transaction, one-phase commit occurs, otherwise the transaction is coordinated with a two-phase commit protocol.

A two-phase commit protocol between the transaction manager and all the resources enlisted for a transaction ensures that either all the resource managers commit the transaction or they all abort. When the application requests the commitment of a transaction, the transaction manager issues a PREPARE_TO_COMMIT request to all the resource managers involved. Each of these resources can in turn send a reply indicating whether it is ready for commit (PREPARED) or not (NO). Only when all the resource managers are ready for a commit does the transaction manager issue a commit request (COMMIT) to all the resource managers. Otherwise, the transaction manager issues a rollback request (ABORT) and the transaction is rolled back.

Distributed Transaction Recovery


Note –

Some topics in the documentation pertain to features that are available only in domains that are configured to support clusters. Examples of domains that support clusters are domains that are created with the cluster profile or the enterprise profile. For information about profiles, see Usage Profiles in Sun GlassFish Enterprise Server v2.1.1 Administration Guide.


To enable cluster-wide automatic recovery, you must first facilitate storing of transaction logs in a shared file system. You can do this in one of these ways:

Next, you must set the transaction service's delegated-recovery property to true (the default is false).

For information about setting tx-log-dir and delegated-recovery, see Configuring the Transaction Service. For information about setting log-root and other general logging settings, see Chapter 17, Configuring Logging, in Sun GlassFish Enterprise Server v2.1.1 Administration Guide. For information about system-property and the domain.xml file, see the Sun GlassFish Enterprise Server v2.1.1 Administration Reference.

Configuring the Transaction Service

You can configure the transaction service in the Enterprise Server in the following ways:

The Transaction Manager, the Transaction Synchronization Registry, and UserTransaction

You can access the Enterprise Server transaction manager, a javax.transaction.TransactionManager implementation, using the JNDI subcontext java:comp/TransactionManager or java:appserver/TransactionManager. You can access the Enterprise Server transaction synchronization registry, a javax.transaction.TransactionSynchronizationRegistry implementation, using the JNDI subcontext java:comp/TransactionSynchronizationRegistry or java:appserver/TransactionSynchronizationRegistry. You can also request injection of a TransactionManager or TransactionSynchronizationRegistry object using the @Resource annotation. Accessing the transaction synchronization registry is recommended. For details, see Java Specification Request (JSR) 907.

You can also access java:comp/UserTransaction.

Transaction Logging

The transaction service writes transactional activity into transaction logs so that transactions can be recovered. You can control transaction logging in these ways:

Storing Transaction Logs in a Database

For multi-core machines, logging transactions to a database may be more efficient.

To log transactions to a database, follow these steps:

  1. Create a JDBC connection Pool, and set the non-transactional-connections attribute to true.

  2. Create a JDBC resource that uses the connection pool and note the JNDI name of the JDBC resource.

  3. Create a table named txn_log_table with the schema shown in Table 16–1.

  4. Add the db-logging-resource property to the transaction service. For example:


    asadmin set --user adminuser server1.transaction-service.property.db-logging-resource="jdbc/TxnDS"

    The property's value should be the JNDI name of the JDBC resource configured previously.

  5. To disable file synchronization, use the following asadmin create-jvm-options command:


    asadmin create-jvm-options --user adminuser -Dcom.sun.appserv.transaction.nofdsync
  6. Restart the server.

For information about JDBC connection pools and resources, see Chapter 15, Using the JDBC API for Database Access. For more information about the asadmin create-jvm-options command, see the Sun GlassFish Enterprise Server v2.1.1 Reference Manual.

Table 16–1 Schema for txn_log_table

Column Name 

JDBC Type 

LOCALTID

BIGINT

SERVERNAME

VARCHAR(n)

GTRID

VARBINARY

The size of the SERVERNAME column should be at least the length of the Enterprise Server host name plus 10 characters.

The size of the GTRID column should be at least 64 bytes.

To define the SQL used by the transaction manager when it is storing its transaction logs in the database, use the following flags:

-Dcom.sun.jts.dblogging.insertquery=sql statement
-Dcom.sun.jts.dblogging.deletequery=sql statement

The default statements are as follows:

-Dcom.sun.jts.dblogging.insertquery=insert into txn_log_table values ( ?, ? , ? )
-Dcom.sun.jts.dblogging.deletequery=delete from txn_log_table where localtid = ? and servername = ?

To set one of these flags using the asadmin create-jvm-options command, you must quote the statement. For example:

create-jvm-options '-Dcom.sun.jts.dblogging.deletequery=delete from txn_log_table where gtrid = ?'

You can also set JVM options in the Admin Console. In the developer profile, select the Application Server component and the JVM Settings tab. In the cluster profile, select the JVM Settings component under the relevant configuration. These flags and their statements must also be quoted in the Admin Console. For example:

'-Dcom.sun.jts.dblogging.deletequery=delete from txn_log_table where gtrid = ?'

Recovery Workarounds

The Enterprise Server provides workarounds for some known issues with the recovery implementations of the following JDBC drivers. These workarounds are used unless explicitly disabled.

In the Oracle thin driver, the XAResource.recover method repeatedly returns the same set of in-doubt Xids regardless of the input flag. According to the XA specifications, the Transaction Manager initially calls this method with TMSTARTSCAN and then with TMNOFLAGS repeatedly until no Xids are returned. The XAResource.commit method also has some issues.

To disable the Enterprise Server workaround, set the oracle-xa-recovery-workaround property value to false. For details about how to set this property, see Configuring the Transaction Service.


Note –

These workarounds do not imply support for any particular JDBC driver.


Chapter 17 Using the Java Naming and Directory Interface

A naming service maintains a set of bindings, which relate names to objects. The Java EE naming service is based on the Java Naming and Directory InterfaceTM (JNDI) API. The JNDI API allows application components and clients to look up distributed resources, services, and EJB components. For general information about the JNDI API, see http://java.sun.com/products/jndi/.

You can also see the JNDI tutorial at http://java.sun.com/products/jndi/tutorial/.

This chapter contains the following sections:

Accessing the Naming Context

The Enterprise Server provides a naming environment, or context, which is compliant with standard Java EE requirements. A Context object provides the methods for binding names to objects, unbinding names from objects, renaming objects, and listing the bindings. The InitialContext is the handle to the Java EE naming service that application components and clients use for lookups.

The JNDI API also provides subcontext functionality. Much like a directory in a file system, a subcontext is a context within a context. This hierarchical structure permits better organization of information. For naming services that support subcontexts, the Context class also provides methods for creating and destroying subcontexts.

The rest of this section covers these topics:


Note –

Each resource within a server instance must have a unique name. However, two resources in different server instances or different domains can have the same name.


Global JNDI Names

Global JNDI names are assigned according to the following precedence rules:

  1. A global JNDI name assigned in the sun-ejb-jar.xml, sun-web.xml, or sun-application-client.xml deployment descriptor file has the highest precedence. See Mapping References.

  2. A global JNDI name assigned in a mapped-name element in the ejb-jar.xml, web.xml, or application-client.xml deployment descriptor file has the second highest precedence. The following elements have mapped-name subelements: resource-ref, resource-env-ref, ejb-ref, message-destination, message-destination-ref, session, message-driven, and entity.

  3. A global JNDI name assigned in a mappedName attribute of an annotation has the third highest precedence. The following annotations have mappedName attributes: @javax.annotation.Resource, @javax.ejb.EJB, @javax.ejb.Stateless, @javax.ejb.Stateful, and @javax.ejb.MessageDriven.

  4. A default global JNDI name is assigned in some cases if no name is assigned in deployment descriptors or annotations.

    • For an EJB 2.x dependency or a session or entity bean with a remote interface, the default is the fully qualified name of the home interface.

    • For an EJB 3.0 dependency or a session bean with a remote interface, the default is the fully qualified name of the remote business interface.

    • If both EJB 2.x and EJB 3.0 remote interfaces are specified, or if more than one 3.0 remote interface is specified, there is no default, and the global JNDI name must be specified.

    • For all other component dependencies that must be mapped to global JNDI names, the default is the name of the dependency relative to java:comp/env. For example, in the @Resource(name="jdbc/Foo") DataSource ds; annotation, the global JNDI name is jdbc/Foo.

Accessing EJB Components Using the CosNaming Naming Context

The preferred way of accessing the naming service, even in code that runs outside of a Java EE container, is to use the no-argument InitialContext constructor. However, if EJB client code explicitly instantiates an InitialContext that points to the CosNaming naming service, it is necessary to set the java.naming.factory.initial property to com.sun.jndi.cosnaming.CNCtxFactory in the client JVM when accessing EJB components. You can set this property as a command-line argument, as follows:


-Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory

Or you can set this property in the code, as follows:

Properties properties = null;
      try {
            properties = new Properties();
            properties.put("java.naming.factory.initial",
                  "com.sun.jndi.cosnaming.CNCtxFactory");
      ...

The java.naming.factory.initial property applies to only one instance; it is not cluster-aware.

Accessing EJB Components in a Remote Application Server

The recommended approach for looking up an EJB component in a remote Enterprise Server from a client that is a servlet or EJB component is to use the Interoperable Naming Service syntax. Host and port information is prepended to any global JNDI names and is automatically resolved during the lookup. The syntax for an interoperable global name is as follows:

corbaname:iiop:host:port#a/b/name

This makes the programming model for accessing EJB components in another Enterprise Server exactly the same as accessing them in the same server. The deployer can change the way the EJB components are physically distributed without having to change the code.

For Java EE components, the code still performs a java:comp/env lookup on an EJB reference. The only difference is that the deployer maps the ejb-reference element to an interoperable name in an Enterprise Server deployment descriptor file instead of to a simple global JNDI name.

For example, suppose a servlet looks up an EJB reference using java:comp/env/ejb/Foo, and the target EJB component has a global JNDI name of a/b/Foo.

The ejb-ref element in sun-web.xml looks like this:

<ejb-ref>
   <ejb-ref-name>ejb/Foo</ejb-ref-name>
   <jndi-name>corbaname:iiop:host:port#a/b/Foo</jndi-name>
<ejb-ref>

The code looks like this:

Context ic = new InitialContext();
Object o = ic.lookup("java:comp/env/ejb/Foo");

For a client that doesn’t run within a Java EE container, the code just uses the interoperable global name instead of the simple global JNDI name. For example:

Context ic = new InitialContext();
Object o = ic.lookup("corbaname:iiop:host:port#a/b/Foo");

Objects stored in the interoperable naming context and component-specific (java:comp/env) naming contexts are transient. On each server startup or application reloading, all relevant objects are re-bound to the namespace.

Naming Environment for Lifecycle Modules

Lifecycle listener modules provide a means of running short or long duration tasks based on Java technology within the application server environment, such as instantiation of singletons or RMI servers. These modules are automatically initiated at server startup and are notified at various phases of the server life cycle. For details about lifecycle modules, see Chapter 13, Developing Lifecycle Listeners.

The configured properties for a lifecycle module are passed as properties during server initialization (the INIT_EVENT). The initial JNDI naming context is not available until server initialization is complete. A lifecycle module can get the InitialContext for lookups using the method LifecycleEventContext.getInitialContext() during, and only during, the STARTUP_EVENT, READY_EVENT, or SHUTDOWN_EVENT server life cycle events.

Configuring Resources

The Enterprise Server exposes the following special resources in the naming environment. Full administration details are provided in the following sections:

External JNDI Resources

An external JNDI resource defines custom JNDI contexts and implements the javax.naming.spi.InitialContextFactory interface. There is no specific JNDI parent context for external JNDI resources, except for the standard java:comp/env/.

Create an external JNDI resource in one of these ways:

Custom Resources

A custom resource specifies a custom server-wide resource object factory that implements the javax.naming.spi.ObjectFactory interface. There is no specific JNDI parent context for external JNDI resources, except for the standard java:comp/env/.

Create a custom resource in one of these ways:

Using a Custom jndi.properties File

To use a custom jndi.properties file, specify the path to the file in one of the following ways:

This adds the jndi.properties file to the Shared Chain class loader. For more information about class loading, see Chapter 2, Class Loaders.

For each property found in more than one jndi.properties file, the Java EE naming service either uses the first value found or concatenates all of the values, whichever makes sense.

Mapping References

The following XML elements in the Enterprise Server deployment descriptors map resource references in application client, EJB, and web application components to JNDI names configured in the Enterprise Server:

These elements are part of the sun-web.xml, sun-ejb-ref.xml, and sun-application-client.xml deployment descriptor files. For more information about how these elements behave in each of the deployment descriptor files, see Appendix A, Deployment Descriptor Files, in Sun GlassFish Enterprise Server v2.1.1 Application Deployment Guide.

The rest of this section uses an example of a JDBC resource lookup to describe how to reference resource factories. The same principle is applicable to all resources (such as JMS destinations, JavaMail sessions, and so on).

The @Resource annotation in the application code looks like this:

@Resource(name="jdbc/helloDbDs") javax.sql.DataSource ds;

This references a resource with the JNDI name of java:comp/env/jdbc/helloDbDs. If this is the JNDI name of the JDBC resource configured in the Enterprise Server, the annotation alone is enough to reference the resource.

However, you can use an Enterprise Server specific deployment descriptor to override the annotation. For example, the resource-ref element in the sun-web.xml file maps the res-ref-name (the name specified in the annotation) to the JNDI name of another JDBC resource configured in the Enterprise Server.

<resource-ref>
   <res-ref-name>jdbc/helloDbDs</res-ref-name>
   <jndi-name>jdbc/helloDbDataSource</jndi-name>
</resource-ref>

Chapter 18 Using the Java Message Service

This chapter describes how to use the JavaTM Message Service (JMS) API. The Sun Java System Enterprise Server has a fully integrated JMS provider: the Sun Java System Message Queue software.

For general information about the JMS API, see “Chapter 31: The Java Message Service API” in the Java EE 5 Tutorial.

For detailed information about JMS concepts and JMS support in the Enterprise Server, see Chapter 4, Configuring Java Message Service Resources, in Sun GlassFish Enterprise Server v2.1.1 Administration Guide.

This chapter contains the following sections:

The JMS Provider

The Enterprise Server support for JMS messaging, in general, and for message-driven beans, in particular, requires messaging middleware that implements the JMS specification: a JMS provider. The Enterprise Server uses the Sun GlassFish Message Queue software as its native JMS provider. The Message Queue software is tightly integrated into theEnterprise Server, providing transparent JMS messaging support. This support is known within Enterprise Server as the JMS Service. The JMS Service requires only minimal administration.

The relationship of the Message Queue software to the Enterprise Server can be one of these types: EMBEDDED, LOCAL, or REMOTE. The effects of these choices on the Message Queue broker life cycle are as follows:

For more information about setting the type and the default JMS host, see Configuring the JMS Service.

For more information about the Message Queue software, refer to the documentation at http://docs.sun.com/coll/1343.11.

For general information about the JMS API, see the JMS web page at http://java.sun.com/products/jms/index.html.


Note –

Some topics in the documentation pertain to features that are available only in domains that are configured to support clusters. Examples of domains that support clusters are domains that are created with the cluster profile or the enterprise profile. For information about profiles, see Usage Profiles in Sun GlassFish Enterprise Server v2.1.1 Administration Guide.


Message Queue Resource Adapter

The Sun GlassFish Message Queue software is integrated into the Enterprise Server using a resource adapter that is compliant with the Connector specification. The module name of this system resource adapter is jmsra. Every JMS resource is converted to a corresponding connector resource of this resource adapter as follows:

You use connector configuration tools to manage JMS resources. For more information, see Chapter 12, Developing Connectors.

Generic Resource Adapter

The Enterprise Server provides a generic resource adapter for JMS, for those who want to use a JMS provider other than Sun GlassFish Message Queue. For details, see http://genericjmsra.dev.java.net/ and Configuring the Generic Resource Adapter for JMS in Sun GlassFish Enterprise Server v2.1.1 Administration Guide.

Administration of the JMS Service

To configure the JMS Service and prepare JMS resources for use in applications deployed to the Enterprise Server, you must perform these tasks:

For more information about JMS administration tasks, see Chapter 4, Configuring Java Message Service Resources, in Sun GlassFish Enterprise Server v2.1.1 Administration Guide and the Sun GlassFish Message Queue 4.4 Administration Guide.

Configuring the JMS Service

The JMS Service configuration is available to all inbound and outbound connections pertaining to the Enterprise Server cluster or instance. You can edit the JMS Service configuration in the following ways:

You can override the JMS Service configuration using JMS connection factory settings. For details, see Chapter 4, Configuring Java Message Service Resources, in Sun GlassFish Enterprise Server v2.1.1 Administration Guide.


Note –

The Enterprise Server instance must be restarted after configuration of the JMS Service.


The Default JMS Host

A JMS host refers to a Sun GlassFish Message Queue broker. A default JMS host for the JMS service is provided, named default_JMS_host. This is the JMS host that the Enterprise Server uses for performing all Message Queue broker administrative operations, such as creating and deleting JMS destinations.

If you have created a multi-broker cluster in the Message Queue software, delete the default JMS host, then add the Message Queue cluster’s brokers as JMS hosts. In this case, the default JMS host becomes the first JMS host in the AddressList. For more information about the AddressList, see JMS Connection Features. You can also explicitly set the default JMS host; see Configuring the JMS Service.

When the Enterprise Server uses a Message Queue cluster, it executes Message Queue specific commands on the default JMS host. For example, when a physical destination is created for a Message Queue cluster of three brokers, the command to create the physical destination is executed on the default JMS host, but the physical destination is used by all three brokers in the cluster.

Creating JMS Hosts

You can create additional JMS hosts in the following ways:

For machines having more than one host, use the Host field in the Admin Console or the -–mqhost option of create-jms-host to specify the address to which the broker binds.

Checking Whether the JMS Provider Is Running

You can use the asadmin jms-ping command to check whether a Sun GlassFish Message Queue instance is running. For details, see the Sun GlassFish Enterprise Server v2.1.1 Reference Manual.

Creating Physical Destinations

Produced messages are delivered for routing and subsequent delivery to consumers using physical destinations in the JMS provider. A physical destination is identified and encapsulated by an administered object (a Topic or Queue destination resource) that an application component uses to specify the destination of messages it is producing and the source of messages it is consuming.

If a message-driven bean is deployed and the Queue physical destination it listens to doesn’t exist, the Enterprise Server automatically creates the physical destination and sets the value of the property maxNumActiveConsumers to -1 (see Load-Balanced Message Inflow). However, it is good practice to create the Queue physical destination beforehand.

You can create a JMS physical destination in the following ways:

To purge all messages currently queued at a physical destination, use the asadmin flush-jmsdest command. This deletes the messages before they reach any message consumers. For details, see the Sun GlassFish Enterprise Server v2.1.1 Reference Manual.

To create a destination resource, see Creating JMS Resources: Destinations and Connection Factories.

Creating JMS Resources: Destinations and Connection Factories

You can create two kinds of JMS resources in the Enterprise Server:

In either case, the steps for creating a JMS resource are the same. You can create a JMS resource in the following ways:


Note –

All JMS resource properties that used to work with version 7 of the Enterprise Server are supported for backward compatibility.


Restarting the JMS Client After JMS Configuration

When a JMS client accesses a JMS administered object for the first time, the client JVM retrieves the JMS service configuration from the Enterprise Server. Further changes to the configuration are not available to the client JVM until the client is restarted.

JMS Connection Features

The Sun GlassFish Message Queue software supports the following JMS connection features:

Both these features use the AddressList configuration, which is populated with the hosts and ports of the JMS hosts defined in the Enterprise Server. The AddressList is updated whenever a JMS host configuration changes. The AddressList is inherited by any JMS resource when it is created and by any MDB when it is deployed.


Note –

In the Sun GlassFish Message Queue software, the AddressList property is called imqAddressList.


Connection Pooling

The Enterprise Server pools JMS connections automatically.

To dynamically modify connection pool properties using the Admin Console, go to either the Connection Factories page (see Creating JMS Resources: Destinations and Connection Factories) or the Connector Connection Pools page (see Deploying and Configuring a Stand-Alone Connector Module).

To use the command line, use the asadmin create-connector-connection-pool command to manage the pool (see Deploying and Configuring a Stand-Alone Connector Module.

For the developer profile, the addresslist-behavior JMS service attribute is set to random by default. This means that each ManagedConnection (physical connection) created from the ManagedConnectionFactory selects its primary broker in a random way from the AddressList.

For the cluster and enterprise profiles, the addresslist-behavior JMS service attribute is set to priority by default. This means that the first broker in the AddressList is selected first. This first broker is the local colocated Message Queue broker. If this broker is unavailable, connection attempts are made to brokers in the order in which they are listed in the AddressList. This ensures colocated production and consumption of messages and equitable load distribution across the Message Queue broker cluster.

When a JMS connection pool is created, there is one ManagedConnectionFactory instance associated with it. If you configure the AddressList as a ManagedConnectionFactory property, the AddressList configuration in the ManagedConnectionFactory takes precedence over the one defined in the Enterprise Server.

Connection Failover

To specify whether the Enterprise Server tries to reconnect to the primary broker if the connection is lost, set the reconnect-enabled attribute in the JMS service. To specify the number of retries and the time between retries, set the reconnect-attempts and reconnect-interval-in-seconds attributes, respectively.

If reconnection is enabled and the primary broker goes down, the Enterprise Server tries to reconnect to another broker in the AddressList. The AddressList is updated whenever a JMS host configuration changes. The logic for scanning is decided by two JMS service attributes, addresslist-behavior and addresslist-iterations.

You can override these settings using JMS connection factory settings. For details, see Chapter 4, Configuring Java Message Service Resources, in Sun GlassFish Enterprise Server v2.1.1 Administration Guide.

The Sun GlassFish Message Queue software transparently transfers the load to another broker when the failover occurs. JMS semantics are maintained during failover.

Load-Balanced Message Inflow

You can configure ActivationSpec properties of the jmsra resource adapter in the sun-ejb-jar.xml file for a message-driven bean using activation-config-property elements. Whenever a message-driven bean (EndPointFactory) is deployed, the connector runtime engine finds these properties and configures them accordingly in the resource adapter. See activation-config-property in Sun GlassFish Enterprise Server v2.1.1 Application Deployment Guide.

The Enterprise Server transparently enables messages to be delivered in random fashion to message-driven beans having same ClientID. The ClientID is required for durable subscribers.

For nondurable subscribers in which the ClientID is not configured, all instances of a specific message-driven bean that subscribe to same topic are considered equal. When a message-driven bean is deployed to multiple instances of the Enterprise Server, only one of the message-driven beans receives the message. If multiple distinct message-driven beans subscribe to same topic, one instance of each message-driven bean receives a copy of the message.

To support multiple consumers using the same queue, set the maxNumActiveConsumers property of the physical destination to a large value. If this property is set, the Sun GlassFish Message Queue software allows multiple message-driven beans to consume messages from same queue. The message is delivered randomly to the message-driven beans. If maxNumActiveConsumers is set to -1, there is no limit to the number of consumers.

To ensure that local delivery is preferred, set addresslist-behavior to priority. This setting specifies that the first broker in the AddressList is selected first. This first broker is the local colocated Message Queue instance. If this broker is unavailable, connection attempts are made to brokers in the order in which they are listed in the AddressList. This setting is the default for Enterprise Server instances that belong to a cluster.


Note –

Some topics in the documentation pertain to features that are available only in domains that are configured to support clusters. Examples of domains that support clusters are domains that are created with the cluster profile or the enterprise profile. For information about profiles, see Usage Profiles in Sun GlassFish Enterprise Server v2.1.1 Administration Guide.


JMS Service High Availability

There are two levels of availability for JMS components:

You can enable data availability in the Sun GlassFish Message Queue cluster that comprises the Java Message Service (JMS). Messages are saved to the high-availability database (HADB) if HADB is installed, data availability is enabled, and the enterprise profile is selected. For information about profiles, see Usage Profiles in Sun GlassFish Enterprise Server v2.1.1 Administration Guide. You must enable availability for the Enterprise Server instances before you can enable data availability for the corresponding brokers.


Note –

Individual applications and modules cannot control or override JMS availability.


To enable data availability, select the Availability Service component under the relevant configuration in the Admin Console. Check the Availability Service box. To enable availability for the JMS service, select the JMS Availability tab, then check the Availability Service box. All instances in an Enterprise Server cluster should have the same instance availability and JMS availability settings to ensure consistent behavior. For details, see the Sun GlassFish Enterprise Server v2.1.1 High Availability Administration Guide.


Note –

Some topics in the documentation pertain to features that are available only in domains that are configured to support clusters. Examples of domains that support clusters are domains that are created with the cluster profile or the enterprise profile. For information about profiles, see Usage Profiles in Sun GlassFish Enterprise Server v2.1.1 Administration Guide.


Transactions and Non-Persistent Messages

During transaction recovery, non-persistent messages might be lost. If the broker fails between the transaction manager’s prepare and commit operations, any non-persistent message in the transaction is lost and cannot be delivered. A message that is not saved to a persistent store is not available for transaction recovery.

Authentication With ConnectionFactory

If your web, EJB, or client module has res-auth set to Container, but you use the ConnectionFactory.createConnection("user","password") method to get a connection, the Enterprise Server searches the container for authentication information before using the supplied user and password. Version 7 of the Enterprise Server threw an exception in this situation.

Message Queue varhome Directory

The Sun GlassFish Message Queue software uses a default directory for storing data such as persistent messages and its log file. This directory is called varhome. The Enterprise Server uses domain-dir/imq as the varhome directory if the type of relationship between the Enterprise Server and the Message Queue software is LOCAL or EMBEDDED. If the relationship type is REMOTE, the Message Queue software determines the varhome location. For more information about the types of relationships between the Enterprise Server and Message Queue, see The JMS Provider.

When executing Message Queue scripts such as as-install/imq/bin/imqusermgr, use the -varhome option to point the scripts to the Message Queue data if the relationship type is LOCAL or EMBEDDED. For example:

imqusermgr -varhome $AS_INSTALL/domains/domain1/imq add -u testuser

For more information about the Message Queue software, refer to the documentation at http://docs.sun.com/coll/1343.11.

Delivering SOAP Messages Using the JMS API

Web service clients use the Simple Object Access Protocol (SOAP) to communicate with web services. SOAP uses a combination of XML-based data structuring and Hyper Text Transfer Protocol (HTTP) to define a standardized way of invoking methods in objects distributed in diverse operating environments across the Internet.

For more information about SOAP, see the Apache SOAP web site at http://xml.apache.org/soap/index.html.

You can take advantage of the JMS provider’s reliable messaging when delivering SOAP messages. You can convert a SOAP message into a JMS message, send the JMS message, then convert the JMS message back into a SOAP message. The following sections explain how to do these conversions:

ProcedureTo Send SOAP Messages Using the JMS API

  1. Import the MessageTransformer library.

    import com.sun.messaging.xml.MessageTransformer;

    This is the utility whose methods you use to convert SOAP messages to JMS messages and the reverse. You can then send a JMS message containing a SOAP payload as if it were a normal JMS message.

  2. Initialize the TopicConnectionFactory, TopicConnection, TopicSession, and publisher.

    tcf = new TopicConnectionFactory();
    tc = tcf.createTopicConnection();
    session = tc.createTopicSession(false,Session.AUTO_ACKNOWLEDGE);
    topic = session.createTopic(topicName);
    publisher = session.createPublisher(topic);
  3. Construct a SOAP message using the SOAP with Attachments API for Java (SAAJ).

    /*construct a default soap MessageFactory */
    MessageFactory mf = MessageFactory.newInstance();
    * Create a SOAP message object.*/
    SOAPMessage soapMessage = mf.createMessage();
    /** Get SOAP part.*/
    SOAPPart soapPart = soapMessage.getSOAPPart();
    /* Get SOAP envelope. */
    SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
    /* Get SOAP body.*/
    SOAPBody soapBody = soapEnvelope.getBody();
    /* Create a name object. with name space */
    /* http://www.sun.com/imq. */
    Name name = soapEnvelope.createName("HelloWorld", "hw",
     "http://www.sun.com/imq");
    * Add child element with the above name. */
    SOAPElement element = soapBody.addChildElement(name)
    /* Add another child element.*/
    element.addTextNode( "Welcome to Sun Java System Web Services." );
    /* Create an atachment with activation API.*/
    URL url = new URL ("http://java.sun.com/webservices/");
    DataHandler dh = new DataHandler (url);
    AttachmentPart ap = soapMessage.createAttachmentPart(dh);
    /*set content type/ID. */
    ap.setContentType("text/html");
    ap.setContentId("cid-001");
    /**  add the attachment to the SOAP message.*/
    soapMessage.addAttachmentPart(ap);
    soapMessage.saveChanges();
  4. Convert the SOAP message to a JMS message by calling the MessageTransformer.SOAPMessageintoJMSMessage() method.

    Message m = MessageTransformer.SOAPMessageIntoJMSMessage (soapMessage, 
    session );
  5. Publish the JMS message.

    publisher.publish(m);
  6. Close the JMS connection.

    tc.close();

ProcedureTo Receive SOAP Messages Using the JMS API

  1. Import the MessageTransformer library.

    import com.sun.messaging.xml.MessageTransformer;

    This is the utility whose methods you use to convert SOAP messages to JMS messages and the reverse. The JMS message containing the SOAP payload is received as if it were a normal JMS message.

  2. Initialize the TopicConnectionFactory, TopicConnection, TopicSession, TopicSubscriber, and Topic.

    messageFactory = MessageFactory.newInstance();
    tcf = new com.sun.messaging.TopicConnectionFactory();
    tc = tcf.createTopicConnection();
    session = tc.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
    topic = session.createTopic(topicName);
    subscriber = session.createSubscriber(topic);
    subscriber.setMessageListener(this);
    tc.start();
  3. Use the OnMessage method to receive the message. Use the SOAPMessageFromJMSMessage method to convert the JMS message to a SOAP message.

    public void onMessage (Message message) {
    SOAPMessage soapMessage =
     MessageTransformer.SOAPMessageFromJMSMessage( message,
     messageFactory ); }
  4. Retrieve the content of the SOAP message.

Chapter 19 Using the JavaMail API

This chapter describes how to use the JavaMailTM API, which provides a set of abstract classes defining objects that comprise a mail system.

This chapter contains the following sections:

Introducing JavaMail

The JavaMail API defines classes such as Message, Store, and Transport. The API can be extended and can be subclassed to provide new protocols and to add functionality when necessary. In addition, the API provides concrete subclasses of the abstract classes. These subclasses, including MimeMessage and MimeBodyPart, implement widely used Internet mail protocols and conform to the RFC822 and RFC2045 specifications. The JavaMail API includes support for the IMAP4, POP3, and SMTP protocols.

The JavaMail architectural components are as follows:

For more information, see Chapter 5, Configuring JavaMail Resources, in Sun GlassFish Enterprise Server v2.1.1 Administration Guide and the JavaMail specification at http://java.sun.com/products/javamail/. A useful JavaMail tutorial is located at http://java.sun.com/developer/onlineTraining/JavaMail/.

Creating a JavaMail Session

You can create a JavaMail session in the following ways:

JavaMail Session Properties

You can set properties for a JavaMail Session object. Every property name must start with a mail- prefix. The Enterprise Server changes the dash (-) character to a period (.) in the name of the property and saves the property to the MailConfiguration and JavaMail Session objects. If the name of the property doesn’t start with mail-, the property is ignored.

For example, if you want to define the property mail.from in a JavaMail Session object, first define the property as follows:

Looking Up a JavaMail Session

The standard Java Naming and Directory Interface (JNDI) subcontext for JavaMail sessions is java:comp/env/mail.

Registering JavaMail sessions in the mail naming subcontext of a JNDI namespace, or in one of its child subcontexts, is standard. The JNDI namespace is hierarchical, like a file system’s directory structure, so it is easy to find and nest references. A JavaMail session is bound to a logical JNDI name. The name identifies a subcontext, mail, of the root context, and a logical name. To change the JavaMail session, you can change its entry in the JNDI namespace without having to modify the application.

The resource lookup in the application code looks like this:

InitialContext ic = new InitialContext();
String snName = "java:comp/env/mail/MyMailSession";
Session session = (Session)ic.lookup(snName);

For more information about the JNDI API, see Chapter 17, Using the Java Naming and Directory Interface.

Sending and Reading Messages Using JavaMail

The following sections describe how to send and read messages using the JavaMail API:

ProcedureTo Send a Message Using JavaMail

  1. Import the packages that you need.

    import java.util.*;
    import javax.activation.*;
    import javax.mail.*;
    import javax.mail.internet.*;
    import javax.naming.*;
  2. Look up the JavaMail session.

    InitialContext ic = new InitialContext();
    String snName = "java:comp/env/mail/MyMailSession";
    Session session = (Session)ic.lookup(snName);

    For more information, see Looking Up a JavaMail Session.

  3. Override the JavaMail session properties if necessary.

    For example:

    Properties props = session.getProperties();
    props.put("mail.from", "user2@mailserver.com");
  4. Create a MimeMessage.

    The msgRecipient, msgSubject, and msgTxt variables in the following example contain input from the user:

    Message msg = new MimeMessage(session);
    msg.setSubject(msgSubject);
    msg.setSentDate(new Date());
    msg.setFrom();
    msg.setRecipients(Message.RecipientType.TO, 
       InternetAddress.parse(msgRecipient, false));
    msg.setText(msgTxt);
  5. Send the message.

    Transport.send(msg);

ProcedureTo Read a Message Using JavaMail

  1. Import the packages that you need.

    import java.util.*;
    import javax.activation.*;
    import javax.mail.*;
    import javax.mail.internet.*;
    import javax.naming.*;
  2. Look up the JavaMail session.

    InitialContext ic = new InitialContext();
    String snName = "java:comp/env/mail/MyMailSession";
    Session session = (javax.mail.Session)ic.lookup(snName);

    For more information, see Looking Up a JavaMail Session.

  3. Override the JavaMail session properties if necessary.

    For example:

    Properties props = session.getProperties();
    props.put("mail.from", "user2@mailserver.com");
  4. Get a Store object from the Session, then connect to the mail server using the Store object’s connect() method.

    You must supply a mail server name, a mail user name, and a password.

    Store store = session.getStore();
    store.connect("MailServer", "MailUser", "secret");
  5. Get the INBOX folder.

    Folder folder = store.getFolder("INBOX");
  6. It is efficient to read the Message objects (which represent messages on the server) into an array.

    Message[] messages = folder.getMessages();

Chapter 20 Using the Application Server Management Extensions

Sun GlassFish Enterprise Server uses Enterprise Server Management eXtensions (AMX) for management and monitoring purposes. AMX technology exposes managed resources for remote management as the JavaTM Management eXtensions (JMXTM) API.

The Enterprise Server incorporates the JMX 1.2 Reference Implementation, which was developed by the Java Community Process as Java Specification Request (JSR) 3, and the JMX Remote API 1.0 Reference Implementation , which is JSR 160.

This chapter assumes some familiarity with the JMX technology, but the AMX interfaces can be used for the most part without understanding JMX. For more information about JMX, see the JMX specifications and Reference Implementations.

For information about creating custom MBeans, see Chapter 14, Developing Custom MBeans.

This chapter contains the following topics:

About AMX

AMX is an API that exposes all of the Enterprise Server configuration, monitoring and JSR 77 MBeans as easy-to-use client-side dynamic proxies implementing the AMX interfaces. To understand the design and implementation of the AMX API, you can get started with this white paper.

Complete API documentation for AMX is provided in the Enterprise Server package.

com.sun.appserv.management

The code samples in this section are taken from the package:

com.sun.appserv.management.sample

The Enterprise Server is based around the concept of administration domains. Each domain consists of one or more managed resources. A managed resource can be an Enterprise Server instance, a cluster of such instances, or a manageable entity within a server instance. A managed resource is of a particular type, and each resource type exposes a set of attributes and administrative operations that change the resource’s state.

Managed resources are exposed as JMX management beans, or MBeans. While the MBeans can be accessed using standard JMX APIs (for example, MBeanServerConnection), most users find the use of the AMX client-side dynamic proxies much more convenient.

Virtually all components of the Enterprise Server are visible for monitoring and management through AMX. You can use third-party tools to perform all common administrative tasks programmatically, based on the JMX and JMX Remote API standards.

The AMX API consists of a set of interfaces. The interfaces are implemented by client-side dynamic proxies, each of which is associated with a server-side MBean in the Domain Administration Server (DAS). AMX provides routines to obtain proxies for MBeans, starting with the DomainRoot interface (see http://glassfish.dev.java.net/nonav/javaee5/amx/javadoc/com/sun/appserv/management/DomainRoot.html).


Note –

The term AMX interface in the context of this document should be understood as synonymous with a client-side dynamic proxy implementing that interface.


You can navigate generically through the MBean hierarchy using the com.sun.appserv.management.base.Container interface (see http://glassfish.dev.java.net/nonav/javaee5/amx/javadoc/com/sun/appserv/management/base/Container.html). When using AMX, the interfaces defined are implemented by client-side dynamic proxies, but they also implicitly define the MBeanInfo that is made available by the MBean or MBeans corresponding to it. Certain operations defined in the interface might have a different return type or a slightly different name when accessed through the MBean directly. This results from the fact that direct access to JMX requires the use of ObjectName, whereas the AMX interfaces use strongly typed proxies implementing the interface(s).

AMX MBeans

All AMX MBeans are represented as interfaces in a subpackage of com.sun.appserv.management (see http://glassfish.dev.java.net/nonav/javaee5/amx/javadoc/com/sun/appserv/management/package-summary.html) and are implemented by dynamic proxies on the client-side. Note that client-side means any client, wherever it resides. AMX may be used within the server itself such as in a custom MBean. While you can access AMX MBeans directly through standard JMX APIs, most users find the use of AMX interface (proxy) classes to be most convenient.

An AMX MBean belongs to an Enterprise Server domain. There is exactly one domain per DAS. Thus all MBeans accessible through the DAS belong to a single Enterprise Server administrative domain. All MBeans in an Enterprise Server administrative domain, and hence within the DAS, belong to the JMX domain amx. All AMX MBeans can be reached by navigating through the DomainRoot.


Note –

Any MBeans that do not have the JMX domain amx are not part of AMX, and are neither documented nor supported for use by clients.


AMX defines different types of MBean, namely, configuration MBeans, monitoring MBeans, utility MBeans and Java EE management JSR 77 MBeans. These MBeans are logically related in the following ways:

Configuration MBeans

Configuration information for a given Enterprise Server domain is stored in a central repository that is shared by all instances in that domain. The central repository can only be written to by the DAS. However, configuration information in the central repository is made available to administration clients through AMX MBeans.

The configuration MBeans are those that modify the underlying domain.xml or related files. Collectively, they form a model representing the configuration and deployment repository and the operations that can be performed on them.

The Group Attribute of configuration MBeans, obtained from getGroup(), has a value of com.sun.appserv.management.base.AMX.GROUP_CONFIGURATION.

Monitoring MBeans

Monitoring MBeans provide transient monitoring information about all the vital components of the Enterprise Server.

The Group Attribute of monitoring MBeans, obtained from getGroup(), has a value of com.sun.appserv.management.base.AMX.GROUP_MONITORING.

Utility MBeans

Utility MBeans provide commonly used services to the Enterprise Server.

The Group Attribute of utility MBeans, obtained from getGroup(), has a value of com.sun.appserv.management.base.AMX.GROUP_UTILITY.

Java EE Management MBeans

The Java EE management MBeans implement, and in some cases extend, the management hierarchy as defined by JSR 77, which specifies the management model for the whole Java EE platform.

The AMX JSR 77 MBeans offer access to configuration and monitoring MBeans using the getMonitoringPeer() and getConfigPeer() methods.

The Group Attribute of Java EE management MBeans, obtained from getGroup(), has a value of com.sun.appserv.management.base.AMX.GROUP_JSR77.

Other MBeans

MBeans that do not fit into one of the above four categories have the value com.sun.appserv.management.base.AMX.GROUP_OTHER. One such example is com.sun.appserv.management.deploy.DeploymentMgr (see http://glassfish.dev.java.net/nonav/javaee5/amx/javadoc/com/sun/appserv/management/deploy/DeploymentMgr.html).

MBean Notifications

All AMX MBeans that emit Notifications place a java.util.Map within the UserData field of a standard JMX Notification, which can be obtained using Notification.getUserData(). Within the map are one or more items, which vary according to the Notification type. Each Notification type, and the data available within the Notification, is defined in the Javadoc of the MBean (AMX interface) that emits it.

Note that certain standard Notifications, such as javax.management.AttributeChangeNotification (see http://java.sun.com/javase/6/docs/api/javax/management/AttributeChangeNotification.html) do not and cannot follow this behavior.

Access to MBean Attributes

An AMX MBean Attribute is accessible in three ways:

All dotted names that are accessible through the command line interface are available as Attributes within a single MBean. This includes properties, which are provided as Attributes beginning with the prefix property., for example, server.property.myproperty.


Note –

Certain attributes that ought to be of a specific type, such as int, are declared as java.lang.String. This is because the value of the attribute may be a template of a form such as ${HTTP_LISTENER_PORT}.


Dynamic Client Proxies

Dynamic Client Proxies are an important part of the AMX API, and enhance ease-of-use for the programmer.

JMX MBeans can be used directly by an MBeanServerConnection (see http://java.sun.com/javase/6/docs/api/javax/management/MBeanServerConnection.html) to the server. However, client proxies greatly simplify access to Attributes and operations on MBeans, offering get/set methods and type-safe invocation of operations. Compiling against the AMX interfaces means that compile-time checking is performed, as opposed to server-side runtime checking, when invoked generically through MBeanServerConnection.

See the API documentation for the com.sun.appserv.management package and its sub-packages for more information about using proxies. The API documentation explains the use of AMX with proxies. If you are using JMX directly (for example, by usingMBeanServerConnection), the return type, argument types, and method names might vary as needed for the difference between a strongly-typed proxy interface and generic MBeanServerConnection/ObjectName interface.

Connecting to the Domain Administration Server

As stated in Configuration MBeans, the AMX API allows client applications to connect to Enterprise Server instances using the DAS. All AMX connections are established to the DAS only: AMX does not support direct connections to individual server instances. This makes it simple to interact with all servers, clusters, and so on, with a single connection.

Sample code for connecting to the DAS is shown in Connecting to the DAS. The com.sun.appserv.management.helper.Connect class (see http://glassfish.dev.java.net/nonav/javaee5/amx/javadoc/com/sun/appserv/management/helper/Connect.html) is also available.

Examining AMX Code Samples

An overview of the AMX API and code samples that demonstrate various uses of the AMX API can be found at http://glassfish.dev.java.net/nonav/javaee5/amx/samples/javadoc/index.html and http://glassfish.dev.java.net/nonav/javaee5/amx/samples/javadoc/amxsamples/Samples.html.

The sample implementation is based around the SampleMain class. The principal uses of AMX demonstrated by SampleMain are the following:

All of these actions are performed by commands that you give to SampleMain. Although these commands are executed by SampleMain, they are defined as methods of the class Samples, which is also found in the com.sun.appserv.management.sample package.

The SampleMain Class

The SampleMain class creates a connection to a DAS, and creates an interactive loop in which you can run the various commands defined in Samples that demonstrate different uses of AMX.

Connecting to the DAS

The connection to the DAS is shown in the following code.

[...]
public static AppserverConnectionSource
    connect(
        final String host,
        final int port,
        final String user,
        final String password,
        final TLSParams tlsParams )
        throws IOException
        {
            final String info = "host=" + host + ", port=" + port +
                ", user=" + user + ", password=" + password +
                ", tls=" + (tlsParams != null);

            SampleUtil.println( "Connecting...:" + info );

            final AppserverConnectionSource conn    =
                new AppserverConnectionSource(
                    AppserverConnectionSource.PROTOCOL_RMI,
                    host, port, user, password, tlsParams, null);

            conn.getJMXConnector( false );

            SampleUtil.println( "Connected: " + info );

            return( conn );
        }
[...]

A connection to the DAS is obtained using an instance of the com.sun.appserv.management.client.AppserverConnectionSource class. For the connection to be established, you must know the name of the host and port number on which the DAS is running, and have the correct user name, password and TLS parameters.

After the connection to the DAS is established, DomainRoot is obtained as follows:

DomainRoot domainRoot = appserverConnectionSource.getDomainRoot();

This DomainRoot instance is a client-side dynamic proxy to the MBean amx:j2eeType=X-DomainRoot,name=amx.

See the API documentation for com.sun.appserv.management.client.AppserverConnectionSource for further details about connecting to the DAS using the AppserverConnectionSource class.

However, if you prefer to work with standard JMX, instead of getting DomainRoot, you can get the MBeanServerConnection or JMXConnector, as shown:

MBeanServerConnection conn =
appserverConnectionSource.getMBeanServerConnection( false );
JMXConnector jmxConn =
appserverConnectionSource.getJMXConnector( false );

Starting an Enterprise Server

The Samples.startServer method demonstrates how to start an Enterprise Server.

In this sample AMX implementation, all the tasks are performed by the command start-server when you run SampleMain. See the startServer method to see how this command is implemented. Click the method name to see the source code.

Deploying an Archive

The Samples.uploadArchive() and deploy methods demonstrate how to upload and deploy a Java EE archive file.

Displaying the AMX MBean Hierarchy

The Samples.displayHierarchy method demonstrates how to display the AMX MBean hierarchy.

Setting Monitoring States

The Samples.setMonitoring method demonstrates how to set monitoring states.

Accessing AMX MBeans

The Samples.handleList method demonstrates how to access many (but not all) configuration elements.

Accessing and Displaying the Attributes of an AMX MBean

The Samples.displayAllAttributes method demonstrates how to access and display the attributes of an AMX MBean.

Listing AMX MBean Properties

The Samples.displayAllProperties method demonstrates how to list AMX MBean properties.

Performing Queries

The Samples.demoQuery method demonstrates how to perform queries.

The demoQuery() method uses other methods that are defined by Samples, namely displayWild(), and displayJ2EEType().

Monitoring Attribute Changes

The Samples.demoJMXMonitor method demonstrates how to monitor attribute changes.

Undeploying Modules

The Samples.undeploy method demonstrates how to undeploy a module.

Stopping an Enterprise Server

The Samples.stopServer method demonstrates how to stop an Enterprise Server. The stopServer method simply calls the Samples.getJ2EEServer method on a given server instance, and then calls J2EEServer.stop.

Running the AMX Samples

The following section lists the steps to run the AMX samples.

ProcedureTo Run the AMX Sample

  1. Ensure that the JAR file appserv-ext.jar has been added to your classpath. Some examples also require that j2ee.jar be present.

  2. Define a SampleMain.properties file, which provides the parameters required by AppserverConnectionSource to connect to the DAS.

    The file SampleMain.properties file should use the following format:

    connect.host=localhost
    connect.port=8686
    connect.user=admin
    connect.password=admin123
    connect.truststore=sample-truststore
    connect.truststorePassword=changeme
    connect.useTLS=true

    Note –

    If you are running the Enterprise Server enterprise profile, TLS must be used (provided it has not been turned off). The useTLS property must therefore be set to useTLS=true. For information about profiles, see Usage Profiles in Sun GlassFish Enterprise Server v2.1.1 Administration Guide.


  3. Scripts are provided in the com.sun.appserv.management.sample package to run the AMX samples.

    Start SampleMain by running the appropriate script for your platform:

    • run-samples.sh on UNIX or Linux platforms

    • run-samples.bat on Microsoft Windows platforms

  4. After SampleMain is running, you can interact with it by typing the commands examined above:

    • Enter Command> start-server serverName

    • Enter Command> list-attributes

      You see output like this:

          --- Attributes for X-DomainRoot=amx ---
          AttributeNames=[...]
          BulkAccessObjectName=amx:j2eeType=X-BulkAccess,name=na
          DomainConfigObjectName=amx:j2eeType=X-DomainConfig,name=na
          MBeanInfoIsInvariant=true
          J2EEDomainObjectName=amx:j2eeType=J2EEDomain,name=amx
          AppserverDomainName=amx
          ObjectName=amx:j2eeType=X-DomainRoot,name=amx
          [...]
    • Enter Command> show-hierarchy

      You see output like this:

          X-DomainRoot=amx
          X-ConfigDottedNames
          X-SystemInfo
          X-QueryMgr
          X-DeploymentMgr
          X-UploadDownloadMgr
          X-BulkAccess
          X-MonitoringDottedNames
          X-JMXMonitorMgr
          X-Sample
          X-DomainConfig
          X-WebModuleConfig=admingui
          X-WebModuleConfig=adminapp
          X-WebModuleConfig=com_sun_web_ui
          X-JDBCResourceConfig=jdbc/__default
          X-JDBCResourceConfig=jdbc/__TimerPool
          X-J2EEApplicationConfig=MEjbApp
          [...]
    • Enter Command> list

      You see output like this:

          --- Top-level ---
          ConfigConfig: [server2-config, default-config, server-config,
          server3-config]
          ServerConfig: [server3, server, server2]
          StandaloneServerConfig: [server3, server, server2]
          ClusteredServerConfig: []
          ClusterConfig: []
          [...]
    • Enter Command> list-properties

      You see output like this:

          Properties for:
          amx:j2eeType=X-JDBCConnectionPoolConfig,name=DerbyPool
          Password=pbPublic
      DatabaseName=jdbc:derby://localhost:9092/sun-appserv-samples
          User=pbPublic
          [...]
    • Enter Command> query

      You see output like this:

          --- Queried for j2eeType=X-*ResourceConfig ---
          j2eeType=X-JDBCResourceConfig,name=jdbc/__default
          j2eeType=X-JDBCResourceConfig,name=jdbc/__TimerPool
          [...]
    • And so on for the other commands:

      Enter Command> demo-jmx-monitor

      Enter Command> set-monitoring monitoringLevel (one of HIGH, LOW or OFF)

      Enter Command> stop-server serverName

      Enter Command> quit