You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by Stefano Bagnara <ap...@bago.org> on 2008/09/01 15:56:59 UTC

Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Robert Burrell Donkin ha scritto:
> SieveToMultiMailbox is the major remaining issue on the road to
> separating out an IMAP protocol library. it's a good example of some
> of the problems with the remaining mailets in JAMES. hopefully,
> thinking about solving them in this case may be applied more widely.
> 
> ----
> 
> SieveToMultiMailbox is tightly coupled to a large IMAP specific API
> (mailboxmanager) but uses only a tiny portion of it. an alternative
> implementation of the mailboxmanager API would be faced with
> implementing at least 29 methods spread over 3 interfaces. the mailet
> only delivers a mail to a mailbox which should really require a single
> call to a single method. this pattern is repeated across JAMES. the
> API is shared by protocols, data stores and mailets resulting in
> unnecessary large and imprecise interfaces. mailets typically only use
> a small subset of the function required by protocols and stores.
> explicit SPIs specialised for mailets would be a better approach.
> these could be independently versioned allowing the APIs used
> internally by JAMES to be safely varied.
> 
> an SPI interface for mailboxes as simple as (for example):
> 
> public void put(String url, Mail mail);
> 
> would suffice
> 
> ----
> 
> SieveToMultiMailbox is tightly coupled to avalon. the IMAP dependency
> is loaded by a service lookup using avalon. JAMES server is the only
> mailet container that is likely to support avalon. more modern IoC
> containers (for example, spring) would unobtrusively inject the
> required dependency. replacing magic lookup with construction
> injection would mean adding something like:
> 
> public SieveToMultiMailbox(MailboxSPI spi)
> 
> this would mean refactoring the mailet/matcher loading code to allow
> replacement by an implementation that uses a modern container. (i've
> always been keen on being able to ship independent self-contained mail
> applications built from mailets which could just be dropped into a
> running server.) the complexity would come creating a mixed system.
> using some sort of avalon-aware service adapters would probably be
> necessary.
> 
> MailboxSPI might be provided by adapting a mailbox manager service.
> 
> ----
> 
> opinions?

I prefer setter injection to constructor injection (expecially as we 
have an init method in the mailet api).

I don't understand if you are proposing something to be added to the 
mailet specification or simply you are proposing to change the way james 
specific mailets are written so to not require avalon knowledge to the 
james specific mailets.

Another doubt is about the use of "String url": can you give more 
details on the allowed values for url and the way it works (a couple of 
examples would suffice, I guess)?

Last point, and the least important, I don't like the SPI postfix.
The same interface could be used by SMTPServer/Fetchmail to store 
messages to the spool. In fact a spool repository could expose this 
interface (ignoring the url) or we could expose it via the Store by 
looking up the appropriate spool repository and storing the message to it.

Stefano

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Robert Burrell Donkin <ro...@gmail.com>.
On Wed, Sep 3, 2008 at 8:31 AM, Bernd Fondermann
<be...@googlemail.com> wrote:
> On Mon, Sep 1, 2008 at 23:58, Robert Burrell Donkin
> <ro...@gmail.com> wrote:
>> On Mon, Sep 1, 2008 at 2:56 PM, Stefano Bagnara <ap...@bago.org> wrote:
>>> Robert Burrell Donkin ha scritto:
>>>>
>> IMHO JAMES specific mailets are an anti-pattern. we need to work
>> towards decoupling minimal SPIs for mailets from the large APIs used
>> internally by JAMES. i prefer to think about mailet loaders and
>> processor assemblers indepedently. avalon is not a good match for this
>> problem. more modern IoC containers like pico or spring as *much*
>> better.
>
> +1
>
> The underlying question is: What dependencies do mailets need? There
> is not a general answer to this question!

+1

> Some mailets need only the mail itself and maybe some abstract
> (just-a-name) "target" processor. Some might need access to services
> through a generalizable interface, independent of James. Some even
> might need James-specific services.
> If we provide a solution to the first case, that'd be a pretty big
> step forward, already.
> The third case we already have solved :-)
> The second one is the toughest, because it needs a lot of knowlegde
> about how mailets could want to interact with their container. Every
> interaction is actually executed by looking up a container service and
> making calls to its service interface. So we could work towards a
> solution by defining the different dependent services we find in
> existing mailets and define interfaces for every one of them. So we
> avoid the need for having one swiss knife solution for everything and
> concentrate on the different aspects of mailet-container dependency
> one-by-one.

+1

- robert

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Stefano Bagnara <ap...@bago.org>.
Bernd Fondermann ha scritto:
> On Mon, Sep 1, 2008 at 23:58, Robert Burrell Donkin
> <ro...@gmail.com> wrote:
>> On Mon, Sep 1, 2008 at 2:56 PM, Stefano Bagnara <ap...@bago.org> wrote:
>>> Robert Burrell Donkin ha scritto:
>> IMHO JAMES specific mailets are an anti-pattern. we need to work
>> towards decoupling minimal SPIs for mailets from the large APIs used
>> internally by JAMES. i prefer to think about mailet loaders and
>> processor assemblers indepedently. avalon is not a good match for this
>> problem. more modern IoC containers like pico or spring as *much*
>> better.
> 
> +1
> 
> The underlying question is: What dependencies do mailets need? There
> is not a general answer to this question!
> Some mailets need only the mail itself and maybe some abstract
> (just-a-name) "target" processor. Some might need access to services
> through a generalizable interface, independent of James. Some even
> might need James-specific services.
> If we provide a solution to the first case, that'd be a pretty big
> step forward, already.
> The third case we already have solved :-)
> The second one is the toughest, because it needs a lot of knowlegde
> about how mailets could want to interact with their container. Every
> interaction is actually executed by looking up a container service and
> making calls to its service interface. So we could work towards a
> solution by defining the different dependent services we find in
> existing mailets and define interfaces for every one of them. So we
> avoid the need for having one swiss knife solution for everything and
> concentrate on the different aspects of mailet-container dependency
> one-by-one.

Here is a 2 years old overview, but we didn't change much in the code so 
it is probably current:
http://markmail.org/message/ktrgsga4enenhy4z

Stefano

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Bernd Fondermann <be...@googlemail.com>.
On Mon, Sep 1, 2008 at 23:58, Robert Burrell Donkin
<ro...@gmail.com> wrote:
> On Mon, Sep 1, 2008 at 2:56 PM, Stefano Bagnara <ap...@bago.org> wrote:
>> Robert Burrell Donkin ha scritto:
>>>
> IMHO JAMES specific mailets are an anti-pattern. we need to work
> towards decoupling minimal SPIs for mailets from the large APIs used
> internally by JAMES. i prefer to think about mailet loaders and
> processor assemblers indepedently. avalon is not a good match for this
> problem. more modern IoC containers like pico or spring as *much*
> better.

+1

The underlying question is: What dependencies do mailets need? There
is not a general answer to this question!
Some mailets need only the mail itself and maybe some abstract
(just-a-name) "target" processor. Some might need access to services
through a generalizable interface, independent of James. Some even
might need James-specific services.
If we provide a solution to the first case, that'd be a pretty big
step forward, already.
The third case we already have solved :-)
The second one is the toughest, because it needs a lot of knowlegde
about how mailets could want to interact with their container. Every
interaction is actually executed by looking up a container service and
making calls to its service interface. So we could work towards a
solution by defining the different dependent services we find in
existing mailets and define interfaces for every one of them. So we
avoid the need for having one swiss knife solution for everything and
concentrate on the different aspects of mailet-container dependency
one-by-one.

  Bernd

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Robert Burrell Donkin <ro...@gmail.com>.
On Wed, Sep 3, 2008 at 9:07 PM, Stefano Bagnara <ap...@bago.org> wrote:
> Robert Burrell Donkin ha scritto:
>>
>> On Wed, Sep 3, 2008 at 11:36 AM, Stefano Bagnara <ap...@bago.org> wrote:
>>
>> <snip>
>>
>>> Do you want to implementa LinearProcessor that simply ignore the
>>> MailetLoader/MatcherLoader service and use it's own loading mechanism?
>>>
>>> I'm not sure I like this, but it can be a PoC.
>>
>> IMO making assembly a service is a mistake. processor should assemble
>> themselves.
>
> I don't understand.
>
> We have:
>
> SpoolManager (top level component)
> MailetLoader (top level service)
> MatcherLoader (top level service)
>
> SpoolManager instantiate and configure a MailProcessor, in our case it
> instantiate the StateAwareProcessorList and configure it with an Avalon
> Configuration.
>
> StateAwareProcessorList is a MailProcessor that configures a number of
> "labelled" MailProcessors using parts/childs of its Configurations. The
> default implementation is LinearProcessor.
>
> LinearProcessor read a list of matcher/mailet name from the received
> configuration and ask Mailet/Matcher Loaders for instances given the name
> and the Configuration subtree for that mailet.
>
> Are you proposing to change the above behaviour or to introduce new
> alternative implementations with a different behaviour?
> Can you detail what components would you like to add or what services you
> would like to reimplement?
>
> Otherwise if you prefer to speak with code I can wait for the code so we
> better understand each other.

i think i've managed to confuse you. probably easier for me to create
an example or two and commit it.

- robert

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Stefano Bagnara <ap...@bago.org>.
Robert Burrell Donkin ha scritto:
> On Wed, Sep 3, 2008 at 11:36 AM, Stefano Bagnara <ap...@bago.org> wrote:
> 
> <snip>
> 
>> Do you want to implementa LinearProcessor that simply ignore the
>> MailetLoader/MatcherLoader service and use it's own loading mechanism?
>>
>> I'm not sure I like this, but it can be a PoC.
> 
> IMO making assembly a service is a mistake. processor should assemble
> themselves.

I don't understand.

We have:

SpoolManager (top level component)
MailetLoader (top level service)
MatcherLoader (top level service)

SpoolManager instantiate and configure a MailProcessor, in our case it 
instantiate the StateAwareProcessorList and configure it with an Avalon 
Configuration.

StateAwareProcessorList is a MailProcessor that configures a number of 
"labelled" MailProcessors using parts/childs of its Configurations. The 
default implementation is LinearProcessor.

LinearProcessor read a list of matcher/mailet name from the received 
configuration and ask Mailet/Matcher Loaders for instances given the 
name and the Configuration subtree for that mailet.

Are you proposing to change the above behaviour or to introduce new 
alternative implementations with a different behaviour?
Can you detail what components would you like to add or what services 
you would like to reimplement?

Otherwise if you prefer to speak with code I can wait for the code so we 
better understand each other.

Stefano

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Robert Burrell Donkin <ro...@gmail.com>.
On Wed, Sep 3, 2008 at 11:36 AM, Stefano Bagnara <ap...@bago.org> wrote:

<snip>

> Do you want to implementa LinearProcessor that simply ignore the
> MailetLoader/MatcherLoader service and use it's own loading mechanism?
>
> I'm not sure I like this, but it can be a PoC.

IMO making assembly a service is a mistake. processor should assemble
themselves.

