Archive for the ‘Articles in English’ Category

Spring field injection

Tuesday, June 17th, 2008

Few weeks ago, I worked on an interesting task. I had to find out how to migrate my customer’s proprietary framework to Spring. The framework was quite similar to Spring, although there were some differences. They used combination of XML and annotation configuration. Every property had special annotation saying that it is a property. XML schema for configuration was generated based on this annotation. So basically you had XML configuration that said what to inject to the annotated fields. The problem was that they did not have set methods for the fields.

And of course, the customer did not want to change all their classes just to migrate to Spring. It meant that they needed configure all the beans using Spring, but inject the dependencies directly, not through set methods.

I know that it is ugly and not recommended but in this case I think I have good excuse. It is a customer’s requirement. The question of course is how to do it.

You can try to use Spring post-processor. If you register instance of InstantiationAwareBeanPostProcessor you can use method postProcessPropertyValues to manipulate with property values just before Spring attempts to inject them. So you can inject the values into fields by yourself. And it works. The trouble is that you have to do property instantiation and conversion by yourself too. I almost managed to do it when I encountered a big problem - inner beans. In Spring, you can define a bean inside another bean. In order to inject the inner bean to the outer bean, the inner bean has to be already instantiated. But postProcessPropertyValues method is called before inner bean instantiation. So that is a blind alley.

OK, post-processor can not be used, let’s do it more hard-core. Spring has something called BeanWrapper. It is used by Spring for setting bean properties. Great, that is the point where I can force Spring to inject into the fields. The only thing I need to do, is to inject my BeanWrapper implementation into Spring. There is only one small trouble. It is not possible to do it. Unsurprisingly, dependency injection does not work inside the dependency injection code. I tried hard, but did not find any simple and safe way how to replace default BeanWrapper implementation. (If you know how to do it, please let me know)

So, if it is not possible to force Spring to inject without set method, let’s give him what he is asking for. The final solution is simple. When instantiating beans, I do not instantiate the original class but a subclass that is generated in the runtime and has all needed set methods. For the class generation I use Javassist, it is simple and powerful. To make the integration with Spring as simple as possible, I use factory bean. So the Spring XML config file looks like this

	<bean id="beanFactory" class="net.krecan.beanfactory.SetMethodGeneratingBeanFactory"/>
	<bean id="sampleClass"
		      factory-bean="beanFactory"
		      factory-method="createBean">
		<constructor-arg value="net.krecan.beanfactory.Sample"/>
		<property name="textProperty" value="test.txt"/>
		<property name="intProperty" value="123"/>
		<property name="simpleSample">
			<bean factory-bean="beanFactory"
			   factory-method="createBean">
				<constructor-arg value="net.krecan.beanfactory.SimpleSample"/>
				<property name="textProperty" value="hallo"/>

			</bean>

		</property>
	</bean>

Instead of providing class name in the bean definition, factory-bean attribute is used. Spring than calls method createBean on the factory bean with parameter taken from the constructor-arg element. It contains the class name of the bean. The result of the method call is used as a bean instance and all the properties are set by Spring.

Of course, you do not have to write it this way every time you want to instantiate this kind of bean. Simple custom namespace can be created in order to simplify the syntax.

In the future, when my customer realize that setters are a good thing, the factory can be easily replaced by a dummy implementation.

To reiterate, direct injection of dependencies from XML to the fields without using set methods is not supported by Spring. You can choose between XML based configuration using set methods or annotation based configuration. It is extremely hard to change default Spring behavior. And maybe it is a good thing. So if you need to do ugly XML based field injection, your only choice is to generate set methods in the runtime. Or maybe something else, but I have no idea what.

(more…)

Let’s play with OSGi, Spring and Maven, part 2

Sunday, June 1st, 2008

In the first part of this article, we have finished and tested DAO part of the application. Today we are going to create the UI and connect all the parts using Service bundle.

If you think about it, you realize that UI bundle is exactly the same as the DAO bundle. It only exports a service. In this case it implements DataReceiver interface from the Common bundle. Therefore, pom.xml, generated MANIFEST.MF file and Spring configuration file will be similar to that we have seen in part 1. So I will skip this bundle and jump directly to the Service layer.

In the Service bundle we want to use both DAO and UI. We want to periodically pull the data from the DataLoader and push them to the DataReceiver service.

Let’s start with bundle metadata.

	<plugin>
	    <groupId>org.apache.felix</groupId>
	    <artifactId>maven-bundle-plugin</artifactId>
	    <extensions>true</extensions>
	    <configuration>
	    	<instructions>
	    	 <Private-Package>
	    	    net.krecan.spring.osgi.service.*
	    	 </Private-Package>
	    	</instructions>
	    </configuration>
	  </plugin>

