Monday Feb 28, 2011

Transparent JDBC Connection Pool Reconfiguration in GlassFish 3.1

Transparent jdbc-connection-pool re-configuration

Transparent jdbc-connection-pool re-configuration


A feature using which redeployment of jdbc-connection-pool due to attribute or property change can be handled transparent to applications that use the pool. Whenever a set of properties / attributes (eg: host-name, port-number etc.,) of jdbc-connection-pool are changed, the connection-pool is destroyed and re-created based on the new values. Any application that is using the connection-pool need to be re-deployed (or application disable and enable must happen) due to pool re-configuration. Using this feature, existing applications can roll-over to new connection pool transparently. It is also possible that there can be in-flight transactions that is using the connections when the pool is re-configured. This feature will make sure that the new requests are queued till re-configuration is complete, however will allow requests that have already acquired atleast one connection from the pool and is part of a transaction. Thus, in-flight transactions' connection requests will be honoured and the transaction can complete.  

A new property named 'dynamic-reconfiguration-wait-timeout-in-seconds' will help to allow in-flight requests to complete.

  • asadmin> set server.resources.jdbc-connection-pool.<POOL_NAME>.property.dynamic-reconfiguration-wait-timeout-in-seconds=30
All new requests will wait for the pool reconfiguration to complete and connections will be acquired using re-configured pool configuration.
All in-use connections, in-flight transactions that span even after 'wait-timeout' is elapsed will have to be re-tried.Applications can define "application" scoped and "module" scoped resources in the archive.

NOTE : Not all attribute changes to jdbc-connection-pool requires application redeploy, eg., steady-pool-size, max-pool-size etc.,



Application Scoped Resources in GlassFish

Application Scoped Resources in GlassFish

Application Scoped Resources


Often, all applications require various type of resources for its usage. These resources can be of JDBC, JMS, Connector, JavaMail, Custom, JNDI etc., User can create resources using appropriate CLI (Command Line Interface) or using GUI. GlassFish supports both of them. There is also support to define resources in an xml file that conforms to "glassfish-resources.dtd" and using "add-resources resources-xml-file" command, all the resources
defined in the resources xml file can be created. Almost all of these options involve multiple step ie., create the resources first and then let the application
use these resources. These resources are usually shared across applications. These resources must also be undeployed when application(s) no longer need them.

Application Scoped Resources helps to bundle the resource definitions along with the application and as part of deployment of the application, these
resources are created and made available to the application. Similarly, these resources will be automatically destroyed when the application is undeployed.
Also, by scoping these resources within the application, these resources are available only for the application and hence can be free from resource-starvation due to other application's usage of these resources.
Java EE 6 also introduces application component environment namespaces which includes the following scopes.
  • java:comp : per component namespace
  • java:module : namespace shared by all components in a module (eg: ejb's in a ejb-jar.xml)
  • java:app : namespace shared by all components, modules in an application (eg: application-client, web component, ejb component in an application, .ear)
  • java:global : global namespace for all applications in the server
Applications can define "application" scoped and "module" scoped resources in the archive.
  • resource's "name"/"jndi-name" attribute prefixed with value "java:module/" will make the resource available all the ejb components defined in its ejb-jar.xml (All EJBs in an ejb-jar.xml)
  • resource's "name"/"jndi-name" attribute prefixed with value "java:app/" will make the resource available across all components/modules in the application (EJBs, Servlet, Application Client in the application)


Sample archive layout that bundles glassfish-resources.xml:


ear
      -> META-INF
                              -> application.xml
                              -> glassfish-resources.xml [Application scoped resources]
      -> web-module
                  -> WEB-INF
                                        -> web.xml
                                        -> glassfish-web.xml
                                        -> glassfish-resources.xml [Module scoped resources]
     -> ejb-module 
                 -> META-INF
                                         -> ejb-jar.xml
                                         -> glassfish-ejb-jar.xml
                                         -> glassfish-resources.xml [Module scoped resources]


Demo application :

The sample application provided demonstrates the usage of jdbc-resources across the application,  on various scopes. The sample has following components
  • web component [Servlet.java]
  • ejb component(s) [HelloStatefulEJB.java and HelloEJB.java]
  • application client [Client.java]
There are three "glassfish-resources.xml" (s) in the application, one at the "ear" level, one each at "web-module" and "ejb-module" level  respectively. (Similar to the "sample archive layout" shown above)
  • application-level glassfish-resources.xml defines a jdbc-connection-pool and jdbc-resource by name "java:app/app-scoped-pool" and "java:app/app-scoped-resource" respectively.
  • glassfish-resources.xml in WEB-INF directory of web-module defines a jdbc-connection-pool and jdbc-resource by name "java:module/web-module-scoped-pool" and "java:module/web-module-scoped-resource" respectively.
  • glassfish-resources.xml in META-INF directory of ejb-module defines a jdbc-connection-pool and jdbc-resource by name "java:module/ejb-module-scoped-pool" and "java:module/ejb-module-scoped-resource" respectively.
When executed for a particular resource name, the sample application will do lookup of the specified resource in Application Client, EJB(s), Servlet and based on the availability
of the resource in the component's scope it will either use the provided resource or the default jdbc-resource (jdbc/__default) when the resource specified is not available
in the component's scope.

Following are the jdbc resources defined (or exported) by the application.


  1. java:app/app-scoped-resource
  2. java:module/ejb-module-scoped-resource
  3. java:module/web-module-scoped-resource



Steps to execute:

  1. Ensure that JDK 1.6 is installed and the environment variable JAVA_HOME is set
    1. Ensure that the environment variable PATH has JAVA_HOME/bin added to it.
  2. Ensure that ANT is installed and the environment variable ANT_HOME is set
    1. Ensure that the environment variable PATH has ANT_HOME/bin added to it.
  3. Download GlassFish 3.1
  4. Install GlassFish 3.1
  5. Start GlassFish (asadmin start-domain domain1)
  6. Start Derby database (asadmin start-database)
  7. Download the sample
  8. Extracted location of sample is referred as "SAMPLE_HOME"
  9. goto SAMPLE_HOME
  10. set environment variable GF_HOME to GlassFish's installation location.
  11. "ant all" will compile, assemble, deploy, run the application and then undeploy the application.


Sample Output :

Existing build.xml is configured to demostrate the availability of the following resources across Application Client, Servlet, EJB(s)

  • java:global/env/Servlet_Resource
  • java:app/env/HelloStatefulEJB_Resource
  • java:module/env/HelloEJB_Resource
  • java:comp/env/Appclient_Resource


Sample output for
"java:app/app-scoped-resource" will look like :


     [exec] Mode : appclient
     [exec] Resource name : java:app/app-scoped-resource
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec] REQUESTED RESOURCE                   : java:app/app-scoped-resource
     [exec] ACTUAL RESOURCE USED                 : java:app/app-scoped-resource
     [exec] RESULT                               : RESOURCE ACCESSIBLE
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec]
     [exec] Mode : servlet
     [exec] Resource name : java:app/app-scoped-resource
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec] REQUESTED RESOURCE                   : java:app/app-scoped-resource
     [exec] ACTUAL RESOURCE USED                 : java:app/app-scoped-resource
     [exec] RESULT                               : RESOURCE ACCESSIBLE
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec]
     [exec] Mode : stateful_ejb
     [exec] Resource name : java:app/app-scoped-resource
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec] REQUESTED RESOURCE                   : java:app/app-scoped-resource
     [exec] ACTUAL RESOURCE USED                 : java:app/app-scoped-resource
     [exec] RESULT                               : RESOURCE ACCESSIBLE
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec]
     [exec] Mode : stateless_ejb
     [exec] Resource name : java:app/app-scoped-resource
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec] REQUESTED RESOURCE                   : java:app/app-scoped-resource
     [exec] ACTUAL RESOURCE USED                 : java:app/app-scoped-resource
     [exec] RESULT                               : RESOURCE ACCESSIBLE
     [exec] ----------------------------------------------------------------------------------------------------------


In the above sample, "RESULT" indicate that the jdbc-resource "java:app/app-scoped-resource" is available across all components (EJB(s), Servlet, Application Client)

Similarly, sample output for the resource of name "java:module/ejb-module-scoped-resource" will look like :


     [exec] Mode : appclient
     [exec] Resource name : java:module/ejb-module-scoped-resource
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec] REQUESTED RESOURCE                   : java:module/ejb-module-scoped-resource
     [exec] ACTUAL RESOURCE USED                 : jdbc/__default
     [exec] RESULT                               : RESOURCE NOT ACCESSIBLE
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec]
     [exec]
     [exec] Mode : servlet
     [exec] Resource name : java:module/ejb-module-scoped-resource
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec] REQUESTED RESOURCE                   : java:module/ejb-module-scoped-resource
     [exec] ACTUAL RESOURCE USED                 : jdbc/__default
     [exec] RESULT                               : RESOURCE NOT ACCESSIBLE
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec]
     [exec]
     [exec] Mode : stateful_ejb
     [exec] Resource name : java:module/ejb-module-scoped-resource
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec] REQUESTED RESOURCE                   : java:module/ejb-module-scoped-resource
     [exec] ACTUAL RESOURCE USED                 : java:module/ejb-module-scoped-resource
     [exec] RESULT                               : RESOURCE ACCESSIBLE
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec]
     [exec]
     [exec] Mode : stateless_ejb
     [exec] Resource name : java:module/ejb-module-scoped-resource
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec] REQUESTED RESOURCE                   : java:module/ejb-module-scoped-resource
     [exec] ACTUAL RESOURCE USED                 : java:module/ejb-module-scoped-resource
     [exec] RESULT                               : RESOURCE ACCESSIBLE
     [exec] ----------------------------------------------------------------------------------------------------------


In the above sample, "RESULT" indicate that the datasource "java:module/ejb-module-scoped-resource" is available only for the EJB components in the ejb-jar.xml ie., HelloEJB and HelloStatefulEJB.