- robert

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Stefano Bagnara <ap...@bago.org>.
Robert Burrell Donkin ha scritto:
> On Tue, Sep 2, 2008 at 9:53 AM, Stefano Bagnara <ap...@bago.org> wrote:
>> IN past we discussed about what IoC style we prefer and SDI was the
>> "winner":
>> http://issues.apache.org/jira/browse/JAMES-494
>>
>> Here you can find the biggest poll we've ever had ;-)
>> http://markmail.org/message/rfagbuq6t3au7uia
>> "G" questions was about dependency injection.
> 
> i did remark that setting injection is more popular but i don't intend
> to set a president, just take one more step forward. it may give some
> pointers towards more general solutions

I agree. I just wanted to share with you what we discussed in past.

>> Removing the default constructor will also make my new mailet report maven
>> module to fail obtaining the getMailetInfo/getMatcherInfo answer. It have to
>> get a newInstance in order to invoke that method.
>>
>> Not a big deal, and if you go with CDI it will anyway be easy to refactor to
>> SDI in any moment.
> 
> setter injection would work best with annotations or interfaces
> 
> paired interfaces could be retrofitted easily. for example
> 
> interface Mailbox
> 
> interface MailboxAware
> {
>    public void setMailbox(Mailbox mailbox)
> }

I call this "enabling interfaces", and I love them.

>>> 2. no conventions need to be established or explained. as a temporary
>>> measure, it's easy to check and inject a limited number of SPIs
>>> through reflection.
>>>
>>> i would prefer to avoid major changes before moving IMAP out
>> We have a "store" method in MailetContext and we deprecated it because it
>> was not clear how to proceed and we simply discouraged it's usage to feel
>> more free to change it later :-)
> 
> IMHO MailetContext suffers from doing both too much and too little

I agree.

>>>> I don't understand if you are proposing something to be added to the
>>>> mailet
>>>> specification
>>> ATM AIUI the mailet specification is silent on assembly and service
>>> acquisition. one advantage of this strategy is that it's possible to
>>> alter these characteristics without altering the mailet specification.
>> True and False... there was not support anything using services will not
>> work on current containers. So let's say "there's no way to be backward
>> compatible, so we can do whatever we want" ;-)
>>
>> Every existing container will fail to load a mailet without a default
>> constructor.
> 
> i'm not sure how you know that's true

I know of some mailet containers: James, MailCatcher. All of them use 
class.newInstance() to load a mailet.

If you know of an existing *mailet* container not doing so and 
leveraging more flexible containers to instantiate mailets I would be 
happy to know this.

>> [...]
>> When I refactored this in my mind there was the idea to bring as many
>> components to a top level. The idea is that StateAwareProcessorList could be
>> a component itself and the SpoolManager could simply depend on a
>> MailProcessor component.
>>
>> This should be easy to do now. I didn't do that before simply because when I
>> worked on this everyone was worried about backward compatibility, so no
>> change was allowed to break config.xml and db content compatibility. There
>> are many hacks in the code to deal with this.
> 
> i'm not sure why factoring out the processor would break configuration
> compatibility

Because of the way "Configuration" object works in Phoenix.
The SpoolProcessor contains the Configuration for 
StateAwareProcessorList so if you move StateAwareProcessorList to an 
external component phoenix will initialize it before the spoolmanager 
and there is no way to get the configuration from SpoolManager. You 
should let phoenix instantiate the StateAwareProcessorList 
"unconfigured" and then manually configure it when it will "service" the 
SpoolManager. Indeed an hack.

If you instead don't like of config.xml compatibility then you simply 
take the xml tree for the StateAwareProcessorList and move it outside 
from the <spoolmanager> block.

>>>> or simply you are proposing to change the way james specific
>>>> mailets are written so to not require avalon knowledge to the james
>>>> specific
>>>> mailets.
>>> IMHO JAMES specific mailets are an anti-pattern. we need to work
>>> towards decoupling minimal SPIs for mailets from the large APIs used
>>> internally by JAMES. i prefer to think about mailet loaders and
>>> processor assemblers indepedently. avalon is not a good match for this
>>> problem. more modern IoC containers like pico or spring as *much*
>>> better.
>> I agree that james specific mailets are antipattern.
>> To make them generic you have to define services at the mailet level.
>> And make the services generic.
>>
>> To change the service lookup method without publicizing the services does
>> not make the mailets portable to other services.
>> If a Mailet depends on SpoolRepository interface we can remove avalon and
>> the service manager by using simple CDI/SDI, but in the end the mailet will
>> be only usable where SpoolRepository implementations are available.
>> SpoolRepository is james specific.
>>
>> MailboxSPI is james specific until we make it part of a generic API
>> supported by compliant containers.
>> I don't understand what is your idea about this? Do you want to make an
>> mailet-spi package with optional services to be supported by advanced
>> containers?
> 
> yep
> 
>>> i strongly dislike the use of the magic avalon service attribute. IMHO
>>> if a mailet is coupled to avalon then it should implement the standard
>>> servicable interface. the container could then recognize this and
>>> configure the mailet appropriately.
>> I agree that the context and the service lookup are a bad idea for mailets.
>> IMHO this is a necessary change, but this alone won't change the fact that
>> mailets are james specific.
>>
>> In http://issues.apache.org/jira/browse/JAMES-494 you can see the easiest
>> approach is to add setters for dependencies and make the "service" method
>> lookup the services and set them via setters. This way the avalon container
>> will keep working while non avalon containers can simply use setters.
> 
> i'm not sure i agree with this being the easiest approach. there are
> known issues when trying to implement good setter injection frameworks
> and conventions would have to be established for setter names unless
> annotations are used.
> 
> the simplest approach would be to use constructor injection and
> exclude optional dependencies
> 
> IMO the best approach for setter injection would be to create an
> alternative spring processor loader
> 
> i'd like to be able to deploy a self contained jar'd mail application
> eg (sketching somewhat):
> 
> META-INF/org/apache/james/list-processor.xml
> 
> <procesor loader='org.apache.james.mailet.container.Spring'>
>    <mailet name='ListManager'>
> ....
>    </mailet>
> </processor>
> 
> META-INF/org/apache/james/spring-mailets.xml
> 
> <beans>
>  <bean id='ListManager' class=...>
> ....
>  </bean>
> </beans>

Currently it is not the Processor loading the mailets but the 
MailetLoader and MatcherLoader services. YOu have to create new 
implementations of that services.

In StateAwareProcessorList each processor can optionally declare an 
alternative implementation via the "class" attribute, defaulting to 
org.apache.james.transport.LinearProcessor.

As you can see the LinearProcessor uses the MailetLoader and 
MatcherLoader services to load the mailets given their name and their 
configuration.

Do you want to implementa LinearProcessor that simply ignore the 
MailetLoader/MatcherLoader service and use it's own loading mechanism?

I'm not sure I like this, but it can be a PoC.

>>>> Another doubt is about the use of "String url": can you give more details
>>>> on
>>>> the allowed values for url and the way it works (a couple of examples
>>>> would
>>>> suffice, I guess)?
>>> i've been thinking for a long while that there might be a lot to gain
>>> in flexibility by moving towards APIs using URIs
>>>
>>> but it's still hazy...
>>>
>>>> Last point, and the least important, I don't like the SPI postfix.
>>>> The same interface could be used by SMTPServer/Fetchmail to store
>>>> messages
>>>> to the spool. In fact a spool repository could expose this interface
>>>> (ignoring the url) or we could expose it via the Store by looking up the
>>>> appropriate spool repository and storing the message to it.
>>> i have been thinking about that direction
>>>
>>> for example, POSTing to "mailto://joe@example.org" is an elegant and
>>> concise way to express the idea of forwarding a mail. this can be used
>>> for delivery as well. for example "mailet://joe@localhost".
>>>
>>> the advantage of using URLs is that it's easier to present interfaces
>>> which work ok for a wider variety of protocols. for example POSTing to
>>> "imap://joe@localhost/INBOX" could be distringuished from
>>> "james://joe@localhost/INBOX" and "mailbox://joe@localhost/INBOX".
>>> might be possible to do some interesting stuff this way.
>> I like this stuff very much. I discussed a similar thing in past. I named it
>> "destinations":
>> http://markmail.org/message/xkcttgyqmfwpieew
>>
>> In my 2005 idea "destinations" was particular email addresses because email
>> address is more "mail" oriented than url, but mail is moving to different
>> transport and everyone probably better understand urls than email addresses.
>>
>> But I think it would be a very interesting paradigm to use urls for anything
>> from local spool management, to remote delivery to forward and anything
>> else.
>>
>> The issue I see here is that we should understand how they works before
>> starting to add interfaces using this urls.
> 
> the sieve mailet is still experiement: it's a good opportunity just to
> give it a go and take the chance to live with it for a while

As long as it is clear that this can be dropped at any time and it is 
only an experiment, and that there is no agreement yet that it is the 
correct solution, I'm fine with it. Go ahead.

Stefano

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Robert Burrell Donkin <ro...@gmail.com>.
On Wed, Sep 3, 2008 at 11:45 AM, Stefano Bagnara <ap...@bago.org> wrote:
> David Jencks ha scritto:
>>
>> On Sep 2, 2008, at 12:46 PM, Robert Burrell Donkin wrote:
>>>
>>> On Tue, Sep 2, 2008 at 9:53 AM, Stefano Bagnara <ap...@bago.org> wrote:
>
>>>>> Robert Burrell Donkin wrote:
>>>>>
>>>>> ATM AIUI the mailet specification is silent on assembly and service
>>>>> acquisition. one advantage of this strategy is that it's possible to
>>>>> alter these characteristics without altering the mailet specification.
>>>>
>>>> True and False... there was not support anything using services will not
>>>> work on current containers. So let's say "there's no way to be backward
>>>> compatible, so we can do whatever we want" ;-)
>>>>
>>>> Every existing container will fail to load a mailet without a default
>>>> constructor.
>>>
>>> i'm not sure how you know that's true
>>>
>> FWIW although you have to supply some metadata (currently via code or
>> annotations) Geronimo can construct components through constructor
>> injection: there shouldn't be any problem constructing a maillet.
>>
>> I thought spring could too if you jumped through enough configuration
>> hoops but I'm definitely not a spring expert.
>
> Most generic container supports CDI/SDI and other weird styles. I was
> talking of *existing* *mailet* containers. So I am talking of real code
> implementing at least a MailetContext. Of course if I write a geronimo based
> mailet container and I depend on geronimo to load mailets I can use CDI, but
> this is off topic.
> I was confuting the fact that using CDI was better than SDI because there
> was no need to alter the mailet specification.

i had intended to assert the general point that changing the way that
mailets assemble their dependencies does not require a change

>> I am really really strongly in favor of constructor injection of final
>> fields.
>
> This introduce a discussion about what is/should be final. Can a
> MailetContext be altered during execution of a mailet? Can a DataSource be
> changed? Can a MailboxSPI service implementation be altered during the
> mailet lifecycle?

one of the roles of a container builder should be to shield the
contained implementation from concurrency. the mailet specification is
weak on concurrency so using immutable structural elements makes a lot
of sense.

