John,
On 27/03/2012 14:56, John D. Ament wrote:
> Nigel,
>
> So a few things. I guess I made the assumption that create == retrieve. I suppose there could be a difference - for
> example, looking up via JNDI gives you a remote object reference, but instantiating the connection factory in activemq
> is creating the implementation of connection factory. When I was using getReference, it was really pointing out that
> it could be either - a remote object or an actually instantiated object. This could be vendor specific.
>
Ah, I see. I think whether the connection factory is a "remote object reference" is an implementation detail (it
certainly isn't one in the cases I am familiar with). The object might be stored in JNDI as a Reference, but that
reference will be turned back to a ConnectionFactory instance when it is looked up.
(But we're just discussing the name of a method here)
> See below for the rest.
Ditto.
>
> John
>
> On Tue, Mar 27, 2012 at 6:59 AM, Nigel Deakin <nigel.deakin_at_oracle.com <mailto:nigel.deakin_at_oracle.com>> wrote:
>
> 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)
>
>
>
>
> Right, Properties implements Map (and extends Hashtable, thus requiring it to be synchronized). Ideally, I would
> expect the argument to be Map<String,Object>, or Map<String,String> which could be a properties file. Note that
> properties is actually <Object, Object> type, harming some of the type safety.
> http://docs.oracle.com/javase/7/docs/api/java/util/Properties.html
>
Yes, I like that. Map<String,String> would indeed be better.
>> 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);
>
>
> So would it be a new requirement that the constructor supports an argument of properties or Map (as I am pushing above).
Yes, that is what I am proposing.
Nigel
>
> 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.
>>
>>
>>
>