On Tue, Mar 17, 2015 at 3:29 PM Nigel Deakin <nigel.deakin_at_oracle.com>
wrote:
> On 17/03/2015 17:10, John D. Ament wrote:
> > Changing to users again...
>
> (Staying on users to avoid you having to change the recipient when you
> reply)
>
> > On Tue, Mar 17, 2015 at 10:38 AM Nigel Deakin <nigel.deakin_at_oracle.com
> <mailto:nigel.deakin_at_oracle.com>> wrote:
> >
> > On 17/03/2015 12:31, John D. Ament wrote:
> > > I think using a service loader approach would be the best, and
> most consistent option.
> > >
> > > ConnectionFactory cf = JMS.newConnectionFactory(map);
> > >
> > > or
> > >
> > > ConnectionFactory cf = JMS.newConnectionFactory();
> > >
> > > Where JMS is a new class added by the EG, similar to provider
> classes in WebSocket, JPA, BeanValidation etc.
> > >
> > > John
> >
> > Who implements the "JMS" class? Does each JMS provider have to
> supply its own implementation?
> >
> >
> > The JMS provider implements it.
> > The most common approach is a service loader, leveraged by CDI, Bean
> Val, WebSocket.
> > Less common is a factory like EJBContainer. JPA has their own thing
> entirely based on a custom file entry.
> >
> > If it is implemented by the JMS provider, how how does the
> application choose which whose implementation of the "JMS"
> > class it wishes to use, bearing in mind that the same application
> must be able to use multiple JMS providers?
> >
> >
> > ServiceLoaders. If you have multiple impls on the path, an option like
> JPA's is possible, or adding a map of options to
> > look for would help.
>
> Right. We should have a discussion about the role of ServiceLoader.
>
> But, if I understand it correctly, ServiceLoader is really just a bit of
> portable convenience code which instantiates a
> specific service provider object on behalf of an application. It still
> relies on having a standard API to instantiate
> that object.
>
> So we *still* need to define a portable API that the ServiceLoader
> mechanism (or whatever convenience code we adopt) is
> able to instantiate a JMS provider-specific object provided by a
> particular JMS provider.
>
Yes, of course. Here's a simple example (free to use)
public interface JMS {
public static ConnectionFactory
createConnectionFactory(Map<String,Object> params) {
ServiceLoader<JMS> serviceLoader = ServiceLoader.load(JMS.class);
for(JMS jms : serviceLoader) {
if(jms.isAcceptable(params)) {
return jms.create(params);
}
}
throw new IllegalArgumentException("No match for providers
"+params);
}
/**
* Determines if this JMS provider can accept the parameters
* @param params
* @return true if the parameters can be used by this provider, false
if not.
*/
boolean isAcceptable(Map<String,Object> params);
/**
* Creates a ConnectionFactory based on the configuration parameters
passed in
* @param params
* @return a ConnectionFactory from this JMS Provider
*/
ConnectionFactory create(Map<String,Object> params);
}
Basically, we loop through the found JMS implementations, see if they can
accept this ambiguous map of configuration options, and returns back a
connection factory from that implementation.
John
>
> >
> > If the same implementation is expected to work for each JMS
> provider, then how does the implementation know how to
> > instantiate a given ConnectionFactory?
> >
> >
> > They're generally no args constructors with init methods.
>
> Yes, as you say, if we want to support ServiceLoader then (to quote the
> docs) "provider classes must have a
> zero-argument constructor"
>
> Given this, what kind of class is the "provider class"?
>
> Is it a "factory for connection factories", as in your "JMS" suggestion
> above?
>
> Or is it the factory we already have, which is ConnectionFactory (we would
> need to mandate a no-arg constructor if we
> want it to be used by ServiceLoader)?
>
> I have to return to the question I asked earlier: do we need a
> provider-specific factory of connection factories, and,
> if so, why?
>
> Nigel
>
>
>
>
>
>