note that this is argument about who should worry, not what. so (for
example) if a container wanted to be able to change a mailbox
implementation during operation the the container should ensure that a
suitable proxy was passed into the mailet on construction and should
take responsibility for ensure that that substitution is performed
safely (perhaps by ensuring that service is suspended).

- robert

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Stefano Bagnara <ap...@bago.org>.
David Jencks ha scritto:
> On Sep 2, 2008, at 12:46 PM, Robert Burrell Donkin wrote:
>> On Tue, Sep 2, 2008 at 9:53 AM, Stefano Bagnara <ap...@bago.org> wrote:
 >>>> Robert Burrell Donkin wrote:
>>>> ATM AIUI the mailet specification is silent on assembly and service
>>>> acquisition. one advantage of this strategy is that it's possible to
>>>> alter these characteristics without altering the mailet specification.
>>>
>>> True and False... there was not support anything using services will not
>>> work on current containers. So let's say "there's no way to be backward
>>> compatible, so we can do whatever we want" ;-)
>>>
>>> Every existing container will fail to load a mailet without a default
>>> constructor.
>>
>> i'm not sure how you know that's true
>>
> FWIW although you have to supply some metadata (currently via code or 
> annotations) Geronimo can construct components through constructor 
> injection: there shouldn't be any problem constructing a maillet.
> 
> I thought spring could too if you jumped through enough configuration 
> hoops but I'm definitely not a spring expert.

Most generic container supports CDI/SDI and other weird styles. I was 
talking of *existing* *mailet* containers. So I am talking of real code 
implementing at least a MailetContext. Of course if I write a geronimo 
based mailet container and I depend on geronimo to load mailets I can 
use CDI, but this is off topic.
I was confuting the fact that using CDI was better than SDI because 
there was no need to alter the mailet specification.
For existing containers there was an implicit "mailets have a default 
constructor" and the 2 existing containers + the mailet-report-plugin 
already depends on this. They will throw bad errors if you give them a 
mailet with not default constructor.
Easy to change, but this is not the "current" case, so I don't this this 
is something that move a choice between CDI and SDI.

> I am really really strongly in favor of constructor injection of final 
> fields.

This introduce a discussion about what is/should be final. Can a 
MailetContext be altered during execution of a mailet? Can a DataSource 
be changed? Can a MailboxSPI service implementation be altered during 
the mailet lifecycle?

Stefano

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Bernd Fondermann <be...@googlemail.com>.
On Tue, Sep 2, 2008 at 23:49, Robert Burrell Donkin
<ro...@gmail.com> wrote:
> On Tue, Sep 2, 2008 at 10:32 PM, David Jencks <da...@yahoo.com> wrote:
>
> <snip>
>
>> FWIW although you have to supply some metadata (currently via code or
>> annotations) Geronimo can construct components through constructor
>> injection: there shouldn't be any problem constructing a maillet.
>>
>> I thought spring could too if you jumped through enough configuration hoops
>> but I'm definitely not a spring expert.
>
> i've read that it can (spring is pretty flexible)
>
>> I am really really strongly in favor of constructor injection of final
>> fields.
>
> i use that pattern a lot since it has good concurrency characteristics
> though setter injection is much more popular
>
> (mailets should be protected by their container so this shouldn't be
> such an issue in this case)
>
> IMHO the best approach for the mailets James ships would to be
> agnostic and support both types of injection by providing appropriate
> setters and constructors

I'm a lot fiddling around with designing beans these days and what I
learned is that you have to decide which injection to use on a
case-by-case basis. generally, SDI works pretty good, and I'd second
that for final fields CDI is a first consideration. but there is no
golden rule like XDI is always better than YDI.

   Bernd

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Robert Burrell Donkin <ro...@gmail.com>.
On Thu, Sep 4, 2008 at 10:03 AM, Stefano Bagnara <ap...@bago.org> wrote:
> Robert Burrell Donkin ha scritto:
>>
>> On Wed, Sep 3, 2008 at 9:00 PM, Stefano Bagnara <ap...@bago.org> wrote:
>>>
>>> Robert Burrell Donkin ha scritto:
>>>>
>>>> On Wed, Sep 3, 2008 at 12:03 PM, Stefano Bagnara <ap...@bago.org>
>>>> wrote:
>>
>> <snip>
>>
>>>> i think that we just need to add extensibility to the top level avalon
>>>> aware processor
>>>>
>>>> loaders should be responsible for:
>>>>
>>>> 1. assembling mailets and matchers
>>>> 2. mapping names to assembled instances
>>>>
>>>> processors should be responsible for:
>>>>
>>>> 1. taking mailets and matchers instances from the loader and linking
>>>> them together into a single processing unit
>>>> 2. ensuring that the mailet lifecyle is correctly propergated to all
>>>> contained mailet and matcher instances
>>>
>>> I'm not sure I understand who configures mailet/matchers instances.
>>> I can have multiple ToRepository with different configurations in a
>>> single
>>> container.
>>> ATM the LinearProcessor ask to MailetLoader "give me a mailet named XXX
>>> configured with this avalon Configuration object".
>>
>> i propose separating assembly concerns from basic parameterisation
>>
>> the loader would be resonable for assembling an named instance. for
>> basic mailets (no object dependencies) this would just consist of
>> creating an instance. for advanced mailets with object dependencies
>> and a sophisticated IoC loader (for example, spring) this would
>> consists of create and instance and supplying appropriate
>> dependencies. typically, this would be driven by a configuration
>> document specific to the loader.
>>
>> the processor would take the assembled instance and take
>> responsibility for the mailet lifecycles. it would read a
>> configuration and use it to populate the MailetConfig appropriately.
>
> So, you want to move this code:
> -------
> MailetConfigImpl configImpl = new MailetConfigImpl();
> configImpl.setMailetName(mailetName);
> configImpl.setConfiguration(configuration);
> configImpl.setMailetContext(new MailetContextWrapper(mailetContext,
> getLogger().getChildLogger(mailetName)));
> mailet.init(configImpl);
> --------
> from the MailetLoader to the ProcessorList, just after the
> mailet = mailetLoader.getMailet()..
>
> right?

yes

> Do you want to remove "Configuration" from the getMailet parameter list as
> it would not be used anymore?
>
> In this case the Mailet/Matcher loaders would no more depend on
> MailetContext but would only be a simple object factory for "Named" objects.

yes

> And in spring the loader.getMailet(String name) could simply be mapped to
> applicationContext.getBean(name), right?

yes

> If I understood, this time, it make sense.

:-)

>>> Does "2. mapping names to assembled instances" mean that the loader will
>>> load a ToRepository1, ToRepository2, ToRepositoryN and the LinearProcessr
>>> will ask for the named instances?
>>
>> this is how loading works ATM. the only difference is the assembly is
>> more explicit and more flexible.
>>
>>>> a limit number of SPIs will need to be passed through to loaders. when
>>>> used in an avalon envionment, an avalon aware layer will be needed.
>>>>
>>>>> If we don't care anymore of config.xml compatibility let's start moving
>>>>> self
>>>>> instantiated avalon component to container managed components.
>>>>> We have a lot of them in the code.
>>>>> A search for "ContainerUtil.service(" in our code (or more generically
>>>>> for
>>>>> ContainerUtil) will show any place where we manually do what a
>>>>> container
>>>>> does.
>>>>
>>>> i'm not persuaded that it's necessary to break configuration
>>>> compatibility at this time. typically, breaking compatibility means
>>>> committing to the creation of a much more compelling product and this
>>>> would push back any hope of a 3.0 release for many months.
>>>
>>> So you create alternative implementations for this? I'm not following you
>>> at
>>> all...
>>
>> the whole point of a pluggable architecture is that new stuff can be
>> plugged in without having to break the old
>
> Is this a "yes" ?

your question confused me

>>>>>>> I am really really strongly in favor of constructor injection of
>>>>>>> final
>>>>>>> fields.
>>>>>>
>>>>>> i use that pattern a lot since it has good concurrency characteristics
>>>>>> though setter injection is much more popular
>>>>>>
>>>>>> (mailets should be protected by their container so this shouldn't be
>>>>>> such an issue in this case)
>>>>>>
>>>>>> IMHO the best approach for the mailets James ships would to be
>>>>>> agnostic and support both types of injection by providing appropriate
>>>>>> setters and constructors
>>>>>
>>>>> the problem with mixing CDI and SDI is that CDI expect no default
>>>>> constructor because a default constructor would mean that every
>>>>> dependency
>>>>> is optional.
>>>>
>>>> this is untrue for the CDI containers i've used
>>>
>>> Really? how do they deal with optional dependencies?
>>
>> yes
>>
>> depends on how magic they are. magic containers usually choose the
>> greediest possible constructor (eg pico). those using configuration
>> files just specify the links in there (eg spring).
>
> So you propose to have setters for each dependency, a default constructor
> and a constructor with all of the dependencies and leave out the declaration
> of what is needed and the container specific configuration will deal with
> special cases.

i doubt that many mailets have optional assembly dependencies. if they
do, then alternative constructors could be provided.

- robert

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Stefano Bagnara <ap...@bago.org>.
Robert Burrell Donkin ha scritto:
> On Wed, Sep 3, 2008 at 9:00 PM, Stefano Bagnara <ap...@bago.org> wrote:
>> Robert Burrell Donkin ha scritto:
>>> On Wed, Sep 3, 2008 at 12:03 PM, Stefano Bagnara <ap...@bago.org> wrote:
> 
> <snip>
> 
>>> i think that we just need to add extensibility to the top level avalon
>>> aware processor
>>>
>>> loaders should be responsible for:
>>>
>>> 1. assembling mailets and matchers
>>> 2. mapping names to assembled instances
>>>
>>> processors should be responsible for:
>>>
>>> 1. taking mailets and matchers instances from the loader and linking
>>> them together into a single processing unit
>>> 2. ensuring that the mailet lifecyle is correctly propergated to all
>>> contained mailet and matcher instances
>> I'm not sure I understand who configures mailet/matchers instances.
>> I can have multiple ToRepository with different configurations in a single
>> container.
>> ATM the LinearProcessor ask to MailetLoader "give me a mailet named XXX
>> configured with this avalon Configuration object".
> 
> i propose separating assembly concerns from basic parameterisation
> 
> the loader would be resonable for assembling an named instance. for
> basic mailets (no object dependencies) this would just consist of
> creating an instance. for advanced mailets with object dependencies
> and a sophisticated IoC loader (for example, spring) this would
> consists of create and instance and supplying appropriate
> dependencies. typically, this would be driven by a configuration
> document specific to the loader.
> 
> the processor would take the assembled instance and take
> responsibility for the mailet lifecycles. it would read a
> configuration and use it to populate the MailetConfig appropriately.

So, you want to move this code:
-------
MailetConfigImpl configImpl = new MailetConfigImpl();
configImpl.setMailetName(mailetName);
configImpl.setConfiguration(configuration);
configImpl.setMailetContext(new MailetContextWrapper(mailetContext, 
getLogger().getChildLogger(mailetName)));
mailet.init(configImpl);
--------
from the MailetLoader to the ProcessorList, just after the
mailet = mailetLoader.getMailet()..

right?

Do you want to remove "Configuration" from the getMailet parameter list 
as it would not be used anymore?

