Extending an Encoder

Feedback


The REST Service Publishing Mechanism section gives you an introduction to the REST service publishing mechanism. We can know that when the HTTP request arrives at the REST application object and handled by the implementation class, the response needs to be processed by the encoder before the server sends the representation back to the client.

The encoders provided by SuperMap iServer include: TemplateEncoder (mainly used for HTML format representation), JsonEncoder, RJsonEncoder, XMLEncoder, ImageEncoder (BMP, GIF, JPEG, JPG, PNG, etc.), etc. The resource will select an encoder according to the specified representation format and to process the result. Then the result will be returned in the expected representation format.

SuperMap iServer also provides the extension mechanism for the encoder. If users want to publish the resource as a representation format not supported by SuperMap iServer, users need to extend an encoder.

The two steps for extending the encoder is as follows:

  1. Implementing an Encoder Class

  2. Configuring the Encoder

1. Implementing an Encoder Class

The REST implementation framework of SuperMap iServer provides the abstract class com.supermap.services.rest.encoders.Encoder, from which all encoders inherit. Encoders provided by SuperMap iServer include: ImageEncoder, JsonEncoder, SceneEncoder, StreamEncoder, TemplateEncoder, XMLEncoder, etc.

When extending the encoder, users need to inherit from the Encoder abstract class and implement the abstract methods in the class, or users can inherit from an existing encoder and overwrite the methods in it. Below is a list of some important methods involved.

Method Description
createSupportedMediaTypes() Creates the supported representation format list.
toRepresentation(MediaType, Object) Converts the Java object into the representation of a specified media type.

To construct a custom encoder, inherit from the Encoder abstract class or its child class, and implement or overwrite the methods listed in the above table.

For illustration, here we implement MyEncoder similar to JsonEncoder, with the media type changed to application/cjson. The representation in cjson format is identical to that in json format. The only difference is that the media type in the HTTP response is application/cjson, but not application/json. In practical applications, users can define the specific implementation according to needs.

The hierarchy of MyEncoder is as follows:

The sample code of MyEncoder:

package com.supermap.sample.extendREST;

import java.util.ArrayList;

import java.util.List;

import org.restlet.data.MediaType;

import org.restlet.representation.Representation;

import com.supermap.services.rest.encoders.JsonEncoder;

public class MyEncoder extends JsonEncoder{

        public Representation toRepresentation(MediaType mediaType, Object resourceObj) {

                //Get the representation, which is identical to that in JSON format

                Representation rep = super.toRepresentation(mediaType, resourceObj);

                if(rep != null){

                        //Set the media type in the HTTP response to application/cjson。

                        rep.setMediaType(new MediaType("application/cjson"));

                }

                return rep ;

        }

        protected List<MediaType> createSupportedMediaTypes() {

        List<MediaType> supportedMediaTypes = new ArrayList<MediaType>(); // NOPMD

        //The media type supported by MyEncoder is application/cjson

        supportedMediaTypes.add(new MediaType("application/cjson"));

        return supportedMediaTypes;

    }

}

Up till now, a simple encoder is finished. You can find the sample code in %SuperMap iServer_HOME%/samples/code/ExtendREST.

After comipling, the MyEncoder class needs to be packaged into a Jar package and place the package in %SuperMap iServer_HOME%/webapps/iserver/WEB-INF/lib. In this example, the MyEncoder class is packaged into extendREST.jar.

2. Configuring MyEncoder to REST Service

There are two ways for configuring MyEncoder:

2.1 Add to the external configuration file

2.2 Add to the XML configuration file of your own module

Please note that the server will choose an encoder according to the suffix of the request URI, and return the representation of the corresponding type. By default, the encoder is chosen according to the media type with the value "application/suffix". For instance, if the suffix of the URI is cjson, the server will choose the encoder that supports the media type “application/cjson”. Here MyEncoder will be found by the server. After MyEncoder handles the result, the server will return the response, with the media type being "application/cjson", to the client.

If you don't want the server to follow the corresponding relationship between the URI suffix and the media type, you can show the configuration on iServer. See The relations between URI suffix and media type.

 

2.1 Add to the external configuration file

How to configure MyEncoder to the REST service? First, register an implementation class to a component; Second, configure this component to the resources (you can either configure it to a single resource that possesses this encoder, or configure it to all resources that supports this encoder). The workflow is as follows:

