james-server-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Simon Funnell <simonfunn...@googlemail.com>
Subject As Above, So Below
Date Fri, 20 Nov 2009 17:51:56 GMT

I've been studying the code base and evaluating which approach is the 
best to take. At present, I will try to clarify the framework 
architecture I am using as 'evangelising' might actually be quite 
effective. Firstly, there is nothing new to learn, the architecture is 
exactly the same as the internet. Applications are networks of machines 
and each machine on the network is a component of one or more 
applications. Each machine/component specialises in doing one small job 
very well, for example you could have a network of machines/components 
that do something like the following.

Machine 1's job is to listen on a port for new client connections, when 
a new client comes along, it is accepted and the resulting socket is 
contextualised. A context is basically an object that maintains state, 
such as application/session/request or whatever is relevant. This 
context/state is then dispatched to Machine 2.

Machine 2 will now alter the context state by reading bytes from the 
socket and buffering them in some suitable form before dispatching to 
Machine 3.

Machine 3 is responsible for taking the buffered content and parsing 
into some sort object model, like an email. If an error occurs this 
machine will forward it to an exception handling machine which 
implements the exception policy of the system (Machine 4?). Otherwise, 
it is sent to the next machine (Machine 5?) which does some sort of 
matching or something

And so on.

Now if we want to do some logging at any time, we just put a logging 
machine in between Machine 1 and 2 or between 2 and 3 to check socket 
state, buffer state or some other combination of properties.

To relate this somewhat to James, you are currently using Guice to wire 
components together and.this is equivalent to defining a network. With 
the design I am following there is not really a configuration as such, 
they are basically replaced with policy statements and change logs, 
which are a kind of configuration. Its fair to say James would be a 
network of machines defined by a policy statement. These policy 
statements can be large or small and applied to new or already running 
systems. Newer policy statements always supersede older ones (unless a 
prior policy forbids it). James already has a fairly substantial default 
policy statement like thing, its configuration files. However, to 
understand the benefits of policy statements, instead of configurations, 
it is worth looking at a small example.

In this example I have an installation of James, it does not do any 
logging at present but I want to do some. And this is what I want to do:

For the next two days, between the hours of the 3-5 pm, if a client 
using the SMTP service invokes the Expn command and has a IP address 
matching some address log some information to this file in this format 
and if its between 3.45pm and 4.00pm send me an email with such and such 

This policy is expressed (but doesn't have to be) as an XML document. 
The document is evaluated and the necessary machines are added to the 
network to implement the policy. How the policy is defined and 
implemented is system independent. The new machines added to the network 
that implement the policy usually simply fit in between two existing 
machines and do stuff like filtering, logging, security and anything 
that makes logical sense (putting a logging machine that records 
information about a http request in an smtp service doesn't make logical 
sense). Here, Java is used to create very small, highly robust units of 
functionality with XML policy statements (closer to natural language and 
easy to learn for users) stating how the machines should interact. The 
sophistication of policy statements is increased as the size and 
collective ability of a community of machines/components in a given 
installation grows.

The current mailets and matchers are sort of ideal for use in this 
system as they can (in principle) be easily wrapped/adapted or what not 
to become a network machine. A machine here is simply an object with a 
single method (I've been thinking about using the reflection api's to 
extract individual methods from existing James classes and assign them 
to individual machines but its not straight forward as the existing 
methods in James classes tend to mix concerns together, like application 
logic and writing to an output in a single method)

I hope this is of interest, declarative logging is really easy to 
implement and requires no learning, only a subtle shift in approach. 
James could be implemented as a guice module and a policy statement, in 
fact it would probably would be fairly easy to generate guice modules 
from a policy statement. Its not a direct translation but they are not 
dissimilar in nature. Also I am actually thinking of employing guice 
myself to do a few things, I am not in competition with guice. I am not 
in competition with spring either because its got a load of stuff with 
it mine doesn't. That said, Platformed is not 'just another framework', 
it has features (an architecture) that make it distinct.

I'm thinking about a re-factoring strategy but I am still learning James 
under the hood. Ideally I would like to convince you of the benefits, 
they are fairly obvious.



To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org

View raw message