users@jms-spec.java.net

[jms-spec users] [jsr343-experts] Re: Re: (JMS_SPEC-89) Define standard API to create and configure a ConnectionFactory in Java SE applications and by a Java EE container

From: Nigel Deakin <nigel.deakin_at_oracle.com>
Date: Tue, 27 Mar 2012 11:59:27 +0100

John,

Thanks for the quick feedback!

On 27/03/2012 11:45, John D. Ament wrote:
> My feedback would be that the API should be more like:
>
> Properties props = new Properties();
> props.setProperty("connectionFactoryClassName","com.acmejms.AcmeConnectionFactory"};
> props.setProperty("url","jms://localhost:1234"};
> props.setProperty("user","admin"};
> props.setProperty("password",password);
> ConnectionFactory cf = javax.jms.ConnectionFactories.getReference(props);

I made a careless error in my proposal: I wrote:

ConnectionFactory cf = new javax.jms.ConnectionFactoryCreator(properties props);

which doesn't make sense. I meant to write:

ConnectionFactory cf = javax.jms.ConnectionFactoryCreator.create(properties props);

which is identical to your proposal except that you've suggested a different class and method name (I don't have strong
views about that).

I've corrected the JIRA issue.

Why do you suggest "getReference"? I see this method as creating a new object (a connection factory), whereas you appear
to be thinking of it differently.

>
> I would prefer a cleaner API though - either an equivalent getReference that took in the actual values, or took in a Map.

Properties implements Map. However I think Properties is better because these it expects keys and values to be Strings,
which is what I think is appropriate here (e.g. it allows properties to be read from a file or configured in a GUI)

> I would also prefer if we really needed the connectionFactoryClassName (which, I would think we don't really need)
> that it could be an actual class, not a string.
>
If you have the class declared in the application then you can simply use its constructor, which is defined in the first
part of the proposal.

Properties props = new Properties();
props.setProperty("url","jms://localhost:1234"};
props.setProperty("user","admin"};
props.setProperty("password",password);
ConnectionFactory cf = new com.acme.jms.AcmeConnectionFactory(properties props);

Nigel


> John
>
>
> On Tue, Mar 27, 2012 at 6:05 AM, Nigel Deakin <nigel.deakin_at_oracle.com <mailto:nigel.deakin_at_oracle.com>> wrote:
>
> I have logged this JIRA issue:
> http://java.net/jira/browse/JMS_SPEC-89
>
> This replaced JMS_SPEC-46 which I have withdrawn and closed.
>
> Description follows (this is best viewed in JIRA). Comments please.
>
> Define standard API to create and configure a ConnectionFactory in Java SE applications and by a Java EE container
> ------------------------------------------------------------------------------------------------------------------
>
> This is a proposal to extend the JMS specification to define a standard way of instantiating and configuring
> connection factory objects.
>
> The proposal below is intended to be used by Java SE applications and by Java EE container code such as resource
> adapters, but not by Java EE applications themselves. This is not intended to provide an alternative to Java EE
> configuration via JNDI.
>
> It replaces the proposal made in JMS_SPEC-46 and is being logged as a separate JIRA issue to avoid confusion.
>
> 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 JMS 1.1 specification section 2.3
> "Administration").
>
> 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
>
> * it means that a generic JMS resource adapter, which wraps the connection factories of third-party JMS providers,
> cannot instantiate those connection factories directly but must instead look then up from JNDI
>
> * it requires Java SE applications which use JMS to use JNDI as the only way to keep provider-specific
> configuration separate from their code. Applications cannot manage configuration their own way, such as by using
> properties files.
>
> h4. Proposed standard for instantiating a connection factory and setting properties
>
> It is proposed that for Java SE applications, and for Java EE container code only, but not for Java EE
> applications, a ConnectionFactory can be instantiated and configured by invoking a constructor which takes a
> Properties object as an argument:
>
> {noformat}
> Properties props = new Properties();
> props.setProperty("url","jms://localhost:1234"};
> props.setProperty("user","admin"};
> props.setProperty("password",password);
> ConnectionFactory cf = new com.acme.jms.AcmeConnectionFactory(properties props);
> {noformat}
>
> Note that since properties are passed into the constructor rather than be set after the object has been created in
> order this allows connection factories to be implemented as immutable objects which cannot be changed after
> creation. That's why this proposal does not suggest setting properties directly on the connection factory.
> (Another reason why this proposal does not suggest setting properties directly on the connection factory is that
> it would require changes to the javax.jms.ConnectionFactotry interface which would be inappropriate for connection
> factories in a Java EE environment.)
>
> Even though this approach is intended to avoid the need to use JNDI it remains the goal of JMS to allow the
> creation of applications which are portable between JMS providers. This means that declaring provider-specific
> classes in the application is discouraged. Instead, a new utility class javax.jms.ConnectionFactoryCreator will be
> provided by JMS which allows the provider-specific connection factory class name to be passed in as just another
> property. This could be used as follows:
>
> {noformat}
> Properties props = new Properties();
> props.setProperty("connectionFactoryClassName","com.acmejms.AcmeConnectionFactory"};
> props.setProperty("url","jms://localhost:1234"};
> props.setProperty("user","admin"};
> props.setProperty("password",password);
> ConnectionFactory cf = new javax.jms.ConnectionFactoryCreator(properties props);
> {noformat}
>
> In the above example, the property values are hardcoded just to make the example clearer. However it would be
> recommended that they be defined separately from the application.
>
> Why is this not proposed for Java EE applications?
> --------------------------------------------------
>
> Note that this proposal does not cover Java EE applications. This is because in the Java EE web and application
> container a connection factory cannot be created in isolation because it needs to participate in the connection
> pooling facilities of the container. The JCA API defines two methods on
> javax.resource.spi.ManagedConnectionFactory to create a connection factory: createConnectionFactory() and
> createConnectionFactory(ConnectionManager cxManager).
>
> This also provides another reason why the above proposal passes properties to the connection factory constructor
> rather than allowing them to be set on the connection factory instance. If we had allowed the latter this would
> have added new methods to the Connectionfactory interface whose use we would have needed to explicitly disallow
> for Java EE applications.
>
> Proposed standard properties:
> -----------------------------
>
> The following standard connection factory properties are proposed:
>
> Property name Type Description
> 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)
> clientId String clientId that will be used when a connection is created
> url String Opaque string which defines how to connect to the JMS provider
>
> This proposal deliberately keeps the list of standard properties to a bare minimum, and abandons the longer list
> proposed in JMS_SPEC-46. It is expected that JMS providers will define their own additional properties.
>
>
>