To list the resources defined in application/module scope :

$GF_HOME/bin/asadmin list-applications --resources --subcomponents

app-scoped-resources-demoApp  <ear, appclient, ejb, web>
  java:app/app-scoped-resource    <JdbcResource>
  java:app/app-scoped-pool    <JdbcConnectionPool>
  app-scoped-resources-demo-client.jar  <AppClientModule>
  app-scoped-resources-demo-ejb.jar     <EJBModule>       
    java:module/ejb-module-scoped-resource    <JdbcResource>
    java:module/ejb-module-scoped-pool    <JdbcConnectionPool>
  app-scoped-resources-demo-web.war     <WebModule>       
    java:module/web-module-scoped-resource    <JdbcResource>
    java:module/web-module-scoped-pool    <JdbcConnectionPool>
Command list-applications executed successfully.

For more information about application-scoped-resources including the domain.xml configuration representation, using dotted-names-get/set command to re-configure the resources, monitoring information,
flush-connection-pool and ping-connection-pool commands, please refer the demo.





References :



Tuesday Dec 29, 2009

Applying Scope for JDBC Resources in GlassFish

JDBC Resources With Scope in GlassFish

Applying Scope for JDBC Resources in GlassFish

Java EE 6 introduces new set of application component environment namespace scopes.
Using the scope, an application can define (or export) a name such that it is visible for other components or modules within the application or even visible globally.

Scope:

  • java:comp : per component namespace
  • java:module : namespace shared by all components in a module (eg: ejb's in a ejb-jar.xml)
  • java:app : namespace shared by all components, modules in an application (eg: application-client, web component, ejb component in an application, .ear)
  • java:global : global namespace for all applications in the server

It is possible to define names with scope and thus make it available across the module, application or globally.

eg:
  • <res-ref-name> element's "name" attribute with prefixed value "java:comp/env/" will make the resource available only for the component in which it is defined (eg: Servlet or EJB or Application Client)
  • <res-ref-name> element's "name" attribute with prefixed value "java:module/env/" will make the resource available all the ejb components defined in its ejb-jar.xml (All EJBs in an ejb-jar.xml)
  • <res-ref-name> element's "name" attribute with prefixed value "java:app/env/" will make the resource available across all components/modules in the application (EJBs, Servlet, Application Client in the application)
  • <res-ref-name> element's "name" attribute with prefixed value "java:global" will  make the resource available across the server

By default, if no prefix is specified it will be equivalent to "java:comp"

Demo application :

The sample application provided demonstrates the usage of various scopes across the application,  by specifying resource-ref in deployment-descriptors. The sample has following components
  • web component [Servlet.java]
  • ejb component(s) [HelloStatefulEJB.java and HelloEJB.java]
  • application client [Client.java]
When executed for a particular resource name, the sample application will do lookup of the resource in Application Client, EJB(s), Servlet and based on the availability
of the resource in the component's scope it will either use the provided resource (datasource) or the default jdbc-resource (jdbc/__default).

Following are the resources defined (or exported) by the application.
  • java:global/env/Servlet_Resource
  • java:app/env/HelloStatefulEJB_Resource
  • java:module/env/HelloEJB_Resource
  • java:comp/env/Appclient_Resource

From the name, the scope of the resource, component in which the resource is defined can be identified.
In the following example :java:app/env/HelloStatefulEJB_Resource
Scope is "app"
Resource is defined for "HelloStatefulEJB"



Steps to execute:

  1. Ensure that JDK 1.6 is installed and the environment variable JAVA_HOME is set
    1. Ensure that the environment variable PATH has JAVA_HOME/bin added to it.
  2. Ensure that ANT is installed and the environment variable ANT_HOME is set
    1. Ensure that the environment variable PATH has ANT_HOME/bin added to it.
  3. Download GlassFish v3
  4. Install GlassFish v3
  5. Start GlassFish (asadmin start-domain domain1)
  6. Start Derby database (asadmin start-database)
  7. Download the sample
  8. Extracted location of sample is referred as "SAMPLE_HOME"
  9. goto SAMPLE_HOME
  10. set environment variable GF_HOME to GlassFish's installation location.
  11. "ant all" will compile, assemble, deploy, run the application and then undeploy the application.


Sample Output :

Existing build.xml is configured to demostrate the availability of the following resources across Application Client, Servlet, EJB(s)

  • java:global/env/Servlet_Resource
  • java:app/env/HelloStatefulEJB_Resource
  • java:module/env/HelloEJB_Resource
  • java:comp/env/Appclient_Resource


Sample output for
"java:module/env/HelloEJB_Resource" will look like :

     [exec] Mode : appclient
     [exec] Resource name : java:module/env/HelloEJB_Resource
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec] REQUESTED RESOURCE              : java:module/env/HelloEJB_Resource
     [exec] ACTUAL RESOURCE USED          : jdbc/__default
     [exec] RESULT                                        : RESOURCE NOT ACCESSIBLE
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec]
     [exec]
     [exec] Mode : servlet
     [exec] Resource name : java:module/env/HelloEJB_Resource
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec] REQUESTED RESOURCE              : java:module/env/HelloEJB_Resource
     [exec] ACTUAL RESOURCE USED          : jdbc/__default
     [exec] RESULT                                        : RESOURCE NOT ACCESSIBLE
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec]
     [exec]
     [exec] Mode : stateful_ejb
     [exec] Resource name : java:module/env/HelloEJB_Resource
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec] REQUESTED RESOURCE              : java:module/env/HelloEJB_Resource
     [exec] ACTUAL RESOURCE USED          : java:module/env/HelloEJB_Resource
     [exec] RESULT                                        : RESOURCE ACCESSIBLE
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec]
     [exec]
     [exec] Mode : stateless_ejb
     [exec] Resource name : java:module/env/HelloEJB_Resource
     [exec] ----------------------------------------------------------------------------------------------------------
     [exec] REQUESTED RESOURCE              : java:module/env/HelloEJB_Resource
     [exec] ACTUAL RESOURCE USED          : java:module/env/HelloEJB_Resource
     [exec] RESULT                                        : RESOURCE ACCESSIBLE
     [exec] ----------------------------------------------------------------------------------------------------------



In the above sample, "RESULT" indicate that the datasource "java:module/env/HelloEJB_Resource" is available only for the EJB components in the ejb-jar.xml ie., HelloEJB and HelloStatefulEJB.


References :



Tuesday Dec 15, 2009

DataSource Resource Definition in GlassFish v3

Java EE 6 introduces DataSource Resource Definition via Common Annotations Specification.
Refer the Enterprise tech tip on DataSource Definition published recently.

Wednesday Dec 02, 2009

Java EE Connector Architecture 1.6 Reference Implementation

GlassFish : Connector 1.6 Reference Implementation

Java EE Connector Architecture 1.6 Reference Implementation :


Connector 1.6 Specification is approved now ! Also refer the announcement by Siva. GlassFish v3 is the reference implementation of this version of the specification.
Developers can write resource-adapters leveraging the new features introduced in this specification and deploy the resource-adapters in
GlassFish v3. GlassFish v3 builds are available now !

Major features of Connector 1.6 specification available in GlassFish v3 :

  • Ease of Use : Annotation

    • It is now possible to develop a resource-adapter using various annotations defined in Connector 1.6, without deployement descriptor (ra.xml)
      • Refer the blog made available during GlassFish v3 Preview SDK release
  • Generic and Standard Work Context Mechanism

    • Generic work context contract enables a resource adapter to control the contexts in which the work instances submitted by it are executed by the application server's WorkManager.
      • Connector 1.6 mandates the following Work Context mechanisms to be supported by all application servers
        • Transaction Context (Similar to existing ExecutionContext)
        • Security Context 
        • Hints Context
  • Bean Validation support for resource-adapters

    • With Bean Validation mechanisms made available in Java EE 6 specification, Connector 1.6 allows resource-adapters to use Bean Validation mechanisms to validate various resource-adapter artifacts ie., ResourceAdapter, AdministeredObject, ManagedConnectionFactory, ActivationSpec JavaBeans.

Miscellaneous :

  • ClassLoading Requirements

    • Connector 1.6 specification recommends that the availability of resource-adapters to applications should be based on the reference of resource-adapter in the application's deployment-descriptor (or its equivalent annotations). These references can be via resource-ref (connector-resource), resource-env-ref (administered-object), resource-adapter-mid (for inbound). By default, GlassFish v3 supports the above recommendation.
  • Runtime Transaction Support

    • With the introduction of javax.resource.spi.TransactionSupport, a ManagedConnectionFactory artifact can dynamically request a transaction support level (XA/Local/NoTransaction) at runtime to override the value specified via deployment-descriptor (or its equivalent annotation)

In the coming weeks, you can look forward for more articles, tutorials, blogs on these features.

References :





Sunday May 31, 2009

Resource Adapter Annotations

Connector Annotations

Annotating a Resource Adapter


Java EE Connector Architecture 1.6 Specification introduces new features that include meta-data annotations.
These annotations are used to define various resource-adapter artificats and hence it is possible to have a resource-adapter
without deployment descriptor (ra.xml).

Annotations 

@Connector :

Specify that the JavaBean is a resource adapter JavaBean. Used to provide metadata about the capabilities provided by the resource adapter. It is optional to provide a JavaBean implementing the ResourceAdapter interface.

@ConnectionDefinition(s) :

Annotations to represent a connection definition with managed-connection-factory, connection-factory artifact details.

@AdministeredObject :

Designates a JavaBean as an administered object.

@Activation :

Designates a JavaBean as an ActivationSpec JavaBean. Also provides Message Listener details.

@ConfigProperty :

Specifies to the application server, that the decorated property is a configuration property for that JavaBean. Configuration Properties are now auto-discoverable by the application server and hence need not be specified using the deployment descriptor.

