On Jan 5, 2011, at 342AM, Dan Creswell wrote:
>> 
>> 
>> Key to the modularization was to remove reliance on classdepandjar. I see
>> this as a positive, I'm not sure sure others do. IMO, it really simplifies
>> the project to not rely on classdepandjar, and have modules that produce a
>> single jar. If you all feel very strongly about having classdepandjar AND a
>> modularized project, I still doable, it will just take more work to put
>> classdepandjar back into the mix.
>> 
>> 
> Well, I'm no fan of classdepandjar but removing it is build hassle for me.
> Hassle is no big deal so long as I have a clear path forward. What can you
> do in terms of putting together an example or doc that shows how the
> "typical" Jini service would be built from now on (not sure Blitz is typical
> but there you go)?

The approach I'd give to a developer that is starting a project that will 
result in a River service is a little different from taking an existing well 
established & thought out technology such as Blitz. With Blitz, we're looking 
at a refactoring. So with that in mind I thought I'd give myself an hour, and 
grabbed the Blitz source and took an hour to 'modularize' it. After looking at 
the distribution I decided to break out the project into the following modules, 
with each module producing a single jar, with inter-project dependencies

blitz-\
       | - blitz-stats
       | - blitz-proxy
       | - blitz-service
       | - blitz-ui

The relationship between the modules was planned to be as follows:

blitz-proxy depends on blitz-stats
blitz-service depends on blitz-proxy
blitz-ui depends on blitz-proxy

(There are other transitive deps including Jini and Sleepycat across the stack 
but I will only mention those as a ref for now)

I added gradle build scripts and was making progress but ran into issues with 
the blitz-stats module (containing org.dancres.blitz.stats classes), because by 
itself that package has deps on other Blitz classes, including SpaceImpl, 
Lifecycle, LifecycleRegistry, Logging, ConfigurationFactory (etc...), and I 
didnt want to bring all of this into blitz-stats, since blitz-proxy depends on 
it. So, since I gave myself an hour and simply didnt know (well kinda knew) if 
the decisions I would make would break everything, so I stopped. If you'd like 
maybe we can talk about this offline, be glad to share what I did if interested.

So much for that experiment. However ...

The general approach is to organize a 'service' project as a multi-module 
project, with each module representing  the basic architectural element of a 
distributed service. Breaking this down we have the service's API, the 
service's proxy and the service's implementation (referenced doc 
http://www.rio-project.org/conventions.html)

Given a service project with the name of hello, the service project is composed 
of the following modules:

• hello-api
The hello-api module contains all the classes (interfaces and other classes) 
that is needed to communicate with the service

• hello-proxy
The hello-proxy module (optional), depends on the hello-api module, and 
provides smart proxy support

• hello-service
The hello-service module, depends on the hello-api module (or hello-proxy 
module if used) provides the backend service implementation.

• hello-rule
The hello-rule module (optional), depends on the hello-api module and provides 
support for rules associated with the service.

• hello-ui
The hello-ui module (optional), depends on the hello-api module and provides 
support for a service user interface.

What I have found is I give greater thought as to what needs to go where, and 
what the consequences are to adding classes (and that class's dependencies (and 
transitive dependencies)) to a module. With the multi-module structure we can 
focus on the creation of services as a tuple of api, proxy and implementation. 
I find it more constructive to have the components broken out that produce one 
jar, write test cases for each module, and then write integration test cases 
that incorporate all aspects of the service working together.

In addition, the products of the rproject are easier understood from a user's 
point of view. They follow a convention. For example, its easy to answer the 
question of what jar to include if I want to use a service, you would use (from 
above) hello-api-<version>.jar.

Note that the structure (approach) has been used with Maven, but as previously 
pointed out Gradle is also a very (very) good candidate. Gradle itself uses Ivy 
for dependency resolution, but the important thing is you can deploy your 
service artifacts to a Maven repository where they can be easily included by 
other service developers for use. 

I would like to think that we can take this approach to modularize River. FWIW, 
I think River is an 'easier' candidate than Blitz, and for what thats worth for 
my own project Rio [1]. River's codebase is already organized in such a way 
that is amenable to this model. The service packages are all fairly self 
contained, they have deps to classes found in the platform and into the 
application developers toolkit (jsk-lib). 

Regards

Dennis

[1]  Rio is also built using classdepandjar, and I am going to be doing this 
sort of refactoring for Rio over the next few months.

Reply via email to