cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dan Diephouse <...@envoisolutions.com>
Subject Configuration APIs
Date Fri, 11 Aug 2006 16:11:27 GMT
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;")

3. For the case where we need to override the settings (i.e. overriding 
settings at an endpoint) we would create JAXB objects from the WSDL and 
put them in the service model (our internal representation of the 
service). Say we had some HTTPPolicy object with a timeout setting. We 
would have something like this:

Endpoint endpoint = exchange.get(ENDPOINT);
HTTPPolicy httpPolicy = endpoint.get(HTTP_POLICY);
if (httpPolicy == null)
    httpPolicy = getDefaultHTTPPolicy();

int timeout = httpPolicy.getTimeout();

4. Have a container responsible for injection of the configuration 
beans. This should be a layer on top, not in the core. (This can be our 
own container if we really want which uses the Configuration stuff).

I'll try to preempt a couple of objections people had to this last 
point. It was mentioned that if this was done via Spring the 
configuration would get obscenely complex for users. For instance, lets 
say we have a master cxf.xml containing all the default bean 
definitions. If we want to override just one default value, we have a 
lot of XML to write. I don't think this is true. First, the default 
value plugin for jaxb makes it so that you only have to set the non 
default values in your spring xml. Second, say I have a master cxf.xml 
with all the standard bean definitions. If I have my own context with my 
own httpPolicy bean in it, I can have spring load just mine and not the 
one in cxf.xml. This is because if you give Spring a list of 
configuration files and a bean with an id is in multiple configurations, 
it will only load the last one added. This gives a clear way to override 
settings without complex configuration.

There are probably other/better ways to do configuration in a more IoC 
way as well, and I'd be interested to hear what other people think. On a 
related note, I think that we should work closely with the XBean project 
as their goals are quite close to ours. They are providing configuration 
for Geronimo, SerivceMix, ActiveMQ, etc. I would be very surprised if we 
have any use cases that they don't have. (And I believe someone already 
wrote JAXB2 integration for it...)

Sorry for the long windedness here. But as Eoghan once said... "bring on 
the flames"... :-)

- Dan

-- 
Dan Diephouse
(616) 971-2053
Envoi Solutions LLC
http://netzooid.com


Mime
View raw message