To register the MyEncoder class as a Bean component, we need to add a <bean/> node in the REST application configuration file--AppContext.xml, which is located in %SuperMap iServer_HOME%/webapps/iserver/WEB-INF. As shown below, the MyEncoder class is registered as the MyEncoder Bean component:

<bean id="MyEncoder" class="com.supermap.sample.extendREST.MyEncoder"></bean>

Configuring for a single resource

The configuration of the encoder for a single resource should be performed in Resources.xml. The structure of the resource configuration information is introduced in step 2. Configuring the Algorithm for Extending a Simple Algorithm, where the <extensionEncoderBeanNames/> node under the <resource/> node is mentioned. Each resource configuration item, i.e., <resource/>, can have a child node <extensionEncoderBeanNames/>, specifying the extended encoders via the IDs of the registered Bean components. If there are multiple extended encoders, separate the IDs with “,”. Below is the sample code for configuring MyEncoder for the rectangleArea resource:

<resource>

    <configID>rectangleArea</configID>

    <urlTemplate>/maps/{mapName}/rectangleArea</urlTemplate>

    <resourceType>ArithmeticResource</resourceType>

    <implementClass>com.supermap.sample.extendREST.rectangleAreaResource</implementClass>

    <extensionEncoderBeanNames>MyEncoder</extensionEncoderBeanNames>

    <extensionDecoderBeanNames></extensionDecoderBeanNames>

    <extensionHttpActionHandlerBeanName></extensionHttpActionHandlerBeanName>

</resource>

Now, the rectangleArea resource has one more encoder--MyEncoder, therefore, the representation in application/cjson format is supported.

Restart the service, and access the URI below to simulate the GET request and get the representation in cjson format:

http://localhost:8090/iserver/services/components-rest/rest/maps/WorldMap/rectangleArea.cjson?rect2D={leftBottom:{x:23,y:34},rightTop:{x:40,y:50}}&unit=METER

Since application/cjson is a custom media type and IE cannot parse it, you will be prompted to save the file, as shown below:

After saving the file, open it with the text editor. Then you will find you get the measurement result, which is identical to the representation in json format.

Configuring for all resources

The configuration of the encoder for all resources should be performed in AppContext.xml, i.e., adding a default encoder. In AppContext.xml, the default encoder is specified by the <entry/> node of key="systemEncoders". The sample code for registering the MyEncoder component for all resources in AppContext.xml is shown as below:

<beans>

     ......

     <util:map id="restConfig">

          <entry key="systemEncoders" value="xmlEncoder,jsonEncoder,pjsonEncoder,templateEncoder,MyEncoder" />

     </util:map>

     ......

</beans>

Now, all resources can use MyEncoder. The effect is similar to the cjson of rectangleArea.

Note: Resources.xml and AppContext.xml are located in %SuperMap iServer_HOME%/webapps/iserver/WEB-INF.

 

2.2 Add to the XML configuration file of your own module

In this way , the configuration information can be packaged to Jar so as to facilitate administrators to configure.

This sample extends the resource of the map module. The configure file is: Jar:///META-INF/extensions/services/rest/mapRest (See Configure file introduction).

mapRest configureation is shown as follows:

encoders=com.supermap.sample.extendREST.MyEncoder

decoders=

verifiers=

resourceFiles=config/resource/rest/mappingResources.xml

resourceFiles corresponds to the resource config file.

Jar:///config/resource/rest/mappingResources.xml is configured as follows:

<resources>

        <resource>

            <configID>rectangleArea</configID>

            <urlTemplate>/maps/{mapName}/rectangleArea</urlTemplate>

            <resourceType>ArithmeticResource</resourceType>

            <implementClass>com.supermap.sample.extendREST.RectangleAreaResource</implementClass>

            <extensionEncoderBeanNames>MyEncoder</extensionEncoderBeanNames>

            <extensionDecoderBeanNames></extensionDecoderBeanNames>

        </resource>

<resources>

This step can be packaged to the same Jar package.

 

Now, the extension of an Encoder is finished. The workflow of both the extension parameter parser and the extension HTTP request processor is similar to the encoder.

Note that MyEncoder is very simple. It has no practical meanings. Here we only focus on how to create an extension encoder.