Connector annotations support in GlassFish :

GlassFish V3 will be the reference implementation for Java EE 6 Specification (and hence Java EE Connector Architecture 6 Specification)
GlassFish V3 Preview release has support for connector annotations, so one can deploy an annotated resource-adapter.

Java EE 6 Preview SDK will have samples bundle demonstrating various new features introduced.
Mail Connector RA sample will demonstrate a resource-adapter without deployment descriptor.
This sample was bundled in J2EE SDK 1.4 and is now bundled in Java EE 6 Preview SDK with annotations instead of deployment descriptor.

Java EE 6 Preview SDK is available here, soon.

Connectors sample will be available in "SAMPLES_DIR/javaee6/connectors/apps/mailconnector"
Read the documentation of connectors sample ("SAMPLES_DIR/javaee6/connectors/apps/mailconnector/docs") for more details.

Deployment descriptor elements and equivalent annotations:

<connector xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/connector_1_5.xsd" version="1.5">
   <description>Sample adapter using the JavaMail API</description>
    <display-name>InboundResourceAdapter</display-name>
    <icon></icon>
    <vendor-name>Sun Microsystems, Inc.</vendor-name>
    <eis-type>MAIL</eis-type>
    <resourceadapter-version>1.0</resourceadapter-version>
...
...
...
            <authentication-mechanism>
                <authentication-mechanism-type>BasicPassword</authentication-mechanism-type>
                <credential-interface>javax.resource.spi.security.PasswordCredential</credential-interface>
            </authentication-mechanism>
            <reauthentication-support>false</reauthentication-support>

...
...
</connector>
@Connector(
        description = "Sample adapter using the JavaMail API",
        displayName = "InboundResourceAdapter",
        vendorName = "Sun Microsystems, Inc.",
        eisType = "MAIL",
        version = "1.0",
        authMechanisms = {
                @AuthenticationMechanism(
                    authMechanism = "BasicPassword",
                    credentialInterface = AuthenticationMechanism.CredentialInterface.PasswordCredential
                )
        }

/\*
        // Since the following attribute values denote the default values of the annotation,
        // they need not be specified explicitly

        transactionSupport = TransactionSupport.TransactionSupportLevel.NoTransaction,
        reauthenticationSupport = false
\*/
)

public class ResourceAdapterImpl
    implements ResourceAdapter, java.io.Serializable
{
...
...
}
 <connection-definition>
                <managedconnectionfactory-class>samples.connectors.mailconnector.ra.outbound.ManagedConnectionFactoryImpl</managedconnectionfactory-class>
                <config-property>
                    <config-property-name>serverName</config-property-name>
                    <config-property-type>java.lang.String</config-property-type>
                    <config-property-value>UnknownHostName</config-property-value>
                </config-property>
...
...
                <connectionfactory-interface>samples.connectors.mailconnector.api.JavaMailConnectionFactory</connectionfactory-interface>
                                           <connectionfactory-impl-class>samples.connectors.mailconnector.ra.outbound.JavaMailConnectionFactoryImpl</connectionfactory-impl-class>
                <connection-interface>samples.connectors.mailconnector.api.JavaMailConnection</connection-interface>
                <connection-impl-class>samples.connectors.mailconnector.ra.outbound.JavaMailConnectionImpl</connection-impl-class>
            </connection-definition>
@ConnectionDefinition(
        connectionFactory = samples.connectors.mailconnector.api.JavaMailConnectionFactory.class,
        connectionFactoryImpl = samples.connectors.mailconnector.ra.outbound.JavaMailConnectionFactoryImpl.class,
        connection = samples.connectors.mailconnector.api.JavaMailConnection.class,
        connectionImpl = samples.connectors.mailconnector.ra.outbound.JavaMailConnectionImpl.class
)
public class ManagedConnectionFactoryImpl implements
    ManagedConnectionFactory, Serializable
{
...
...
 @ConfigProperty(
            type = String.class,
            defaultValue = "UnknownHostName"
    )
    public void setServerName(String serverName)
    {
        String oldName = this.serverName;
        this.serverName = serverName;
        changes.firePropertyChange("serverName", oldName, serverName);
    }

}
 <messageadapter>
                <messagelistener>
                    <messagelistener-type>samples.connectors.mailconnector.api.JavaMailMessageListener</messagelistener-type>
                    <activationspec>
                        <activationspec-class>samples.connectors.mailconnector.ra.inbound.ActivationSpecImpl</activationspec-class>
                        <required-config-property>
                            <config-property-name>serverName</config-property-name>
                        </required-config-property>
                        <required-config-property>
                            <config-property-name>userName</config-property-name>
                        </required-config-property>
                        <required-config-property>
                            <config-property-name>password</config-property-name>
                        </required-config-property>
                        <required-config-property>
                            <config-property-name>folderName</config-property-name>
                        </required-config-property>
                        <required-config-property>
                            <description>Normally imap or pop3</description>
                            <config-property-name>protocol</config-property-name>
                        </required-config-property>
                    </activationspec>
                </messagelistener>
            </messageadapter>
@Activation(
        messageListeners = {samples.connectors.mailconnector.api.JavaMailMessageListener.class}

)
public class ActivationSpecImpl implements javax.resource.spi.ActivationSpec,
                                           java.io.Serializable
{
...
 @ConfigProperty()
    // serverName property value
    private String serverName = new String("");

    @ConfigProperty()
    // userName property value
    private String userName = new String("");

    @ConfigProperty()
    // password property value
    private String password = new String("");

    @ConfigProperty()
    // folderName property value
    private String folderName = new String("Inbox");

    // protocol property value
    // Normally imap or pop3
    @ConfigProperty(
            description = "Normally imap or pop3"
    )
    private String protocol = new String("imap");


...
...
}


References:

Thursday Jun 14, 2007

JDBC Connection Pool Templates - GlassFish

JDBC Connection Pool Templates for GlassFish

Templates to create JDBC Connection Pool & Resource


Often, setting up connection pool (datasource) against various databases will require knowledge on
mandatory property names to successfully connect to database.

GlassFish V2 has templates to create connection pool & resource against various databases & jdbc drivers.

Once appropriate values for properties like, user, password, databaseName, serverName are set in the template,  they
can be used multiple times.

GlassFish V2 has templates available in GF_INSTALL_DIR/lib/install/templates/resources/jdbc

How to use :


1)  copy the jdbc-driver to AS_INSTALL_DIR/domains/<DOMAIN_NAME>/lib/ext
2)  restart appserver
3)  edit the appropriate jdbc-driver template to fill username, password, hostname, databasename, portnumber etc.,
3a) [Optional] select appropriate resource-type & datasource-classname. Templates are provided with the list of
    datasource-classnames for respective resource-types of the jdbc-vendor, if available.
4)  asadmin add-resources jdbc-driver-template.xml (eg: AS_INSTALL_DIR/lib/install/templates/resources/jdbc/javadb_type4_datasource.xml)
5)  asadmin ping-connection-pool connection-pool-name

For more information, refer GF_INSTALL_DIR/lib/install/templates/resources/jdbc/README and respective datasource-template.xml files.

These templates can be used against GlassFish V1 also.

Templates :


Database Vendor
JDBC Driver Vendor
datasource-template-file
JavaDB / Derby
Derby
javadb_type4_datasource.xml
Oracle
Oracle Thin Driver
oracle_type4_datasource.xml
Oracle
Inet Driver
oracle_inet_datasource.xml
Oracle
Sun bundled DataDirect Driver
(available in SJSAS EE builds)
oracle_dd_datasource.xml
MySQL
MySQL Connector/J
mysql_type4_datasource.xml
PostgreSQL
PostgreSQL Driver
postgresql_type4_datasource.xml
DB2
Sun bundled DataDirect Driver
(available in SJSAS EE builds)
db2_dd_datasource.xml
DB2
IBM DB2 JDBC type-4 driver
db2_jcc_datasource.xml
Sybase
Sun bundled DataDirect Driver
(available in SJSAS EE builds)
sybase_dd_datasource.xml
Sybase
Inet Driver
sybase_inet_datasource.xml
Sybase
jConnect Driver
sybase_jconn_datasource.xml
Microsoft SQL Server
Sun bundled DataDirect Driver
(available in SJSAS EE builds)
microsoft_dd_datasource.xml
Microsoft SQL Server Inet Driver
microsoft_inet_datasource.xml
Microsoft SQL Server jTDS Driver
microsoft_jtds_datasource.xml
Microsoft SQL Server 2000
Microsoft
microsoft_sqlserver2000_datasource.xml
Microsoft SQL Server 2005 Microsoft
microsoft_sqlserver2005_datasource.xml

The templates listed above will be available in GlassFish v2 b51

Similarly, templates for other databases can be done.
If you have a template for a particular database that is not listed here,
please post it to dev@glassfish.dev.java.net or users@glassfish.dev.java.net

Friday Jun 01, 2007

Monitoring JDBC Connection Pool - GlassFish

Monitoring jdbc connection pool in GlassFish
Monitoring JDBC Connection pool will provide statistics on the usage of connection pool.
This can be used to tune the connection pool according to the application usage.

Monitoring JDBC Connection pool can be done in the following ways.

1) Admin console (GUI)
2) CLI
3) Programatically using AMX

1) Admin console


Configuration > Monitoring > Set Jdbc Connection Pool to HIGH
and save.
enable monitoring for jdbc connection pool

Common Tasks > View Monitoring Data > (RHS) Monitor > Resources
will list the connection pools that are referred by the application.
This will list the monitoring statistics of jdbc-connection-pools that are used by the application.

Monitoring data


2) CLI

Using dotted-names-command we can enable monitoring levels for various modules.

To find the monitoring levels dotted-name:
GF_HOME/bin/asadmin list \*monitor\*
server.monitoring-service
server.monitoring-service.module-monitoring-levels


