Author: David Le Strat
Company: Home

DRAFT

Proposal for Jetspeed 2 Service Framework

Introduction:

“Inversion of Control is about software components doing what they are told, when they are told. Your OO application could well become unmaintainable without it.”
Paul Hammant, ThoughtWorks

The purpose of Inversion of Control (IoC) is to promote the use of interfaces instead of classes and therefore produce much cleaner and maintainable code.  The goals of a service framework leveraging IoC are to make:

•	Testing become easy,
•	Maintenance become easy,
•	Configuration become easy,
•	Reuse become easy.

As part of Jetspeed 2 redesign, it is paramount to select a service framework that will provide Jetspeed with a flexible and non intrusive foundation.

Goals of J2 Service Framework:

Jetspeed 2 service framework goals should be:

•	Non-intrusive service framework which requires as little as possible framework specific code.
o	Provide a framework that support an interface and its implementation without framework specific code involved.
•	A framework that can be extended to provide:
o	Transparent JMX support of deployed modules.
o	Hot deployment and configuration.
•	A framework that allows deploying self contained components/ self configurable components.
•	The service framework can be extended to enable components as web services.
•	The service framework can be extended to provide performance monitoring of components.

Proposed Service Framework:

A combination of Picocontainer and Aspect Oriented Programming.  When service orchestration is required, Cornerstone could be used as the orchestration framework.

1. Why Picocontainer?

PicoContainer is the simplest container for IoC:
•	Pico implements IoC type 3 – constructors.
•	Pico components are assembled by registration.
•	Pico components can optionally implement lifecycle methods (start, stop, dispose)

PicoContainer can be easily wrapped with a service manager to provide configurable components.  Services could therefore follow the structure:

•	MyService
o	src
•	api
•	impl
o	conf
•	jetspeed-service.xml

Which would get deployed as:

•	MyService
o	META-INF
•	jetspeed-service.xml
o	org.apache.jetspeed

The service manager can be a singleton object responsible for instantiating the various services or leverage Aspect Oriented Programming (see below).

2. Differences with Other Service Frameworks

IoC type 0 – No IoC

public class Girl implements Servicable {
Kissable kissable;

public void service(ServiceManager mgr) {
kissable = new Boy();
}

public void kissYourKissable() {
kissable.kiss();
}
}

•	No meta data, but the dependencies cannot be changed.

IoC type 1 - Avalon

public class Girl implements Servicable {
Kissable kissable;
public void service(ServiceManager mgr) {
kissable = (Kissable) mgr.lookup(“kissable”);
}

public void kissYourKissable() {
kissable.kiss();
}
}

<container>
<classloader>
<classpath> … </classpath>
</classloader>
<component name=“kissable“ class=“Boy">
<configuration> … </configuration>
</component>
<component name=“girl" class=“Girl" />
</container>

•	Dependencies are fetched from a ServiceManager and hooked up with meta-data.
•	In the case of Avalon, the container must be loaded for to access services outside the Avalon container.
•	The class must implement any of the lifecycle interfaces.  A component cannot be looked up without loading the container up.  To so extent intrusive.

IoC type 2 – Spring

public class Girl {
Kissable kissable;

public void setKissable(Kissable kissable) {
this.kissable = kissable;
}

public void kissYourKissable() {
kissable.kiss();
}
}

<beans>
<bean id=“boy" class=“Boy"/>
<bean id=“girl“ class=“Girl">
<property name=“kissable">
<ref bean=“boy"/>
</property>
</bean>
</beans>

•	Dependencies provided by JavaBean setters.  Meta-data is needed.

Ioc type 3 – Pico

public class Girl {
Kissable kissable;

public Girl(Kissable kissable) {
this.kissable = kissable;
}

public void kissYourKissable() {
kissable.kiss();
}
}

A ServiceManager singleton loads up the components:

PicoContainer container = new DefaultPicoContainer();
container.registerComponentImplementation(clazz);

The ServiceManager provide access to the service.

Girl girl = (Girl)
ServicesManager.getInstance().getService(Girl.class);

•	Minimal metadata is required, interface are recommended but not required.
•	The implementation dependencies on the framework are minimized.
•	JMX and aspect integrations are provided through Nanocontainer.

Ioc type 3 – Hivemind (IP Issues)
Though a great potential candidate, Hivemind has not been evaluated given the on-going Intellectual Property issue.

Cornerstone:

A service orchestration framework.

•	One method per “Service”

public String invokeDirect(String timeZone,
String dateStyle) throws ServiceException
{
…
}

•	Service invocation based on configuration of service:

Service =
Cornerstone.getServiceManager()
.createServiceByName(serviceName);
context = new BaseContext();
context.setValue("tz102", "GMT-0800");
context.setValue("tz103", "GMT+0800");
context.setValue("df103", DateService.DATE_FORMAT_SHORT);
String lastDateString = (String) service.invoke(context);

•	Service configuration defines the sequence and the parameters.

•	Cornerstone customization vision is real but intrusive.  Could it be used to orchestrate Pico services when needed?
•	Integrated with JMX.

3. The Use of AOP.

AOP could be used to greatly enhanced the flexibility of J2.  Examples of possible aspects are:

•	Logging aspect (http://aspectwerkz.codehaus.org/examples_2.html#Logging): To log method entry point and exit points.
http://www.developer.com/java/other/article.php/10936_3109831_1
•	Caching aspect (http://aspectwerkz.codehaus.org/examples_2.html#Caching). To cache rendered portlets.
•	Security aspect (http://blogs.codehaus.org/people/jboner/) leveraging JAAS to authenticate and authorize user to use portal resources.

4. Pico and AOP Combined.

AOP can be used to intercept the invocation of the class constructor and return the service.  Basically doing ServicesManager.getInstance().getService(clazz); when the constructor is invoked.

See:
•	http://wiki.codehaus.org/picocontainer/UseScriptingToWireAndConfigureComponents
•	http://www.jroller.com/page/tirsen
•	http://lists.codehaus.org/pipermail/picocontainer-dev/2003-September/001090.html
•	http://lists.codehaus.org/pipermail/picocontainer-dev/2003-August/000957.html

The 2 solutions combined provide a great amount of flexibility.

Code sample with AspectJ:

privileged public aspect ConfigureServiceManager
{
	public pointcut createServiceManager(ServiceManager manager) : 
		execution (protected ServiceManager.new()) 
		&& this(manager);

	after(ServiceManager manager) : createServiceManager(manager)
	{
		final MutablePicoContainer container =
			manager._container; 

		container.registerComponentImplementation(
			Dispatcher.class,
			SMTPDispatcher.class); 
		container.registerComponentImplementation(
			MailerService.class);
	}
}