This configuration of the Maven OSGi plugin is going to generate following MANIFEST.MF file.


Manifest-Version: 1.0
Bundle-Name: demo-spring-osgi-service
Build-Jdk: 1.5.0_15
Built-By: lukas
Created-By: Apache Maven Bundle Plugin
Private-Package: net.krecan.spring.osgi.service
Import-Package: net.krecan.spring.osgi,org.apache.commons.logging
Bundle-ManifestVersion: 2
Bundle-SymbolicName: net.krecan.spring-osgi.demo-spring-osgi-service
Tool: Bnd-0.0.255
Bnd-LastModified: 1212320410936
Bundle-Version: 1.0.0.SNAPSHOT

You can see that we do not export any package. It is not needed. Service bundle only coordinates DAO and UI, it does not need to expose anything.

Import-Package directive is more interesting. Maven plugin analyzed Java classes and figured out that import of net.krecan.spring.osgi and org.apache.commons.logging package is needed. The first one is exported by our Common bundle, the other one is provided by the commons-logging package. Great, I do not have to specify dependencies by hand, Maven plugin does it automatically.

OK, OSGi is configured, we can try to use our services. Again, I will use Spring OSGi integration. I will create following Spring XML configuration in the META-INF/spring directory of the Service bundle

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>

	<osgi:reference id="dataLoader" interface="net.krecan.spring.osgi.DataLoader"/>

	<osgi:list id="receivers"  interface="net.krecan.spring.osgi.DataReceiver"/>

	<bean id="dataDistributor" class="net.krecan.spring.osgi.service.DataDistributor">
		<property name="dataLoader" ref="dataLoader"/>
		<property name="receivers" ref="receivers"/>
	</bean>

	<!-- Timer config -->
	...	

</beans>

(Full version can be downloade here)

By osgi:reference element we say, that we want to find a service that implements DataLoader service. If such service is running in the OSGi engine, we can use the reference as a Spring bean with ID “dataLoader”. So we can inject it to the dataDistributor bean like any other Spring bean. That is great. The source code is not bound to OSGi at all. If you wish, you can switch form OSGi to a simple deployment, to remote invocation, web service or whatever you want. The source code will remain unchanged. The only thing we need to change is the configuration.

Do you wonder what happens, if there is no DataLoader service running? The answer is simple. Service bundle will wait for it. When DataLoader became available, the Service bundle will start to pull data from it. (This behavior can be changed by the cardinality attribute)

osgi:list element is similar to osgi:reference. It supports multiple references. It implements normal java.util.List. Again, we can inject it to an ordinary Spring bean. Moreover, the list is magic. If new service with given interface appears in the OSGi container, it is automagically added to the list. So I do not have to care about it.

The rest of the Spring config is not connected with OSGi. It just starts timer job that calls dataDistributor.loadAndSend method every 100ms.

And now we can test it. We will again use Spring OSGi support for integration tests. First of all, we have to say which bundles we are going to use.

	protected String[] getTestBundlesNames() {
		return new String[] {
			"net.krecan.spring-osgi, demo-spring-osgi-dao, "+DEMO_VERSION,
			"net.krecan.spring-osgi, demo-spring-osgi-ui, "+DEMO_VERSION,
			"net.krecan.spring-osgi, demo-spring-osgi-service, "+DEMO_VERSION,
		};
	}

And now we can run the test.

	public void testAddUi() throws InterruptedException, BundleException, IOException
	{
		Thread.sleep(500);
		LOG.info("Starting alternative UI");
		Resource bundleResource = locateBundle("net.krecan.spring-osgi, demo-spring-osgi-ui-alternative, "+DEMO_VERSION);
		Bundle bundle = bundleContext.installBundle(bundleResource.getURL().toString());
		bundle.start();
		LOG.info("Alternative UI started");
		Thread.sleep(500);
		LOG.info("Stopping alternative UI");
		bundle.stop();
		LOG.info("Alternative UI stopped");
		Thread.sleep(500);

	}

To make it more interesting, we will run the test for 500ms and then we will add and start alternative UI bundle. After another 500ms we will stop the alternative UI bundle again. It will result into following log output.

