Hi all,
Over the past 6 months I have been really getting into the COP approach. Starting with Excaliber, a brief foray over to XWork, and now the porting of Turbine and Fulcrum to Merlin. And over the past month's I have had to explain repeatedly why I am interested in using a container and components in my applications.
Sorry, I didn't want to ignore your message, but more info down low.
And of course, the number one complaint/concern: "I don't want to implement somebodies interfaces.. Isn't that like EJB?" To which I typically respond that implementing a Startable/Stoppable/Configurable interface is no different then what you would be doing anyway if you needed that functionality. And you are implementing well understood, widespread interfaces. Especially the Startable/Stoppable interfaces, that makes complete sense. Some people people do point out that instead of a Configurable interface, they would set a series of javabean properties. To which I respond that eventually, if you have too many, you end up with a config object, so you might as well start out with Configurable. And you can always do it by hand via JavaBeans. And this satifies most people..
To tell the truth, alot of this complaint line falls under stylistic differences. I prefer to do JavaBean style components, or I NIH (Not Invented Here) syndrome. The thing about the interfaces is that you don't *have* to implement any of them. They just add some nice features that help make writing the component easier.
Even how you obtain your services can fall under this approach.
It is a far cry from EJBs because EJBs force you to implement an interface that mixes several concerns so your component has several empty methods, and write a "key" object, and write a static "Home" class.
Which brings me to the one thing people really don't get.. Why do I have to implement Serviceable to get a hook into other components? Why can't the container just give me the components? I mean, in my java code inside the component I have to pick what I want. Why not define it outside and have the container set it? And I get all balled up in explanations.. Of which I can think of many, like at run time I can pick and choose my components I need.. If I have setting X, I get component X. If I have setting Y, I get component Y. However, this did kinda make me wonder... Why can't I just expose the components I need and provide a setter? Most of the time, I always want an instance of component X. In fact, often, because of unit testing, if I have a dependency on component Y, then I just provide a setter, so that at unit test time I can pass in my MockY component, versus having to use a custom test configuration loaded through avalon.
What is the difference between the ServiceManager and JNDI, other than the fact that it is a much lighter weight thing?
Many of these people can understand the use of JNDI, but they don't like the ServiceManager because they have their own pet way of doing things.
That said, there are always valid points in every point of view. Many times it is a balance that must be struck for each project. For example, systems that are simple enough to have one instance of a component would be easier to write if the component were passed in through a setter. Systems that require dynamically managed components where an instance can be disposed of and replaced dynamically have a different set of requirements--hense they need a lookup mechanism.
To be fair the ComponentManager/ServiceManager concept was cooked up way back before J2EE and EJBs. We discussed adopting JNDI, but at the time there were disagreements over how to look up items bound to JNDI. Would "Context" items, "Configuration" values, and "Services" all be bound in there?
Avalon was born as a server side component framework, but it is perfectly comfortable on the desktop as well. Implementing a ServiceManager is very much easier than implementing a JNDI service provider.
The idea of using setters as a way to provide components is a very new concept. Personally, I don't like the approach because of the systems that I have had to maintain that were done with static accessors all over the place and other major set backs. So my bias is based completely on those negative experiences. I recognize that, and I see value in the setter approach as long as all your components are set once.
The ServiceManager has the concept of a defined set of time that a client has a hold of a component. You lookup() and release() components. This approach has the advantage of letting the container know without a doubt when it is safe to upgrade a component. It gets us philisophically closer to the 0 downtime system.
With a setter based system, you don't have those contracts, so the only safe thing is code for write-once. Which also means that you have to take special care to manage concurrency issues and balance the synchronization vs. stability within the system.
Imagine if you had a component like this:
EmailManager {
void logIn(String user, String password);
Message[] getMessages();
void sendMessage( Message message );
void deleteMessage( Message message );
void logOut();
}This component makes certain assumptions about the order the methods will be called. Now, let's assume that we don't have any synchronization issues to worry about. If at any time the container chooses to update the component implementation, we run the risk that it will be done in the middle of using it. For instance, we may have logged in, obtained our messages, and then the server upgrades the component with the setEmailManager(). Not only have we not logged out with the old component, we aren't logged in with the new component. When we call sendMessage() or deleteMessage() next, we will be in an unknown state.
That at least is the argument against the setters. Many systems are not that complex, and make many assumptions about the type of environment that the application will be run in. For instance, one assumption is one user, one thread, unchanging components. In this case, whatever you choose is a matter of personal taste.
If there is any potential for your system to grow into a mult-user, multi-threaded, dynamic system--the setter approach will become a hindrance. In fact there will need to be more esoteric magic that has to be performed to maintain the health of the system. The lookup approach of either ServiceManager or JNDI will be easier to handle these demanding requirements. JNDI doesn't make sense for smaller systems or embedded systems--so the happy medium we have is the ServiceManager.
It is neither right nor wrong, it is just the solution we have come up with. We are looking to make things work with other folk's component types such as Nano/Pico/Spring container type components. It is very possible to do with the existing modern Avalon containers. We just don't have a nice generic way of incorporating those features.
<snip/>
On a related note.. If you had this facade (?)/interface layer, then the various Activity lifecyle interfaces wouldn't need to be implmented. I could instead provide a mapping file that said: For my component, I do implement the Startable interface, I just didn't implement it, and my method is called "begin()". This would work for noarg methods especially well. Actually, I guess would this be a proxy?
This component proxy you are talking about is also a nice way to incorporate interceptors which make it easier to add new functionality to all components in the system.
--
"They that give up essential liberty to obtain a little temporary safety
deserve neither liberty nor safety."
- Benjamin Franklin
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
