I am totally new to Web Feature Service (WFS) but I want to build an Android application with ksoap2-android on top of an API publishing its data via WFS. I would like to request data from the API passing them the bounding box parameter to limit the data that will be returned.
Questions:
- How can I put the
GetFeature
object into the SOAP envelope? - How can I use
JAXBElement
on the Android client? See edit from March 15, 2012
Here are some links to the API that might help to understand their format.
Example: WFS-1.1 GetFeature POST request, http://data.wien.gv.at/daten/geoserver/wfs
<?xml version="1.0" encoding="UTF-8"?>
<wfs:GetFeature service="WFS" version="1.1.0"
outputFormat="JSON"
xmlns:ogdwien="http://www.wien.gv.at/ogdwien"
xmlns:wfs="http://www.opengis.net/wfs"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:gml="http://www.opengis.net/gml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/wfs
http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" >
<wfs:Query typeName="ogdwien:BAUMOGD">
<ogc:Filter>
<ogc:BBOX>
<ogc:PropertyName>SHAPE</ogc:PropertyName>
<gml:Envelope srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
<gml:lowerCorner>16.3739 48.2195</gml:lowerCorner>
<gml:upperCorner>16.3759 48.2203</gml:upperCorner>
</gml:Envelope>
</ogc:BBOX>
</ogc:Filter>
</wfs:Query>
</wfs:GetFeature>
This is the Android code I came up with by now. This is mostly inspirated by examples from the ksoap2-android wiki. I am totally unsure whether the namespace, methodName and url are correct!
// KSOAP2Client.java
private class MyAsyncTask extends AsyncTask<Void, Void, Object> {
String namespace = "http://www.wien.gv.at/ogdwien";
String methodName = "GetFeature";
String url = "http://data.wien.gv.at/daten/geoserver/wfs";
protected Object doInBackground(Void... voids) {
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = false;
SoapObject soapObject = new SoapObject(namespace, methodName);
envelope.setOutputSoapObject(soapObject);
// TODO Put request parameters in the envelope. But how?
try {
HttpTransportSE httpTransportSE = new HttpTransportSE(url);
httpTransportSE.debug = true;
httpTransportSE.call(namespace + methodName, envelope);
return (Object)soapSerializationEnvelope.getResponse();
} catch (Exception exception) {
exception.printStackTrace();
}
return null;
}
}
EDIT: March 15, 2012
I managed to get further and I almost reached what seems to be the solution. I found the schema definitions for those namespaces used in the XML request and linked them to my project. That allows me to assemble the objects for the request.
// TODO The core libraries won't work with Android.
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
// TODO Not sure if the versions fit with the service.
import net.opengis.filter.v_1_1_0.BBOXType;
import net.opengis.filter.v_1_1_0.FilterType;
import net.opengis.filter.v_1_1_0.PropertyNameType;
import net.opengis.gml.v_3_1_1.DirectPositionType;
import net.opengis.gml.v_3_1_1.EnvelopeType;
import net.opengis.wfs.v_1_1_0.GetFeatureType;
import net.opengis.wfs.v_1_1_0.QueryType;
[...]
List<Double> lowerCornerList = new Vector<Double>();
lowerCornerList.add(16.3739);
lowerCornerList.add(48.2195);
List<Double> upperCornerList = new Vector<Double>();
upperCornerList.add(16.3759);
upperCornerList.add(48.2203);
DirectPositionType lowerCornerDirectPositionType = new DirectPositionType();
lowerCornerDirectPositionType.setValue(lowerCornerList);
DirectPositionType upperCornerDirectPositionType = new DirectPositionType();
upperCornerDirectPositionType.setValue(upperCornerList);
EnvelopeType envelopeType = new EnvelopeType();
envelopeType.setSrsName("http://www.opengis.net/gml/srs/epsg.xml#4326");
envelopeType.setLowerCorner(lowerCornerDirectPositionType);
envelopeType.setUpperCorner(upperCornerDirectPositionType);
List<Object> propertyNames = new Vector<Object>();
propertyNames.add(new String("SHAPE"));
PropertyNameType propertyNameType = new PropertyNameType();
propertyNameType.setContent(propertyNames);
// TODO Check parameters of JAXBElement.
JAXBElement<EnvelopeType> e = new JAXBElement<EnvelopeType>(null, null, envelopeType);
BBOXType bboxType = new BBOXType();
bboxType.setPropertyName(propertyNameType);
bboxType.setEnvelope(e);
// TODO Check parameters of JAXBElement.
JAXBElement<BBOXType> spatialOps = new JAXBElement<BBOXType>(null, null, bboxType);
FilterType filterType = new FilterType();
filterType.setSpatialOps(spatialOps);
QueryType queryType = new QueryType();
List<QName> typeNames = new Vector<QName>();
// TODO Check parameters of QName.
typeNames.add(new QName("ogdwien", "BAUMOGD"));
queryType.setTypeName(typeNames);
GetFeatureType featureType = new GetFeatureType();
featureType.setService("WFS");
featureType.setVersion("1.1.0");
featureType.setOutputFormat("JSON");
featureType.setMaxFeatures(new BigInteger("5"));
String namespace = "http://www.wien.gv.at/ogdwien";
String methodName = "GetFeature";
// TODO Is this the correct action?
String action = "http://data.wien.gv.at/daten/wfs?service=WFS&request=GetFeature&version=1.1.0&typeName=ogdwien:BAUMOGD&srsName=EPSG:4326";
String url = "http://data.wien.gv.at/daten/geoserver/wfs";
// TODO Is this the correct way to add GetFeature?
SoapObject soapObject = new SoapObject(namespace, methodName);
PropertyInfo propertyInfo = new PropertyInfo();
propertyInfo.setName("GetFeature");
propertyInfo.setValue(featureType);
soapObject.addProperty(propertyInfo);
Still there are a major problem and some minor problems left. The major problem is that JAXBElement
is contained in a core library (javax.xml.bind.JAXBElement
) that Android refuses to consume. The minor problems are stated in the comments and TODOs.
EDIT: April 27, 2012
As I read this post I imagine that something similar might apply to my problem. I haven't tried yet.
EDIT: May, 09, 2012
Here is the error message from Eclipse when you try to compile JAXBElement for Android.