Testing Camel routes with Spring OSGi properties

If you are writing Camel routes using Spring to deploy to ServiceMix, you can’t use regular Spring properties, since ServiceMix is an OSGi container. Instead, you have to use OSGi properties. But if you try to start up your Spring context in a unit test, it will fail, since there is no OSGi environment. How can you get round this? One solution is for your tests to load the spring xml as an xml file before they instantiate the spring context. That way, they can replace the OSGi references with a regular spring property loader. Let’s see what this looks like.

In my Spring file I’ve got the OSGix namespace:

xmlns:osgix="http://www.springframework.org/schema/osgi-compendium"

Then an OSGix property loader, and a regular property placeholder that references it:

<osgix:cm-properties id="props" persistent-id="claimsExport"/>
<context:property-placeholder properties-ref="props"/>

In my test code, I have the following helper method:

public static String replaceOSGiPropertyLoader(String springXmlLocation) 
    throws ParserConfigurationException, IOException, 
    SAXException, XPathExpressionException, TransformerException {
    log.info("Removing Spring osgix property loader");
    DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    File springFile = new File(springXmlLocation);
    Document doc = builder.parse(new InputSource(new FileInputStream(springFile)));
    // find the osgix properties bean
    XPath xpath = XPathFactory.newInstance().newXPath();
    Node osgiProps = (Node) xpath.evaluate("/beans/cm-properties",doc, XPathConstants.NODE);
    // remove it
    // first get the root node
    Node beanNode = doc.getFirstChild();
    // remove the child
    beanNode.removeChild(osgiProps);
    // now adjust the spring properties bean to load the props directly from the file
    Element propertyPlaceholder = (Element) xpath.evaluate("/beans/property-placeholder",doc, XPathConstants.NODE);
    // remove the ref to the osgi bean
    propertyPlaceholder.removeAttribute("properties-ref");
    // add a reference directly to the file that has the properties in
    propertyPlaceholder.setAttribute("location","classpath:claimsExport.cfg");
 
    // now write out the resultant xml
    Transformer transformer = TransformerFactory.newInstance().newTransformer();
    StringWriter writer = new StringWriter();
    transformer.transform(new DOMSource(doc),new StreamResult(writer));
    // return the string representation of the spring xml file
    return writer.toString();
}

The OSGix property loader loads properties from a file with a name that matches its persistent id. In this case, the file is called claimsExport.cfg. You can see that the helper method simply updates the Spring property placeloader to load the properties directly from that file.

You can use the code as:

String springXml = replaceOSGiPropertyLoader("your-path/app-context.xml");
springContext = new GenericXmlApplicationContext(new ByteArrayResource(springXml.getBytes("utf-8")));

Thanks to Ben Oday’s blog for telling me about the spring osgix property loader.

This entry was posted in Camel, Java, Spring and tagged , . Bookmark the permalink.

2 Responses to Testing Camel routes with Spring OSGi properties

  1. Alex says:

    It is very tricky solution…
    There is simplier and more convinient solution.
    You can move osgix:cm-properties definition to separate file under META-INF/spring folder. I hope you know that all contexts under META-INF/spring are started when bundle starts.
    And for tests you can use separate context with only util:properties in it.
    But all beans definition will be in your initial context. So for test you`ll use both of them.

Leave a Reply

Your email address will not be published. Required fields are marked *

502,303 Spambots Blocked by Simple Comments

HTML tags are not allowed.