To get monitoring level of various modules :
GF_HOME/bin/asadmin get server.monitoring-service.module-monitoring-levels.\*
server.monitoring-service.module-monitoring-levels.connector-connection-pool = OFF
server.monitoring-service.module-monitoring-levels.connector-service = OFF
server.monitoring-service.module-monitoring-levels.ejb-container = OFF
server.monitoring-service.module-monitoring-levels.http-service = OFF
server.monitoring-service.module-monitoring-levels.jdbc-connection-pool = OFF
server.monitoring-service.module-monitoring-levels.jms-service = OFF
server.monitoring-service.module-monitoring-levels.jvm = OFF
server.monitoring-service.module-monitoring-levels.orb = OFF
server.monitoring-service.module-monitoring-levels.thread-pool = OFF
server.monitoring-service.module-monitoring-levels.transaction-service = OFF
server.monitoring-service.module-monitoring-levels.web-container = OFF

To set monitoring level of jdbc-connection-pool to HIGH :
GF_HOME/bin/asadmin set server.monitoring-service.module-monitoring-levels.jdbc-connection-pool=HIGH
server.monitoring-service.module-monitoring-levels.jdbc-connection-pool = HIGH

To list all dotted-names that contain "oracle" :
GF_HOME/bin/asadmin list --monitor=true \*oracle\*
server.resources.oracledb_type4_pool


To get monitoring information of jdbc-connection-pool "oracledb_type4_pool" :
GF_HOME/bin/asadmin get  --monitor=true server.resources.oracledb_type4_pool.\*server.resources.oracledb_type4_pool.averageconnwaittime-count = 0
server.resources.oracledb_type4_pool.averageconnwaittime-description = No Description was available
server.resources.oracledb_type4_pool.averageconnwaittime-lastsampletime = 1180696935585
server.resources.oracledb_type4_pool.averageconnwaittime-name = AverageConnWaitTime
server.resources.oracledb_type4_pool.averageconnwaittime-starttime = 1180696749055
server.resources.oracledb_type4_pool.averageconnwaittime-unit = milliseconds
server.resources.oracledb_type4_pool.connrequestwaittime-current = 0
server.resources.oracledb_type4_pool.connrequestwaittime-description = Provides a range value that indicates the longest, shortest wait times of connection requests since the last sampling. The current value indicates the wait time of the last request that was serviced by the pool.
server.resources.oracledb_type4_pool.connrequestwaittime-highwatermark = 0
server.resources.oracledb_type4_pool.connrequestwaittime-lastsampletime = 1180696935581
server.resources.oracledb_type4_pool.connrequestwaittime-lowwatermark = 0
server.resources.oracledb_type4_pool.connrequestwaittime-name = ConnRequestWaitTime
server.resources.oracledb_type4_pool.connrequestwaittime-starttime = 1180696749055
server.resources.oracledb_type4_pool.connrequestwaittime-unit = milliseconds
server.resources.oracledb_type4_pool.dotted-name = server.resources.oracledb_type4_pool
server.resources.oracledb_type4_pool.numconnacquired-count = 0
server.resources.oracledb_type4_pool.numconnacquired-description = Provides a count value reflecting the number of connections acquired from the pool since the last sampling
server.resources.oracledb_type4_pool.numconnacquired-lastsampletime = 1180696935599
server.resources.oracledb_type4_pool.numconnacquired-name = NumConnAcquired
server.resources.oracledb_type4_pool.numconnacquired-starttime = 1180696749055
server.resources.oracledb_type4_pool.numconnacquired-unit = Count
server.resources.oracledb_type4_pool.numconncreated-count = 0
server.resources.oracledb_type4_pool.numconncreated-description = Provides a count value reflecting the number of connections that were created by the pool since the last sampling.
server.resources.oracledb_type4_pool.numconncreated-lastsampletime = 1180696935591
server.resources.oracledb_type4_pool.numconncreated-name = NumConnCreated
server.resources.oracledb_type4_pool.numconncreated-starttime = 1180696749055
server.resources.oracledb_type4_pool.numconncreated-unit = Count
server.resources.oracledb_type4_pool.numconndestroyed-count = 0
server.resources.oracledb_type4_pool.numconndestroyed-description = Provides a count value reflecting the number of connections that were destroyed since the last sampling
server.resources.oracledb_type4_pool.numconndestroyed-lastsampletime = 1180696935590
server.resources.oracledb_type4_pool.numconndestroyed-name = NumConnDestroyed
server.resources.oracledb_type4_pool.numconndestroyed-starttime = 1180696749055
server.resources.oracledb_type4_pool.numconndestroyed-unit = Count
server.resources.oracledb_type4_pool.numconnfailedvalidation-count = 0
server.resources.oracledb_type4_pool.numconnfailedvalidation-description = Provides a count value reflecting the number of connections in the connection pool that failed validation since the start time till the last sample time.
server.resources.oracledb_type4_pool.numconnfailedvalidation-lastsampletime = 1180696935594
server.resources.oracledb_type4_pool.numconnfailedvalidation-name = NumConnFailedValidation
server.resources.oracledb_type4_pool.numconnfailedvalidation-starttime = 1180696749055
server.resources.oracledb_type4_pool.numconnfailedvalidation-unit = Count
server.resources.oracledb_type4_pool.numconnfree-current = 8
server.resources.oracledb_type4_pool.numconnfree-description = Provides a count value reflecting the number of connections in the connection pool that are free as of the last sampling
server.resources.oracledb_type4_pool.numconnfree-highwatermark = 0
server.resources.oracledb_type4_pool.numconnfree-lastsampletime = 1180696935590
server.resources.oracledb_type4_pool.numconnfree-lowwatermark = 0
server.resources.oracledb_type4_pool.numconnfree-name = NumConnFree
server.resources.oracledb_type4_pool.numconnfree-starttime = 1180696749055
server.resources.oracledb_type4_pool.numconnfree-unit = Count
server.resources.oracledb_type4_pool.numconnnotsuccessfullymatched-count = 0
server.resources.oracledb_type4_pool.numconnnotsuccessfullymatched-description = No Description was available
server.resources.oracledb_type4_pool.numconnnotsuccessfullymatched-lastsampletime = 1180696935601
server.resources.oracledb_type4_pool.numconnnotsuccessfullymatched-name = NumConnNotSuccessfullyMatched
server.resources.oracledb_type4_pool.numconnnotsuccessfullymatched-starttime = 1180696749055
server.resources.oracledb_type4_pool.numconnnotsuccessfullymatched-unit = Count
server.resources.oracledb_type4_pool.numconnreleased-count = 0
server.resources.oracledb_type4_pool.numconnreleased-description = Provides a count value reflecting the number of connections released back to the pool since the last sampling
server.resources.oracledb_type4_pool.numconnreleased-lastsampletime = 1180696935586
server.resources.oracledb_type4_pool.numconnreleased-name = NumConnReleased
server.resources.oracledb_type4_pool.numconnreleased-starttime = 1180696749055
server.resources.oracledb_type4_pool.numconnreleased-unit = Count
server.resources.oracledb_type4_pool.numconnsuccessfullymatched-count = 0
server.resources.oracledb_type4_pool.numconnsuccessfullymatched-description = No Description was available
server.resources.oracledb_type4_pool.numconnsuccessfullymatched-lastsampletime = 1180696935601
server.resources.oracledb_type4_pool.numconnsuccessfullymatched-name = NumConnSuccessfullyMatched
server.resources.oracledb_type4_pool.numconnsuccessfullymatched-starttime = 1180696749055
server.resources.oracledb_type4_pool.numconnsuccessfullymatched-unit = Count
server.resources.oracledb_type4_pool.numconntimedout-count = 0
server.resources.oracledb_type4_pool.numconntimedout-description = Provides a count value reflecting the number of connections in the connection pool that timed out since the start time till the last sample time.
server.resources.oracledb_type4_pool.numconntimedout-lastsampletime = 1180696935602
server.resources.oracledb_type4_pool.numconntimedout-name = NumConnTimedOut
server.resources.oracledb_type4_pool.numconntimedout-starttime = 1180696749055
server.resources.oracledb_type4_pool.numconntimedout-unit = Count
server.resources.oracledb_type4_pool.numconnused-current = 0
server.resources.oracledb_type4_pool.numconnused-description = Provides Connection usage statistics. In addition to number of connections being used currently, this also provides information about the Maximum number of connections that were used(High Watermark).
server.resources.oracledb_type4_pool.numconnused-highwatermark = 0
server.resources.oracledb_type4_pool.numconnused-lastsampletime = 1180696935592
server.resources.oracledb_type4_pool.numconnused-lowwatermark = 0
server.resources.oracledb_type4_pool.numconnused-name = NumConnUsed
server.resources.oracledb_type4_pool.numconnused-starttime = 1180696749055
server.resources.oracledb_type4_pool.numconnused-unit = Count
server.resources.oracledb_type4_pool.numpotentialconnleak-count = 0
server.resources.oracledb_type4_pool.numpotentialconnleak-description = Provides a count value reflecting the number of potential connection leaks
server.resources.oracledb_type4_pool.numpotentialconnleak-lastsampletime = 1180696935601
server.resources.oracledb_type4_pool.numpotentialconnleak-name = NumPotentialConnLeak
server.resources.oracledb_type4_pool.numpotentialconnleak-starttime = 1180696749055
server.resources.oracledb_type4_pool.numpotentialconnleak-unit = Count
server.resources.oracledb_type4_pool.waitqueuelength-count = 0
server.resources.oracledb_type4_pool.waitqueuelength-description = Provides a count value indicating the number of connection requests in the queue waiting to be servied.
server.resources.oracledb_type4_pool.waitqueuelength-lastsampletime = 1180696935597
server.resources.oracledb_type4_pool.waitqueuelength-name = WaitQueueLength
server.resources.oracledb_type4_pool.waitqueuelength-starttime = 1180696749055
server.resources.oracledb_type4_pool.waitqueuelength-unit = Count



