Category Archives: Spring

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

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.

Selects are IN

Today it will be short. I will write about one small Spring feature that I have discovered recently. It is another nice functionality of SimpleJdbcTemplate.

Imagine that you want to find all account with given account numbers. Since we want to gain maximal performance we want to do it in one SQL statement.

SELECT ACCOUNT_NUMBER, BALANCE FROM ACCOUNT WHERE ACCOUNT_NUMBER IN (?, ?)

Using Spring it is easy. The only trouble is, that I do not know number of account numbers beforehand. Therefore I do not know the number of question marks needed in the SQL query. Of course I can create the statement dynamically using string manipulation, but the code would be messy. Fortunately Spring comes to rescue. If I use named parameters in SimpleJdbcTemplate, Spring will automatically do everything for me. So the code will be nice and simple as it should be

	public List<Account> findAccounts(Set<String> accountNumbers)
	{
		return getSimpleJdbcTemplate().query(
				"SELECT ACCOUNT_NUMBER, BALANCE FROM ACCOUNT WHERE ACCOUNT_NUMBER IN (:accountNumbers)",
				ACCOUNT_ROW_MAPPER,
				Collections.singletonMap("accountNumbers", accountNumbers)
		);
	}

Nice, isn’t it? Source code can be found in SVN. More details are in the Spring documentation.

Simple JDBC template

Občas se mi stane, že nepotřebuji celou tu mašinérii kolem ORM. Chci jenom přistupovat do databáze. Zavolat pár insertů a pár selectů. V té chvíli přichází na řadu JDBC. Je samozřejmě možné používat JDBC přímo, ale jak říká Rod Johnson, je to „sackable offence“. (česky asi důvod k vyhazovu). Zvládnout bez chyby všechny ty try, catche, finally, zavírání connection, result setů a kdoví čeho ještě je jen pro zkušené a velmi disciplinované vývojáře. Spring odjakživa poskytoval rozhranní JdbcTemplate, které krásně usnadňovalo volání JDBC a staralo se o všechnu tu nudnou a nebezpečnou práci se správou zdrojů. Chybělo mi tam ale několik věcí. První z nich bylo pojmenování parametrů jak je známe třeba z HQL. Prostě jsem místo všech těch otazníků v query chtěl psát jména parametrů. Chybělo mi také lepší provázanost s Javou 5 a generiky. (To mi mimochodem dost chybí i u JPA query, která je novější než Java 5).

Nevím jestli se vám to také děje. Já když už umím nějakou technologii, tak se mi občas stane, že mi její zajímavé novinky občas uniknou. Podobně mi uniklo zavedení SimpleJdbcTemplate do Springu 2.0. SimpleJdbcTemplate totiž všechny mé stesky řeší. Nejlépe si to ukážeme na příkladě (ten je převzatý z mého skvělého a nepostradatelného projektu MvnIndex.org, který si teď všichni povinně stáhnete a začnete ho používat, nebo se naštvu a už nikdy nic podobného nenapíšu).

Nejlepší je naimplementovat DAO, které rozšiřuje SimpleJdbcDaoSupport. Tím si ušetříme spoustu práce, stačí nám už jen injektnout do této třídy DataSource. Pak už máme k dispozici SimpleJdbcTemplate a můžeme si dovolit například takovéto volání:



  public List<BasicArtifactInfo> searchArtifacts(String searchExpression, PagingInfo pagingInfo) {
    Map<String,Object> args = new HashMap<String, Object>();
    args.put("searchExpression""%"+searchExpression+"%");
    args.put("from", pagingInfo.getFrom());
    args.put("size", pagingInfo.getSize());
    return getSimpleJdbcTemplate().query(
          "select distinct group_id, artifact_id from ARTIFACT where artifact_id like :searchExpression or group_id like :searchExpression order by if(group_id like :searchExpression, 0, 1), group_id, artifact_id limit :from, :size"
          BASIC_ARTIFACT_INFO_MAPPER , 
          args);
  }

Vidíme že atributy dotazu dáme jednoduše do mapy, zavoláme dotaz, poskytneme mapovač výsledků a je to. V dotazu můžeme použít jména parametrů stejně jako to známe z HQL. Takže můžeme například psát „... where artifact_id like :searchExpression or group_id like :searchExpression...“. Pro mapování výsledků musíme implementovat jednoduché rozhraní ParameterizedRowMapper.



  private static final ParameterizedRowMapper<BasicArtifactInfo> BASIC_ARTIFACT_INFO_MAPPER = new ParameterizedRowMapper<BasicArtifactInfo>(){
    public BasicArtifactInfo mapRow(ResultSet rs, int rowNumthrows SQLException {
      return new BasicArtifactInfo(rs.getString("group_id"), rs.getString("artifact_id"));
    }
  };

Vidíme, že generika jsou tu plně podporována, takže si nemusíme dělat hlavu s přetypováváním, varováními překladače atp. Super ne? A to jsem zapomněl na to hlavní. Spring se mi postará o vytvoření PreparedStatementů, správu transakcí, mapování vyjímek a prostě o všechno na co jsme od něj zvyklí.

Takže pokud je pro vás Hibernate moc těžkopádný a nechcete se učit iBatis, pokud chcete jen volat JDBC, zkuste se podívat na SimpleJdbcTemplate, stojí to za to.

Celou třídu si můžete prohlédnout v SVN.