jsr343-experts@jms-spec.java.net

[jsr343-experts] Re: (JMS_SPEC-46) Define standard API to create and configure a ConnectionFactory

From: Nigel Deakin <nigel.deakin_at_oracle.com>
Date: Mon, 19 Sep 2011 15:36:02 +0100

Dear all,

On 16/09/2011 16:32, Nigel Deakin wrote:
> A month ago I made this proposal:
>
> On 11/08/2011 16:46, Nigel Deakin wrote:
>> I have created this JIRA issue
>> http://java.net/jira/browse/JMS_SPEC-46
>>
>> Aspects of this issue were raised by both Clebert and Emran, but I believe there is a wider requirement which comes out
>> of the Java EE platform initiatative to allow JMS and other resources to be specified in more detail.
>>
>> Clebert wrote: "[I would like to see the ability] to instantiate connection factories directly. I would make a relation
>> to JDBC here. You can make here an analogy to JDBC as you don't need JNDI to make an initial connection."
>>
>> Emran wrote: "[I would like to see] API on connection factories to create connections with secure transport (I have seen
>> this feature in the jms containers as a configurable property on connection factories)."
>>
>> This is quite a long description and it may be easier to read the formatted version in the JIRA issue rather than the
>> text version below. In any case, I would appreciate your comments on what is a small but potentially very significant
>> change.
>
> In response I got just one comment, from Reza, who wrote: "This seems like an excellent, timely change.". There were no
> other comments. Since this is potentially quite a significant change, at least for vendors, I'd like to invite some more
> specific comments rather than simply declare that it approved by default.
>
> In particular, I'd like to invite Clebert and Emran, who raised this issue originally, whether this satisfies their
> requirements. It would also be good to hear from the other representatives of JMS vendors on this EG...
>
> Nigel

I've been thinking more about how my proposal would work in a Java EE environment where the JMS connection factory is
provided by the resource adapter, not the underlying JMS provider.

In such an environment, the connection factory is provided by the resource adapter and is created by calling one of two
createConnectionFactory methods on the javax.resource.spi.ManagedConnectionFactory:

This typically happens as part of the JNDI lookup. The ManagedConnectionFactory instance is implemented by the resource
adapter and is required to be a JavaBean.

So I think my suggestion that the connection factory would be defined and instantiated simply by using a no-arg
constructor may be too simplistic (though it may be OK for Java SE). I'll need to investigate this further, but for now
I'd like to withdraw the proposal that a connection factory be created using a no-arg constructor.

However I think all the other proposals, which define a set of standard properties for connection factories, can
probably still stand.

One of the reasons I think these are needed is that, separately, the Java EE Expert Group is discussing whether to allow
connection factories to be defined in JNDI using @JMSConnectionFactoryDefinition annotations, analogous to
@DataSourceDefinition annotations.

These provide a standard way to *create* connection factories in JNDI, which is currently completely non-standard.

The general idea of having this annotation is probably out of our scope, but might look something like this:

  @JMSConnectionFactoryDefinition(
    name="java:app/MyJMSFactory",
    resourceType="javax.jms.QueueConnectionFactory",
    resource-adapter="somera",
    clientId="foo",
    connectionTimeout=10,
    initialPoolSize=5,
    maxPoolSize=15
)

However the actual connection factory properties that can be defined are definitely within our scope to define (apart
from those which are related to pooling).

Nigel