3) Using AMX :

It is possible to get monitoring information programmatically,
using AMX (Application Server Management Extenstions).
Following sample will get few of the monitoring information of the specified jdbc-connection-pool, (oracledb_type4_pool) periodically.

Dependency : appserv-ext.jar


import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import com.sun.appserv.management.client.AppserverConnectionSource;
import java.util.TimerTask;
import java.util.Timer;
public class JDBCConPoolMonitoringInfoCollector {
    public static final String[] properties = {"numconnused-current", "numconndestroyed-count",
            "numconncreated-count", "numconnacquired-count", "numconnreleased-count",
            "averageconnwaittime-count", "connrequestwaittime-current", "numconnfailedvalidation-count",
            "numconnnotsuccessfullymatched-count", "numconnsuccessfullymatched-count", "numconntimedout-count",
            "waitqueuelength-count", "numpotentialconnleak-count"};
    public static final String USER_PASSWORD = "adminadmin";
    public static final int JMX_PORT = 8686;
    public static final String DOTTED_NAME_GET = "dottedNameGet";
    public static final String USER = "admin";
    public static final String CONFIG = "server-config";
    public static final String HOST_NAME = "localhost";

    public static void main(String[] args)
            throws Exception {
        JDBCConPoolMonitoringInfoCollector client = new JDBCConPoolMonitoringInfoCollector();
        client.runTest();
    }

    public void runTest() throws Exception {
        Timer timer = new Timer();
        timer.schedule(new Poller(), 1000, 1000 \* 10); //Time Interval
    }

    class Poller extends TimerTask {
        public void run() {
            for (String property : properties) {
                try {
                    int result = getMonitorablePropertyOfConnectionPool("<CONNECTION_POOL_NAME>",
                            property, HOST_NAME, JMX_PORT, USER, USER_PASSWORD, CONFIG);
                    System.out.println(property + " : " + result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
         System.out.println("-------------------------------------------------------------------");
        }
    }

    public int getMonitorablePropertyOfConnectionPool(String poolName, String property, String hostName, int JMX_PORT, String user, String password, String configName) throws Exception {
        AppserverConnectionSource appserver =
                new AppserverConnectionSource(AppserverConnectionSource.PROTOCOL_RMI, hostName, JMX_PORT, user, password, null);
        MBeanServerConnection connection = appserver.getJMXConnector(false).getMBeanServerConnection();
        ObjectName objectName =
                new ObjectName("amx:j2eeType=X-MonitoringDottedNames,name=na");
        String params[] = new String[]{String.class.getName()};
        Object values[] = new Object[]{"server.resources." + poolName + "." + property};
        javax.management.Attribute returnValue = (javax.management.Attribute) connection.invoke(objectName, DOTTED_NAME_GET, values, params);
        return new Integer(returnValue.getValue().toString());
    }
}


Sample Output :

-------------------------------------------------------------------
numconnused-current : 30
numconndestroyed-count : 276
numconncreated-count : 308
numconnacquired-count : 1033
numconnreleased-count : 1003
averageconnwaittime-count : 44
connrequestwaittime-current : 0
numconnfailedvalidation-count : 0
numconnnotsuccessfullymatched-count : 1197
numconnsuccessfullymatched-count : 884
numconntimedout-count : 0
waitqueuelength-count : 0
numpotentialconnleak-count : 0
-------------------------------------------------------------------
numconnused-current : 30
numconndestroyed-count : 284
numconncreated-count : 316
numconnacquired-count : 1076
numconnreleased-count : 1046
averageconnwaittime-count : 42
connrequestwaittime-current : 0
numconnfailedvalidation-count : 0
numconnnotsuccessfullymatched-count : 1233
numconnsuccessfullymatched-count : 922
numconntimedout-count : 0
waitqueuelength-count : 0
numpotentialconnleak-count : 0
-------------------------------------------------------------------


References :



Thursday May 10, 2007

JDBC 4.0 support in GlassFish-V2



GlassFish V2 supports JDBC 4.0 applications in jdk 1.6
Users can configure jdbc 4.0 capable datasource by specifying the vendor classname while creating jdbc connection pool.
Following sample will illustrate how to create a jdbc 40 capable datasource using JavaDB (aka Derby).

GlassFish v2 bundles JavaDB which supports jdbc 4.0 also.
JDBC 4.0 datasource implementation classes provided by Derby are :

org.apache.derby.jdbc.ClientConnectionPoolDataSource40
org.apache.derby.jdbc.ClientDataSource40
org.apache.derby.jdbc.ClientXADataSource40


To create a jdbc-connection-pool in GlassFish, templates are provided for various databases
in GF_INSTALL_DIR/lib/install/templates/resources/jdbc

"javadb_type4_datasource.xml" is for jdbc-3.0 datasource.

eg:
Copy the file and modify the "datasource-classname" to "org.apache.derby.jdbc.ClientDataSource40"
and "res-type" to "javax.sql.DataSource"
Specify appropriate values to connection parameters eg (user, password, hostname, databasename etc.,)
and name of jdbc connection pool and jdbc resource.

<resources>
    <jdbc-connection-pool
        name="jdbc-40-pool"
        datasource-classname="org.apache.derby.jdbc.ClientDataSource40"
        res-type="javax.sql.DataSource">
        <property name="user" value="userid"/>
        <property name="password" value="secret"/>
        <property name="databaseName" value="testdb"/>
        <property name="serverName" value="localhost"/>
        <property name="portNumber" value="1527"/>
        <property name="connectionAttributes" value=";create=true"/>
    </jdbc-connection-pool>

    <jdbc-resource
        enabled="true"
        jndi-name="jdbc/jdbc-40-resource"
        object-type="user"
        pool-name="jdbc-40-pool"/>
</resources>

Create jdbc connection pool & resource as :

GF_INSTALL_DIR/bin/asadmin add-resources GF_INSTALL_DIR/lib/install/templates/resources/jdbc/javadb_jdbc40_datasource.xml
 =========================
Added Resource Type: jdbc-connection-pool
 =========================
Added Resource Type: jdbc-resource
Command add-resources executed successfully.

FAQ:

1) GlassFish is already installed using jdk 1.5. Can its run-time be jdk 1.6 ?
Yes. change the AS_JAVA entry in GF_INSTALL_DIR/config/asenv.conf to use jdk 1.6 and restart app.server

2) GlassFish is installed using jdk 1.6. Is it possible to use jdbc 3.0 datatsources ?
Yes, no changes are required.

Bundles Used :

  • JavaDB (Derby 10.2.2.0) bundled with GlassFish


Monday Apr 16, 2007

Connection Validation in GlassFish JDBC Connection Pool

 

Connection Pool manages a pool of connections and serves the user requests quickly as creating a new
connection for each user request will take longer time. Since the connections are pooled, it is possible
that a connection may become invalid or stale, i.e., database server may set the connection state to
closed because of network failure or database might have been restarted. In such scenario, if the application
retrieves a connection from connection pool, failure will occur indicating that the connection is no more valid.


To circumvent stale connections issue, connection pool property "is-connection-validation-required" can be set
to true. This flag indicates the connection pool to validate the connection for every request by the application.
Validating a connection ensures that the connection is in healthy state. If the connection validation fails,
connection will be removed from the pool and the application will get valid connection. [Pool will either return the
next valid connection or create a new connection]. Thus validation ensures that every getConnection() request
by the application  will be served by a valid connection.

To set validation :
eg: DerbyPool

Following command will list resources by name "DerbyPool"

AS_INSTALL_ROOT/bin/asadmin list "\*DerbyPool\*"
domain.resources.jdbc-connection-pool.DerbyPool


To get the list of connection pool attributes and properties,
AS_INSTALL_ROOT/bin/asadmin get domain.resources.jdbc-connection-pool.DerbyPool.\*
...
...
domain.resources.jdbc-connection-pool.DerbyPool.connection-validation-method = auto-commit
...
...
domain.resources.jdbc-connection-pool.DerbyPool.is-connection-validation-required = false
domain.resources.jdbc-connection-pool.DerbyPool.validation-table-name =


 To enable connection validation :
AS_INSTALL_ROOT/bin/asadmin set domain.resources.jdbc-connection-pool.DerbyPool.is-connection-validation-required=true
domain.resources.jdbc-connection-pool.DerbyPool.is-connection-validation-required = true


By default, the validation mode is "auto-commit". Auto-commit property of the connection to be validated
will be set & reset by the validation logic. Most of the jdbc-drivers cache the "auto-commit" value of the
connection and hence actual validation (connecting to database) does not happen.

Instead, setting table-based validation will ensure that validation happens properly. A valid table name need to
be provided, validation logic will issue a query on this table. If the connection is stale, this query will fail and
hence will be removed from the pool.

To set Table-based validation :

AS_INSTALL_ROOT/bin/asadmin set domain.resources.jdbc-connection-pool.DerbyPool.connection-validation-method=table
domain.resources.jdbc-connection-pool.DerbyPool.connection-validation-method = table

bin/asadmin set domain.resources.jdbc-connection-pool.DerbyPool.validation-table-name=sys.systables
domain.resources.jdbc-connection-pool.DerbyPool.validation-table-name = sys.systables


Sometimes, database restart may result in all the connections in the pool to be invalid.
In such a case, first get connection after restart will result in validating a connection, removing it from the pool,
validating the next connection and so on. Eventually all connections will be validated, removed from the pool
and pool will be reinitialized.

Following property "fail-all-connections" will ensure that when one of the connections become valid, pool will be
reinitialized, ie., all connections will be destroyed and initialized again.

AS_INSTALL_ROOT/bin/asadmin set domain.resources.jdbc-connection-pool.DerbyPool.fail-all-connections=true
domain.resources.jdbc-connection-pool.DerbyPool.fail-all-connections = true


Above property need to be set only in cases where there are more possibilities of database restarts/failures, as
all connections are dropped and recreated for a single connection validation failure.

References

Application Server - Reference Manual > create-jdbc-connection-pool


Tuesday Apr 10, 2007

creating jdbc connection pool & resource in GlassFish

 