In this case the Mailet/Matcher loaders would no more depend on 
MailetContext but would only be a simple object factory for "Named" objects.

And in spring the loader.getMailet(String name) could simply be mapped 
to applicationContext.getBean(name), right?

If I understood, this time, it make sense.

>> Does "2. mapping names to assembled instances" mean that the loader will
>> load a ToRepository1, ToRepository2, ToRepositoryN and the LinearProcessr
>> will ask for the named instances?
> 
> this is how loading works ATM. the only difference is the assembly is
> more explicit and more flexible.
> 
>>> a limit number of SPIs will need to be passed through to loaders. when
>>> used in an avalon envionment, an avalon aware layer will be needed.
>>>
>>>> If we don't care anymore of config.xml compatibility let's start moving
>>>> self
>>>> instantiated avalon component to container managed components.
>>>> We have a lot of them in the code.
>>>> A search for "ContainerUtil.service(" in our code (or more generically
>>>> for
>>>> ContainerUtil) will show any place where we manually do what a container
>>>> does.
>>> i'm not persuaded that it's necessary to break configuration
>>> compatibility at this time. typically, breaking compatibility means
>>> committing to the creation of a much more compelling product and this
>>> would push back any hope of a 3.0 release for many months.
>> So you create alternative implementations for this? I'm not following you at
>> all...
> 
> the whole point of a pluggable architecture is that new stuff can be
> plugged in without having to break the old

Is this a "yes" ?

>>>>>> I am really really strongly in favor of constructor injection of final
>>>>>> fields.
>>>>> i use that pattern a lot since it has good concurrency characteristics
>>>>> though setter injection is much more popular
>>>>>
>>>>> (mailets should be protected by their container so this shouldn't be
>>>>> such an issue in this case)
>>>>>
>>>>> IMHO the best approach for the mailets James ships would to be
>>>>> agnostic and support both types of injection by providing appropriate
>>>>> setters and constructors
>>>> the problem with mixing CDI and SDI is that CDI expect no default
>>>> constructor because a default constructor would mean that every
>>>> dependency
>>>> is optional.
>>> this is untrue for the CDI containers i've used
>> Really? how do they deal with optional dependencies?
> 
> yes
> 
> depends on how magic they are. magic containers usually choose the
> greediest possible constructor (eg pico). those using configuration
> files just specify the links in there (eg spring).

So you propose to have setters for each dependency, a default 
constructor and a constructor with all of the dependencies and leave out 
the declaration of what is needed and the container specific 
configuration will deal with special cases.

I'm fine with this.

Stefano

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Robert Burrell Donkin <ro...@gmail.com>.
On Wed, Sep 3, 2008 at 9:00 PM, Stefano Bagnara <ap...@bago.org> wrote:
> Robert Burrell Donkin ha scritto:
>>
>> On Wed, Sep 3, 2008 at 12:03 PM, Stefano Bagnara <ap...@bago.org> wrote:

<snip>

>> i think that we just need to add extensibility to the top level avalon
>> aware processor
>>
>> loaders should be responsible for:
>>
>> 1. assembling mailets and matchers
>> 2. mapping names to assembled instances
>>
>> processors should be responsible for:
>>
>> 1. taking mailets and matchers instances from the loader and linking
>> them together into a single processing unit
>> 2. ensuring that the mailet lifecyle is correctly propergated to all
>> contained mailet and matcher instances
>
> I'm not sure I understand who configures mailet/matchers instances.
> I can have multiple ToRepository with different configurations in a single
> container.
> ATM the LinearProcessor ask to MailetLoader "give me a mailet named XXX
> configured with this avalon Configuration object".

i propose separating assembly concerns from basic parameterisation

the loader would be resonable for assembling an named instance. for
basic mailets (no object dependencies) this would just consist of
creating an instance. for advanced mailets with object dependencies
and a sophisticated IoC loader (for example, spring) this would
consists of create and instance and supplying appropriate
dependencies. typically, this would be driven by a configuration
document specific to the loader.

the processor would take the assembled instance and take
responsibility for the mailet lifecycles. it would read a
configuration and use it to populate the MailetConfig appropriately.

> Does "2. mapping names to assembled instances" mean that the loader will
> load a ToRepository1, ToRepository2, ToRepositoryN and the LinearProcessr
> will ask for the named instances?

this is how loading works ATM. the only difference is the assembly is
more explicit and more flexible.

>> a limit number of SPIs will need to be passed through to loaders. when
>> used in an avalon envionment, an avalon aware layer will be needed.
>>
>>> If we don't care anymore of config.xml compatibility let's start moving
>>> self
>>> instantiated avalon component to container managed components.
>>> We have a lot of them in the code.
>>> A search for "ContainerUtil.service(" in our code (or more generically
>>> for
>>> ContainerUtil) will show any place where we manually do what a container
>>> does.
>>
>> i'm not persuaded that it's necessary to break configuration
>> compatibility at this time. typically, breaking compatibility means
>> committing to the creation of a much more compelling product and this
>> would push back any hope of a 3.0 release for many months.
>
> So you create alternative implementations for this? I'm not following you at
> all...

the whole point of a pluggable architecture is that new stuff can be
plugged in without having to break the old

>>>>> I am really really strongly in favor of constructor injection of final
>>>>> fields.
>>>>
>>>> i use that pattern a lot since it has good concurrency characteristics
>>>> though setter injection is much more popular
>>>>
>>>> (mailets should be protected by their container so this shouldn't be
>>>> such an issue in this case)
>>>>
>>>> IMHO the best approach for the mailets James ships would to be
>>>> agnostic and support both types of injection by providing appropriate
>>>> setters and constructors
>>>
>>> the problem with mixing CDI and SDI is that CDI expect no default
>>> constructor because a default constructor would mean that every
>>> dependency
>>> is optional.
>>
>> this is untrue for the CDI containers i've used
>
> Really? how do they deal with optional dependencies?

yes

depends on how magic they are. magic containers usually choose the
greediest possible constructor (eg pico). those using configuration
files just specify the links in there (eg spring).

- robert

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Stefano Bagnara <ap...@bago.org>.
Robert Burrell Donkin ha scritto:
> On Wed, Sep 3, 2008 at 12:03 PM, Stefano Bagnara <ap...@bago.org> wrote:
>> Robert Burrell Donkin ha scritto:
>>> On Tue, Sep 2, 2008 at 10:32 PM, David Jencks <da...@yahoo.com>
>>> wrote:
>>>
>>> <snip>
>>>
>>>> FWIW although you have to supply some metadata (currently via code or
>>>> annotations) Geronimo can construct components through constructor
>>>> injection: there shouldn't be any problem constructing a maillet.
>>>>
>>>> I thought spring could too if you jumped through enough configuration
>>>> hoops
>>>> but I'm definitely not a spring expert.
>>> i've read that it can (spring is pretty flexible)
>> Using our spring-bridge you could even load mailets depending on the
>> ServiceManager and the avalon interfaces directly from spring.
>>
>> IMHO the big change is making the mailets top level components for the
>> container and allow the container to deal with them by (for example)
>> introducing a container specific factory with a james generic interface.
>>
>> Phoenix has a big limit in declaring collections of components, so
>> configuring a "processor" as a collection of "matcher/mailets" tuples is not
>> something easy in phoenix, while is trivial in spring and other containers,
>> even in other avalon based containers (like Plexus).
> 
> that's not the approach i'd take
> 
> i think that we just need to add extensibility to the top level avalon
> aware processor
> 
> loaders should be responsible for:
> 
> 1. assembling mailets and matchers
> 2. mapping names to assembled instances
> 
> processors should be responsible for:
> 
> 1. taking mailets and matchers instances from the loader and linking
> them together into a single processing unit
> 2. ensuring that the mailet lifecyle is correctly propergated to all
> contained mailet and matcher instances

I'm not sure I understand who configures mailet/matchers instances.
I can have multiple ToRepository with different configurations in a 
single container.
ATM the LinearProcessor ask to MailetLoader "give me a mailet named XXX 
configured with this avalon Configuration object".

Does "2. mapping names to assembled instances" mean that the loader will 
load a ToRepository1, ToRepository2, ToRepositoryN and the 
LinearProcessr will ask for the named instances?

> a limit number of SPIs will need to be passed through to loaders. when
> used in an avalon envionment, an avalon aware layer will be needed.
> 
>> If we don't care anymore of config.xml compatibility let's start moving self
>> instantiated avalon component to container managed components.
>> We have a lot of them in the code.
>> A search for "ContainerUtil.service(" in our code (or more generically for
>> ContainerUtil) will show any place where we manually do what a container
>> does.
> 
> i'm not persuaded that it's necessary to break configuration
> compatibility at this time. typically, breaking compatibility means
> committing to the creation of a much more compelling product and this
> would push back any hope of a 3.0 release for many months.

So you create alternative implementations for this? I'm not following 
you at all...

>>>> I am really really strongly in favor of constructor injection of final
>>>> fields.
>>> i use that pattern a lot since it has good concurrency characteristics
>>> though setter injection is much more popular
>>>
>>> (mailets should be protected by their container so this shouldn't be
>>> such an issue in this case)
>>>
>>> IMHO the best approach for the mailets James ships would to be
>>> agnostic and support both types of injection by providing appropriate
>>> setters and constructors
>> the problem with mixing CDI and SDI is that CDI expect no default
>> constructor because a default constructor would mean that every dependency
>> is optional.
> 
> this is untrue for the CDI containers i've used

Really? how do they deal with optional dependencies?

>> You can create a CDI component by simply extending an SDI component, hiding
>> the default constructor and add the dependencies constructor.
>> The opposite is not easy, you need an SDI object that wait for the
>> dependencies and in the init method builds the CDI and delegate to it.
> 
> again, untrue in my experience

I don't follow you here.

public class MyCDI {
   private Component myComponent;
   public MyCDI(DependencyA a, DependencyB b) {
      this.a = a;
      this.myComponent = b.getComponent("selector");
   }
}

How do you wrap this in an SDI?
I mean every SDI object can be easily extended to CDI while it is not 
always true for the opposite.
  >> Theoretically CDI is much better, I agree, but I think there are 
real causes
>> behind the SDI style being more used, and this is not because spring didn't
>> support CDI earlier.
> 
> most developers don't write concurrent code. they are familiar with
> beans and unfamiliar with immutable value objects.

We already have an init method in the Mailet api. So we already have 
something that is not CDI oriented. We should have had the MailetContext 
in the constructor or in the service method otherwise.

BTW there are traces of religious issues here. I'll better wait for the 
code.

