The good thing with xbean (yes, there are some pros, even if I think
cons are prevailing) is that it generates a XSD, which is the reference
we never had before.
Yeah it's pretty slick.
The spring namespace can be jettisoned, etc...Anyways, before I do
more work I'll describes the steps for loading server.xml:
/**
* Test ApacheDS Configuration Loading
*/
public void testLoadServerXML()
{
File serverDotXML = new File("src/main/resources/server.xml");
ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put
(_1Package.eNS_PREFIX, new _1ResourceFactoryImpl());
resourceSet.getPackageRegistry().put
(_1Package.eNS_URI, _1Package.eINSTANCE);
Resource serverXMLResource = resourceSet.
createResource(
URI.
createFileURI(serverDotXML.getAbsolutePath()));
//Get the root configuration object
//Get a contained object using a fragment
//etc.
}
Once the serverXMLResource is loaded, the instances of the server
configuration objects can be gotten from it using like this:
serverXMLResource.getObject("nameOfConfigurationObject");
Does this look appealing so far?
Well, basically, this is something like that we want to have, yes. I
don't like the syntax (to much _1,
Yes - I left the _1 in there to keep the tutorial trace as simple as possible.
This _1 corresponds to the namespace prefix of the model's namespace. Since
the schema currently has multiple namespaces, and EMF needed to assign one to
the ecore model, it chose _1. However, fixing this is as simple as opening up
the .ecore model and changing the namespace prefix in the properties editor. I
would choose something like adsConfig. This would now be used instead of the
_1. So instead of _1Package, it would be AdsConfigPackage.
to much work to be done before being
able to do the getObject...), but I'm pretty sure we can keep it more
simple.
For instance, those lines :
ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put
(_1Package.eNS_PREFIX, new _1ResourceFactoryImpl());
resourceSet.getPackageRegistry().put
(_1Package.eNS_URI, _1Package.eINSTANCE);
seems to be totally superfluous,
You are right. After generation these can be put in a utility library and you
could call something like ConfigurationUtil.load() to load to get the root
configuration object.
as the mapping between
_1Package.eNS_PREFIX and _1ResourceFactoryImpl seems to be mandatory,
and could have been injected into the ResourceSetImpl() constructor.
They don't need to be explicit
Sure - For our purposes that's it. If for some reason you wanted to load other
files as well, they would have to follow a similar registration approach....
I need to make 1 correction about my earlier assessment. I said we
could just create an instance of the ADS configuration like this:
ADSConfiguraiton adsConfiguraiton = new ADSConfiguration();
and the server could run using just the defaults contained / generated
into each configuration class. That would be true if all the
configuration were contained in single instance, but obviosly we'd
want a graph. So if the graph were built up manually, the same would
be true...Anyways the configuration graph would have to be built
manually or by the EMF Resource Loading mechanism.
Yes, this is a graph, and a complex one. If we can't get it built
directly by EMF, using the XSD, then i would say that it's not what we
will use.
Well we are using EMF to generate the beans corresponding to the ComplexType
definitions in the XSD. Then when loading server.xml EMF does the parsing and
creates instances of these beans and binds the server.xml element attributes to
the corresponding bean values. So in other words it does what Spring does, but
now the Beans are just pure configuration beans. Their only purpose is to
provide configuration data contained in server.xml.
So if you load server.xml using EMF then you have the Graph. So EMF does build
the graph.
Sometimes during testing of an individual component though, we don't need the
whole graph. We just need the default values in, for example,
AuthenticatorType. So when testing that component we just create an instance
of AuthenticatorType like this:
AuthenticatorType authenticatorType =
_1Factory.eINSTANCE.createAuthenticatorType();
Side note: Remember that if we change the _1 prefix on the ecore model to
adsconfig the above would be AdsConfigFactory.eINSTANCE instead....
If the default values for authenticator type's properties were set in the XSD
(XML Schema) then those have been generated onto the AuthenticatorTypeImpl and
are returned when calling get...(). So this saves time in the sense that Mock
objects don't have to be created. You can use the real server configuration
object and it's corresponding defaults values generated from the XSD.
Things are never simple ... :)
Still not too far off right? :-)
So, to summarize, when doing component development we could place server.xml in src/main/resources and load it using
Resource resource = ADSMavenConfigurationUtilities.load();
which would return the resource containing server.xml. Then to get a particular configuration object you could do
AuthenticatorType authenticatorType = resource.getObject("/server/authenticatorType");
Note that I just made up the URI fragment "/server/authenticatorType", but you
get idea.
So now the big question is, does everyone like developing like this? Since the
configuration data is now separate from classes that provide services, those
classes have to get the configuration data the same way we retrieved it above.
I personally prefer this, but I'm sure there are others that like the Spring
based approach. Something to mull over.
Cheers,
- Ole