 JDBC Connection Pool & Resource can be created in multiple ways.

1) Admin Console

Admin console provides user intuitive interface to create a connection pool & resource for database access.
a) Copy the jdbc driver that will be used for database connectivity, to GLASSFISH_INSTALL/domains/<domainname>/lib/ext or
add the jdbc-driver path to "classpath-prefix" and restart application server.

b) Using Admin console, Common Tasks > create jdbc connection pool

common-tasks

c) Provide a name for the connection pool, select the resource type, select the database vendor and press Next

new jdbc connection pool

d) Console will list the the default pool settings and also the properties of datasource class provided by the vendor.


pool-properties

e) Fill the values for datasource properties, eg: servername, user, password, URL, databasename etc., and press Finish
   
f) Pool will be created

pool created

g) To check whether the values provided for datasource for database connectivity are valid and works fine, press Ping.
Ping will use these properties and try to establish a connection.

ping jdbc connection pool

This connection pool need to be associated with a jdbc-resource.

h) To create a jdbc-resource that will be used by the application :
Resources > Jdbc Resources

new jdbc resource
i) Press New

j) provide the jndi name for the resource and the pool with which the resource need to be associated.

new jdbc resource


k) Press OK, jdbc-resource will be created.

resource-created

2) Using CLI

jdbc-connection-pool can be created as

AS_INSTALL_ROOT/bin/asadmin create-jdbc-connection-pool --datasourceclassname oracle.jdbc.pool.OracleDataSource --restype javax.sql.DataSource --property user=dbuser:password=dbpassword:url="jdbc\\:oracle\\:thin\\:@localhost\\:1521\\:ORCL" oracle-pool
Command create-jdbc-connection-pool executed successfully.

jdbc-resource can be created as
AS_INSTALL_ROOT/bin/asadmin create-jdbc-resource --connectionpoolid oracle-pool jdbc/oracle-resource
Command create-jdbc-resource executed successfully.

To test whether the connection settings are correct, ping connection pool
AS_INSTALL_ROOT/bin/asadmin ping-connection-pool oracle-pool
Command ping-connection-pool executed successfully.

Properties of connection pool can be read/changed as follows.
AS_INSTALL_ROOT/bin/asadmin list \*oracle-pool\*
domain.resources.jdbc-connection-pool.oracle-pool

List the properties of connection pool
AS_INSTALL_ROOT/bin/asadmin get domain.resources.jdbc-connection-pool.oracle-pool.\*
domain.resources.jdbc-connection-pool.oracle-pool.allow-non-component-callers = false
domain.resources.jdbc-connection-pool.oracle-pool.associate-with-thread = false
domain.resources.jdbc-connection-pool.oracle-pool.connection-creation-retry-attempts = 0
domain.resources.jdbc-connection-pool.oracle-pool.connection-creation-retry-interval-in-seconds = 10
domain.resources.jdbc-connection-pool.oracle-pool.connection-leak-reclaim = false
domain.resources.jdbc-connection-pool.oracle-pool.connection-leak-timeout-in-seconds = 0
domain.resources.jdbc-connection-pool.oracle-pool.connection-validation-method = auto-commit
domain.resources.jdbc-connection-pool.oracle-pool.datasource-classname = oracle.jdbc.pool.OracleDataSource
domain.resources.jdbc-connection-pool.oracle-pool.description =
domain.resources.jdbc-connection-pool.oracle-pool.fail-all-connections = false
domain.resources.jdbc-connection-pool.oracle-pool.idle-timeout-in-seconds = 300
domain.resources.jdbc-connection-pool.oracle-pool.is-connection-validation-required = false
domain.resources.jdbc-connection-pool.oracle-pool.is-isolation-level-guaranteed = true
domain.resources.jdbc-connection-pool.oracle-pool.lazy-connection-association = false
domain.resources.jdbc-connection-pool.oracle-pool.lazy-connection-enlistment = false
domain.resources.jdbc-connection-pool.oracle-pool.match-connections = false
domain.resources.jdbc-connection-pool.oracle-pool.max-connection-usage-count = 0
domain.resources.jdbc-connection-pool.oracle-pool.max-pool-size = 32
domain.resources.jdbc-connection-pool.oracle-pool.max-wait-time-in-millis = 60000
domain.resources.jdbc-connection-pool.oracle-pool.name = oracle-pool
domain.resources.jdbc-connection-pool.oracle-pool.non-transactional-connections = false
domain.resources.jdbc-connection-pool.oracle-pool.pool-resize-quantity = 2
domain.resources.jdbc-connection-pool.oracle-pool.property.password = dbpassword
domain.resources.jdbc-connection-pool.oracle-pool.property.url = jdbc:oracle:thin:@localhost:1521:ORCL
domain.resources.jdbc-connection-pool.oracle-pool.property.user = dbuser
domain.resources.jdbc-connection-pool.oracle-pool.res-type = javax.sql.DataSource
domain.resources.jdbc-connection-pool.oracle-pool.statement-timeout-in-seconds = -1
domain.resources.jdbc-connection-pool.oracle-pool.steady-pool-size = 8
domain.resources.jdbc-connection-pool.oracle-pool.transaction-isolation-level =
domain.resources.jdbc-connection-pool.oracle-pool.validate-atmost-once-period-in-seconds = 0
domain.resources.jdbc-connection-pool.oracle-pool.validation-table-name =
domain.resources.jdbc-connection-pool.oracle-pool.wrap-jdbc-objects = false

Changing a property
AS_INSTALL_ROOT/bin/asadmin set domain.resources.jdbc-connection-pool.oracle-pool.steady-pool-size=20
domain.resources.jdbc-connection-pool.oracle-pool.steady-pool-size = 20


AS_INSTALL_ROOT/bin/asadmin get domain.resources.jdbc-connection-pool.oracle-pool.steady-pool-size   
domain.resources.jdbc-connection-pool.oracle-pool.steady-pool-size = 20


3) Using sun-resources.xml templates

sun-resources.xml can be used to create jdbc-connection-pool & resources.
Templates for various databases will be available in GLASSFISH_INSTALL/lib/install/templates/resources/jdbc
Copy and modify the templates with appropriate values.

eg:
copy "oracle_type4_datasource.xml"  as oracle-resource.xml and modify the URL, user, password values.
GLASSFISH_INSTALL/bin/asadmin add-resources GLASSFISH_INSTALL/lib/install/templates/resources/jdbc/oracle-resource.xml
 =========================
Added Resource Type: jdbc-connection-pool
 =========================
Added Resource Type: jdbc-resource
Command add-resources executed successfully.


4) Creating Connection Pool & Resource programmatically

Using AMX (Application Server Management Extenstions) resource/pool can be created. Following snippet
will create a connection pool, resource and resource-ref for the "server" instance.
[needs appserv-ext.jar in classpath]
import java.util.Map;
import java.util.HashMap;

import com.sun.appserv.management.client.AppserverConnectionSource;
import com.sun.appserv.management.DomainRoot;
import com.sun.appserv.management.config.\*;


public class ResourceCreator {
    public static final String hostName = "localhost";
    public static final int JMX_PORT = 8686;
    public static final String user = "admin";
    public static final String password = "adminadmin";

    public static void main(String[] args) throws Exception {
        AppserverConnectionSource appserver =
                new AppserverConnectionSource(AppserverConnectionSource.PROTOCOL_RMI, hostName, JMX_PORT, user, password, null);

        String connPoolName = "mysql-con-pool";
        String resourceName = "jdbc/mysql-resource";

        DomainRoot domainRoot = appserver.getDomainRoot();

        //check whether the con.pool already exists, else, create one
        Map<String, JDBCConnectionPoolConfig> conPoolMap = domainRoot.getDomainConfig().getJDBCConnectionPoolConfigMap();
        if (conPoolMap.containsKey(connPoolName)) {
            System.out.println("JDBC Connection pool : " + connPoolName + " already exists");
        } else {
            Map<String, String> map = new HashMap<String, String>();
            map.put("property.user", "jagadish");
            map.put("ResType", "javax.sql.ConnectionPoolDataSource");
            map.put("property.password", "jagadish");
            map.put("property.databaseName", "jagadish");
            map.put("property.url", "jdbc:mysql://localhost:3306/jagadish");

            domainRoot.getDomainConfig().createJDBCConnectionPoolConfig(connPoolName, "com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource", map);
            System.out.println("JDBC Connection pool : " + connPoolName + " created ! ");
        }

        //check whether the jdbc resource already exists, else, create one
        Map<String, JDBCResourceConfig> resMap = domainRoot.getDomainConfig().getJDBCResourceConfigMap();
        if (resMap.containsKey(resourceName)) {
            System.out.println("JDBC Resource : " + resourceName + " already exists");
        } else {
            domainRoot.getDomainConfig().createJDBCResourceConfig(resourceName, connPoolName, null);
            System.out.println("JDBC Resource : " + resourceName + " created !");
        }

        //create a resource-ref for the instance "server"
        Map<String, StandaloneServerConfig> map1 = domainRoot.getDomainConfig().getStandaloneServerConfigMap();
        {
            StandaloneServerConfig sc = map1.get("server");
            Map<String, ResourceRefConfig> rm = sc.getResourceRefConfigMap();

            if (rm.containsKey(resourceName)) {
                System.out.println(resourceName + " already referenced for the server instance");
            } else {
                sc.createResourceRefConfig(resourceName, true);
                System.out.println(resourceName + " reference created for the server instance");
            }
        }
    }
}

References :

GlassFish
Administration Guide > configuring connection pool
Administration Guide > configurations for specific drivers
AMX

 

Friday Mar 16, 2007

Sequoia database clustering middleware with GlassFish

Using Sequoia with GlassFish

