cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Andrea Smyth <andrea.sm...@iona.com>
Subject Re: Configuration APIs
Date Wed, 23 Aug 2006 13:07:42 GMT
Dan Diephouse wrote:

> Andrea Smyth wrote:
>
>> Dan Diephouse wrote:
>>
>>> I'd like to start discussing the Configuration apis for CXF. The 
>>> main celtix configuration APIs which have integrated by default are 
>>> here:
>>>
>>> http://svn.forge.objectweb.org/cgi-bin/viewcvs.cgi/celtix/trunk/celtix-common/src/main/java/org/objectweb/celtix/configuration/

>>>
>>>
>>> For those who aren't familiar with Celtix, let me try to outline how 
>>> this works. There is a tree of Configuration objects. Configurations 
>>> allow to look up a value like so:
>>>
>>> Configuration config = 
>>> getBus().getConfiguration().get.Child(HTTP_LISTENER_CONFIGURATION_URI);
>>> HTTPListenerPolicy policy = 
>>> config.getObject(HTTPListenerPolicy.class, "httpListener");
>>>
>>> Where the Bus is kind of the central object in Celtix. It has a 
>>> configuration root node which is accessed via 
>>> bus.getConfiguration().  When initializing the bus a 
>>> ConfigurationBuilder is used to build Configurations. These 
>>> Configurations are backed by  ConfigurationProviders. 
>>> ConfigurationProviders provide the actual objects. So there is a 
>>> Spring ConfigurationProvider which looks up beans from the Spring 
>>> context. There is also one which will pull configuration out of a 
>>> WSDL. The objects (like HTTPListenerPolicy) are built from XML and 
>>> are JAXB beans defined by a schema.
>>>
>>> Here's a more concrete example:
>>>
>>> http://svn.forge.objectweb.org/cgi-bin/viewcvs.cgi/celtix/trunk/celtix-distribution/src/main/samples/configuration/client.xml?view=auto&rev=947

