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 Bernd Fondermann <be...@googlemail.com> on 2006/10/02 15:03:41 UTC
Re: OSGi: First steps with Knopflerfish
On 9/30/06, Joachim Draeger <jd...@joachim-draeger.de> wrote:
> Am Samstag, den 30.09.2006, 12:07 +0200 schrieb Bernd Fondermann:
>
> > > Doing some POJOification can't be bad but I don't consider it a blocker.
> > > How do you know HOW to decouple components when you don't know where to
> > > go? When you decouple it from something you have to couple it to another
> > > thing. Being a bit container dependent can make things clearer.
> >
> > Agreed. But the situation as it is now is, that the components are
> > heavily coupled with
> > a. phoenix lifecycle interfaces
>
> What is the problem with them? In another container the Interface might
> be named Lifecycle and the methods activate() and deactive(). Just
> refactoring. The question is how the things done in
> configure/start/stop/initialize/dispose fit into other frameworks.
Three problems:
1. component must import lifecycle stuff and becomes container aware
(_not_ IoC in the narrow sense!)
2. lifecycle methods cannot simply be "renamed" if there are
ServiceManagers stored in the component itself (bad. sometimes
difficult to refactor, when you get the SM in the first call (say:
initialize()) and need it in the second (say: configure()))
3. livecycle method of different containers are not neccessarily
compatible/interchangable
> > b. avalon configuration stuff
>
> Yes, some POJOification should be done here, too. Did we decide how to
> do this?
No, not yet. We have setters on most components, but much of the
configuration and intialization is still very very dependent on the
framework. some consider this as being ok, I don't.
> IMO classes with only a few configuration options should carry their
> attributes + getters/setters themselves. More complicated configs should
> be moved to separate pure POJO beans.
Exactly.
> > c. avalon/phoenix ServiceManager
>
> AFAIK POJOification in progress, or even finished?
in progress, sometimes delicate.
> > d. avalon logger (superclass)
>
> What do you suppose? I consider this as refactoring. :-)
Well, logging is not a semantical super-construct of a component, it
is a side-aspect.
By extending AbstractLogEnabled you hinder more semantically
beneficial class hierarchies. Bad.
> > e. verbose + redundant config in environment.xml, *.xinfo
>
> You mean assembly.xml?
Yes, sorry... should have checked that beforehand.
> Is there a possibility to avoid that redundancy
> in Avalon? Apart from that I find them both quite readable.
You have to do the following:
1. Declare a component
2. Declare for the component, which other components it references
3. Declare for the SM, which components it propagates to each component
4. Implement in the service() method a lookup and typecast.
This is not inversion of control, this is "all stages control".
It is redundant, since James uses full qualified class names everywhere.
With 4.) in place, 2) and 3) become uneccessary, no additional
information is added, being of any use for SM or the component.
> > This is bad (IMHO) even if you do _not_ want to change container.
> > For example, look at the unit tests and the setup() methods. much too
> > much has to be done there to execute a simple test. this is mock-up
> > hell ;-)
>
> I completely agree, but I don't consider this as a blocker for
> evaluating different containers or even try to wire some James stuff
> together in order to try it inside an OSGi bundle.
Right. BTW, I am not opposing OSGi. There have other containers been
brought into the discussion, like Spring, xbeans, AFAIR. Stefano did a
poll which one should be preferred, with diverging opinions.
My take on this is: Let's fix our components at first, then decide
about switching containers.
Bernd
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
Re: OSGi: First steps with Knopflerfish
Posted by Bernd Fondermann <be...@googlemail.com>.
Didn't have the time to get back to this thread sooner, sorry.
more inline...
Bernd
On 10/3/06, Stefano Bagnara <ap...@bago.org> wrote:
> Bernd Fondermann wrote:
> > On 10/2/06, Stefano Bagnara <ap...@bago.org> wrote:
> >> Bernd Fondermann wrote:
> >> >> > a. phoenix lifecycle interfaces
> >> >>
> >> >> What is the problem with them? In another container the Interface
> >> might
> >> >> be named Lifecycle and the methods activate() and deactive(). Just
> >> >> refactoring. The question is how the things done in
> >> >> configure/start/stop/initialize/dispose fit into other frameworks.
> >> >
> >> > Three problems:
> >> > 1. component must import lifecycle stuff and becomes container aware
> >> > (_not_ IoC in the narrow sense!)
> >>
> >> THis is easy: don't implement interfaces in the main object, create an
> >> extension for that object implementing all of the lifecycle interfaces
> >> needed.
> >
> > :-) coming up with that solution strategy is easy. implementing this
> > solution isn't. ;-)
>
> The problem is not that the components are container aware: the problem
> is that the components do what the containers should do with
> child-components. So we have components that manually manage the
> lifecycle for the nested components. Removing this thing is not easy.
ok, I reviewed the lifecycle code and recognized those nested
components. I wasn't aware of this.
> If I find the time (I already have too much things in my todo list) I
> would like to elaborate something on component-factories to be used to
> be able to be container-agnostic when working on jspf: we started having
> a bunch of services (SPFChecker, DNSService, Logger, SPFParser) that
> could be used by child components.
> If I'll do this and I'll be happy with the result I will say something
> to get your opinions.
ok, fine.
> >> > 2. lifecycle methods cannot simply be "renamed" if there are
> >> > ServiceManagers stored in the component itself (bad. sometimes
> >> > difficult to refactor, when you get the SM in the first call (say:
> >> > initialize()) and need it in the second (say: configure()))
> >>
> >> Right. And we should try to isolate the service() call and the
> >> servicemanager references from our code: it should be easy.
> >
> > not always easy, but: yes.
>
> Can you point out a difficult scenario? I often think that trying to
> find a solution to one of the concrete (possibily one of the difficult
> issue) is much better than talking theoretically.
For example AbstractJamesService.
The service method receives the ServiceManager, which is then locally
stored and re-used in initialize().
Another case is the one you described above: when a component needs to
configure subcomponents, SM is stored locally and the component does
lifecycling on its own.
> >> >> > b. avalon configuration stuff
> >> >>
> >> >> Yes, some POJOification should be done here, too. Did we decide how to
> >> >> do this?
> >> >
> >> > No, not yet. We have setters on most components, but much of the
> >> > configuration and intialization is still very very dependent on the
> >> > framework. some consider this as being ok, I don't.
> >>
> >> I'm happy with avalon lifecycle dependencies: I would like to remove the
> >> Serviceable/ServiceManager stuff (in favor of setters/enabling
> >> interfaces). I would like to not be dependant on the
> >> Avalon-Configuration stuff (I don't know how).
> >
> > ok, that would be the base for a common goal. it would already be a
> > great achievement, even when still running under avalon lifecycle.
>
> I agree, and we can skip other container discussions until we have not
> fixed this starting points.
>
> I would like to know if you (and others) agree that the 2 points
> (Service / Configuration) are "must" steps anyway, indipendently from
> the final container we'll choose.
+1
> >> >> > d. avalon logger (superclass)
> >> >>
> >> >> What do you suppose? I consider this as refactoring. :-)
> >> >
> >> > Well, logging is not a semantical super-construct of a component, it
> >> > is a side-aspect.
> >> > By extending AbstractLogEnabled you hinder more semantically
> >> > beneficial class hierarchies. Bad.
> >>
> >> You simply have to remove "extends AbstractLogEnabled", add "implements
> >> LogEnabled" and add 2 methods copied from AbstractLogEnabled and you'll
> >> have fixed this. So this is a non-issue.
> >
> > a "non-issue"?? From writing unit test/mock up objects I am under the
> > impression it _is_ an issue, but I will have to have a look again to
> > come up with concrete examples.
>
> Yes please. Otherwise I fear I've not understood the problem.
Currently, for AbstractJamesServices, the class hierarchie is as follows:
o.a.j.core.AbstractJamesService
extends
o.a.a.cornerstone.services.connection.AbstractHandlerFactory
extends
o.a.a.framework.logger.LogEnabled
So in this case there is no _easy_ way to go from class
AbstractLogEnabled to interface LogEnabled.
And moving AbstractLogEnabled/LogEnabled from Avalon to James code is
not so simple, too. Because AbstractHandlerFactory is not from James.
AbstractJamesService is subclassed by NNTPServer, SMPTServer,
RemoteManager and POP3Server.
> Here is what I understood you want to do:
> 1) Search "extends AbstractLogEnabled" => 61 classes.
> 2) for each:
> a. Remove "extends AbstractLogEnabled" add "implements LogEnabled"
> b. add a "private Logger logger" field
> c. add an enableLogging(Logger logger) method as the setter
> d. add a Logger getLogger() method as the getter
> 3) Search "setupLogger" => 4 classes.
> 4) for each:
> a. implement the setupLogger method that run a call a
> getLogger().getChildLogger() and call the enableLogging for the child
> component.
> 5) Champagne: we don't have an abstract root class (but Object) anymore.
>
> Is this what you want?
> What is the advantages you get from this change?
Champagne :-)
Plus the possibility to extend a super class which actually adds value
to the child class.
Bernd
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
Re: OSGi: First steps with Knopflerfish
Posted by Stefano Bagnara <ap...@bago.org>.
Bernd Fondermann wrote:
> On 10/2/06, Stefano Bagnara <ap...@bago.org> wrote:
>> Bernd Fondermann wrote:
>> >> > a. phoenix lifecycle interfaces
>> >>
>> >> What is the problem with them? In another container the Interface
>> might
>> >> be named Lifecycle and the methods activate() and deactive(). Just
>> >> refactoring. The question is how the things done in
>> >> configure/start/stop/initialize/dispose fit into other frameworks.
>> >
>> > Three problems:
>> > 1. component must import lifecycle stuff and becomes container aware
>> > (_not_ IoC in the narrow sense!)
>>
>> THis is easy: don't implement interfaces in the main object, create an
>> extension for that object implementing all of the lifecycle interfaces
>> needed.
>
> :-) coming up with that solution strategy is easy. implementing this
> solution isn't. ;-)
The problem is not that the components are container aware: the problem
is that the components do what the containers should do with
child-components. So we have components that manually manage the
lifecycle for the nested components. Removing this thing is not easy.
If I find the time (I already have too much things in my todo list) I
would like to elaborate something on component-factories to be used to
be able to be container-agnostic when working on jspf: we started having
a bunch of services (SPFChecker, DNSService, Logger, SPFParser) that
could be used by child components.
If I'll do this and I'll be happy with the result I will say something
to get your opinions.
>> > 2. lifecycle methods cannot simply be "renamed" if there are
>> > ServiceManagers stored in the component itself (bad. sometimes
>> > difficult to refactor, when you get the SM in the first call (say:
>> > initialize()) and need it in the second (say: configure()))
>>
>> Right. And we should try to isolate the service() call and the
>> servicemanager references from our code: it should be easy.
>
> not always easy, but: yes.
Can you point out a difficult scenario? I often think that trying to
find a solution to one of the concrete (possibily one of the difficult
issue) is much better than talking theoretically.
>> The most
>> difficult part is how we currently propagate the ServiceManager to the
>> Mailets (via Mailet Context).
>> How should we propagate such dependencies to Mailets?
>
> For Mailets, I don't know. There has been a thread about it and no one
> yet came up with a good solution, AFAIR.
I remember the same: I would like to use enabling interfaces for
mailets, but it seems that at least Noel is on the opposite side
proposing JNDI lookups.
>> > 3. livecycle method of different containers are not neccessarily
>> > compatible/interchangable
>>
>> And this is the bigger issue: "container agnostic components" are only
>> an utopia. As soon as you write not-hello-world componets you will have
>> requirements for the lifecycle and the dependencies behaviours and this
>> will need lines of code or much lines of container configurations to be
>> addressed. Saying that your component is container agnostic simply means
>> that the component is not complete and will need much more work in order
>> to make it working in any specific container.
>
> ooh-kaay... do you consider the whole IoC approach,
> separation-of-concerns, low coupling, ... as utopia(s)? Up to some
> point it works quite well in reality, I think.
Maybe I have not been clear enough: I'm a big fan of IoC, but Avalon is
all about IoC (just think that it is the only framework enforcing IoC
for logging). This is unfortunately enough to be container agnostic.
Being container agnostic means simply separate the container agnostic
things from the container specific things: you will still have both in
the resulting application/component and most times the container
specific part is not trivial.
Btw this is a too much theoretical discussion: I think that we all know
what is the real world out there.
>> >> > b. avalon configuration stuff
>> >>
>> >> Yes, some POJOification should be done here, too. Did we decide how to
>> >> do this?
>> >
>> > No, not yet. We have setters on most components, but much of the
>> > configuration and intialization is still very very dependent on the
>> > framework. some consider this as being ok, I don't.
>>
>> I'm happy with avalon lifecycle dependencies: I would like to remove the
>> Serviceable/ServiceManager stuff (in favor of setters/enabling
>> interfaces). I would like to not be dependant on the
>> Avalon-Configuration stuff (I don't know how).
>
> ok, that would be the base for a common goal. it would already be a
> great achievement, even when still running under avalon lifecycle.
I agree, and we can skip other container discussions until we have not
fixed this starting points.
I would like to know if you (and others) agree that the 2 points
(Service / Configuration) are "must" steps anyway, indipendently from
the final container we'll choose.
I think that this is true for the first but I'm not yet sure about the
Configuration thing: OSGi has 2 default services for Preferences and
Configurations and they do not seem to have a direct mapping on
Configurations used by other containers/framework.
>> >> > d. avalon logger (superclass)
>> >>
>> >> What do you suppose? I consider this as refactoring. :-)
>> >
>> > Well, logging is not a semantical super-construct of a component, it
>> > is a side-aspect.
>> > By extending AbstractLogEnabled you hinder more semantically
>> > beneficial class hierarchies. Bad.
>>
>> You simply have to remove "extends AbstractLogEnabled", add "implements
>> LogEnabled" and add 2 methods copied from AbstractLogEnabled and you'll
>> have fixed this. So this is a non-issue.
>
> a "non-issue"?? From writing unit test/mock up objects I am under the
> impression it _is_ an issue, but I will have to have a look again to
> come up with concrete examples.
Yes please. Otherwise I fear I've not understood the problem.
Here is what I understood you want to do:
1) Search "extends AbstractLogEnabled" => 61 classes.
2) for each:
a. Remove "extends AbstractLogEnabled" add "implements LogEnabled"
b. add a "private Logger logger" field
c. add an enableLogging(Logger logger) method as the setter
d. add a Logger getLogger() method as the getter
3) Search "setupLogger" => 4 classes.
4) for each:
a. implement the setupLogger method that run a call a
getLogger().getChildLogger() and call the enableLogging for the child
component.
5) Champagne: we don't have an abstract root class (but Object) anymore.
Is this what you want?
What is the advantages you get from this change?
>> I would like to keep the IoC style for Loggers: I always hated the
>> static way to access loggers that 99% of projects out there use. One of
>> the things because Avalon is great is for trying to enforce IoC for
>> logging (IMO).
>
> IoC loggers are good... never thought about hating those static
> loggers, but will consider this for the future ;-)
>
> Bernd
If you'll manage *static* loggers in environment with complex
classloaders hierarchy you will hate them for sure.. you'll revert to
non-static loggers with static factories, but I already hate this anyway ;-)
Stefano
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
Re: OSGi: First steps with Knopflerfish
Posted by Bernd Fondermann <be...@googlemail.com>.
On 10/2/06, Stefano Bagnara <ap...@bago.org> wrote:
> Bernd Fondermann wrote:
> >> > a. phoenix lifecycle interfaces
> >>
> >> What is the problem with them? In another container the Interface might
> >> be named Lifecycle and the methods activate() and deactive(). Just
> >> refactoring. The question is how the things done in
> >> configure/start/stop/initialize/dispose fit into other frameworks.
> >
> > Three problems:
> > 1. component must import lifecycle stuff and becomes container aware
> > (_not_ IoC in the narrow sense!)
>
> THis is easy: don't implement interfaces in the main object, create an
> extension for that object implementing all of the lifecycle interfaces
> needed.
:-) coming up with that solution strategy is easy. implementing this
solution isn't. ;-)
>
> > 2. lifecycle methods cannot simply be "renamed" if there are
> > ServiceManagers stored in the component itself (bad. sometimes
> > difficult to refactor, when you get the SM in the first call (say:
> > initialize()) and need it in the second (say: configure()))
>
> Right. And we should try to isolate the service() call and the
> servicemanager references from our code: it should be easy.
not always easy, but: yes.
> The most
> difficult part is how we currently propagate the ServiceManager to the
> Mailets (via Mailet Context).
> How should we propagate such dependencies to Mailets?
For Mailets, I don't know. There has been a thread about it and no one
yet came up with a good solution, AFAIR.
> > 3. livecycle method of different containers are not neccessarily
> > compatible/interchangable
>
> And this is the bigger issue: "container agnostic components" are only
> an utopia. As soon as you write not-hello-world componets you will have
> requirements for the lifecycle and the dependencies behaviours and this
> will need lines of code or much lines of container configurations to be
> addressed. Saying that your component is container agnostic simply means
> that the component is not complete and will need much more work in order
> to make it working in any specific container.
ooh-kaay... do you consider the whole IoC approach,
separation-of-concerns, low coupling, ... as utopia(s)? Up to some
point it works quite well in reality, I think.
> >> > b. avalon configuration stuff
> >>
> >> Yes, some POJOification should be done here, too. Did we decide how to
> >> do this?
> >
> > No, not yet. We have setters on most components, but much of the
> > configuration and intialization is still very very dependent on the
> > framework. some consider this as being ok, I don't.
>
> I'm happy with avalon lifecycle dependencies: I would like to remove the
> Serviceable/ServiceManager stuff (in favor of setters/enabling
> interfaces). I would like to not be dependant on the
> Avalon-Configuration stuff (I don't know how).
ok, that would be the base for a common goal. it would already be a
great achievement, even when still running under avalon lifecycle.
> >> > d. avalon logger (superclass)
> >>
> >> What do you suppose? I consider this as refactoring. :-)
> >
> > Well, logging is not a semantical super-construct of a component, it
> > is a side-aspect.
> > By extending AbstractLogEnabled you hinder more semantically
> > beneficial class hierarchies. Bad.
>
> You simply have to remove "extends AbstractLogEnabled", add "implements
> LogEnabled" and add 2 methods copied from AbstractLogEnabled and you'll
> have fixed this. So this is a non-issue.
a "non-issue"?? From writing unit test/mock up objects I am under the
impression it _is_ an issue, but I will have to have a look again to
come up with concrete examples.
> I would like to keep the IoC style for Loggers: I always hated the
> static way to access loggers that 99% of projects out there use. One of
> the things because Avalon is great is for trying to enforce IoC for
> logging (IMO).
IoC loggers are good... never thought about hating those static
loggers, but will consider this for the future ;-)
Bernd
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
Re: OSGi: First steps with Knopflerfish
Posted by Stefano Bagnara <ap...@bago.org>.
Bernd Fondermann wrote:
>> > a. phoenix lifecycle interfaces
>>
>> What is the problem with them? In another container the Interface might
>> be named Lifecycle and the methods activate() and deactive(). Just
>> refactoring. The question is how the things done in
>> configure/start/stop/initialize/dispose fit into other frameworks.
>
> Three problems:
> 1. component must import lifecycle stuff and becomes container aware
> (_not_ IoC in the narrow sense!)
THis is easy: don't implement interfaces in the main object, create an
extension for that object implementing all of the lifecycle interfaces
needed.
> 2. lifecycle methods cannot simply be "renamed" if there are
> ServiceManagers stored in the component itself (bad. sometimes
> difficult to refactor, when you get the SM in the first call (say:
> initialize()) and need it in the second (say: configure()))
Right. And we should try to isolate the service() call and the
servicemanager references from our code: it should be easy. The most
difficult part is how we currently propagate the ServiceManager to the
Mailets (via Mailet Context).
How should we propagate such dependencies to Mailets?
> 3. livecycle method of different containers are not neccessarily
> compatible/interchangable
And this is the bigger issue: "container agnostic components" are only
an utopia. As soon as you write not-hello-world componets you will have
requirements for the lifecycle and the dependencies behaviours and this
will need lines of code or much lines of container configurations to be
addressed. Saying that your component is container agnostic simply means
that the component is not complete and will need much more work in order
to make it working in any specific container.
>> > b. avalon configuration stuff
>>
>> Yes, some POJOification should be done here, too. Did we decide how to
>> do this?
>
> No, not yet. We have setters on most components, but much of the
> configuration and intialization is still very very dependent on the
> framework. some consider this as being ok, I don't.
I'm happy with avalon lifecycle dependencies: I would like to remove the
Serviceable/ServiceManager stuff (in favor of setters/enabling
interfaces). I would like to not be dependant on the
Avalon-Configuration stuff (I don't know how).
>> IMO classes with only a few configuration options should carry their
>> attributes + getters/setters themselves. More complicated configs should
>> be moved to separate pure POJO beans.
>
> Exactly.
How to manage this for parent-child components? We have many of them.
Who parses the configuration file for the child components created by a
top-level component? Currently we delegate the parsing to the child, but
we can't keep this if we want POJOs/Setters as the configuration.
>> > c. avalon/phoenix ServiceManager
>>
>> AFAIK POJOification in progress, or even finished?
I would say in progress.. But we have not made progresses lately.
> in progress, sometimes delicate.
sometimes => often
>> > d. avalon logger (superclass)
>>
>> What do you suppose? I consider this as refactoring. :-)
>
> Well, logging is not a semantical super-construct of a component, it
> is a side-aspect.
> By extending AbstractLogEnabled you hinder more semantically
> beneficial class hierarchies. Bad.
You simply have to remove "extends AbstractLogEnabled", add "implements
LogEnabled" and add 2 methods copied from AbstractLogEnabled and you'll
have fixed this. So this is a non-issue.
I would like to keep the IoC style for Loggers: I always hated the
static way to access loggers that 99% of projects out there use. One of
the things because Avalon is great is for trying to enforce IoC for
logging (IMO).
>> > e. verbose + redundant config in environment.xml, *.xinfo
>>
>> You mean assembly.xml?
>
> Yes, sorry... should have checked that beforehand.
>
>> Is there a possibility to avoid that redundancy
>> in Avalon? Apart from that I find them both quite readable.
>
> You have to do the following:
> 1. Declare a component
> 2. Declare for the component, which other components it references
> 3. Declare for the SM, which components it propagates to each component
> 4. Implement in the service() method a lookup and typecast.
>
> This is not inversion of control, this is "all stages control".
> It is redundant, since James uses full qualified class names everywhere.
> With 4.) in place, 2) and 3) become uneccessary, no additional
> information is added, being of any use for SM or the component.
So you think that autodiscovery is the way? Imho is not sufficient that
a class implement an interface to say that it is the choosen
implementation for that service, so you'll need the assembly for
non-trivial configurations.
>> > This is bad (IMHO) even if you do _not_ want to change container.
>> > For example, look at the unit tests and the setup() methods. much too
>> > much has to be done there to execute a simple test. this is mock-up
>> > hell ;-)
>>
>> I completely agree, but I don't consider this as a blocker for
>> evaluating different containers or even try to wire some James stuff
>> together in order to try it inside an OSGi bundle.
>
> Right. BTW, I am not opposing OSGi. There have other containers been
> brought into the discussion, like Spring, xbeans, AFAIR. Stefano did a
> poll which one should be preferred, with diverging opinions.
>
> My take on this is: Let's fix our components at first, then decide
> about switching containers.
>
> Bernd
I almost agree on this, because I think we should stick to avalon as
long as possible ;-) but I think that the configuration thing and the
dependency management thing cannot and will never been container
agnostic, so we'll have to make a choice before and implement it after.
If there was a container providing a good infrastructure for reloadable,
gui administrable configurations I would try to use it. Maybe eclipse
will release its own preference framework sooner or later but it has a
lot of dependencies on SWT and other eclipse bundles.
Stefano
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org