Sequoia is a open source database clustering middleware that allows any Java application to transparently
access a cluster of databases through JDBC.No code change is required to enable an application to
have failover, replication capabilities.
    This demo will have the modified sample application from Netbeans,  deployed in GlassFish,
interacting with Sequoia controller for database operations. The only change needed in the sample is to
configure the properties of jdbc-connection-pool to interact with Sequoia controller.

Bundles used :

GlassFish v2 build 38
Sequoia 2.10.6
Netbeans 5.5.1 beta

Setup :

Install GlassFish & Netbeans

GlassFish server can be registered through Netbeans > Runtime > Servers > Sun Java System Application Server

register-server


Installation of Sequoia :

Extract the downloaded bundle and set the environment variable SEQUOIA_HOME to the installation (extracted) directory.
Sequoia has sample configurations for various modes. This demo will modify and use the "hsqldb-raidb1-distribution-1.xml"
available in SEQUOIA_HOME/config/virtualdatabases to work with JavaDB bundled with GlassFish.

Sequoia Controller :

Controller is responsible for delegating the requests to underlying databases that are transparent to the application.
Behind the scenes, sequoia will log the requests in a recovery table that will be used during recovery of a failed node
(database). The entire setup can be distributed ie., Application, Sequoia controller, databases to store the application data,
 database to store the recovery log can all be distribued. Controller will load balance the read operations (queries) to one
 of the database nodes and will replicate the write operations (create, drop, insert, delete, update) to all the database nodes.

Configuration of virtual database:

Virtual database represents the configuration of individual database nodes, recovery db node and has credentials for application
 to connect to  controller.
 
copy "hsqldb-raidb1-distribution-1.xml" as "hetero-raidb1-distribution-1.xml"
Change VirtualDatabase name to "heterodb"
Set the "admin" password of AuthenticationManager to "adminadmin" [To do controller operations]
Set the virtualuser login of AuthenticationManager to "jdbc" and password to "jdbc" [For applications to interact with Sequoia]
For this demo, Derby is used in embedded mode.

Configuring individual database nodes for data replication :


<DatabaseBackend name="localhost1" driver="org.apache.derby.jdbc.EmbeddedDriver" url="jdbc:derby:heterodb1;Password=APP;User=APP;databaseName=heterodb1;create=true;" connectionTestStatement="select count(\*) from sys.systables">
      <ConnectionManager vLogin="jdbc" rLogin="APP" rPassword="APP">
        <VariablePoolConnectionManager initPoolSize="10" minPoolSize="5" maxPoolSize="50" idleTimeout="30" waitTimeout="10"/>
      </ConnectionManager>
    </DatabaseBackend>

    <DatabaseBackend name="localhost2" driver="org.apache.derby.jdbc.EmbeddedDriver" url="jdbc:derby:heterodb2;Password=APP;User=APP;databaseName=heterodb2;create=true;" connectionTestStatement="select count(\*) from sys.systables">
      <ConnectionManager vLogin="jdbc" rLogin="APP" rPassword="APP">
        <VariablePoolConnectionManager initPoolSize="10" minPoolSize="5" maxPoolSize="50" idleTimeout="30" waitTimeout="10"/>
      </ConnectionManager>
    </DatabaseBackend>
  

Configuring recovery log table :


  <RecoveryLog driver="org.apache.derby.jdbc.EmbeddedDriver"
        url="jdbc:derby:recoverydb1;Password=APP;User=APP;databaseName=recoverydb1;create=true;" login="APP" password="APP">
        <RecoveryLogTable tableName="RECOVERY" logIdColumnType="BIGINT"
          vloginColumnType="VARCHAR (500) " sqlColumnType="VARCHAR(500)"
          extraStatementDefinition=",PRIMARY KEY (log_id)"/>
        <CheckpointTable tableName="CHECKPOINT"
          checkpointNameColumnType="VARCHAR(500) "/>
        <BackendTable tableName="BACKEND"
          databaseNameColumnType="VARCHAR(500) "
          backendNameColumnType="VARCHAR(500) "
          checkpointNameColumnType="VARCHAR(500) "/>
        <DumpTable tableName="DUMP" dumpNameColumnType="VARCHAR(500) "
          dumpDateColumnType="TIMESTAMP"
          dumpPathColumnType="VARCHAR(500) "
          dumpFormatColumnType="VARCHAR(500) "
          checkpointNameColumnType="VARCHAR(500) "
          backendNameColumnType="VARCHAR(500) "
          tablesColumnType="VARCHAR(500) "/>
      </RecoveryLog>

Configuring the Backuper :

Backuper is used to take complete backup of a node (backend) and can be used to create a new backend or
transfer the backup to another controller to bring back the controller from failure.

Above sample configration uses Derby's Embedded driver and hence setting Derby Embedded backuper.
<Backup>
      <Backuper backuperName="DerbyEmbeddedBackuper"
        className="org.continuent.sequoia.controller.backup.backupers.DerbyEmbeddedBackuper"
        options="zip=true"/>
</Backup>

Complete virtual database configuration file can be downloaded from here and copied to SEQUOIA_HOME/config/virtualdatbases

Copy the JavaDB driver (derby.jar available in GlassFish_Install_Dir/javadb/lib) to $SEQUOIA_HOME/drivers so that they
are available for Sequoia controller.


Controller configuration :

Configuration file sample is available at SEQUOIA_HOME/config/controller
copy "controller-distributed-1.xml" to "hetero-distributed-1.xml" and set the virtual database to use.

 <VirtualDatabase configFile="hetero-raidb1-distribution-1.xml" virtualDatabaseName="heterodb" autoEnableBackends="true"/>

Complete controller configuration file can be downloaded from here and copied to SEQUOIA_HOME/config/controller

Starting the Sequoia controller :

SEQUOIA_HOME/bin/controller.sh -f config/controller/hetero-distributed-1.xml


20:31:21,629 INFO controller.core.Controller Sequoia  controller (2.10.6)
20:31:21,694 INFO controller.core.Controller Loading configuration file: config/controller/hetero-distributed-1.xml
20:31:21,791 INFO controller.core.Controller JMX is enabled
20:31:21,820 INFO controller.core.Controller Starting JMX server on host: 127.0.0.1
20:31:22,185 INFO backup.backupers.DerbyEmbeddedBackuper DerbyEmbeddedBackuper backup compression is set to true
20:31:22,223 INFO backend.DatabaseBackend.localhost1 Adding connection manager for virtual user "jdbc"
20:31:22,229 INFO backend.DatabaseBackend.localhost2 Adding connection manager for virtual user "jdbc"
20:31:22,234 INFO backend.DatabaseBackend.localhost3 Adding connection manager for virtual user "jdbc"
20:31:25,899 INFO sequoia.controller.recoverylog Creating recovery log table: RECOVERY
20:31:26,011 INFO sequoia.controller.recoverylog Creating checkpoint table: CHECKPOINT
20:31:26,160 INFO sequoia.controller.recoverylog Creating backend table: BACKEND
20:31:26,227 INFO sequoia.controller.recoverylog Creating dump table: DUMP
20:31:26,410 INFO controller.RequestManager.heterodb Request manager will parse requests with the following granularity: TABLE
20:31:26,417 INFO controller.virtualdatabase.heterodb Using Hedera properties file:/hedera_jgroups.properties
-------------------------------------------------------
GMS: address is127.0.0.1:32771
-------------------------------------------------------
20:31:31,211 INFO controller.virtualdatabase.heterodb Group heterodb connected to Member(address=/127.0.0.1:32771, uid=heterodb)
20:31:31,211 INFO controller.virtualdatabase.heterodb First controller in group heterodb
20:31:31,422 INFO sequoia.controller.recoverylog Checking recovery log consistency
20:31:31,533 WARN controller.virtualdatabase.heterodb Cannot enable backend localhost1 from a known state. Resynchronize this backend by restoring a dump.
20:31:31,536 WARN controller.virtualdatabase.heterodb Cannot enable backend localhost2 from a known state. Resynchronize this backend by restoring a dump.
20:31:31,538 WARN controller.virtualdatabase.heterodb Cannot enable backend localhost3 from a known state. Resynchronize this backend by restoring a dump.
20:31:31,539 INFO controller.core.Controller Adding VirtualDatabase heterodb
20:31:31,553 INFO controller.core.Controller Waiting for connections on 0.0.0.0:25322
20:31:31,562 INFO controller.core.Controller Controller started on 2007.03.08 10 at08:31:31 PM IST
20:31:31,562 INFO controller.core.Controller Controller 127.0.0.1:25322 ready, listening to requests ...

Initializing the nodes using the Sequoia console:

SEQUOIA_HOME/bin/console.sh

Launching the Sequoia controller console
Initializing Controller module...
Initializing VirtualDatabase Administration module...
Initializing SQL Console module...
Sequoia driver (Sequoia core v2.10.6) successfully loaded.

localhost:1090 > admin heterodb
Virtual database Administrator Login > admin
Virtual database Administrator Password >
Ready to administrate virtual database heterodb

heterodb(admin) > initialize localhost1 force
Virtual Database heterodb has been successfully initialized from backend localhost1

heterodb(admin) > initialize localhost2 force
Virtual Database heterodb has been successfully initialized from backend localhost2

heterodb(admin) > enable localhost1
Enabling backend localhost1 from its last known checkpoint

heterodb(admin) > enable localhost2
Enabling backend localhost2 from its last known checkpoint

Now both the nodes are initialized and can serve for replication.

Sample application :


Start Netbeans, Create a new project > Samples > Enterprise > CustomerCMP

CustomerCMP application


select the jdbc-connection-pool

jdbc-pool-properties


and change the configuration (DataSource Classname, Properties) to point to sequoia controller

modified-pool-properties

For GlassFish to talk to Sequoia controller, copy the Sequoia jdbc-driver from $SEQUOIA_HOME/drivers/sequoia-driver.jar to
GLASSFISH_HOME/domains/domain/lib/ext

