Camel CXF Geocoder example

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Camel-geocoder component is useful if you want to gather geographical information. This particular example provides you the latitude and longitude of the given address. For an instance, the response below shows the latitude and longitude for Paris, France:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:geo="http://www.bushorn.com/camel/geo-service/">
<soapenv:Header/>
<soapenv:Body>
<geo:GeoServiceRequest>
<address>Paris, France</address>
</geo:GeoServiceRequest>
</soapenv:Body>
</soapenv:Envelope>

 

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:geo="http://www.bushorn.com/camel/geo-service/">
<soapenv:Header/>
<soapenv:Body>
<GeoServiceResponse>
<details>48.856614,2.3522219</details>
</GeoServiceResponse>
</soapenv:Body>
</soapenv:Envelope>

 

Actually camel-geocoder gets you lot of information for any address, as a first version this example supports only latitude and longitude. I will add more details in the soap response going forward. By the way, the following JSON payload is received from the geocoder component.

GeocodeResponse{status=OK, results=[GeocoderResult{types=[locality, political], formattedAddress='Paris, France', addressComponents=[GeocoderAddressComponent{longName='Paris', shortName='Paris', types=[locality, political]}, GeocoderAddressComponent{longName='Paris', shortName='75', types=[administrative_area_level_2, political]}, GeocoderAddressComponent{longName='Île-de-France', shortName='IDF', types=[administrative_area_level_1, political]}, GeocoderAddressComponent{longName='France', shortName='FR', types=[country, political]}], geometry=GeocoderGeometry{location=LatLng{lat=48.856614, lng=2.3522219}, locationType=APPROXIMATE, viewport=LatLngBounds{southwest=LatLng{lat=48.815573, lng=2.224199}, northeast=LatLng{lat=48.9021449, lng=2.4699208}}, bounds=LatLngBounds{southwest=LatLng{lat=48.815573, lng=2.224199}, northeast=LatLng{lat=48.9021449, lng=2.4699208}}}, partialMatch=false}, GeocoderResult{types=[sublocality_level_1, sublocality, political], formattedAddress='Paris, 33770 Salles, France', addressComponents=[GeocoderAddressComponent{longName='Paris', shortName='Paris', types=[sublocality_level_1, sublocality, political]}, GeocoderAddressComponent{longName='Salles', shortName='Salles', types=[locality, political]}, GeocoderAddressComponent{longName='Gironde', shortName='33', types=[administrative_area_level_2, political]}, GeocoderAddressComponent{longName='Aquitaine', shortName='Aquitaine', types=[administrative_area_level_1, political]}, GeocoderAddressComponent{longName='France', shortName='FR', types=[country, political]}, GeocoderAddressComponent{longName='33770', shortName='33770', types=[postal_code]}], geometry=GeocoderGeometry{location=LatLng{lat=44.562918, lng=-0.8655079999999999}, locationType=APPROXIMATE, viewport=LatLngBounds{southwest=LatLng{lat=44.56156901970849, lng=-0.866856980291502}, northeast=LatLng{lat=44.56426698029149, lng=-0.864159019708498}}, bounds=null}, partialMatch=false}]}

How this example is implemented ?

1. A SOAP gateway endpoint ( camel from endpoint ) is exposed using camel-cxf component

<route id="geocoder-service-callout">
<from uri="cxf:bean:geo-service-endpoint" />

<!-- This removes soap envelope - this is not required if cxf dataformat is PAYLOAD -->
<setBody><xpath>//geo:GeoServiceRequest</xpath></setBody>
<convertBodyTo type="String" />

<!-- Setting this header overrides the address configured in geo coder endpoint -->
<setHeader headerName="CamelGeoCoderAddress"><xpath resultType="String">//geo:GeoServiceRequest/address/text()</xpath></setHeader>

<log message="Geo request body ${body}" />

<!-- The hard-coded address will be overridden by CamelGeoCoderAddress header value-->
<to uri="geocoder:address:Paris, France" />

<log message="Geo response body ${body}" />

<!-- This required as xslt expects a xml element match -->
<setBody id="reset-body"><simple>&lt;data/&gt;</simple></setBody>

<to uri="xslt:transformation/geo-service-response.xsl" />

<!-- This xslt adds soap envelope - this is not required if cxf dataformat is PAYLOAD -->
<to uri="xslt:transformation/soap-wrapper.xsl" />

</route>

 

2. The address is extracted from the request message and set to CamelGeoCoderAddress camel header. This in turn passes the address to geocoder API:

<setHeader headerName="CamelGeoCoderAddress"><xpath resultType="String">//geo:GeoServiceRequest/address/text()</xpath></setHeader>

3. API returns latitude and longitude information through headers. (This example is still not using the JSON payload from geocoder API). This header is straight away passed to a xslt which generates response xml. (CamelGeoCoderLatlng)

Camel-Geocoder component provides various headers containing the address details. All of them are listed under ‘Message Headers’ section of the documentation : http://camel.apache.org/geocoder.html

4. Further the response xml is wrapped with soap-envelope and sent out.

The complete code is hosted in here at GitHub: https://github.com/gnanagurus/camel-guru-projects/tree/master/camel-cxf-geocoder-example

Facebooktwittergoogle_plusredditpinterestlinkedinmail
Gnanaguru Sattanathan

Gnanaguru Sattanathan

I am a Integration developer and a open source enthusiast. My areas of interest includes Enterprise messaging & SOA. Twitter: @tallguru

You may also like...

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>