2008-06-01 14:33:55,818 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:55 CEST 2008 )
2008-06-01 14:33:55,908 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:55 CEST 2008 )
2008-06-01 14:33:56,009 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:56 CEST 2008 )
2008-06-01 14:33:56,108 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:56 CEST 2008 )
2008-06-01 14:33:56,209 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:56 CEST 2008 )
2008-06-01 14:33:56,308 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:56 CEST 2008 )
2008-06-01 14:33:56,317 INFO [net.krecan.spring.osgi.dao.ServiceOsgiTest] {main} - Starting alternative UI
2008-06-01 14:33:56,384 INFO [net.krecan.spring.osgi.dao.ServiceOsgiTest] {main} - Alternative UI started
2008-06-01 14:33:56,408 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:56 CEST 2008 )
2008-06-01 14:33:56,508 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:56 CEST 2008 )
2008-06-01 14:33:56,508 INFO [net.krecan.spring.osgi.ui.alternative.AlternativeDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:56 CEST 2008 )
2008-06-01 14:33:56,609 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:56 CEST 2008 )
2008-06-01 14:33:56,609 INFO [net.krecan.spring.osgi.ui.alternative.AlternativeDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:56 CEST 2008 )
2008-06-01 14:33:56,708 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:56 CEST 2008 )
2008-06-01 14:33:56,708 INFO [net.krecan.spring.osgi.ui.alternative.AlternativeDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:56 CEST 2008 )
2008-06-01 14:33:56,809 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:56 CEST 2008 )
2008-06-01 14:33:56,809 INFO [net.krecan.spring.osgi.ui.alternative.AlternativeDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:56 CEST 2008 )
2008-06-01 14:33:56,884 INFO [net.krecan.spring.osgi.dao.ServiceOsgiTest] {main} - Stopping alternative UI
2008-06-01 14:33:56,909 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:56 CEST 2008 )
2008-06-01 14:33:56,909 INFO [net.krecan.spring.osgi.ui.alternative.AlternativeDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:56 CEST 2008 )
2008-06-01 14:33:57,009 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:57 CEST 2008 )
2008-06-01 14:33:57,009 INFO [net.krecan.spring.osgi.ui.alternative.AlternativeDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:57 CEST 2008 )
2008-06-01 14:33:57,101 INFO [net.krecan.spring.osgi.dao.ServiceOsgiTest] {main} - Alternative UI stopped
2008-06-01 14:33:57,108 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:57 CEST 2008 )
2008-06-01 14:33:57,209 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:57 CEST 2008 )
2008-06-01 14:33:57,311 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:57 CEST 2008 )
2008-06-01 14:33:57,409 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:57 CEST 2008 )
2008-06-01 14:33:57,509 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:57 CEST 2008 )
2008-06-01 14:33:57,614 INFO [net.krecan.spring.osgi.ui.DefaultDataReceiver] {timerFactory} - ***** Received data: Data ( text = Hallo Sun Jun 01 14:33:57 CEST 2008 )

It looks exactly how it should. Messages from the alternative UI appear and then disappear together with corresponding bundle. That’s what OSGi is all about. It enables dynamic binding of components. We can replace or plug-in services dynamically in the runtime.

To reiterate. Today we have seen OSGi in action. We have connected several services using Spring support and we have seen dynamic nature of OSGi. And what’s the best, our source code is not aware of OSGi. What a nice example of dependency injection.

Next time, we will try to play a bit with the example. I want to run it standalone, without Spring integration testing support and I’d like to test how it is resistant to class loader leaks.

Source code is accessible in here.

Let’s play with OSGi, Spring and Maven, part 1

Thursday, May 29th, 2008

In programming every problem can be solved by adding another layer of abstraction

Today, I am going to write about my experiments with OSGi. Please, be aware that I do not know OSGi. Moreover, I am too lazy to learn it. But I know Spring and Maven quite well, so I will use them quite extensively.

I will try to implement following sample application

Sample application

We will have 5 bundles in total. Bundle is basic building block when working with OSGi applications. Please, read the OSGi documentation for more details.

We will have the Common bundle, which is quite simple passive bundle. It contains DataLoader and DataReceiver interfaces and Data object. This bundle does not provide any service, but every other bundle has compile-time dependency on it.

DAO bundle provides DataLoader service implementation. Please, imagine that there is some really cool data access logic.

UI bundle provides DataReciver service implementation. Again, we will pretend that there is something more sophisticated than printing to the console. To make the example more interesting, we will have two different implementations of the UI.

And in the middle of the application sits Service bundle that loads data from the DAO layer and propagates them to the UI layer.

Before diving into the code, I want to point out one interesting thing. If you look at the picture, you will see red and black arrows. Black arrows represent compile-time dependencies. Basically it means, that when I want to compile UI, Service and DAO, I have to have Common jar in the classpath. But I do not need to have there any other bundle. It means, that the bundles are really decoupled. They just do not need to know about each other. They are independent. Do you understand? That’s the modularity we are looking for. The only thing the bundle needs to know is the interface of the service. Did I already mention that the bundles are independent? If not, I am saying it right know. They are independent.