>>>
>>>
>>> Here the configuration is backed by spring. The beans are looked up 
>>> by convention - to get the configuration for the web service port 
>>> Celtix uses the id format of "BUS_ID.SERVICE_NAME.PORT_NAME". Which 
>>> turns into the <bean id /> format you see there.
>>>
>>> Requirements that this meets:
>>> 1. Live replacement of a configuration in the system. Since an 
>>> HTTPListenerPolicy is queried every time a listener is created, we
>>> just need to replace it in the configuration tree and the effects 
>>> will be seen across the system. It is relatively easy to have a JMX 
>>> component which does this.
>>> 2. Ability to have configuration come from multiple sources - wsdl, 
>>> spring, etc. For instance, I could set up a policy for a specific
>>> endpoint in my WSDL and have a default policy in my spring config.
>>> 3. Allows configuration to be schema validated. (This is oppsed to 
>>> say the spring approach where you type <propert name="foo"/> and 
>>> hope that it is actually a property).
>>> 4. Creates a relatively straightforward way to supply configurations 
>>> in the standard case. A user just writes their Spring definition 
>>> with the standard name and its configured.
>>>
>>> ---
>>>
>>> Hopefully I've explained this somewhat well. Now, I want to talk 
>>> about what I don't like about it.
>>>
>>> 1. Its not very IoC like. Control is not inverted. For instance, the 
>>> Celtix spring integration looks up beans from the context instead of
>>> having the beans be injected in. This loses a lot of the power of 
>>> Spring as I can't control how things are wired up. Instead Celtix is 
>>> controlling it for me.
>>>
>>> 2. It is not very friendly to people just using the API and wiring 
>>> things up themselves (like embedders and people doing unit tests) .
>>> Instead of doing something like this:
>>>
>>> HTTPListenerPolicy policy = new HTTPListenerPolicy()
>>> httptransport = new HTTPTransport();
>>> httptransport.setPolicy(policy);
>>>
>>> I have to do:
>>>
>>> HTTPListenerPolicy policy = new HTTPListenerPolicy()
>>> ConfigurationImpl c = new ConfigurationImpl();
>>> c.setObject("httpListenerPolicy", policy);
>>> getBus().getConfiguration().setChild(HTTP_LISTENER_CONFIGURATION_URI, 
>>> c);
>>> new HTTPTransport(getBus());
>>>
>>> IMO, the API should focus on making itself a great API and friendly 
>>> to developers. This isn't very developer friendly, it is completely 
>>> focused on people building things from XML.
>>>
>>> Furthermore this relies on me instantiating the Bus and loading all 
>>> the configurations. What if I don't want to load the Bus? What if I 
>>> want to mock the bus? This isn't very easy with the current setup.
>>>
>>> 3. It is not very friendly to other containers
>>> Not all containers provide an String/id based mechanism to look up 
>>> objects. And not all provide easy ways to setup jaxb beans. Some, 
>>> like Plexus/Pico, are more component based than bean based. It would 
>>> be much easier if the configuration was part of the object (ala 
>>> point #2 above), than if it had to be looked up from a Configuration.
>>>
>>> ---
>>>
>>> What I would like to propose is this:
>>> 1. Remove the Configuration APIs and use getter/setter/constructor 
>>> injenction.
>>
>>>
>>> 2  Still use JAXB generated beans from schema. In addition to this 
>>> though, take the default values which are in the schema and have the 
>>> "default value plugin" from the JAXB project preinit the private 
>>> fields with those values. (i.e. <element name="timeout" 
>>> default="10"/> would turn into "private int timeout = 10;")
>>>
>> Hi Dan,
>>
>> For 1. and 2 to work - do you envision the configurable components to 
>> inherit from their generated beans (instead of delegate to them as is 
>> the case now)?
>
> I'd probably prefer that the Transports took a configuration as a 
> property instead. That way we can find the most appropriate 
> configuration, and then apply. For instance:
>
> HTTPTransportPolicy transportPolicy = 
> operation.get(HTTP_TRANSPORT_POLICY);
> if (transportPolicy == null)
>  transportPolicy = endpoint.get(HTTP_TRANSPORT_POLICY):
>
> if (transportPolicy == null)
>  transportPolicy = service.get(HTTP_TRANSPORT_POLICY):
>
> if (transportPolicy == null)
>  transportPolicy = getDefaultPolicy();
>
> Obviously we could encode this logic to be more compact (i.e. I want a 
> method which will search a hierarchy of Maps for any property), but I 
> think it gets the idea across that a transport policy could come from 
> any location. So I don't think it makes sense to have transports 
> extend their configuration.

I am not sure I understand what you are getting at here:
If you say you want to use getter/setter/constructor injection, what do 
you want to inject into? Say in the case of the http server transport, 
the transport itself has properties httpServer, authorization, 
sslServer, contextMatchStrategy (of  type HTTPServerPolicy, 
AuthorizationPolicy, SSLServerPolicy, String resp), and these get injected.
Now, for "nice xml" in Spring configuration, you'd have to associate 
associate (via a NamespaceHandler, BeanDefinitionParser) a schema with 
the http server transport (the bean).
While Spring 2,0 rc3 docs describe how to do this mapping manually and 
does not mention tools for automation, I believe it should be automated. 
There are two ways do do that:
a) Start with a schema and generate an (abstract base) bean - from which 
the real bean inherits (that's what I was referring to), or
b) Start with the bean implementation and generate the schema, using 
standard @Resource or some custom annotation.

>> We could even vamp up the generated beans from being pure Jaxws 
>> generated beans to also meet the 'configuration from multiple 
>> sources' requirement. And use the generic CXF management framework (a 
>> layer above JMX) to remote manage those beans and so on.
>
> How exactly are you thinking of vamping up the beans?

If the abstract base bean is generated, it could be generated with 
getters that use additional configuration providers in case no value was 
injected. Generated getters would first check if the data member 
provides a value, and if that is not the case, ask the registered 
configuration providers in turn to find a value (and in that sense would 
actually behave very similar to the current  Configuration object).
In your example above this could be done by a configuration provider 
that introspects the service model, and as such would allow to pull in 
wsdl extensions - added to the port, the service, the binding elements, 
much like as WS-Policy. It's basically what you call a method that 
"searches a hierarchy of maps for a property". I am actually using such 
a provider already in the http transport - except that in case it only 
checks the endpoint info's property map (because we only expect 
HTTPServerPolicy as an extension element of the WSDL port element).
A service model based configuration provider is only one example of 
retrieving values if none were injected - there may be other sources of 
information, and the service model should not hold information that is 
not model related.

Does that make sense?

Andrea.

> I do like the idea that the CXF mgmt framework operates on the beans 
> though (as opposed to configuration).
>
>> Not sure about the limitations of the inheritance approach though 
>> (single inheritance I mean).
>> But it would enforce the point of configuration metatadata (or schema 
>> as per Spring 2.0) being part of a component's interface.
>>
>> Andrea.
>
>
> Cheers,
> - Dan
>
>


Mime
View raw message