Stefano

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Robert Burrell Donkin <ro...@gmail.com>.
On Wed, Sep 3, 2008 at 12:03 PM, Stefano Bagnara <ap...@bago.org> wrote:
> Robert Burrell Donkin ha scritto:
>>
>> On Tue, Sep 2, 2008 at 10:32 PM, David Jencks <da...@yahoo.com>
>> wrote:
>>
>> <snip>
>>
>>> FWIW although you have to supply some metadata (currently via code or
>>> annotations) Geronimo can construct components through constructor
>>> injection: there shouldn't be any problem constructing a maillet.
>>>
>>> I thought spring could too if you jumped through enough configuration
>>> hoops
>>> but I'm definitely not a spring expert.
>>
>> i've read that it can (spring is pretty flexible)
>
> Using our spring-bridge you could even load mailets depending on the
> ServiceManager and the avalon interfaces directly from spring.
>
> IMHO the big change is making the mailets top level components for the
> container and allow the container to deal with them by (for example)
> introducing a container specific factory with a james generic interface.
>
> Phoenix has a big limit in declaring collections of components, so
> configuring a "processor" as a collection of "matcher/mailets" tuples is not
> something easy in phoenix, while is trivial in spring and other containers,
> even in other avalon based containers (like Plexus).

that's not the approach i'd take

i think that we just need to add extensibility to the top level avalon
aware processor

loaders should be responsible for:

1. assembling mailets and matchers
2. mapping names to assembled instances

processors should be responsible for:

1. taking mailets and matchers instances from the loader and linking
them together into a single processing unit
2. ensuring that the mailet lifecyle is correctly propergated to all
contained mailet and matcher instances

a limit number of SPIs will need to be passed through to loaders. when
used in an avalon envionment, an avalon aware layer will be needed.

> If we don't care anymore of config.xml compatibility let's start moving self
> instantiated avalon component to container managed components.
> We have a lot of them in the code.
> A search for "ContainerUtil.service(" in our code (or more generically for
> ContainerUtil) will show any place where we manually do what a container
> does.

i'm not persuaded that it's necessary to break configuration
compatibility at this time. typically, breaking compatibility means
committing to the creation of a much more compelling product and this
would push back any hope of a 3.0 release for many months.

>>> I am really really strongly in favor of constructor injection of final
>>> fields.
>>
>> i use that pattern a lot since it has good concurrency characteristics
>> though setter injection is much more popular
>>
>> (mailets should be protected by their container so this shouldn't be
>> such an issue in this case)
>>
>> IMHO the best approach for the mailets James ships would to be
>> agnostic and support both types of injection by providing appropriate
>> setters and constructors
>
> the problem with mixing CDI and SDI is that CDI expect no default
> constructor because a default constructor would mean that every dependency
> is optional.

this is untrue for the CDI containers i've used

> You can create a CDI component by simply extending an SDI component, hiding
> the default constructor and add the dependencies constructor.
> The opposite is not easy, you need an SDI object that wait for the
> dependencies and in the init method builds the CDI and delegate to it.

again, untrue in my experience

> Theoretically CDI is much better, I agree, but I think there are real causes
> behind the SDI style being more used, and this is not because spring didn't
> support CDI earlier.

most developers don't write concurrent code. they are familiar with
beans and unfamiliar with immutable value objects.

- robert

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Stefano Bagnara <ap...@bago.org>.
Robert Burrell Donkin ha scritto:
> On Tue, Sep 2, 2008 at 10:32 PM, David Jencks <da...@yahoo.com> wrote:
> 
> <snip>
> 
>> FWIW although you have to supply some metadata (currently via code or
>> annotations) Geronimo can construct components through constructor
>> injection: there shouldn't be any problem constructing a maillet.
>>
>> I thought spring could too if you jumped through enough configuration hoops
>> but I'm definitely not a spring expert.
> 
> i've read that it can (spring is pretty flexible)

Using our spring-bridge you could even load mailets depending on the 
ServiceManager and the avalon interfaces directly from spring.

IMHO the big change is making the mailets top level components for the 
container and allow the container to deal with them by (for example) 
introducing a container specific factory with a james generic interface.

Phoenix has a big limit in declaring collections of components, so 
configuring a "processor" as a collection of "matcher/mailets" tuples is 
not something easy in phoenix, while is trivial in spring and other 
containers, even in other avalon based containers (like Plexus).

If we don't care anymore of config.xml compatibility let's start moving 
self instantiated avalon component to container managed components.
We have a lot of them in the code.
A search for "ContainerUtil.service(" in our code (or more generically 
for ContainerUtil) will show any place where we manually do what a 
container does.

>> I am really really strongly in favor of constructor injection of final
>> fields.
> 
> i use that pattern a lot since it has good concurrency characteristics
> though setter injection is much more popular
> 
> (mailets should be protected by their container so this shouldn't be
> such an issue in this case)
> 
> IMHO the best approach for the mailets James ships would to be
> agnostic and support both types of injection by providing appropriate
> setters and constructors

the problem with mixing CDI and SDI is that CDI expect no default 
constructor because a default constructor would mean that every 
dependency is optional.

You can create a CDI component by simply extending an SDI component, 
hiding the default constructor and add the dependencies constructor.
The opposite is not easy, you need an SDI object that wait for the 
dependencies and in the init method builds the CDI and delegate to it.

Theoretically CDI is much better, I agree, but I think there are real 
causes behind the SDI style being more used, and this is not because 
spring didn't support CDI earlier.

Only my 2 cents.

BTW let's go ahead with the style you prefer. Refactor a CDI to an SDI 
will take a lot less than this discussion already took and maybe we'll 
also introduce Annotations in this discussion before we'll have a 
release, so no need to discuss this "details" at this moment.

Stefano

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Robert Burrell Donkin <ro...@gmail.com>.
On Tue, Sep 2, 2008 at 10:32 PM, David Jencks <da...@yahoo.com> wrote:

<snip>

> FWIW although you have to supply some metadata (currently via code or
> annotations) Geronimo can construct components through constructor
> injection: there shouldn't be any problem constructing a maillet.
>
> I thought spring could too if you jumped through enough configuration hoops
> but I'm definitely not a spring expert.

i've read that it can (spring is pretty flexible)

> I am really really strongly in favor of constructor injection of final
> fields.

i use that pattern a lot since it has good concurrency characteristics
though setter injection is much more popular

(mailets should be protected by their container so this shouldn't be
such an issue in this case)

IMHO the best approach for the mailets James ships would to be
agnostic and support both types of injection by providing appropriate
setters and constructors

- robert

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by David Jencks <da...@yahoo.com>.
On Sep 2, 2008, at 12:46 PM, Robert Burrell Donkin wrote:

> On Tue, Sep 2, 2008 at 9:53 AM, Stefano Bagnara <ap...@bago.org>  
> wrote:
>> Robert Burrell Donkin ha scritto:
>>>
>>> On Mon, Sep 1, 2008 at 2:56 PM, Stefano Bagnara <ap...@bago.org>  
>>> wrote:
>>>>
>>>> Robert Burrell Donkin ha scritto:
>>>>>
>>>>> SieveToMultiMailbox is the major remaining issue on the road to
>>>>> separating out an IMAP protocol library. it's a good example of  
>>>>> some
>>>>> of the problems with the remaining mailets in JAMES. hopefully,
>>>>> thinking about solving them in this case may be applied more  
>>>>> widely.
>>>>>
>>>>> ----
>>>>>
>>>>> SieveToMultiMailbox is tightly coupled to a large IMAP specific  
>>>>> API
>>>>> (mailboxmanager) but uses only a tiny portion of it. an  
>>>>> alternative
>>>>> implementation of the mailboxmanager API would be faced with
>>>>> implementing at least 29 methods spread over 3 interfaces. the  
>>>>> mailet
>>>>> only delivers a mail to a mailbox which should really require a  
>>>>> single
>>>>> call to a single method. this pattern is repeated across JAMES.  
>>>>> the
>>>>> API is shared by protocols, data stores and mailets resulting in
>>>>> unnecessary large and imprecise interfaces. mailets typically  
>>>>> only use
>>>>> a small subset of the function required by protocols and stores.
>>>>> explicit SPIs specialised for mailets would be a better approach.
>>>>> these could be independently versioned allowing the APIs used
>>>>> internally by JAMES to be safely varied.
>>>>>
>>>>> an SPI interface for mailboxes as simple as (for example):
>>>>>
>>>>> public void put(String url, Mail mail);
>>>>>
>>>>> would suffice
>>>>>
>>>>> ----
>>>>>
>>>>> SieveToMultiMailbox is tightly coupled to avalon. the IMAP  
>>>>> dependency
>>>>> is loaded by a service lookup using avalon. JAMES server is the  
>>>>> only
>>>>> mailet container that is likely to support avalon. more modern IoC
>>>>> containers (for example, spring) would unobtrusively inject the
>>>>> required dependency. replacing magic lookup with construction
>>>>> injection would mean adding something like:
>>>>>
>>>>> public SieveToMultiMailbox(MailboxSPI spi)
>>>>>
>>>>> this would mean refactoring the mailet/matcher loading code to  
>>>>> allow
>>>>> replacement by an implementation that uses a modern container.  
>>>>> (i've
>>>>> always been keen on being able to ship independent self- 
>>>>> contained mail
>>>>> applications built from mailets which could just be dropped into a
>>>>> running server.) the complexity would come creating a mixed  
>>>>> system.
>>>>> using some sort of avalon-aware service adapters would probably be
>>>>> necessary.
>>>>>
>>>>> MailboxSPI might be provided by adapting a mailbox manager  
>>>>> service.
>>>>>
>>>>> ----
>>>>>
>>>>> opinions?
>>>>
>>>> I prefer setter injection to constructor injection (expecially as  
>>>> we have
>>>> an
>>>> init method in the mailet api).
>>>
>>> i know a lot of people prefer setter injection but constructor
>>> injection has some advantages in this case:
>>>
>>> 1. it prevents uninitialised use of the mailet. this should give a
>>> clean failure when anyone tries to use it with an incompatible  
>>> mailet
>>> loader.
>>
>> THe mailet api require an "init" method. In that method we can  
>> check if the
>> services are there and throw exceptions to prevent this.
>> This also does not introduce multiple constructors when dealing with
>> optional dependencies.
>>
>> IN past we discussed about what IoC style we prefer and SDI was the
>> "winner":
>> http://issues.apache.org/jira/browse/JAMES-494
>>
>> Here you can find the biggest poll we've ever had ;-)
>> http://markmail.org/message/rfagbuq6t3au7uia
>> "G" questions was about dependency injection.
>
> i did remark that setting injection is more popular but i don't intend
> to set a president, just take one more step forward. it may give some
> pointers towards more general solutions
>
>> Removing the default constructor will also make my new mailet  
>> report maven
>> module to fail obtaining the getMailetInfo/getMatcherInfo answer.  
>> It have to
>> get a newInstance in order to invoke that method.
>>
>> Not a big deal, and if you go with CDI it will anyway be easy to  
>> refactor to
>> SDI in any moment.
>
> setter injection would work best with annotations or interfaces
>
> paired interfaces could be retrofitted easily. for example
>
> interface Mailbox
>
> interface MailboxAware
> {
>   public void setMailbox(Mailbox mailbox)
> }
>
>>> 2. no conventions need to be established or explained. as a  
>>> temporary
>>> measure, it's easy to check and inject a limited number of SPIs
>>> through reflection.
>>>
>>> i would prefer to avoid major changes before moving IMAP out
>>
>> We have a "store" method in MailetContext and we deprecated it  
>> because it
>> was not clear how to proceed and we simply discouraged it's usage  
>> to feel
>> more free to change it later :-)
>
> IMHO MailetContext suffers from doing both too much and too little
>
>>>> I don't understand if you are proposing something to be added to  
>>>> the
>>>> mailet
>>>> specification
>>>
>>> ATM AIUI the mailet specification is silent on assembly and service
>>> acquisition. one advantage of this strategy is that it's possible to
>>> alter these characteristics without altering the mailet  
>>> specification.
>>
>> True and False... there was not support anything using services  
>> will not
>> work on current containers. So let's say "there's no way to be  
>> backward
>> compatible, so we can do whatever we want" ;-)
>>
>> Every existing container will fail to load a mailet without a default
>> constructor.
>
> i'm not sure how you know that's true
>
FWIW although you have to supply some metadata (currently via code or  
annotations) Geronimo can construct components through constructor  
injection: there shouldn't be any problem constructing a maillet.

