Daniel Kulp wrote: > (I apologize in advance for the length of this email... After meeting > with Jim and Sebastien for the last two days, there are a LOT of thoughts > swirling around in my head....) > > One of the questions that came up in the discussions was something along > the lines of "if a user wants to replace the Axis 2 ws implementation > with Celtix, how would they do it?" Or, more generally: "In tuscany, > if I want to replace XXXX with YYYY where YYYY is functionally > equivalent, how can I do it?" (XXXX being a binding.*, container.*, > etc...) > > The "simple" answer is something along the lines of: delete the XXXX jars, > add the YYYY jars, muck with the classpath, done. However, that really > sucks. Telling users to muck with things down on that level is usually > not a good idea and can generally result in bad things happening. The > other problem with this approach is that there is no way that a user > could use BOTH XXXX and YYYY in the same system since XXXX is completely > deleted. >
This has been an area I have been wondering about as well as we start to increase the number of system services included in the runtime. In the SCA specification a module can be built up from multiple fragments which "magically" get combined together. In Java this is done by merging all "sca.fragment" files found on the classpath, coupling together the concepts of assembly with the provision of code. To be blunt, I think this sucks. It means that, as you describe, users end up mixing mucking with the classpath to perform SCA assembly, and potentially means they end up adding components to their application just because they needed a class from some jar file. It also does not deal with how configuration is done at the module level. Yes, one way is to include it in a subsystem definition but there is not consistency on how it is done for a bare module. For example, when a WAR file is deployed with an sca.module file in it then in Tuscany our approach is to define the module component name and URI from the webapps context path and leave all configuration properties as defaults. I would prefer to see a solution where we treated a module file as a type (which it is) and had configuration information in some other artifact - like a module component configuration file. This file would allow us to specify values for that module and would also allow us to define the location of the type (e.g. as the URL of the sca.module file). I know the argument has been that this requires the user to have a configuration file for the component. But, as a user, I actually prefer a model like that where I remain in control of what is running than one where things get configured by "magic." > One idea I came up with is a concept of "aliasing". All components > would always register with a very specific name. Instead of binding.ws, > it would be binding.axis2; instead of container.js, it would be > container.rhino, etc... Tuscany would then have some configuration > that would "bind" the specific name to the "generic" name. This could > come from a config file, a system property, etc.... If the user want > to change the underlying implementation of one of the generic > > One advantage of this that the user then has more control in their > assembly. If they want to use a more "portable" form and allow the > sca/tuscany runtime to use the default, they can do something like > "implementation.js" or "binding.ws" and the tuscany runtime would use the > appropriate one that is configured. However, if the user wants the > specific version (using some advanced feature of axis or something...), > they can specifically use "binding.axis2" or "implementation.rhino". It > allows complete coexistence. In a module, you could actually use both > "binding.axis2" and "binding.celtix" as well as the default "binding.ws" > that may or may not point to one of them. > I think we need to extend this concept to the general level, applying to both user components and system services (like containers, bindings, etc). Any service provider must declare metadata about the services that it offers and any service consumer similarly declare what services it is willing to consume. For example, a JavaScipt service provider could declare that it provides "implementation.js", "implementation.rhino", "implementation.rhino.1R6" containers. Similarly, when deploying a component implementation the user could declare that it requires a "implementation.rhino" container environment. The deployment system would then be able to deploy that component to any runtime where "implementation.rhino" was available but not where some other implementation of .js was used. One idea I have floated before (but perhaps not on this list) is that the user can provide alternative implementations of a component. For example, they may choose to provide both Java and C++ implementations. This would allow the deployment system to select the most appropriate for the selected runtime (e.g. Java if deployed to a J2EE environment, C++ if front-end deployment to Apache HTTPD was selected). The key thing is that providers and consumers provider sufficient metadata about the service they are using to interact. This is not jsut functional (i.e. the API) but also non-function requirements like implementation language, version, quality of service, licensing, ... > > The next "issue" this brings up is how to provide a usable system if the > user HASN'T configured anything (zero config) as well as validate that a > user that has configured something hasn't shot themself in the foot. On > thought with this is that when something registers with the system, it > not only registers it's name, but also can return a list of services it > can provide. Example: Name: binding.axis2, Provides: binding.ws > > With that additional bit of information, the runtime could automatically > wire stuff up with no configuration as well as validate configuration. > (example: I alias "binding.ws" to "binding.jsonrpc". That shouldn't > work since jsonrpc doesn't provide that service.) In the case where > there are two or more implementations that provide a service, it could be > a "first one registered" or "undetermined" or anything. The other > thing about this is that a single "thing" could possibly provide > multiple services. Example: Name: binding.celtix Provides: > binding.ws, binding.corba, binding.blah) > I think this is a good direction to move in. We want as rich a metadata environment as possible, ideally one that captures all the criteria users use to determine which provider any consumer will use. I hope that if we have a rich enough model we don't end up with those kind of ambiguities, or if we do then it is because the user really doesn't care and so any of the available choices are valid. -- Jeremy
