JBoss 7: Retrieve list of configured datasources at runtime

Introduction

Working with database connections on enterprise application servers like JBoss is in 99.9% very simple and well standardized. After configuring your environment, you can use JPA in order to handle all database interactions. In that way, during coding, you do not need to create any database connections or bother what is the name of database as well as datasource name. However, there is this 0.1% of cases in which your application is extraordinary (been there ;-) ) and you need to have some more information and control over your database connections. If you do, in this post you will find how to retrieve a list of available datasources.

I assume you already know

JBoss7, JMX basics, Datasource configuration on JBoss 7, JEE concepts, JConsole basics (JConsole intro).

I am working with:

JBoss-7.1.1.Final, using Windows 8

State of application

Let’s assume we have 2 datasources configured: ExampleDS and PostgresXADS.

avaliable_datasources

JBoss Admin Console – JNDI tree showing configured datasources

JConsole-eye view

In order to programmatically retrieve information about those datasources, we will use JMX MBeans, which are holding all information we need at that point. Basically we will do simple lookup, which you can also obtain using JConsole. We will use JMX Names :
1) For Local datasources: “jboss.as:subsystem=datasources,data-source=*”
2) For XA datasources: “jboss.as:subsystem=datasources,xa-data-source=*” 

If you have your JBoss running please open JConsole (how to?) and find mbeans representing datasources (MBeans tab–> then choose from the tree: jboss.as–>datasources). Depending on your JBoss datasources configuration, you should see something like:

JConsole : List of  datasources

JConsole : List of datasources

If you click on “Attributes” of any datasource from the tree, you will be presented with more detailed information about MBean. For instance it can look like:

JConsole: Datasource details

JConsole: Datasource details

In the above figure you can see some of the attributes of chosen MBean. What is interesting for us is jndiName, which states for JNDI address under which ExampleDS datasource is stored. Having it, we can easily lookup the Datasource instance from JNDI Context. Now the question: how to write Java code which does the same?

Code point of view

Simple code snippet which presents how to list Datasources. I am running this code in managed EJB Stateless Bean.

/**
 * get list of jboss managed datasources 
 */ 
@Override 
public List<DataSource> getAvailableDatasources() { 

  List<DataSource> availableDatasources = new ArrayList<DataSource>(); 
  try { 

    // retrieve the mbean server 
    MBeanServer server = java.lang.management.ManagementFactory.getPlatformMBeanServer(); 

    // key for retrieving mbeans representing LOCAL Datasource 
    // configuration from JMX namespace: jboss.as:subsystem=datasources (1) 
    String localDataSourceKeyName = "data-source"; 

    //add datasources of given type to the list
    addDatasourcesForKeyName(availableDatasources, server, localDataSourceKeyName);

    // key for retrieving mbeans representing XA Datasource  
    // configuration from JMX namespace: jboss.as:subsystem=datasources (2) 
    String xADataSourceKeyName = "xa-data-source"; 

    addDatasourcesForKeyName(availableDatasources, server, xADataSourceKeyName); 

  } catch (Exception e) { 
    //handle exception
  } 

  return availableDatasources; 
} 

/**  
  * Method which fills availableDatasources list with DataSource references. References are retrieved via JMX.
  * @param availableDatasources - list to which method will add datasoruces 
  * @param server - reference to mbean server 
  * @param dataSourceKeyName - part of jmx name which will be used to retrieve the datasource mbeans 
 */ 
private void addDatasourcesForKeyName(List availableDatasources, MBeanServer server, String dataSourceKeyName) throws MalformedObjectNameException, NamingException, AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException { 

  // Get the starting point of the namespace 
  Context ctx = new InitialContext(); 

  // create jmx filter name eg. (3)
  // "jboss.as:subsystem=datasources,xa-data-source=*" 
  final ObjectName filterName = new ObjectName("jboss.as:subsystem=datasources," + dataSourceKeyName + "=*"); 

  // get the results matching given filter. (4) 
  final Set<ObjectInstance> mBeans = server.queryMBeans(filterName, null); 

  // iterate over mbeans and retrieve information about jndi-name of datasource 
  for (final ObjectInstance mBean : mBeans) { 

    // get name for mbean describing current datasource mbean   
    ObjectName mbeanName = mBean.getObjectName(); 

    // one of the attributes of mbean is 
    // "jndiName" , we will read that attribute now:(5) 
    String bindName = (String) server.getAttribute(mbeanName, "jndiName"); 

    // having the jndi-name, we can look up the datasource instance 
    DataSource ds = (DataSource) ctx.lookup(bindName); 
    availableDatasources.add(ds); 
  } 
}

Some more detailed explanation to the code :

1,2) Example of desired mbean name can look like this: “jboss.as:subsystem=datasources,data-source=ExampleDS”. This is the same name which we have looked up in JConsole before (see)

3) We are creating object which represents JMX Name . (read more: JMX).

4) We are getting all mbeans which are listed under given JMX filter name. We should get the same list which we have seen in the mbean tree in the JConsole : see

5) Having the exact JMX name of an MBean, we can get any of its attributes or even call any of its public methods. In this case we just need to read out the “jndiName” attribute. (see the list of attributes here: list)

5) Having the JNDI-Name of the Datasource, we are  actually having its JNDI address under which given Datasource is stored in application context.

Summary

Presented code is very simple and may not need so much of explanation, but I think it is good to know how it works in the background and also how to check the results on JConsole – which can spare some time and avoid unexpected results.

If you are going to use the same code on JBoss 6, you must take into consideration, that it will not work there, since the whole server configuration is different and also provided Management Beans are different. If you would like to see how to do the same operation on JBoss 6,  you can read it in my other blog post: List datasources on JBoss 6

Links which explain more about mentioned topics:

Configuring Datasources on JBoss7: https://docs.jboss.org/author/display/AS7/DataSource+configurationhttp://planet.jboss.org/post/how_to_create_an_manage_datasources_in_as7

JMX best practices: http://www.oracle.com/technetwork/java/javase/tech/best-practices-jsp-136021.html

JMX documentation: http://www.oracle.com/technetwork/java/javase/tech/docs-jsp-135989.html

Some words about MBeans on JBoss:  http://docs.jboss.org/jbossas/docs/Server_Configuration_Guide/4/html/Using_JMX_as_a_Microkernel-JBoss_MBean_Services.html

JConsole: http://docs.oracle.com/javase/7/docs/technotes/guides/management/jconsole.html

Advertisements

One Response to JBoss 7: Retrieve list of configured datasources at runtime

  1. Pingback: JBoss 7.x : Retrieve Datasource properties ( username, database name, password) at runtime, using JMX | My Fascinations

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: