Posts in the ‘java’ Category

One of the joys of using the bemokoLive development framework is the ease with which you can integrate with external content services.  I’ve recently been working on a site which needs consume a .NET generated webservice.

For this integration, I decided to use GroovyWS which provides a very nice interface to the world of Apache CXF.    Setting up the webservice is simplicity itself:

proxy = new WSClient(WSDL URL, this.class.classLoader)
proxy.initialize()

This was all going well until I tried to use the login webservice call.  The login provides a token which is needed to authenticate all further calls to the webservice.  The XML returned from the webservice is:

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <AuthHeader xmlns="https://app.restaurantdiary.com/webservices/ReservationService/">
      <Token>string</Token>
    </AuthHeader>
  </soap:Header>
  <soap:Body>
    <LoginResponse xmlns="https://app.restaurantdiary.com/webservices/ReservationService/" />
  </soap:Body>
</soap:Envelope>

Notice that the token is returned in the SOAP header, not the SOAP body.  It seems that CXF is geared up for reading the body of the message only, getting to the headers is not simple.  So my problem was being able to get the token and add it to further calls.

I tried many searches of the internet, but it seems that either no one has ever had to do this or they have and didn’t write about it.  Hopefully the following example will help if you ever need to do this.  The following example is in Groovy.

Before I get to the actual example, let me take a quick diversion, but useful, diversion on logging.

I spent hours trying to see the SOAP request and response that was being sent and received, using network sniffers and the like.  Communicating over SSL also meant I was doomed to failure.  Then I discovered interceptors, notably the LoggingInInterceptor and the LoggingOutInterceptor.  This simple piece of code allowed me to log the incoming and outgoing requests

proxy.client.getInInterceptors().add(new org.apache.cxf.interceptor.LoggingInInterceptor())
proxy.client.getOutInterceptors().add(new org.apache.cxf.interceptor.LoggingOutInterceptor())

I still didn’t have my AuthHeader though.  After a lot of experimenting, I found I could access the headers with this piece of code

def headerList = proxy.client.getResponseContext().get(Header.HEADER_LIST)

This was good.  Accessing the auth token was fairly simple after that:

SoapHeader sh = headerList[0]
 def doc = sh.getObject()
 def list = doc.getElementsByTagName("Token")
 token = list.item(0).getFirstChild().getNodeValue()
 log.debug("Token = " + token)

Yay, token now safely stored in my variables…. Now to add the token to future headers

List<Header> headers = new ArrayList<Header>();
SOAPFactory sf = SOAPFactory.newInstance()
def authElement = sf.createElement(new
QName(namespace, "AuthHeader"))
def tokenElement = authElement.addChildElement("Token")
tokenElement.addTextNode(token)
SoapHeader tokenHeader = new SoapHeader(new QName(namespace, "AuthHeader"), authElement);
headers.add(tokenHeader);
proxy.client.getRequestContext().put(Header.HEADER_LIST, headers)

This code adds the auth header with the token into the SOAP headers for every future request.

Hopefully if you are trying to use SOAP headers with CXF, this post will save you some time.

Posted in: java, mobile No Comments

Well we finally got around to upgrade all our unit tests to new features. About time really!

We use maven and the maven-surefire-plugin for running our unit tests during our build process. Let’s look at the steps I did to get migrate.

  • All our test cases extend from a single abstract test case class called AbstractLiveTestCase that in our Junit 3 integration extended from junit.framework.TestCase. For Junit 4, tests are described with annotations so we don’t need to extend this class anymore – so I (1) removed the “extends TestCase” from our AbstractLiveTestCase
  • The Junit 3 TestClass class used to provide all the handy assert functions. These are now provided as org.junit.Assert static methods so I went through each of our tests and (2) added “import static org.junit.Assert.*;” to the top of each class. With the handing auto source code formatting in Eclipse enabled, Eclipse automatically expanded the “org.junit.Assert.*” imports to the explicit ones needed for that class when I saved it.
  • And finally (3) Added @Test to each test method so that Junit would know what tests to run.

Basically that was it – surefire/maven/junit picked up the test cases in the new style – and in most cases that’s job done. However we wanted to go a little further.

We had also implemented in Junit 3 a handy feature that outputted a quick ERROR message in the system out of a test run so we could quickly see the failure. By default maven’s surefire simply tells you there was a failure, but you have to look at a file to see what it was. Bit of pain that, so in our Junit 3 extension we would provide more info on the screen when a failure occurred, for example we might see something like:

Running com.bemoko.live.platform.mwc.sites.LiveSiteTestCase
ERROR : *** Test Failure *** Site home not correct expected: but was: @ line 17 of com.bemoko.live.platform.mwc.sites.LiveSiteTestCase (com.bemoko.live.platform.BemokoTestListener)
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.01 sec <<< FAILURE!

In Junit 3 we did this by overriding the runTest method of the TestCase class. In Junit 4 we can use runners and listeners. To start with we set the @RunWith annotation on our AbstractLiveTestCase to indicate that all of our tests should run with a specified runner …

@RunWith(BemokoTestRunner.class)
public abstract class AbstractLiveTestCase {

The runner was defined to register a listener …

1
2
3
4
5
6
7
8
9
10
public class BemokoTestRunner extends BlockJUnit4ClassRunner {
	public BemokoTestRunner(Class<?> clazz) throws InitializationError {
		super(clazz);
	}
	@Override
	public void run(final RunNotifier notifier) {
		notifier.addListener(new BemokoTestListener());
		super.run(notifier);
	}
}

and the listener was defined to listen for failures …

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class BemokoTestListener extends RunListener {
	private static Log log = LogFactory.getLog(BemokoTestListener.class);
	@Override
	public void testFailure(Failure failure) {
		Throwable t = failure.getException();
		if (t instanceof Exception) {
			log.error("*** Test Failure *** " + t.getMessage(), t);
		} else {
			if (t.getMessage() != null) {
				log.error("*** Test Failure *** " + t.getMessage() + " @ "
						+ getErrorLocation(t.getStackTrace()));
			} else {
				log.error("*** Test Failure *** ", t);
			}
		}
	}
	@Override
	public void testIgnored(Description description) {
		if (log.isWarnEnabled()) {
			log.warn("+++ Test ignored +++ " + description.getDisplayName());
		}
	}
	private String getErrorLocation(StackTraceElement[] st) {
		for (StackTraceElement ste : st) {
			if (ste.getClassName().startsWith("com.bemoko")
			    && !ste.getClassName().contains("AbstractLiveTestCase")) {
			  return "line " + ste.getLineNumber() + " of " + ste.getClassName();
			}
		}
		return "(line number and class not known)";
	}
}

in this way I can handle events from my tests in any way I see fit and much more elegant that the Junit 3 implementation I previously had.

Job done and we’re all sorted for our unit test framework for the foreseeable future.

Posted in: java 1 Comment