By default, INTGeoServer provides a set of web services to access datasets of various types.
There are applications where these web services do not suffice, or particular clients need a different JSON format. As INTGeoServer is a modular platform, you can modify the default behavior without modifying its core: you only need to add .jar files to the existing deployments.
The INTGeoServer API allows you to plug "request handlers". Each request handler is the implementation of a different service, with its own URL. For a better understanding of request handlers, you can follow this tutorial.
This tutorial demonstrates how web services can be added. Here is an example of request handler that provides the meta data of a file passed as parameter.
public class FileMetaDataRequestHandler extends AbstractFilePathAndProviderRequestHandler {
private static final String FILE_METADATA_PATH = "/filemetadata";
public FileMetaDataRequestHandler() {
}
@Override
public boolean canHandleRequest() {
String pathInfo = IntGeoServiceContextGlobal.get().getRequestPathInfo();
return pathInfo != null && pathInfo.equals(FILE_METADATA_PATH);
}
@Override
public int getPrefetchType() {
return META_DATA_PREFETCH;
}
@Override
public JsonNode handleFilePathAndProviderRequest(JsonNode jsonObject, AbstractPathAndProvider pathAndProvider) throws Exception {
JSONObject fileJSON = new JSONObject();
pathAndProvider.populateDataJSONObject(fileJSON, null);
return fileJSON;
}
@Override
public AbstractJSONServiceRequestHandler getInstance() {
return new FileMetaDataRequestHandler();
}
}
The JSON output is documented in this article.
In many cases, your own web service will provide a different JSON output than the default web service, but reuse the same INTGeo Data API to access the data itself. Here is an example of request handler that provides the meta data of a well dataset passed as parameter.
public class WellDataRequestHandler extends AbstractFilePathAndProviderRequestHandler {
private static String WELL_DATA_PATH = "/welldata";
@Override
public boolean canHandleRequest() {
String pathInfo = IntGeoServiceContextGlobal.get().getRequestPathInfo();
return pathInfo != null && pathInfo.equals(WELL_DATA_PATH);
}
@Override
public JsonNode handleFilePathAndProviderRequest(JsonNode jsonObject, AbstractPathAndProvider pathAndProvider) throws Exception {
IntGeoServiceContext httpContext = IntGeoServiceContextGlobal.get();
PrintWriter out = null;
ObjectNode responseJsonObject = JsonNodeFactory.instance.objectNode();
IWellData wellData = IData.factory.createNewInstance(pathAndProvider.getPath(), IWellData.class);
responseJsonObject.put("name", wellData.getDataName());
responseJsonObject.put("nullValue", wellData.getNullValue());
IUnit zUnit = wellData.getZUnit();
responseJsonObject.put("zUnitSymbol", wellData.getZUnit().getSymbol());
responseJsonObject.put("zUnitName", wellData.getZUnit().getName());
ArrayNode unitSymbols = JsonNodeFactory.instance.arrayNode();
for (IUnit currentUnit : IUnit.Factory.getAllUnits()) {
if (currentUnit.canConvert(zUnit)) {
unitSymbols.add(currentUnit.getSymbol());
}
}
responseJsonObject.set("compatibleZUnitSymbols", unitSymbols);
JSONArrayUtil.setDoubleArrayNode(responseJsonObject, "curveMds", ((AbstractWellData) wellData).getLogCurveDepths());
JSONArrayUtil.setDoubleArrayNode(responseJsonObject, "deviationMds", ((AbstractWellData) wellData).getDeviationCurveDepths());
ArrayNode curveNames = JsonNodeFactory.instance.arrayNode();
for (String currentCurveName : wellData.getAllCurveNames()) {
curveNames.add(currentCurveName);
}
ArrayNode logArrayNames = JsonNodeFactory.instance.arrayNode();
for (String currentLogArrayName : wellData.getAllLogArrayNames()) {
logArrayNames.add(currentLogArrayName);
}
ArrayNode deviationNames = JsonNodeFactory.instance.arrayNode();
for (String currentDeviationName : wellData.getAllDeviationNames()) {
deviationNames.add(currentDeviationName);
}
ArrayNode markerNames = JsonNodeFactory.instance.arrayNode();
for (String currentMarkerName : wellData.getAllMarkerNames()) {
markerNames.add(currentMarkerName);
}
responseJsonObject.set("logCurveNames", curveNames);
responseJsonObject.set("deviationCurveNames", deviationNames);
responseJsonObject.set("markerNames", markerNames);
responseJsonObject.set("logArrayNames", logArrayNames);
responseJsonObject.put("hasTrajectory", wellData.getTrajectory() != null);
DataObjectStateUtil.addObjectStateHash(httpContext, wellData);
return responseJsonObject;
}
@Override
public AbstractJSONServiceRequestHandler getInstance() {
return new WellDataRequestHandler();
}
}
The INTGeo Data API calls are highlighted in bold. The JSON output is documented in this article.
Adding web services is a practical way to provide more features to your INTGeoServer. In some cases, you only want to make minor modifications to the JSON API: you want to add proprietary information to an existing web service, without requiring all clients to use different URLs.The easiest way to do this is to:
unplug the built-in service
plug your own with the same URL
To unplug a built-in service, use a layer.xml entry. For example, to unplug the WellDataRequestHandler, use this entry:
<folder name="com.interactive.intgeoapi.server.requesthandlers.AbstractJSONServiceRequestHandler">
<file name="com.interactive.intgeo.server.well.requesthandlers.WellDataRequestHandler.instance_hidden" />
</folder>
To plug your own, use this entry as a template:
<folder name="com.interactive.intgeoapi.server.requesthandlers.AbstractJSONServiceRequestHandler">
<file name="com.mycompany.intgeo.server.well.requesthandlers.MyWellDataRequestHandler.instance">
<attr name="position" intvalue="180"/>
</file>
</folder>
As long as the implementations of canHandleRequest are identical, you just performed a substitution of the built-in service with your own.