Testing ServiceMix 4.3 services with PaxExam

In the project that I’m currently working on we are developing a set of extensions for ServiceMix – more or less some monitoring stuff. It’s pretty simple using SMX ExchangeListeners – you implement the interface, register it via Spring DM and voila – you have everything you need. But how are you going to test it? Of course, we write unit tests, and functional tests, but all of them are leaving NMR/OSGi stuff behind – you just don’t include osgi-beans.xml’s. This leaves us with untested code – my baaaaad ;) Fortunately, here comes a rescue – it’s PaxExam. It’s a framework for testing OSGi services in various containers – most notably felix & equinox. But making it play nicely with latest & greates ServiceMix 4.3 was not so easy – so I what to share it. I made a sample project, it’s on my 

github It consists of 2 modules: first contains service & listener under test, and the second one contains The Test. I won’t go into details about the service bundle – it’s just cxf-bc endpoint passing invocations to camel router, which sets output message. The listener is also very simple. The point is that we have 2 of most widely used smx components, with OSGi packaging and OSGi-config configuration. This leaves us with itests module. It’s core is BaseIntegrationTest, which contains Pax Exam configuration and some utility methods. Pax Exam configuration was the most difficult part for me. The reason is that servicemix consists of many, many dependant projects, each of them having own release cycle, and Pax Exam has it’s own. Anyway, here is what works for me (note – it’ll work with sun jdk 1.6 only I think). JUnit test (which is of course no unit test btw) using Pax Exam has to have static configuration method, which tells testing framework how to prepare container – which one, which parameters, which bundles to install. It looks like this: So, what should go into configuration method? First, we have to set up system packages. We have to exclude StAX API and some SOAP APIs from system packages: The system property “org.ops4j.pax.runner.platform.ee” tells PaxRunner where to look for system packages. I copied them from SMX distro – except that I had to add two Sun packages containing Schema and JAXP implementations – otherwise XPath & schema failed to work. Still, to make SchemaFactory work I had to manually add system property specifying implementation class. Next thing is rather standard PaxExam configuration: OSGi container, logging profile, spring and spring DM setup (note – you have to use 1.2 version, not the latest one): Two notes here. A profile is a set of bundles predefined to be used in PaxExam. Also note that we don’t use System.setProperty, but PaxExam DSL expression. The reason is that the OSGi container is run separately, so we have to distinguish system properties used to start it, and properties that will be accessible to bundles inside it. Then comes felix install configuration. I wanted to mimic SMX configuration conventions (files in etc dir, ended with .cfg), so I copied felixInstall configuration and add appropriate system properties. Note, that we set start level to 2. In Karaf deafatul start level is 60, in PaxRunner – it’s 5. But I decided to stay with Pax way – don’t have that many bundles to need so fine grained configuration. Now, karaf configuration. It’s also pretty standard, just remember that we need Aries bluepring in version 0.2-incubation, and not 0.1 (as PaxExam has it) or latest 0.3 Now, time for Servicemix components configuration. We’ll use nice PaxExam feature – feature scan. This means that we can specify Karaf features package, and PaxExam will install appropriate bundles. So, we choose servicemix features, specify servicemix-camel, camel-nmr and servicemix-cxf-bc, and …? And it turns out that servicemix-cxf-bc has unresolved dependencies :/ The reason is that it was (at least it seems so ;)) tested with full distro, which contains also activemq-blueprint feature. Since we don’t want activemq for our test setup, we’ll install required bundles manually: Now, everything is ready for the final step – installation of services bundle: mavenBundle(“pl.touk.smx4”, “paxExamSample-service”) To make testing easier I also created few util methods. Two interesting ones are: getBean and sendMessage. getBean uses ServiceTracker to get Spring/Blueprint bean registered as a OSGi service. Note, that it is done asynchronously – that’s why we need Thread.sleep for ServiceTracker. sendMessage wraps interaction with NMR – it creates inOut exchange, populates it and send synchronously via channel. Well… this setup is not particularly easy, but once we get through it, the tests look quite nice: This sends test message down the NMR, check that output is ok, and that it was caught by Listener. What’s left to do? You can see some nasty explicit dependencies in configuration – should be taken from maven. Next goal would also be to run SOAPUI tests for testing end to end interaction. But let’s leave it for next entry. To sum up: I think PaxExam is a great tool, although the setup is not so easy. Tests setup is quite long – actually it’s faster to build the service bundle and run update on Servicemix to see changes. That’s why I would rather recommend using PaxExam for regression tests, run on Hudson (whooops, Jenkins ;))