The red arrows are run-time dependencies. That’s what OSGi framework is for. It will find for us the implementations of the interfaces (services) and will connect them together.

DAO service

So lets dive to the code. We will start with the DAO service. OSGi uses MANIFEST.MF file for defining its meta-data. Since I am to lazy to write it, I will use Maven plugin to generate it for me.

<plugin>
	<groupId>org.apache.felix</groupId>
	<artifactId>maven-bundle-plugin</artifactId>
	<extensions>true</extensions>
	<configuration>
		<instructions>
		 <Export-Package>
		 	net.krecan.spring.osgi
		 </Export-Package>
		 <Private-Package>
		 	net.krecan.spring.osgi.*
		 </Private-Package>
		</instructions>
	</configuration>
</plugin>

As you can see, I am using Apache Felix plugin for Maven. It generates following MANIFEST.MF file for me.


Manifest-Version: 1.0
Export-Package: net.krecan.spring.osgi
Private-Package: net.krecan.spring.osgi.dao
Built-By: krel
Tool: Bnd-0.0.255
Bundle-Name: demo-spring-osgi-dao
Created-By: Apache Maven Bundle Plugin
Bundle-Version: 1.0.0.SNAPSHOT
Build-Jdk: 1.6.0_03
Bnd-LastModified: 1211919191482
Bundle-ManifestVersion: 2
Import-Package: net.krecan.spring.osgi
Bundle-SymbolicName: net.krecan.spring-osgi.demo-spring-osgi-dao

It says that I am importing package net.krecan.spring.osgi. That’s the package where the interfaces are defined in. And I am exporting this package again, since I am publishing implementation of one of the interfaces. (Well, I am not sure if its true, but it did not work, when this package was not exported.) All other packages are private. It means, that they can not be used be other bundles. Wow, it is something like Java 7 superpackages.

Ok, OSGi is almost configured, the only think we need to do is to define the service. But again, I am to lazy to learn OSGi. What to do? What about Spring?. Spring provides support for OSGi. So I can export whatever Spring bean I want as an OSGi service. The only think I have to do, is to put following XML file into META-INF/spring directory.

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>

	<osgi:service ref="dataLoader"
		interface="net.krecan.spring.osgi.DataLoader" />

	<bean id="dataLoader"
		class="net.krecan.spring.osgi.dao.DefaultDataLoader" />
</beans>

(Full version can be downloade here)

I am publishing dataLoader bean as an implementation of DataLoader interface. Later on, when some other bundle will look for the service, it will just say, that it wants implementation of this interface and OSGi will find it.
And that’s it. I have created my first OSGi bundle. What? You do not believe that it works? Ok, I will test it using Spring OSGi testing support. We will write simple integration test.

package net.krecan.spring.osgi.dao;

import net.krecan.spring.osgi.DataLoader;

import org.osgi.framework.ServiceReference;
import org.springframework.osgi.test.AbstractConfigurableBundleCreatorTests;
import org.springframework.osgi.test.platform.Platforms;

/**
 * Tests the DAO bundle.
 * @author Lukas Krecan
 *
 */
public class DaoOsgiTest extends AbstractConfigurableBundleCreatorTests {

private static final String DEMO_VERSION = "1.0-SNAPSHOT";

	protected String getPlatformName() {
		   return Platforms.FELIX;
	}

	protected String[] getTestBundlesNames() {
		return new String[] {
			"net.krecan.spring-osgi, demo-spring-osgi-dao, "+DEMO_VERSION,
		};
	}

	/**
	 * The superclass provides us access to the root bundle
	 * context via the 'getBundleContext' operation
	 */
	public void testOSGiStartedOk() {
		assertNotNull(bundleContext);
	}

	public void testGetDataLoader() throws Exception {
		ServiceReference ref = bundleContext.getServiceReference(DataLoader.class.getName());
        assertNotNull("Service Reference is null", ref);
        try {
        	DataLoader dataLoader = (DataLoader) bundleContext.getService(ref);
            assertNotNull("Cannot find the service", dataLoader);
            assertNotNull("Data are null", dataLoader.loadData());
        } finally {
            bundleContext.ungetService(ref);
        }
	}
}

The test extends AbstractConfigurableBundleCreatorTests which takes care of starting OSGi engine (Apache Felix in this case) and loading all necessary bundles. The only think we have to specify is the name of the bundle under test. (The test loads the bundles from the local Maven repository by default.) We can than test whether the bundle is started and the service is running.

That’s all for today, in the next part we will discuss UI bundle and the service bundle. I will be glad for any feedback, so if you will spot any mistake in the text, please let me know. Of course I accept the compliments as well.

Source code is accessible in here.