camel-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Christian Schneider <ch...@die-schneider.net>
Subject Easy One way soap services
Date Tue, 19 Jan 2010 21:53:42 GMT
Hi all,

I am thinking about how to make one way services easier. Currently I 
generate code for the service using cxf codegen and use the camel-cxf 
module to create a client or endpoint that can be routed over jms using 
the camel-jms component. Using CXF for this task is a little overkill as 
very few features of CXF are used and quite a lot of configuration has 
to be done. I wonder if this can be done easier.

I have experimented with a possible solution for the server part. It 
looks like this:
from("jms:myqueue").process(new 
SoapProcessor("com.example.customerservice")).to("bean:serviceHandler");

The idea is that a soap message for the service comes in over jms. The 
soap processor parses the soap xml, strips the Envelope and Body and 
unmarshals the content using JAXB. The processor needs the package name 
of the generated stub code for the service. The advantage over using 
camel-cxf is that there is much less configuration and you do not need 
cxf at runtime (which means much less jars). Additionally the 
serviceHandler bean only needs to have a method with the expected classs 
type as input parameter it does not need to implement a service 
interface. I have added the code of SoapProcessor to the mail as it is 
quite small.

So what do you think? Does it make sense to have such small scale SOAP 
functionality in camel?
I am thinking about turning my Processor into a DataFormat and provide 
marshalling and unmarshalling. Does this make sense or is a processor 
better?

Greetings

Christian

-- 

Christian Schneider
---
http://www.liquid-reality.de

----


import java.io.InputStream;
import java.util.Iterator;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;

public class SoapProcessor implements Processor {

	private XPathExpression xpathExpression;
	private Unmarshaller unmarshaller;

	public SoapProcessor(String jaxbPackage) {
		super();
		XPath xpath = XPathFactory.newInstance().newXPath();
		xpath.setNamespaceContext(new SoapNameSpaceContext());
		try {
			xpathExpression = xpath.compile("/soap:Envelope/soap:Body/*");
			JAXBContext jContext = JAXBContext.newInstance(jaxbPackage);
			unmarshaller = jContext.createUnmarshaller();
		} catch (XPathExpressionException e) {
			throw new RuntimeException(e.getMessage(), e);
		} catch (JAXBException e) {
			throw new RuntimeException(e.getMessage(), e);
		}
		
	}

	private final class SoapNameSpaceContext implements NamespaceContext {
		private static final String SOAP_NAMESPACE = "http://schemas.xmlsoap.org/soap/envelope/";

		public Iterator<?>  getPrefixes(String namespaceURI) {
			return null;
		}

		public String getPrefix(String namespaceURI) {
			return null;
		}

		public String getNamespaceURI(String prefix) {
			return SOAP_NAMESPACE;
		}
	}

	public void process(Exchange exchange) throws Exception {
		InputStream request = exchange.getIn().getBody(InputStream.class);
		InputSource is = new InputSource(request);
		Element payload = (Element) xpathExpression.evaluate(is, XPathConstants.NODE);
		JAXBElement<?>  el = (JAXBElement<?>) unmarshaller.unmarshal(payload);
		Object o = el.getValue();
		exchange.getIn().setBody(o);
	}

}


Mime
View raw message