Thursday, August 12, 2010

Spring property-placeholder with OSGi

Here are some notes on adding support for properties files to a project. I have it deployed as an OSGI bundle on Fuse ESB 4.2 (aka Apache ServiceMix), but it can be used in various containers/configurations. Anyways, here are the steps...

first, add these required Maven dependencies to your project...
<dependency>
  <groupid>org.springframework.osgi</groupid>
  <artifactid>spring-osgi-core</artifactid>
  <version>1.2.0</version>
</dependency>
<dependency>
  <groupid>org.springframework</groupid>
  <artifactid>spring-context</artifactid>
  <version>2.5.6.SEC01</version>
</dependency>

then, add the following spring XML..
<beans xmlns:context="http://www.springframework.org/schema/context"
            xmlns:osgi="http://www.springframework.org/schema/osgi"
            xmlns:osgix="http://www.springframework.org/schema/osgi-compendium"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns="http://www.springframework.org/schema/beans"
            xsi:schemalocation="
                http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd
                http://www.springframework.org/schema/osgi-compendium http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd">
    <osgix:cm-properties id="props" persistent-id="my.props">
        <prop key="property.name">default value</prop>
    </osgix:cm-properties>
    <context:property-placeholder properties-ref="props"></context:property-placeholder>
    <bean id="myBean" lass="com.company.MyClass">
        <property name="property" value="${property.name}"></property>
    </bean>
</beans>  

finally, create a properties file...
add a file called "my.props.cfg" to your container's classpath (/fuse/etc directory, etc) that contains key=value line separated properties...

tips on using this in practice...
  • the filename must match the <osgix:cm-properties> persistent-id attribute and end with ".cfg". also, avoid using dashes in the filename...
  • this will NOT work in unit tests, you'll need to override your spring XML file under /src/test/resources, remove references to osgi-compendium and hardcode the properties
another option altogether...use the SystemClassLoader
put your properties files in the /servicemix/conf/ directory (doesn't exist by default).  This is in a bundle's classpath and can be loaded as follows...
       
        try {
            Properties prop = new Properties();
            ClassLoader sysClassLoader = ClassLoader.getSystemClassLoader();
            InputStream is = sysClassLoader.getResourceAsStream("my.properties");
            prop.load(is);
        } catch (Exception e) {
            logger.error("error getting props->" + e);
        }

This won't leverage the osgi benefits, but is simple and will work for most cases...

1 comment:

  1. Useful stuff! For testing I'm parsing the spring xml file and replacing the reference to the osgix property loader with the regular spring property loader:

    http://hedleyproctor.com/2013/02/testing-camel-routes-with-spring-osgi-properties/

    ReplyDelete