>
>
>> Nigel
>>
>>
>> This is a proposal to extend the JMS specification to define a standard way of instantiating and configuring connection
>> factory objects.
>>
>> Background
>> ----------
>>
>> A connection factory is an example of an administered object. The JMS 1.1 specification establishes the convention
>> whereby administered objects (connection factories and destinations) are not created in application code. Instead they
>> are created by an administrator using tools specific to the JMS provider and stored in JNDI. The application code then
>> looks up the connection factory or destination from JNDI and uses them in accordance with the JMS API.
>>
>> The purpose of this is clearly stated in the specification: it is to allow everything that is non-standard and specific
>> to a particular JMS provider to be kept out of the code itself. (See "Relevant sections of the JMS 1.1 Specification"
>> below).
>>
>> In the case of connection factories, this means that the application doesn't have to contain any information about how
>> to connect to the JMS provider. For example, if the JMS provider is running on some remote server, the application
>> doesn't contain any information about the location of the server or the protocol used to connect to it. All this
>> information is defined when the connection factory is created by an administrator, separate from the application itself.
>>
>> However the JMS specification says nothing about how the connection factory itself is created or configured, other than
>> saying that it is done by "provider-specific facilities". All it says is that:
>>
>> * it must implement javax.jms.ConnectionFactory,
>> * it must implement javax.naming.Referenceable and java.io.Serializable, so it can be stored in all JNDI naming contexts
>> (section 4.2)
>> * it is *recommended* that implementations "follow the JavaBeans design patterns"
>> * it allows client identifier to be set (section 4.3.2)
>>
>> However the specification does not define:
>>
>> * how a connection factory is instantiated
>> * how the location of the server is defined
>> * how client identifier is set
>> * how other properties are set
>>
>> Now although this omission from the JMS 1.1 specification is no doubt deliberate, it does cause some difficulties:
>>
>> * it is not possible to develop standard tools for creating connection factories (and binding them in JNDI) which work
>> with multiple JMS providers
>>
>> * in a Java EE environment, there is no standard way of configuring the JMS requirements of a particular application
>>
>> * it is inconsistent with way in which a JDBC DataSource objects is defined, both in a Java SE and a Java EE
>> environment. This is discussed more in 'How JDBC DataSource objects are configured'.
>>
>> Proposals
>> ---------
>>
>> It is proposed that the way that a ConnectionFactory is created and configured be partially standardised in a manner
>> similar to JDBC DataSource objects, as follows:
>>
>> * A ConnectionFactory implementation is a JavaBean, and may be instantiated by executing the no-arg constructor of its
>> implementation class. For example:
>>
>> ConnectionFactory cf = Class.forName("com.sun.messaging.ConnectionFactory")
>>
>> * The JMS specification will define a set of properties which may be used to identify and describe a ConnectionFactory
>> implementation.
>>
>> || Property name || Type || Description||
>> | description | String | description of this connection factory|
>> | user | String| user name (may be overridden when createConnection is called) |
>> | password | String| password corresponding to user name may be overridden when createConnection is called) |
>> | networkProtocol | String| network protocol used to communicate with the JMS provider |
>> | serverName | String| server name of the JMS provider |
>> | portNumber | String| port number of the JMS provider |
>> | networkProtocols | String[] | array of network protocols used to communicate with the JMS provider |
>> | serverNames | String[] | array of server names of the JMS provider |
>> | portNumbers | String[] | array of port numbers of the JMS provider |
>> | url | String| Opaque string which defines how to connect to the JMS provider |
>> | clientId | String| JMS client identifier |
>>
>> * ConnectionFactory properties follow the convention specified for properties of JavaBeans components in the JavaBeans
>> 1.01 Specification. ConnectionFactory implementations may augment this set with implementation-specific properties. If
>> new properties are added, they must be given names that do not conflict with the
>> standard property names.
>>
>> * ConnectionFactory implementations must provide "getter" and "setter" methods for each property they support. These
>> properties typically are intended to be initialized before the object is bound in JNDI for subsequent use by an
>> application.
>>
>> * ConnectionFactory properties are not intended to be directly accessible by JMS clients. This design is reinforced by
>> defining the access methods on the implementation class rather than on the public DataSource interface used by
>> applications. Furthermore, the object that the client manipulates can be a wrapper that only
>> implements the ConnectionFactory interface. The setter and getter methods for the properties need not be exposed to the
>> client.
>>
>> * Management tools that need to manipulate the properties of a ConnectionFactory implementation can access those
>> properties using introspection.
>>
>> Note that this gives three alternative ways to define how the connection factory should communicate with the server:
>>
>> * an opaque URL string
>>
>> * a tuple of (networkProtocol, serverName, portNumber), where networkProtocol may be omitted
>>
>> * an array of such tuples, represented here as three separate arrays
>>
>> A JMS provider may support all, some or none of these alternatives.
>>
>> * If both URL and one of the other forms are supported and both are supplied, the URL is used.
>>
>> * If the single tuple (networkProtocol, serverName, portNumber) is supported, then a single-element array of tuples will
>> also be supported
>>
>> (Much of the wording above is based on section 9.4.1 'DataSource properties' of the JDBC 4.0 specification.)
>>
>> How JDBC DataSource objects are configured
>> ------------------------------------------
>>
>> This section describes how, although JDBC DataSource objects are similar in concept to JMS ConnectionFactory objects,
>> the JDBC and Java EE specifications define in much more detail how DataSource objects are created and configured than
>> the JMS specification defines for ConnectionFactory objects.
>>
>> A JMS ConnectionFactory is a factory for creating connections to a JMS provider, using the createConnection method. In
>> JDBC, a javax.jdbc.DataSource fulfils a similar role as a factory for creating connections to a JDBC database, using the
>> getConnection method.
>>
>> Section 9.4.2 recommends that javax.jdbc.DataSource objects are stored in JNDI to allow database-specific configuration
>> to be kept separate from the application. This much is similar to JMS.
>>
>> However the JNDI specification differs from JMS in providing a lot of guidance on how to create a DataSource. Section
>> 9.4.1 contains a whole list of standard data source properties which may be supported:
>>
>> * databaseName
>> * dataSourceName
>> * description
>> * networkProtocol
>> * password
>> * portNumber
>> * roleName
>> * serverName
>> * user
>>
>> Although the specification suggests that not all DataSource implementations support all properties, it does define names
>> for these most common properties, and specifies that when supported, they must be configurable using standard JavaBeans
>> "setters and getters".
>>
>> In addition, a DataSource may be instantiated by invoking its no-arg constructor. This isn't stated explicitly in the
>> spec (if the DataSource were a JavaBean then a no-arg constructor would be mandatory, but the spec only states that its
>> properties follow the conventions specified for properties of JavaBeans, not that a DataSource is itself a JavaBean) but
>> in practice the convention that it can is well-established.
>>
>> This means that a DataSource may be instantiated, given the name of the implementation class as a String, using code of
>> the following form:
>>
>> DataSource ds = Class.forName("oracle.jdbc.pool.OracleDataSource")
>>
>> Meanwhile, the Java EE 6 specification defines a DataSourceDefinition annotation and a corresponding <data-source>
>> element which defines the following properties of a DataSource:
>>
>> * className (required)
>> * name (required)
>> * databaseName
>> * description
>> * initialPoolSize
>> * isolationLevel
>> * loginTimeout
>> * maxIdleTime
>> * maxPoolSize
>> * maxStatements
>> * minPoolSize
>> * password
>> * portNumber
>> * properties
>> * serverName
>> * transactional
>> * url
>> * user
>>
>> This is a longer list than is defined in JDBC, partly because the JDBC spec is older, but also because it also includes
>> pooling properties. Perhaps of the most interest is the url property, which may be provided as an alternative to
>> serverName and port.
>>
>> Relevant sections of the JMS 1.1 Specification
>> ----------------------------------------------
>>
>> The relevant sections of the JMS specification are given below:
>>
>> Section 2.3 'Administration'
>>
>> "It is expected that JMS providers will differ significantly in their underlying messaging technology. It is also
>> expected there will be major differences in how a provider’s system is installed and administered.
>>
>> "If JMS clients are to be portable, they must be isolated from these proprietary aspects of a provider. This is done by
>> defining JMS administered objects that are created and customized by a provider's administrator and later used by
>> clients. The client uses them through JMS interfaces that are portable. The administrator creates them using
>> provider-specific facilities.
>>
>> "There are two types of JMS administered objects:
>>
>> • "ConnectionFactory - This is the object a client uses to create a connection with a provider.
>> • "Destination - This is the object a client uses to specify the destination of messages it is sending and the source of
>> messages it receives.
>>
>> "Administered objects are placed in a JNDI namespace by an administrator. A JMS client typically notes in its
>> documentation the JMS administered objects it requires and how the JNDI names of these objects should be provided to it.
>>
>> Section 4.2 'Administered Objects'
>>
>> "JMS administered objects are objects containing JMS configuration information that are created by a JMS administrator
>> and later used by JMS clients. They make it practical to administer JMS applications in the enterprise.
>>
>> "Although the interfaces for administered objects do not explicitly depend on JNDI, JMS establishes the convention that
>> JMS clients find them by looking them up in a namespace using JNDI.
>>
>> "An administrator can place an administered object anywhere in a namespace. JMS does not define a naming policy.
>>
>> "This strategy of partitioning JMS and administration provides several benefits:
>>
>> • It hides provider-specific configuration details from JMS clients.
>> • It abstracts JMS administrative information into Java objects that are easily organized and administered from a common
>> management console.
>> • Since there will be JNDI providers for all popular naming services, this means JMS providers can deliver one
>> implementation of administered objects that will run everywhere.
>>
>> "An administered object should not hold on to any remote resources. Its lookup should not use remote resources other
>> than those used by JNDI itself.
>>
>> "Clients should think of administered objects as local Java objects. Looking them up should not have any hidden side
>> effects or use surprising amounts of local resources.
>>
>> "JMS defines two administered objects, Destination and ConnectionFactory.
>>
>> "It is expected that JMS providers will provide the tools an administrator needs to create and configure administered
>> objects in a JNDI namespace. JMS provider implementations of administered objects should be both
>> javax.naming.Referenceable and java.io.Serializable so that they can be stored in all JNDI naming contexts. In addition,
>> it is recommended that these implementations follow the JavaBeans design patterns."
>>
>>