You May Also Like

Phonegap / Cordova and cross domain ssl request problem on android.

In one app I have participated, there was a use case:
  • User fill up a form.
  • User submit the form.
  • System send data via https to server and show a response.
During development there wasn’t any problem, but when we were going to release production version then some unsuspected situation occurred. I prepare the production version accordingly with standard flow for Android environment:
  • ant release
  • align
  • signing
During conduct tests on that version, every time I try to submit the form, a connection error appear. In that situation, at the first you should check whitelist in cordova settings. Every URL you want to connect to, must be explicit type in:
res/xml/cordova.xml
If whitelist looks fine, the error is most likely caused by inner implementation of Android System. The Android WebView does not allow by default self-signed SSL certs. When app is debug-signed the SSL error is ignored, but if app is release-signed connection to untrusted services is blocked.



Workaround


You have to remember that secure connection to service with self-signed certificate is risky and unrecommended. But if you know what you are doing there is some workaround of the security problem. Behavior of method
CordovaWebViewClient.onReceivedSslError
must be changed.


Thus add new class extended CordovaWebViewClient and override ‘onReceivedSslError’. I strongly suggest to implement custom onReceiveSslError as secure as possible. I know that the problem occours when app try connect to example.domain.com and in spite of self signed certificate the domain is trusted, so only for that case the SslError is ignored.

public class MyWebViewClient extends CordovaWebViewClient {

   private static final String TAG = MyWebViewClient.class.getName();
   private static final String AVAILABLE_SLL_CN
= "example.domain.com";

   public MyWebViewClient(DroidGap ctx) {
       super(ctx);
   }

   @Override
   public void onReceivedSslError(WebView view,
SslErrorHandler handler,
android.net.http.SslError error) {

String errorSourceCName = error.getCertificate().
getIssuedTo().getCName();

       if( AVAILABLE_SLL_CN.equals(errorSourceCName) ) {
           Log.i(TAG, "Detect ssl connection error: " +
error.toString() +
„ so the error is ignored”);

           handler.proceed();
           return;
       }

       super.onReceivedSslError(view, handler, error);
   }
}
Next step is forcing yours app to  use custom implementation of WebViewClient.

public class Start extends DroidGap
{
   private static final String TAG = Start.class.getName();

   @Override
   public void onCreate(Bundle savedInstanceState)
   {
       super.onCreate(savedInstanceState);
       super.setIntegerProperty("splashscreen", R.drawable.splash);
       super.init();

       MyWebViewClient myWebViewClient = new MyWebViewClient(this);
       myWebViewClient.setWebView(this.appView);

       this.appView.setWebViewClient(myWebViewClient);
       
// yours code

   }
}
That is all ypu have to do if minSdk of yours app is greater or equals 8. In older version of Android there is no class
android.net.http.SslError
So in class MyCordovaWebViewClient class there are errors because compliator doesn’t see SslError class. Fortunately Android is(was) open source, so it is easy to find source of the class. There is no inpediments to ‘upgrade’ app and just add the file to project. I suggest to keep original packages. Thus after all operations the source tree looks like:

Class SslError placed in source tree. 
 Now the app created in release mode can connect via https to services with self-signed SSl certificates.

Sygnalizacyjne ABC

Poniższy artykuł oparty jest na wspaniałej pozycji książkowej “System Sygnalizacji nr 7 G. Danielewicz, W.Kabaciński”. Gorąco zachęcam do…

HISE home page

Apache HISE has recenlty kickstarted and has a home page here: http://incubator.apache.org/hise/index.html.Apache HISE is Human Interactions Service Engine. It's an open source implementation of WS HumanTask specification.HISE proposal can be found her...Apache HISE has recenlty kickstarted and has a home page here: http://incubator.apache.org/hise/index.html.Apache HISE is Human Interactions Service Engine. It's an open source implementation of WS HumanTask specification.HISE proposal can be found her...