All the set up is done to build & deploy the application to GlassFish.

From Netbeans, build & deploy the sample application. This will build the project, generate .ear file, start GlassFish,
create connection pools, deploy the application to GlassFish

Once the deployment is successful, run project from Netbeans.
Netbeans will open the browser with the web-application's URL.

customer application


Customer CMP application :

Simple application where customer details can be captured.

create customer 'jagadish'

Create a new customer and ensure that the entries are persisted, through the "search" option provided in the application.

search 'jagadish'

Now, to check the fail-over functionality, disable one of the node (backend) through Sequoia console.
heterodb(admin) > disable localhost2
Disabling backend localhost2 with automatic checkpoint.
heterodb(admin) >

Sequoia Controller will have similar logs :

22:33:13,236 INFO  controller.RequestManager.heterodb All activity is suspended for heterodb
22:33:13,361 INFO  controller.virtualdatabase.heterodb Checkpoint disable
localhost2-127.0.0.1:25322-20070308223313132+0530 was stored
22:33:13,364 INFO  controller.virtualdatabase.heterodb Disabling backend localhost2,
 waiting for current transaction to complete on this
backend
22:33:13,384 INFO  sequoia.controller.connection 5 connections freed on
"jdbc:derby:heterodb1;Password=APP;User=APP;databaseName=heterodb1;create=true;"
22:33:13,509 INFO  controller.virtualdatabase.heterodb Backend localhost2 is now disabled
22:33:13,509 WARN  controller.virtualdatabase.heterodb No information has been found for remote controller
Member(address=/127.0.0.1:32773, uid=heterodb)
22:33:13,509 WARN  controller.virtualdatabase.heterodb Updating backend list with unknown backend localhost2
 disabled on controller
Member(address=/127.0.0.1:32773, uid=heterodb)

Create another customer and ensure that the entries are persisted. [Behind the scenes, localhost1 alone will have
the entries and localhost2 is disabled/down]

create-user-arun

Now disable localhost1 and enable localhost2

heterodb(admin) > disable localhost1
Disabling backend localhost1 with automatic checkpoint.

heterodb(admin) > enable localhost2
Enabling backend localhost2 from its last known checkpoint



Access the application, search for customers of last name "Prasath"

search 'prasath'

There will not be any change in behavior of the application.
Behind the scenes, when localhost2 is enabled, all the entries will be persisted into localhost2 from recovery log's last
known checkpoint and ensure transparent failover & replication.

Multiple controllers :

It is possible to have more than one controller for a virtual database. In such a case, URL for the application will be,
for eg : jdbc:sequoia://127.0.0.1:25322,127.0.0.1:25323/heterodb

Controller-2, virtual database configured similar to as shown above. Backends can be localhost3, localhost4.
Complete controller-2, virtual database file , configuration file can be copied to SEQUOIA_HOME/config/virtualdatabase, SEQUOIA_HOME/config/controller respectively.

With 2 controllers available, it is possible to shutdown an controller as a whole for maintenance. In case one of the controller
 fails (eg, controller-2), sequoia driver will use the other and ensures availability. Backup can be taken on controller-1,
 transferred to controller-2 and nodes can be restored.

Steps in brief :

Disable the backends of controller-2
Add new customers using the application.
Take database dump of localhost1.
localhost:1090 > admin
Virtual Database Name > heterodb
Virtual database Administrator
Login > admin
Virtual database Administrator Password >
Ready to administrate virtual database heterodb

heterodb(admin) > backup localhost1 localhost1.bkp DerbyEmbeddedBackuper /home/jagadish/Desktop
Backend login for backup process > admin
Backend password for backup process >
Backup backend localhost1 in dump file localhost1.bkp


Bring back controller-2
heterodb(admin) > show controllers
heterodb is hosted by 2 controller(s):
127.0.0.1:1091
       
127.0.0.1:1090

Transfer the backup from controller-1 to controller-2 :

heterodb(admin) > transfer dump localhost1.bkp 127.0.0.1:1091 nocopy
Transferring dump localhost1.bkp to controller 127.0.0.1:1091...
Done
Restore the backends using backup.
 
heterodb(admin) > restore backend localhost3 localhost1.bkp.2
Backend login for restore process> admin
Backend password for restore process >

Restoring backend localhost3 with dump localhost1.bkp.2
heterodb(admin) > restore backend localhost4 localhost1.bkp.2
Backend login for restore process> admin
Backend password for restore process >
Restoring backend localhost4 with dump localhost1.bkp.2


Disable controller-1
heterodb(admin) > disable localhost2
Disabling backend localhost2 with automatic checkpoint.
heterodb(admin) > disable localhost1
Disabling backend localhost1 with
automatic checkpoint.

Access the application, customers added when controller-2 was disabled will be visible via controller-2.

References :

GlassFish
Sequoia - Tutorial
Sequoia - Installation Guide
Sequoia - Administration Guide
Netbeans


Technorati Tags:

Thursday Apr 06, 2006

ConnectionSharingInGlassFish

Connection Sharing in GlassFish Application Server

Connection Sharing in GlassFish Application Server

When multiple connections x and y acquired by an application are used within a transaction scope, application server will provide shared connection behavior when the following set of properties are satisfied.

  • x and y are collocated in a single Java Virtual Machine process address space.
  • x and y are using a single transactional resource manager.
  • x and y have identical properties.
  • x and y are marked as shareable.
  • x and y are used within a container-managed or bean-managed transaction scope.

In GlassFish, connections from different jdbc-resources using same connection-pool can be shared.

Ex:

When multiple connection requests to same data-source happen within a transaction, application server may re-use the connection already acquired as a part of the transaction.
Let us consider the following scenario :


	Tx Scope Begins
		get Connection1
		do DB operation
		get Connection2
		do DB operation
	Tx Scope Ends

Suppose, connection-2 has to be acquired from the same data-source as that of connection-1, application server may re-use the physical connection of connection-1.

How do I enable/disable Connection Sharing ?

By specifying the following highlighted property in deployment descriptor (web.xml / ejb-jar.xml). Default value is Shareable.

 <resource-ref>
        <res-ref-name>jdbc/EmployeeAppDB</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
        <res-sharing-scope>Shareable</res-sharing-scope>
    </resource-ref>
To disable sharing:
        <res-sharing-scope>Unshareable</res-sharing-scope>
Note : For Local Transactions, only shareable scope is applicable.

Connection Sharing in BMPs

a) Container Managed Transaction:

   ( <transaction-type>Container</transaction-type>)
		 BMP-Bean-1
			businessMethod(){   // Transaction attribute "Required"
				con1 = dataSource.getConnection();  
				doDBOperation();
				bean2 = lookupBean2;
				bean2.businessMethod();
				con1.close();
			}

		BMP-Bean-2
			businessMethod(){ // Transaction Attribute "Required"
				con2 = dataSource.getConnection(); // same data-source as that of con1 in bean-1
				doDBOperation();
				con2.close();
  			}

During Bean2's method call, connection sharing happens. Application server first acquires a free connection from the connection pool. During connection enlistment, connection association happens which will map the ManagedConnection (and hence physical connection) of con-1 to con-2. Thus DBOperation happens through same physical connection (connection sharing).

What happens to the actual Physical Connection acquired by conn-2 ?

By the end of transaction, physical connection of con-1 is dissociated from conn-2 and conn-2 is mapped back with its actual physical connection. The purpose of this connection association and dissociation can be seen in the following sample.

b)Bean Managed Transaction
		   (<transaction-type>Bean</transaction-type>)
			businessMethod(){   
				UserTransaction uTx = entityContext.getUserTransaction(); 
				try{
					uTx.begin();
					con1 = dataSource.getConnection(); 
					doDBOperation() using con1;

					con2 = dataSource.getConnection(); 
					doDBOperation() using con2; //using physical connection of conn-1, connection sharing.
					uTx.commit();
				}
				catch(SQLException sqle){
					uTx.rollback();
				}
					con1.close();
					doDBOperation() using con2; // using actual physical connection,  no sharing involved.
					con2.close();
			}
After commit/rollback, con2 is associated back with its actual physical connection. Thus during doDBOperation() after the UserTransaction scope, actual physical connection of conn-2 is used.

How do I know that connection-sharing has actually happened?

In the sample above, dataSource ( com.sun.appserv.jdbc.DataSource ) has a method to get the physical connection.

To get the physical connection,
			Connection pc1 = dataSource.getConnection(con1);
			Connection pc2 = dataSource.getConnection(con2);
pc1, pc2 can be retrieved within and outside the scope of a transaction and compared.


  • Picture shows connections' state in Application Server, Resource Adapter (Physical Connection), within and outside the transaction scope.
  • Log shows the connection objects' hash-code value within and outside the transaction scope.

Few interesting scenarios to see whether connection sharing happens or not is,

			a) 
				con1 = dataSource.getConnection();  
				UserTransaction uTx = entityContext.getUserTransaction(); 
				uTx.begin();
					con2 = dataSource.getConnection();  
 					doDBOperation() using connection-1
 					doDBOperation() using connection-2
				uTx.commit();
				con1.close();
				con2.close();
			
			b)
				con1 = dataSource.getConnection();  
				con2 = dataSource.getConnection();  
				UserTransaction uTx = entityContext.getUserTransaction(); 
				uTx.begin();
 					doDBOperation() using connection-1
 					doDBOperation() using connection-2
				uTx.commit();
				con1.close();
				con2.close();
 

Are there any restrictions when connections are used in sharing scope?

Yes, When connection sharing is enabled, certain properties should not be modified. Suppose connection-1's property is changed and when sharing happens, connection-2 will have the modified property. Application Server will throw SharingViolationException. More details can be found in the J2EE Connector Architecture 1.5 Specification, section 7.9 - Transaction Management > Connection Sharing.

Technorati Tags:

About

jagadish

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today