I thought spring could too if you jumped through enough configuration  
hoops but I'm definitely not a spring expert.

I am really really strongly in favor of constructor injection of final  
fields.

thanks
david jencks

>
>
>>> IMHO factoring out the mailet loading and the processor assembly  
>>> from
>>> the spool management would be a major step forward
>>
>> Mmmm.. this is already this way.
>> MailetLoader and MatcherLoader are 2 components used by the  
>> SpoolManager to
>> get instances of the mailets.
>>
>> <!-- The James Spool Manager block  -->
>> <block name="spoolmanager"
>> class="org.apache.james.transport.JamesSpoolManager" >
>> <provide name="spoolrepository"
>> role="org.apache.james.services.SpoolRepository"/>
>> <provide name="matcherpackages"
>> role="org.apache.james.transport.MatcherLoader"/>
>> <provide name="mailetpackages"
>> role="org.apache.james.transport.MailetLoader"/>
>> </block>
>>
>> <block name="matcherpackages"
>> class="org.apache.james.transport.JamesMatcherLoader" >
>> <provide name="James" role="org.apache.mailet.MailetContext"/>
>> <provide name="filesystem"  
>> role="org.apache.james.services.FileSystem" />
>> </block>
>>
>> <block name="mailetpackages"
>> class="org.apache.james.transport.JamesMailetLoader" >
>> <provide name="James" role="org.apache.mailet.MailetContext"/>
>> <provide name="filesystem"  
>> role="org.apache.james.services.FileSystem" />
>> </block>
>>
>> JamesSpoolManager is configurable to define what class to use as  
>> processor
>> defaulting to StateAwareProcessorList.
>> ---
>> processorClass =
>> conf 
>> .getChild 
>> ("processorClass 
>> ").getValue("org.apache.james.transport.StateAwareProcessorList");
>> ----
>>
>> When I refactored this in my mind there was the idea to bring as many
>> components to a top level. The idea is that StateAwareProcessorList  
>> could be
>> a component itself and the SpoolManager could simply depend on a
>> MailProcessor component.
>>
>> This should be easy to do now. I didn't do that before simply  
>> because when I
>> worked on this everyone was worried about backward compatibility,  
>> so no
>> change was allowed to break config.xml and db content  
>> compatibility. There
>> are many hacks in the code to deal with this.
>
> i'm not sure why factoring out the processor would break configuration
> compatibility
>
>>>> or simply you are proposing to change the way james specific
>>>> mailets are written so to not require avalon knowledge to the james
>>>> specific
>>>> mailets.
>>>
>>> IMHO JAMES specific mailets are an anti-pattern. we need to work
>>> towards decoupling minimal SPIs for mailets from the large APIs used
>>> internally by JAMES. i prefer to think about mailet loaders and
>>> processor assemblers indepedently. avalon is not a good match for  
>>> this
>>> problem. more modern IoC containers like pico or spring as *much*
>>> better.
>>
>> I agree that james specific mailets are antipattern.
>> To make them generic you have to define services at the mailet level.
>> And make the services generic.
>>
>> To change the service lookup method without publicizing the  
>> services does
>> not make the mailets portable to other services.
>> If a Mailet depends on SpoolRepository interface we can remove  
>> avalon and
>> the service manager by using simple CDI/SDI, but in the end the  
>> mailet will
>> be only usable where SpoolRepository implementations are available.
>> SpoolRepository is james specific.
>>
>> MailboxSPI is james specific until we make it part of a generic API
>> supported by compliant containers.
>> I don't understand what is your idea about this? Do you want to  
>> make an
>> mailet-spi package with optional services to be supported by advanced
>> containers?
>
> yep
>
>>> i strongly dislike the use of the magic avalon service attribute.  
>>> IMHO
>>> if a mailet is coupled to avalon then it should implement the  
>>> standard
>>> servicable interface. the container could then recognize this and
>>> configure the mailet appropriately.
>>
>> I agree that the context and the service lookup are a bad idea for  
>> mailets.
>> IMHO this is a necessary change, but this alone won't change the  
>> fact that
>> mailets are james specific.
>>
>> In http://issues.apache.org/jira/browse/JAMES-494 you can see the  
>> easiest
>> approach is to add setters for dependencies and make the "service"  
>> method
>> lookup the services and set them via setters. This way the avalon  
>> container
>> will keep working while non avalon containers can simply use setters.
>
> i'm not sure i agree with this being the easiest approach. there are
> known issues when trying to implement good setter injection frameworks
> and conventions would have to be established for setter names unless
> annotations are used.
>
> the simplest approach would be to use constructor injection and
> exclude optional dependencies
>
> IMO the best approach for setter injection would be to create an
> alternative spring processor loader
>
> i'd like to be able to deploy a self contained jar'd mail application
> eg (sketching somewhat):
>
> META-INF/org/apache/james/list-processor.xml
>
> <procesor loader='org.apache.james.mailet.container.Spring'>
>   <mailet name='ListManager'>
> ....
>   </mailet>
> </processor>
>
> META-INF/org/apache/james/spring-mailets.xml
>
> <beans>
> <bean id='ListManager' class=...>
> ....
> </bean>
> </beans>
>
>>>> Another doubt is about the use of "String url": can you give more  
>>>> details
>>>> on
>>>> the allowed values for url and the way it works (a couple of  
>>>> examples
>>>> would
>>>> suffice, I guess)?
>>>
>>> i've been thinking for a long while that there might be a lot to  
>>> gain
>>> in flexibility by moving towards APIs using URIs
>>>
>>> but it's still hazy...
>>>
>>>> Last point, and the least important, I don't like the SPI postfix.
>>>> The same interface could be used by SMTPServer/Fetchmail to store
>>>> messages
>>>> to the spool. In fact a spool repository could expose this  
>>>> interface
>>>> (ignoring the url) or we could expose it via the Store by looking  
>>>> up the
>>>> appropriate spool repository and storing the message to it.
>>>
>>> i have been thinking about that direction
>>>
>>> for example, POSTing to "mailto://joe@example.org" is an elegant and
>>> concise way to express the idea of forwarding a mail. this can be  
>>> used
>>> for delivery as well. for example "mailet://joe@localhost".
>>>
>>> the advantage of using URLs is that it's easier to present  
>>> interfaces
>>> which work ok for a wider variety of protocols. for example  
>>> POSTing to
>>> "imap://joe@localhost/INBOX" could be distringuished from
>>> "james://joe@localhost/INBOX" and "mailbox://joe@localhost/INBOX".
>>> might be possible to do some interesting stuff this way.
>>
>> I like this stuff very much. I discussed a similar thing in past. I  
>> named it
>> "destinations":
>> http://markmail.org/message/xkcttgyqmfwpieew
>>
>> In my 2005 idea "destinations" was particular email addresses  
>> because email
>> address is more "mail" oriented than url, but mail is moving to  
>> different
>> transport and everyone probably better understand urls than email  
>> addresses.
>>
>> But I think it would be a very interesting paradigm to use urls for  
>> anything
>> from local spool management, to remote delivery to forward and  
>> anything
>> else.
>>
>> The issue I see here is that we should understand how they works  
>> before
>> starting to add interfaces using this urls.
>
> the sieve mailet is still experiement: it's a good opportunity just to
> give it a go and take the chance to live with it for a while
>
> - robert
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
> For additional commands, e-mail: server-dev-help@james.apache.org
>


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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Robert Burrell Donkin <ro...@gmail.com>.
On Tue, Sep 2, 2008 at 9:53 AM, Stefano Bagnara <ap...@bago.org> wrote:
> Robert Burrell Donkin ha scritto:
>>
>> On Mon, Sep 1, 2008 at 2:56 PM, Stefano Bagnara <ap...@bago.org> wrote:
>>>
>>> Robert Burrell Donkin ha scritto:
>>>>
>>>> SieveToMultiMailbox is the major remaining issue on the road to
>>>> separating out an IMAP protocol library. it's a good example of some
>>>> of the problems with the remaining mailets in JAMES. hopefully,
>>>> thinking about solving them in this case may be applied more widely.
>>>>
>>>> ----
>>>>
>>>> SieveToMultiMailbox is tightly coupled to a large IMAP specific API
>>>> (mailboxmanager) but uses only a tiny portion of it. an alternative
>>>> implementation of the mailboxmanager API would be faced with
>>>> implementing at least 29 methods spread over 3 interfaces. the mailet
>>>> only delivers a mail to a mailbox which should really require a single
>>>> call to a single method. this pattern is repeated across JAMES. the
>>>> API is shared by protocols, data stores and mailets resulting in
>>>> unnecessary large and imprecise interfaces. mailets typically only use
>>>> a small subset of the function required by protocols and stores.
>>>> explicit SPIs specialised for mailets would be a better approach.
>>>> these could be independently versioned allowing the APIs used
>>>> internally by JAMES to be safely varied.
>>>>
>>>> an SPI interface for mailboxes as simple as (for example):
>>>>
>>>> public void put(String url, Mail mail);
>>>>
>>>> would suffice
>>>>
>>>> ----
>>>>
>>>> SieveToMultiMailbox is tightly coupled to avalon. the IMAP dependency
>>>> is loaded by a service lookup using avalon. JAMES server is the only
>>>> mailet container that is likely to support avalon. more modern IoC
>>>> containers (for example, spring) would unobtrusively inject the
>>>> required dependency. replacing magic lookup with construction
>>>> injection would mean adding something like:
>>>>
>>>> public SieveToMultiMailbox(MailboxSPI spi)
>>>>
>>>> this would mean refactoring the mailet/matcher loading code to allow
>>>> replacement by an implementation that uses a modern container. (i've
>>>> always been keen on being able to ship independent self-contained mail
>>>> applications built from mailets which could just be dropped into a
>>>> running server.) the complexity would come creating a mixed system.
>>>> using some sort of avalon-aware service adapters would probably be
>>>> necessary.
>>>>
>>>> MailboxSPI might be provided by adapting a mailbox manager service.
>>>>
>>>> ----
>>>>
>>>> opinions?
>>>
>>> I prefer setter injection to constructor injection (expecially as we have
>>> an
>>> init method in the mailet api).
>>
>> i know a lot of people prefer setter injection but constructor
>> injection has some advantages in this case:
>>
>> 1. it prevents uninitialised use of the mailet. this should give a
>> clean failure when anyone tries to use it with an incompatible mailet
>> loader.
>
> THe mailet api require an "init" method. In that method we can check if the
> services are there and throw exceptions to prevent this.
> This also does not introduce multiple constructors when dealing with
> optional dependencies.
>
> IN past we discussed about what IoC style we prefer and SDI was the
> "winner":
> http://issues.apache.org/jira/browse/JAMES-494
>
> Here you can find the biggest poll we've ever had ;-)
> http://markmail.org/message/rfagbuq6t3au7uia
> "G" questions was about dependency injection.

i did remark that setting injection is more popular but i don't intend
to set a president, just take one more step forward. it may give some
pointers towards more general solutions

> Removing the default constructor will also make my new mailet report maven
> module to fail obtaining the getMailetInfo/getMatcherInfo answer. It have to
> get a newInstance in order to invoke that method.
>
> Not a big deal, and if you go with CDI it will anyway be easy to refactor to
> SDI in any moment.

setter injection would work best with annotations or interfaces

paired interfaces could be retrofitted easily. for example

interface Mailbox

interface MailboxAware
{
   public void setMailbox(Mailbox mailbox)
}

>> 2. no conventions need to be established or explained. as a temporary
>> measure, it's easy to check and inject a limited number of SPIs
>> through reflection.
>>
>> i would prefer to avoid major changes before moving IMAP out
>
> We have a "store" method in MailetContext and we deprecated it because it
> was not clear how to proceed and we simply discouraged it's usage to feel
> more free to change it later :-)

