Noel J. Bergman wrote:

2. Do an api/impl split (which will make me happy)


Where do you see that we don't?



[warning - I'm probably rambling]


I'm talking about a physical split that would result in the following artifacts:

 * james-server-api-VERSION.jar
 * james-server-impl-VERSION.jar
 * james-mailet-api-VERSION.jar
 * james-mailet-impl-VERSION.jar

There is a really big benefit in doing this seperation when looking at how James can be used within "composite components". Lets assume that we have classic James executing within a classloader - but instead of thinking about James as a standalone server - think of James as just another component. In such a scenario it is handling requests across ports, but also providing a service to other consumer components. Those services could be represented by James exposing the mailet interface, or perhaps enabling a user repository to be shared between multiple components (e.g. both James and OpenIM). These scenarios reflect a requirement for the API classes to be in a classloader common to the provider and consumer classloaders. If you have a single jar file containing both api and impl - then your James implementation classes must be declared way up hight in the classloader heirachy. Worse still is the fact that all of the jar files that James requires must be declared in the same or higher classloader. On the otherhand, if you seperate you project into two seperate project - api and impl - then the only classes you need to expose to a client is the API. The implementation classes stay down with James.

End result is that it is massively easier to wire together components.

There are some open questions here. James has a mailet API and a non-published internal services API. Lets ignore the question about what is intended to be public for a moment and think about what is happening inside Merlin. Basically merlin is wiring together service providers (such as the DNS provider, the POP3 server, the SNTP server, etc. in order to establish the James server component. Lets asume we want to experiment with a shared user repository - i.e. a component that will provide some generic facilities for managing user accounts - and that we expect this facilities to be used by James and other components (e.g. OpenIM). In this scenario both the James and OpenIM implementation needs the user repository APIs - but the implementation classes can be pushed down into the classloader running the actual repository.

End result is that it become rather simple to build new componets from existing components - and technically feasiblke to dynamically rewire components over a management inerface.

If you throw into the equation an interest in build James using Maven, then there is an implication of the physical structure of the source repository. A maven project is basically geared around the creation of a single artifact - e.g. james-server-impl-3.0.jar. I.e. you end up with a lot of subprojects. The upside is that things like unit testing are much more fine grained - version control and dependency management become much more tangible, etc.

Now - in the James case, there are a bunch of subcomponents - each with a potential api and impl project.

* James
* AvalonMailStore
* AvalonUserStore
* DNSServer
* FetchScheduler
* RepositoryManager
* NNTPServer
* NNTPRepositoryImpl
* POP3Server
* RemoteManager
* SMTPServer
* JamesSpoolManager
* SimpleConnectionManager

As you know - I'm not that familiar with the internals of James - but I would guess that from the above you could probably break James down into a number of sub-systems:

 * Mailet/James (mailet api and the james impl and mail store, etc.)
 * user repository and remote access
 * DNS
 * Fetch
 * NNTP
 * POP3
 * SMTP

What I'm trying to in the above list is identify what are the seperate functional testable potentially sharable components with the broader james system. I'm not suggesting that these become publically available services - but I am suggesting that when you consider James as just a component - you stand to gain a lot by disecting its composition and putting in place (a) a build model that provides good granularity on testing and isolation of development effort, and that can be trnslated into (b) a good composition scheme when considering the potential for new subsystems (e.g. an LDAP user repository), or sub-system reuse (e.g. a shared user repository).

If you take a look at avalon-framework, the meta package, and any of the cornerstone components you will find a seperate api and impl project (and in some cases an spi project). The Merlin build example is probably closer to what I figure James should be - i.e. a collection of 4-6 packages, each with a seperate api and implementation subproject. Although this may sound complex - it is actually rather simple to adminster. You can automate the build process to include unit testing across all subsystems, automate the generation of the final application solution, maintain a clean seperation between James and a deployment environment (container), etc.


I'm not saying that there aren't such
cases, but I'm curious as to what you see as concerns.


More "opportunity" than concern. Getting a breakout of james into its component parts would make things easier for people like me to understand what is related to what - would enable better management of test cases, and I think would provide more flexibility for the future.


I don't know if you have looking into the ant build script in MAIN recently but its basically generating a mailet-api, mailet-impl and james jar files (but its a hack by yours-truly) and I would sleep better at night if we get rid of the hack!


3. Use the AbstractMerlinTestCase to deploy james in a container with
services accessible to your unit test - you unit test would only
need two dependency declarations - mailet API and the merlin test
case.



Nice. I do suggest (as I mentioned in a message a few moments ago), that
you and Steve Brewin collaborate on getting BSF support. That would make
testing easier.



Will do.


Cheers, Steve.

--- Noel


--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]





--


Stephen J. McConnell
mailto:[EMAIL PROTECTED]




--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to