IMHO MailetContext suffers from doing both too much and too little

>>> I don't understand if you are proposing something to be added to the
>>> mailet
>>> specification
>>
>> ATM AIUI the mailet specification is silent on assembly and service
>> acquisition. one advantage of this strategy is that it's possible to
>> alter these characteristics without altering the mailet specification.
>
> True and False... there was not support anything using services will not
> work on current containers. So let's say "there's no way to be backward
> compatible, so we can do whatever we want" ;-)
>
> Every existing container will fail to load a mailet without a default
> constructor.

i'm not sure how you know that's true



>> IMHO factoring out the mailet loading and the processor assembly from
>> the spool management would be a major step forward
>
> Mmmm.. this is already this way.
> MailetLoader and MatcherLoader are 2 components used by the SpoolManager to
> get instances of the mailets.
>
> <!-- The James Spool Manager block  -->
> <block name="spoolmanager"
> class="org.apache.james.transport.JamesSpoolManager" >
>  <provide name="spoolrepository"
> role="org.apache.james.services.SpoolRepository"/>
>  <provide name="matcherpackages"
> role="org.apache.james.transport.MatcherLoader"/>
>  <provide name="mailetpackages"
> role="org.apache.james.transport.MailetLoader"/>
> </block>
>
> <block name="matcherpackages"
> class="org.apache.james.transport.JamesMatcherLoader" >
>  <provide name="James" role="org.apache.mailet.MailetContext"/>
>  <provide name="filesystem" role="org.apache.james.services.FileSystem" />
> </block>
>
> <block name="mailetpackages"
> class="org.apache.james.transport.JamesMailetLoader" >
>  <provide name="James" role="org.apache.mailet.MailetContext"/>
>  <provide name="filesystem" role="org.apache.james.services.FileSystem" />
> </block>
>
> JamesSpoolManager is configurable to define what class to use as processor
> defaulting to StateAwareProcessorList.
> ---
> processorClass =
> conf.getChild("processorClass").getValue("org.apache.james.transport.StateAwareProcessorList");
> ----
>
> When I refactored this in my mind there was the idea to bring as many
> components to a top level. The idea is that StateAwareProcessorList could be
> a component itself and the SpoolManager could simply depend on a
> MailProcessor component.
>
> This should be easy to do now. I didn't do that before simply because when I
> worked on this everyone was worried about backward compatibility, so no
> change was allowed to break config.xml and db content compatibility. There
> are many hacks in the code to deal with this.

i'm not sure why factoring out the processor would break configuration
compatibility

>>> or simply you are proposing to change the way james specific
>>> mailets are written so to not require avalon knowledge to the james
>>> specific
>>> mailets.
>>
>> IMHO JAMES specific mailets are an anti-pattern. we need to work
>> towards decoupling minimal SPIs for mailets from the large APIs used
>> internally by JAMES. i prefer to think about mailet loaders and
>> processor assemblers indepedently. avalon is not a good match for this
>> problem. more modern IoC containers like pico or spring as *much*
>> better.
>
> I agree that james specific mailets are antipattern.
> To make them generic you have to define services at the mailet level.
> And make the services generic.
>
> To change the service lookup method without publicizing the services does
> not make the mailets portable to other services.
> If a Mailet depends on SpoolRepository interface we can remove avalon and
> the service manager by using simple CDI/SDI, but in the end the mailet will
> be only usable where SpoolRepository implementations are available.
> SpoolRepository is james specific.
>
> MailboxSPI is james specific until we make it part of a generic API
> supported by compliant containers.
> I don't understand what is your idea about this? Do you want to make an
> mailet-spi package with optional services to be supported by advanced
> containers?

yep

>> i strongly dislike the use of the magic avalon service attribute. IMHO
>> if a mailet is coupled to avalon then it should implement the standard
>> servicable interface. the container could then recognize this and
>> configure the mailet appropriately.
>
> I agree that the context and the service lookup are a bad idea for mailets.
> IMHO this is a necessary change, but this alone won't change the fact that
> mailets are james specific.
>
> In http://issues.apache.org/jira/browse/JAMES-494 you can see the easiest
> approach is to add setters for dependencies and make the "service" method
> lookup the services and set them via setters. This way the avalon container
> will keep working while non avalon containers can simply use setters.

i'm not sure i agree with this being the easiest approach. there are
known issues when trying to implement good setter injection frameworks
and conventions would have to be established for setter names unless
annotations are used.

the simplest approach would be to use constructor injection and
exclude optional dependencies

IMO the best approach for setter injection would be to create an
alternative spring processor loader

i'd like to be able to deploy a self contained jar'd mail application
eg (sketching somewhat):

META-INF/org/apache/james/list-processor.xml

<procesor loader='org.apache.james.mailet.container.Spring'>
   <mailet name='ListManager'>
....
   </mailet>
</processor>

META-INF/org/apache/james/spring-mailets.xml

<beans>
 <bean id='ListManager' class=...>
....
 </bean>
</beans>

>>> Another doubt is about the use of "String url": can you give more details
>>> on
>>> the allowed values for url and the way it works (a couple of examples
>>> would
>>> suffice, I guess)?
>>
>> i've been thinking for a long while that there might be a lot to gain
>> in flexibility by moving towards APIs using URIs
>>
>> but it's still hazy...
>>
>>> Last point, and the least important, I don't like the SPI postfix.
>>> The same interface could be used by SMTPServer/Fetchmail to store
>>> messages
>>> to the spool. In fact a spool repository could expose this interface
>>> (ignoring the url) or we could expose it via the Store by looking up the
>>> appropriate spool repository and storing the message to it.
>>
>> i have been thinking about that direction
>>
>> for example, POSTing to "mailto://joe@example.org" is an elegant and
>> concise way to express the idea of forwarding a mail. this can be used
>> for delivery as well. for example "mailet://joe@localhost".
>>
>> the advantage of using URLs is that it's easier to present interfaces
>> which work ok for a wider variety of protocols. for example POSTing to
>> "imap://joe@localhost/INBOX" could be distringuished from
>> "james://joe@localhost/INBOX" and "mailbox://joe@localhost/INBOX".
>> might be possible to do some interesting stuff this way.
>
> I like this stuff very much. I discussed a similar thing in past. I named it
> "destinations":
> http://markmail.org/message/xkcttgyqmfwpieew
>
> In my 2005 idea "destinations" was particular email addresses because email
> address is more "mail" oriented than url, but mail is moving to different
> transport and everyone probably better understand urls than email addresses.
>
> But I think it would be a very interesting paradigm to use urls for anything
> from local spool management, to remote delivery to forward and anything
> else.
>
> The issue I see here is that we should understand how they works before
> starting to add interfaces using this urls.

the sieve mailet is still experiement: it's a good opportunity just to
give it a go and take the chance to live with it for a while

- robert

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Stefano Bagnara <ap...@bago.org>.
Robert Burrell Donkin ha scritto:
> On Mon, Sep 1, 2008 at 2:56 PM, Stefano Bagnara <ap...@bago.org> wrote:
>> Robert Burrell Donkin ha scritto:
>>> SieveToMultiMailbox is the major remaining issue on the road to
>>> separating out an IMAP protocol library. it's a good example of some
>>> of the problems with the remaining mailets in JAMES. hopefully,
>>> thinking about solving them in this case may be applied more widely.
>>>
>>> ----
>>>
>>> SieveToMultiMailbox is tightly coupled to a large IMAP specific API
>>> (mailboxmanager) but uses only a tiny portion of it. an alternative
>>> implementation of the mailboxmanager API would be faced with
>>> implementing at least 29 methods spread over 3 interfaces. the mailet
>>> only delivers a mail to a mailbox which should really require a single
>>> call to a single method. this pattern is repeated across JAMES. the
>>> API is shared by protocols, data stores and mailets resulting in
>>> unnecessary large and imprecise interfaces. mailets typically only use
>>> a small subset of the function required by protocols and stores.
>>> explicit SPIs specialised for mailets would be a better approach.
>>> these could be independently versioned allowing the APIs used
>>> internally by JAMES to be safely varied.
>>>
>>> an SPI interface for mailboxes as simple as (for example):
>>>
>>> public void put(String url, Mail mail);
>>>
>>> would suffice
>>>
>>> ----
>>>
>>> SieveToMultiMailbox is tightly coupled to avalon. the IMAP dependency
>>> is loaded by a service lookup using avalon. JAMES server is the only
>>> mailet container that is likely to support avalon. more modern IoC
>>> containers (for example, spring) would unobtrusively inject the
>>> required dependency. replacing magic lookup with construction
>>> injection would mean adding something like:
>>>
>>> public SieveToMultiMailbox(MailboxSPI spi)
>>>
>>> this would mean refactoring the mailet/matcher loading code to allow
>>> replacement by an implementation that uses a modern container. (i've
>>> always been keen on being able to ship independent self-contained mail
>>> applications built from mailets which could just be dropped into a
>>> running server.) the complexity would come creating a mixed system.
>>> using some sort of avalon-aware service adapters would probably be
>>> necessary.
>>>
>>> MailboxSPI might be provided by adapting a mailbox manager service.
>>>
>>> ----
>>>
>>> opinions?
>> I prefer setter injection to constructor injection (expecially as we have an
>> init method in the mailet api).
> 
> i know a lot of people prefer setter injection but constructor
> injection has some advantages in this case:
> 
> 1. it prevents uninitialised use of the mailet. this should give a
> clean failure when anyone tries to use it with an incompatible mailet
> loader.

THe mailet api require an "init" method. In that method we can check if 
the services are there and throw exceptions to prevent this.
This also does not introduce multiple constructors when dealing with 
optional dependencies.

IN past we discussed about what IoC style we prefer and SDI was the 
"winner":
http://issues.apache.org/jira/browse/JAMES-494

Here you can find the biggest poll we've ever had ;-)
http://markmail.org/message/rfagbuq6t3au7uia
"G" questions was about dependency injection.

Removing the default constructor will also make my new mailet report 
maven module to fail obtaining the getMailetInfo/getMatcherInfo answer. 
It have to get a newInstance in order to invoke that method.

Not a big deal, and if you go with CDI it will anyway be easy to 
refactor to SDI in any moment.

> 2. no conventions need to be established or explained. as a temporary
> measure, it's easy to check and inject a limited number of SPIs
> through reflection.
> 
> i would prefer to avoid major changes before moving IMAP out

We have a "store" method in MailetContext and we deprecated it because 
it was not clear how to proceed and we simply discouraged it's usage to 
feel more free to change it later :-)

>> I don't understand if you are proposing something to be added to the mailet
>> specification
> 
> ATM AIUI the mailet specification is silent on assembly and service
> acquisition. one advantage of this strategy is that it's possible to
> alter these characteristics without altering the mailet specification.

True and False... there was not support anything using services will not 
work on current containers. So let's say "there's no way to be backward 
compatible, so we can do whatever we want" ;-)

Every existing container will fail to load a mailet without a default 
constructor.

> IMHO factoring out the mailet loading and the processor assembly from
> the spool management would be a major step forward

Mmmm.. this is already this way.
MailetLoader and MatcherLoader are 2 components used by the SpoolManager 
to get instances of the mailets.

<!-- The James Spool Manager block  -->
<block name="spoolmanager" 
class="org.apache.james.transport.JamesSpoolManager" >
   <provide name="spoolrepository" 
role="org.apache.james.services.SpoolRepository"/>
   <provide name="matcherpackages" 
role="org.apache.james.transport.MatcherLoader"/>
   <provide name="mailetpackages" 
role="org.apache.james.transport.MailetLoader"/>
</block>

<block name="matcherpackages" 
class="org.apache.james.transport.JamesMatcherLoader" >
   <provide name="James" role="org.apache.mailet.MailetContext"/>
   <provide name="filesystem" role="org.apache.james.services.FileSystem" />
</block>

<block name="mailetpackages" 
class="org.apache.james.transport.JamesMailetLoader" >
   <provide name="James" role="org.apache.mailet.MailetContext"/>
   <provide name="filesystem" role="org.apache.james.services.FileSystem" />
</block>

JamesSpoolManager is configurable to define what class to use as 
processor defaulting to StateAwareProcessorList.
---
processorClass = 
conf.getChild("processorClass").getValue("org.apache.james.transport.StateAwareProcessorList");
----

When I refactored this in my mind there was the idea to bring as many 
components to a top level. The idea is that StateAwareProcessorList 
could be a component itself and the SpoolManager could simply depend on 
a MailProcessor component.

This should be easy to do now. I didn't do that before simply because 
when I worked on this everyone was worried about backward compatibility, 
so no change was allowed to break config.xml and db content 
compatibility. There are many hacks in the code to deal with this.

>> or simply you are proposing to change the way james specific
>> mailets are written so to not require avalon knowledge to the james specific
>> mailets.
> 
> IMHO JAMES specific mailets are an anti-pattern. we need to work
> towards decoupling minimal SPIs for mailets from the large APIs used
> internally by JAMES. i prefer to think about mailet loaders and
> processor assemblers indepedently. avalon is not a good match for this
> problem. more modern IoC containers like pico or spring as *much*
> better.

I agree that james specific mailets are antipattern.
To make them generic you have to define services at the mailet level.
And make the services generic.

To change the service lookup method without publicizing the services 
does not make the mailets portable to other services.
If a Mailet depends on SpoolRepository interface we can remove avalon 
and the service manager by using simple CDI/SDI, but in the end the 
mailet will be only usable where SpoolRepository implementations are 
available. SpoolRepository is james specific.

MailboxSPI is james specific until we make it part of a generic API 
supported by compliant containers.
I don't understand what is your idea about this? Do you want to make an 
mailet-spi package with optional services to be supported by advanced 
containers?

> i strongly dislike the use of the magic avalon service attribute. IMHO
> if a mailet is coupled to avalon then it should implement the standard
> servicable interface. the container could then recognize this and
> configure the mailet appropriately.

I agree that the context and the service lookup are a bad idea for 
mailets. IMHO this is a necessary change, but this alone won't change 
the fact that mailets are james specific.

In http://issues.apache.org/jira/browse/JAMES-494 you can see the 
easiest approach is to add setters for dependencies and make the 
"service" method lookup the services and set them via setters. This way 
the avalon container will keep working while non avalon containers can 
simply use setters.

>> Another doubt is about the use of "String url": can you give more details on
>> the allowed values for url and the way it works (a couple of examples would
>> suffice, I guess)?
> 
> i've been thinking for a long while that there might be a lot to gain
> in flexibility by moving towards APIs using URIs
> 
> but it's still hazy...
> 
>> Last point, and the least important, I don't like the SPI postfix.
>> The same interface could be used by SMTPServer/Fetchmail to store messages
>> to the spool. In fact a spool repository could expose this interface
>> (ignoring the url) or we could expose it via the Store by looking up the
>> appropriate spool repository and storing the message to it.
> 
> i have been thinking about that direction
> 
> for example, POSTing to "mailto://joe@example.org" is an elegant and
> concise way to express the idea of forwarding a mail. this can be used
> for delivery as well. for example "mailet://joe@localhost".
> 
> the advantage of using URLs is that it's easier to present interfaces
> which work ok for a wider variety of protocols. for example POSTing to
> "imap://joe@localhost/INBOX" could be distringuished from
> "james://joe@localhost/INBOX" and "mailbox://joe@localhost/INBOX".
> might be possible to do some interesting stuff this way.

I like this stuff very much. I discussed a similar thing in past. I 
named it "destinations":
http://markmail.org/message/xkcttgyqmfwpieew

In my 2005 idea "destinations" was particular email addresses because 
email address is more "mail" oriented than url, but mail is moving to 
different transport and everyone probably better understand urls than 
email addresses.

But I think it would be a very interesting paradigm to use urls for 
anything from local spool management, to remote delivery to forward and 
anything else.

The issue I see here is that we should understand how they works before 
starting to add interfaces using this urls.

Stefano

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


Re: [mailets] POJOs (and in particular SieveToMultiMailbox)

Posted by Robert Burrell Donkin <ro...@gmail.com>.
On Mon, Sep 1, 2008 at 2:56 PM, Stefano Bagnara <ap...@bago.org> wrote:
> Robert Burrell Donkin ha scritto:
>>
>> SieveToMultiMailbox is the major remaining issue on the road to
>> separating out an IMAP protocol library. it's a good example of some
>> of the problems with the remaining mailets in JAMES. hopefully,
>> thinking about solving them in this case may be applied more widely.
>>
>> ----
>>
>> SieveToMultiMailbox is tightly coupled to a large IMAP specific API
>> (mailboxmanager) but uses only a tiny portion of it. an alternative
>> implementation of the mailboxmanager API would be faced with
>> implementing at least 29 methods spread over 3 interfaces. the mailet
>> only delivers a mail to a mailbox which should really require a single
>> call to a single method. this pattern is repeated across JAMES. the
>> API is shared by protocols, data stores and mailets resulting in
>> unnecessary large and imprecise interfaces. mailets typically only use
>> a small subset of the function required by protocols and stores.
>> explicit SPIs specialised for mailets would be a better approach.
>> these could be independently versioned allowing the APIs used
>> internally by JAMES to be safely varied.
>>
>> an SPI interface for mailboxes as simple as (for example):
>>
>> public void put(String url, Mail mail);
>>
>> would suffice
>>
>> ----
>>
>> SieveToMultiMailbox is tightly coupled to avalon. the IMAP dependency
>> is loaded by a service lookup using avalon. JAMES server is the only
>> mailet container that is likely to support avalon. more modern IoC
>> containers (for example, spring) would unobtrusively inject the
>> required dependency. replacing magic lookup with construction
>> injection would mean adding something like:
>>
>> public SieveToMultiMailbox(MailboxSPI spi)
>>
>> this would mean refactoring the mailet/matcher loading code to allow
>> replacement by an implementation that uses a modern container. (i've
>> always been keen on being able to ship independent self-contained mail
>> applications built from mailets which could just be dropped into a
>> running server.) the complexity would come creating a mixed system.
>> using some sort of avalon-aware service adapters would probably be
>> necessary.
>>
>> MailboxSPI might be provided by adapting a mailbox manager service.
>>
>> ----
>>
>> opinions?
>
> I prefer setter injection to constructor injection (expecially as we have an
> init method in the mailet api).

i know a lot of people prefer setter injection but constructor
injection has some advantages in this case:

1. it prevents uninitialised use of the mailet. this should give a
clean failure when anyone tries to use it with an incompatible mailet
loader.
2. no conventions need to be established or explained. as a temporary
measure, it's easy to check and inject a limited number of SPIs
through reflection.

i would prefer to avoid major changes before moving IMAP out

> I don't understand if you are proposing something to be added to the mailet
> specification

ATM AIUI the mailet specification is silent on assembly and service
acquisition. one advantage of this strategy is that it's possible to
alter these characteristics without altering the mailet specification.

IMHO factoring out the mailet loading and the processor assembly from
the spool management would be a major step forward

> or simply you are proposing to change the way james specific
> mailets are written so to not require avalon knowledge to the james specific
> mailets.

IMHO JAMES specific mailets are an anti-pattern. we need to work
towards decoupling minimal SPIs for mailets from the large APIs used
internally by JAMES. i prefer to think about mailet loaders and
processor assemblers indepedently. avalon is not a good match for this
problem. more modern IoC containers like pico or spring as *much*
better.

i strongly dislike the use of the magic avalon service attribute. IMHO
if a mailet is coupled to avalon then it should implement the standard
servicable interface. the container could then recognize this and
configure the mailet appropriately.

> Another doubt is about the use of "String url": can you give more details on
> the allowed values for url and the way it works (a couple of examples would
> suffice, I guess)?

i've been thinking for a long while that there might be a lot to gain
in flexibility by moving towards APIs using URIs

but it's still hazy...

> Last point, and the least important, I don't like the SPI postfix.
> The same interface could be used by SMTPServer/Fetchmail to store messages
> to the spool. In fact a spool repository could expose this interface
> (ignoring the url) or we could expose it via the Store by looking up the
> appropriate spool repository and storing the message to it.

i have been thinking about that direction

for example, POSTing to "mailto://joe@example.org" is an elegant and
concise way to express the idea of forwarding a mail. this can be used
for delivery as well. for example "mailet://joe@localhost".

the advantage of using URLs is that it's easier to present interfaces
which work ok for a wider variety of protocols. for example POSTing to
"imap://joe@localhost/INBOX" could be distringuished from
"james://joe@localhost/INBOX" and "mailbox://joe@localhost/INBOX".
might be possible to do some interesting stuff this way.

- robert

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