Important Considerations when Configuring Virtual REST Services
With Web REST Services, the Native REST Service endpoint that is sent by CentraSite to Mediator inside a Virtual REST Service definition is a static element. Once the Virtual REST Service is successfully deployed to Mediator, the real endpoint is returned to CentraSite as part of the response message during deployment. At run time, when a SOAP request is received, that request is POSTed to the endpoint that is statically defined in the Virtual REST Service definition.
However, with REST Services or XML REST Services, the endpoint is flexible. The REST Services or XML REST Services describe data as resources. The resources are accessible through logical endpoints that have application meaning to users. For example, a collection of textbooks might be defined as a resource with the following URL:
http://{host}:{port}/books
A specific book with an identifier of 1234 would be accessible with the following URL:
http://{host}:{port}/books/1234
Due to this difference and others, you should keep the following topics described in this chapter in mind when you configure a REST Virtual REST Service.
Endpoint Manipulation of REST Virtual REST Services
When you configure a Virtual REST Service, you specify the Native REST Service name, an endpoint, and the HTTP method type(s) that are included in the message (GET, POST, PUT, PATCH, DELETE). From this information, CentraSite generates a Virtual REST Service definition that includes REST Service and operation elements, as well as an endpoint and binding element pair for each HTTP method specified.
CentraSite generates an operation name to be included when the Virtual REST Service definition deployment message is sent to Mediator. This means that if you create a Virtual REST Service called VS1, and you specify a Native endpoint, then the endpoint exposed by Mediator for calling the Virtual REST Service will be /ws/VS1/Invoke.
For example, assume the following endpoints are deployed:
Native REST Service endpoint: http://localhost:8080/RESTServices/mtc/member
Virtual REST Service endpoint: http://localhost:5555/ws/VS1/Invoke
Assume that the example Virtual REST Service is deployed with two HTTP method bindings: GET and POST. Both of these bindings have operation elements that include the same HTTP location attribute: member. To better illustrate the functionality, the examples below show a series of sample requests from a consumer including the requests' HTTP method. (At run time, REST message detection is dependent upon a consumer using the correct Content-Type when a request is sent.) Each example shows the expected endpoint that Mediator will send after it has rewritten the endpoint prior to Native REST Service invocation.
Example 1
For a GET, assume that:
The request Content-Type is: application/x-www-form-urlencoded
The endpoint received by Mediator is: http://localhost:5555/ws/VS1/Invoke
The Native REST Service endpoint sent by Mediator is: http://localhost:8080/REST Services/mtc/member
The application function is: The Native REST Service returns a collection of members with summary information.
Example 2
For a GET, assume that:
The request Content-Type is: application/x-www-form-urlencoded
The endpoint received by Mediator is: http://localhost:5555/ws/VS1/Invoke/1234
The Native REST Service endpoint sent by Mediator is: http://localhost:8080/REST Services/mtc/member/1234
The application function is: The Native REST Service returns summary data for a member with this key.
Example 3
For a GET, assume that:
The request Content-Type is: application/x-www-form-urlencoded
The endpoint received by Mediator is: http://localhost:5555/ws/VS1/Invoke/1234?detail=true
The Native REST Service endpoint sent by Mediator is: http://localhost:8080/REST Services/mtc/member/1234?detail=true
The application function is: Query parameters remain intact. Returns a response message with more member details.
Example 4
For a POST, assume that:
The request Content-Type is: application/xml or application/json
The endpoint received by Mediator is: http://localhost:5555/ws/VS1/Invoke/1234
The Native REST Service endpoint sent by Mediator is: http://localhost:8080/REST Services/mtc/member/1234
The application function is: The request message provides the contents needed to create the member resource.
Example 5
For a GET, assume that:
The request Content-Type is: application/x-www-form-urlencoded
The endpoint received by Mediator is: http://localhost:5555/ws/VS1/Invoke/joe
The Native REST Service endpoint sent by Mediator is: http://localhost:8080/REST Services/mtc/member/joe
The application function is: Fetches the member defined with the login joe. (Mediator contains no metadata in its REST Service deployment to differentiate between the login vs. key GET requests.)
Example 6
For a GET, assume that:
The request Content-Type is: application/x-www-form-urlencoded
The endpoint received by Mediator is: http://localhost:5555/ws/VS1/Invoke?type=login&value=joe
The Native REST Service endpoint sent by Mediator is: http://localhost:8080/REST Services/mtc/member?type=login&value=joe
The application function is: The Native REST Service might also support a static endpoint with constraints defined in query parameters. Mediator also supports this approach.
The Request Message’s HTTP Methods and Content-Types for REST and XML REST Services
When you configure the Entry Protocol step of a Virtual REST Service, it is important to specify all the HTTP methods that are supported for the REST Service. For example, if the Virtual REST Service is deployed to Mediator and you selected only the GET method in the Virtual REST Service's details page, then Mediator permits GET invocations. In this case, a POST request will be rejected with a return of statusCode 405 even if the Native REST Service happens to support POSTs.
It is important that the client's requests contain an HTTP Content-Type header. At run time, Mediator determines which message builder to use based on the message’s HTTP method and its Content-Type. (The absence of the soapAction header will indicate to Mediator that the message is an XML message.)
The valid HTTP method/Content-Type combinations are as follows:
This method... | Can be included in a message of this Content-Type... |
POST | application/xml application/json application/x-www-form- urlencoded multipart/form-data or text/xml |
PUT | application/xml application/json application/x-www-form- urlencoded multipart/form-data or text/xml |
GET | application/x-www-form-urlencoded Note: For Axis Free Mediation Content-Type is not required. |
DELETE | application/x-www-form-urlencoded Note: For Axis Free Mediation Content-Type is not required. |
Note:
Keep the following points in mind:
If
Mediator receives a request sent with an HTTP method that is not specified in the Virtual REST Service or Virtual XML REST Service definition, it will return a 405 error.
If
Mediator receives a request sent with a wrong Content-Type, it will return a 415 error. In addition, if the wrong Content-Type is used with a GET or DELETE, then the query parameters contained in the message (if any) will not be processed.
Changing the HTTP Method of a REST Request
When configuring a REST Virtual REST Service, you specify whether to route the requests to the Native REST Service with the same HTTP method that is contained in the requests (GET, POST, PUT, PATCH, DELETE), or whether to route the requests with a different HTTP method.
Typically you want to pass each request to the Native REST Service with the same HTTP method that is contained in the request. For example, if a request contains a GET method, you allow the GET method to be passed to the Native REST Service. However, there might be rare cases in which you want to change the HTTP method of a request to different HTTP method. For example, you might want to:
Expose an XML REST Service as a REST Service.
In this case, the REST Service you create would be a Virtual XML REST Service that exposes the HTTP methods GET, POST, PUT, PATCH and DELETE, but the routing method would always be POST.
Expose a REST Service whose Virtual REST Service only exposes the POST method.
To change the HTTP method of a REST request
On the REST Virtual REST Service, set the value of the HTTP Method field either statically (by explicitly setting the value to
GET,
POST,
PUT, or
DELETE) or dynamically (by setting the value to
Use Context Variable).
In order to use the Use Context Variable option to set the field dynamically, you must write a webMethods IS REST Service that sets a value of GET, POST, PUT, PATCH or DELETE for a predefined context variable named ROUTING_METHOD. You need to invoke this REST Service in the Virtual REST Service's Invoke webMethods IS REST Service action. For more information on using contexts and variables dynamically, see the Changing HTTP Methods in Requests Dynamically using a Context Variable section later in this topic.
CAUTION:
Use this feature carefully, since changing HTTP methods to certain other HTTP methods could result in unintended results or errors.
For example, changing an inbound GET request to a DELETE request would be a serious mistake if the deletion was not intended and the Native REST Service actually deleted a resource when invoked with a DELETE method. Additionally, an incoming POST or PUT request cannot be translated into a GET or DELETE if the request has nested elements.
The Implications of Changing HTTP Methods
When changing this incoming HTTP method... | To... | Note that... |
GET | POST | The Content-Type of the changed request is sent as application/xml or application/json, and the charset is UTF-8. Depending on the structure of the Native REST Service, be aware that the Native REST Service might not be expecting the same payload structure that is being sent. In this case, you would need to transform the request message into the format required by the Native REST Service before Mediator sends the requests to the Native REST Service. For more information, see the Sample XSLT Transformation for GET-to-POST or GET-to-PUT section later in this topic. |
GET | PUT | Identical to GET-to-POST, except that Mediator changes the request's HTTP method from GET to PUT. |
GET | DELETE | No comment. |
POST | GET | Mediator will translate the POSTed request elements into query string parameters, in a root element. Note: An incoming POST or PUT request cannot be translated into a GET or DELETE if the request has nested elements. For example: (this is correct) <person> <lastName>Smith</lastName> </person> (this is incorrect) <person> <name> <last>Smith</last> </name> </person> If you want to send additional parameters as part of the request URL, you can transform this payload. To do this, you can use an XSLT file or a webMethods IS REST Service call to add parameters before the request is sent to the Native REST Service. |
POST | DELETE | Identical to POST-to-GET, except that Mediator changes the request's HTTP method from POST to DELETE. |
POST | PUT | The Content-Type of the changed request is sent as application/xml or application/json, and the charset is UTF-8. |
PUT | GET | Identical to POST-to-GET, except that Mediator changes the request's HTTP method from PUT to GET. |
PUT | POST | The Content-Type of the changed request is sent as application/xml or application/json, and the charset is UTF-8. |
PUT | DELETE | Identical to POST-to-DELETE, except that Mediator changes the request's HTTP method from PUT to DELETE. |
DELETE | GET | No comment. |
DELETE | POST | Identical to GET-to-POST, except that Mediator changes the request's HTTP method from DELETE to POST. |
DELETE | PUT | Identical to GET-to-PUT, except that Mediator changes the request's HTTP method from DELETE to PUT. |
GET, POST, PUT or DELETE | Use Context Variable | See the Changing HTTP Methods in Requests Dynamically using a Context Variable section later in this topic. |
GET or DELETE | POST or PUT | Note that the query parameters will be picked off the URL and stored as top-level elements when the message is sent to the Native REST Service. The query parameters are ignored on the endpoint URL and lost when we POST to the Native provider (that is, don't change the protocol method). |
PATCH | POST or PUT | Note that the query parameters will be picked off the URL and stored as top-level elements when the message is sent to the Native REST Service. The query parameters are ignored on the endpoint URL and lost when we POST to the Native provider (that is, don't change the protocol method). |
Changing HTTP Methods in Requests Dynamically using a Context Variable
Alternatively, instead of changing an HTTP method explicitly (statically) to PUT, POST, GET, PATCH, or DELETE, you can change the HTTP method to the value of a predefined context variable (ROUTING_METHOD) that dynamically resolves to a different HTTP method (PUT, POST, GET, PATCH, or DELETE, as appropriate).
To change the HTTP method dynamically, you create a webMethods IS REST Service and invoke it in the Virtual REST Service's Invoke webMethods IS REST Service action. This webMethods IS REST Service should reference the predefined context variable ROUTING_METHOD. To set the value of ROUTING_METHOD, use the setContextVariableValue method, which is defined in the following class:
com/softwareag/mediator/REST Service/MediatorRuntimeFacade.java
For example:
public static final void updateHttpMethod(IData pipeline)
throws REST ServiceException {
String mcKey = "Message Context";
Object obj = IDataUtil.get(pipeline.getCursor(), mcKey);
if (obj!=null && obj instanceof org.apache.synapse.MessageContext) {
MessageContext msgCtx = (MessageContext) obj;
QName varName =
new QName(MediatorContextVariableType.ROUTING_METHOD.getName());
MediatorRuntimeFacade.setContextVariableValue(varName, "PUT", msgCtx );
}
}
Sample XSLT Transformation for GET-to-POST or GET-to-PUT
As stated in the above table, depending on the structure of the Native REST Service, the Native REST Service might not be expecting the same payload structure that is being sent. In this case, you would need to transform the request message into the format required by the Native REST Service before Mediator sends the requests to the Native REST Service. To do this, you invoke an XSLT file at run time.
Assume that:
The Native REST Service name is
authors.
The Virtual REST Service or Virtual XML REST Service for
authors is named
vs-authors and is made available in
Mediator at this endpoint: http://localhost:5555/ws/vs-authors/Invoke. The targetNamespace of the Virtual REST Service or Virtual XML REST Service is
http://example.com/authors.
Following is a sample XSLT transformation file for the GET-to-POST or GET-to-PUT scenario:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns="http://example.com/authors"
version="1.0">
<xsl:output method="xml" omit-xml-declaration="no" standalone="yes"
indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//ns:invoke/node()">
<xsl:element name="{local-name(.)}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
<xsl:template match="//ns:invoke">
<xsl:element name="authors">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Working with the JSON Content-Type
Mediator can accept a REST Service request that specifies the Content-Type application/json (or application/json/badgerfish) and the HTTP methods PUT, GET, DELETE, PATCH, and POST.
Assuming that the Native REST Service supports both JSON and the HTTP method(s) specified in the request, Mediator can determine the correct REST Service, operation and output format (JSON) to return to the consuming application. There are different ways in which a Native REST Service provider can be prompted to return response content. It will vary with the provider. For example, some providers may rely on the Accept transport header to specify the format the consumer wants. Others may use an element in the request or a query parameter on the URL.
However, suppose for example that the Native REST Service does not support the HTTP method specified in the request (for example, POST). As a workaround, you can configure the Virtual REST Service so that it bridges this difference between the consumer request and the Native REST Service. In this case, you can configure the Virtual REST Service so that it takes the POST and bridges it into an HTTP GET query, and then returns the REST Service to the consumer in the expected JSON format. To implement this, you set the following predefined context variables in a user-defined webMethods IS REST Service that you can invoke in the Virtual REST Service’s Invoke webMethods IS REST Service action:
MESSAGE_TYPE: A Content-Type defined in axis2.xml for a message formatter. This value must be a key in the axis2 message formatters list, since it is used to control message serialization. (The valid choices are defined as attributes of the <messageFormatters/> group in the
Integration Server's axis2.xml configuration.)
BUILDER_TYPE: A Content-Type defined in axis2.xml for a message builder. This value must be a key in the axis2 message builders list since it is used to control building of Native REST Service response messages. (The valid choices are defined as attributes of the <messageBuilders/> group in the
Integration Server's axis2.xml configuration.)
This and other bridging scenarios are discussed in this section.
Note:
Mediator does not support JSON to XML or XML to JSON transformation as part of Request or Response processing. However, you can perform JSON to XML or XML to JSON transformation using the Invoke webMethods Integration Server Service as part of Request or Response processing. You must create these services using Software AG Designer and configure the full name of the service in the Invoke webMethods Integration Server policy.
How Mediator Determines Which Builder and Formatter Classes to Use (and How You Can Override Them)
Mediator makes these determinations at run time as follows:
This table also summarizes how you can override the default determinations.
Run-time Step | Description |
Mediator receives the request from the client | It is important that the client's PUT or POST requests contain the HTTP header Content-Type because the Content-Type header determines the message builder Mediator uses to parse the input stream. (GET or DELETE request do not require a Content-Type header.) |
Mediator sends the request to the REST Service provider | Mediator uses a message formatter to serialize the request, and then sends the serialized request to the Native REST Service provider. Mediator determines the message formatter to use as follows: If you explicitly specify a message formatter (by setting the MESSAGE_TYPE context variable in a webMethods IS REST Service and invoking this REST Service in the Virtual REST Service’s Invoke webMethods IS REST Service action), then Mediator uses that formatter. The Content-Type header that Mediator sends to the Native provider is the one that is associated with the MESSAGE_TYPE context variable. Else, Mediator uses the message formatter associated with the Content-Type sent by the client (and sends the Content-Type to the Native provider). Else, if no Content-Type was sent by the client, then: For PUT requests, the default formatter used (and the Content-Type header that Mediator sends to the Native provider) is application/xml. For POST requests, the default formatter used (and the Content-Type header that Mediator sends to the Native provider) is SOAP (and the request will fail). For GET or DELETE requests (which do not require a Content-Type header), the default formatter used (and the Content-Type header that Mediator sends to the Native provider) is application/x-www-form-urlencoded. |
Mediator receives a response from the REST Service provider | When the provider returns a response to Mediator, a message builder parses the response stream into an Axiom message to be stored in the message context. Mediator determines which message builder to use as follows: 1. Mediator selects the message builder associated with the request's Accept transport header, if one was specified. 2. Else, you can set the BUILDER_TYPE context variable in a webMethods IS REST Service, and invoke this REST Service in the Virtual REST Service’s Invoke webMethods IS REST Service action. Mediator will check that the builder type is a valid Content-Type for the list of builders in axis2.xml. This variable takes priority over the current setting specified in the Accept transport header. That is, Mediator will only use the Accept header to determine the builder type needed to parse a Native provider response if no IS REST Service was written to set the BUILDER_TYPE context variable. 3. Else, Mediator uses the builder associated with the Content-Type specified in the request (assuming that the Content-Type is one of the types that is mapped in axis2.xml). 4. Else, if no Content-Type was specified in the request (for example, a PUT or POST request with no Content-Type, or any GET or DELETE request), or if the Content-Type is not one of the types that is mapped in axis2.xml, then Mediator will default to application/xml. |
Mediator sends a response to the client | Mediator serializes the response and sends it to the client. By default, Mediator uses the formatter that was used to serialize the request sent to the provider. (If the formatter was application/x-www-form-urlencoded (for a GET or DELETE request), then Mediator will instead use application/xml so it can send the response.) You can override the Content-Type that is sent to the client by setting the MESSAGE_TYPE context variable in a webMethods IS REST Service, and invoking this REST Service in the Virtual REST Service’s Invoke webMethods IS REST Service action. |
Scenarios for Requesting JSON Type REST Services
Following are some of the possible scenarios in which JSON type REST Services can be requested. Many scenarios require that you bridge the differences between consumer requests and the Native REST Service (that is, differing HTTP methods and Content-Types). Three of the scenarios are discussed in more detail following the table:
Consumer Sends | Mediator Sends Request to Provider | Mediator Receives Response from Provider | Mediator Sends Response to Consumer | Requirement for Bridging? |
GET | GET | JSON | JSON | Request Processing step bridging |
POST/JSON | POST/JSON | JSON | JSON | No bridging needed |
GET | GET | XML | JSON | Response Processing step bridging |
POST/JSON | GET | JSON | JSON | Request Processing step bridging |
POST/JSON | GET | XML | JSON | Request Processing step bridging and Response Processing step bridging |
POST/JSON | XSLT/GET * | JSON | JSON | Request Processing step bridging |
POST/JSON | XSLT/POST/XML * | XML | XML | Request Processing step bridging |
POST/JSON | POST/JSON | JSON/XSLT * | JSON | Response Processing step bridging |
GET | GET | JSON | XML | Request Processing step bridging and Response Processing step bridging |
POST/XML | POST/JSON | JSON | JSON | Request Processing step bridging |
* The XSLT references indicate where you can perform an XSLT message transformation at either the Request Transformation or Response Transformation action.
In the table above, the required Content-Type settings are not shown, but assume the following:
HTTP Method/Request Content | Required Axis2 Content Type |
GET or DELETE | application/x-www-form-urlencoded |
POST or PUT/XML | application/xml |
POST or PUT/Mapped JSON | application/json |
POST or PUT/Badgerfish | application/json/badgerfish |
JSON Example 1: GET Request, JSON Response
In this example, a consumer sends a GET request to get a Native JSON REST Service. Mediator will send the response to the consumer in the requested JSON format (as indicated by the "output=json" parameter in the query).
The request looks like this:
http://localhost:5555/ws/YahooVS/search?query=wsdl20&output=json
and because this is a GET request, the Content-Type defaults to application/x-www-form-urlencoded.
Note:
For GET or DELETE requests for REST Services, it is not necessary to specify the Content-Type in the request; Mediator will default to application/x-www-form-urlencoded for GET or DELETE requests.
The run-time processing will be as follows:
Consumer Sends | Mediator Sends Request to Provider | Mediator Receives Response from Provider | Mediator Sends Response to Consumer | Requirement for Bridging |
GET | GET | JSON | JSON | Request Processing step bridging |
Since the request is a GET (that is, of Content-Type application/x-www-form-urlencoded), but Mediator expects to receive a JSON stream from the provider, you must send the BUILDER_TYPE application/json to the Native provider. To do this, write and invoke a webMethods IS REST Service in the Virtual REST Service’s Invoke webMethods IS REST Service action. The IS REST Service should include the following predefined context variable set to this value:
Context Variable | Value |
BUILDER_TYPE | application/json |
JSON Example 2: POST/JSON Request, JSON Response (where POST is not supported)
In this example, a consumer sends a POST request (of Content-Type application/json) to a Native REST Service, but the Native REST Service does not support POST.
The request's Content-Type is application/json and its output parameter is set to xml. The reason for this is explained below.
The run-time processing will be as follows:
Consumer Sends | Mediator Sends Request to Provider | Mediator Receives Response from Provider | Mediator Sends Response to Consumer | Requirement for Bridging |
POST/JSON | GET | XML | JSON | Request Processing step bridging Response Processing step bridging |
Configure the Virtual REST Service as follows:
In the Virtual REST Service's Routing Protocols tab, set the value of the HTTP Method field to the value GET. Doing this instructs
Mediator to change the POST to an HTTP GET before
Mediator sends it to the Native REST Service (which is necessary because the Native REST Service does not support POST).
Write and invoke a webMethods IS REST Service in the Virtual REST Service’s
Invoke webMethods IS REST Service action. The IS REST Service should include the following predefined context variables set to the values shown below. The request's
"query": "wsdl20" and
"output": "xml" parameters are transformed into query parameters on the URL before the Native REST Service is invoked. Thus, although the consumer is sending a JSON request, the Native REST Service is instructed to return an XML response to
Mediator.
Context Variable | Value |
MESSAGE_TYPE | application/x-www-form-urlencoded |
BUILDER_TYPE | application/xml |
Write and invoke a webMethods IS REST Service in the Virtual REST Service’s
Invoke webMethods IS REST Service action. The IS REST Service should include the following predefined context variable set to the value shown below. Doing this instructs
Mediator to bridge the XML response from the Native REST Service into JSON format, to be returned to the consumer:
Context Variable | Value |
MESSAGE_TYPE | application/json |
JSON Example 3: GET Request, XML Response
In this example, a consumer sends a GET request to get a Native REST Service. Mediator will send the response to the consumer in the requested XML format (as indicated by the "output=xml" parameter in the query).
The request looks like this:
http://localhost:5555/ws/YahooVS/search?query=wsdl20&output=xml
and because this is a GET request, the Content-Type defaults to application/x-www-form-urlencoded.
The run-time processing will be as follows:
Consumer Sends | Mediator Sends Request to Provider | Mediator Receives Response from Provider | Mediator Sends Response to Consumer | Requirement for Bridging |
GET | GET | JSON | XML | Request Processing step bridging Response Processing step bridging |
Since the request is a GET (that is, of Content-Type application/x-www-form-urlencoded), but Mediator expects to receive a JSON stream from the provider, you must instruct Mediator to send the BUILDER_TYPE application/json to the Native provider. To do this, write and invoke a webMethods IS REST Service in the Virtual REST Service’s Invoke webMethods IS REST Service action. The IS REST Service should include the following predefined context variable set to this value:
Context Variable | Value |
BUILDER_TYPE | application/json |
Since the provider will return a JSON stream to Mediator, but the consumer expects to receive the REST Service in XML output format, you must set the MESSAGE_TYPE to application/xml. To do this, write and invoke a webMethods IS REST Service in the Virtual REST Service’s Invoke webMethods IS REST Service action. The IS REST Service should include the following predefined context variable set to this value:
Context Variable | Value |
MESSAGE_TYPE | application/xml |
Characteristics of the Mapped and Badgerfish JSON Conventions
The open source library that Axis2 uses to support JSON is called Jettison. The Jettison library supports two formats of JSON: Mapped JSON and Badgerfish. Both are syntactically correct from a JSON perspective. However, for Axis Free Mediation, we only support Mapped JSON.
Note:
An important difference between the two is that the Mapped convention returns a REST Service fault if a Virtual REST Service is configured for application/json (Mapped convention) and it encounters a message that has namespaces, while the Badgerfish convention attempts to avoid losing any meaning encoded in XML by preserving namespace declarations. The Axis2 JSON library MessageFormatter will complain if Mediator attempts to transform an XML response that contains namespace declarations. So, either make sure that the requests do not include namespaces, or else set the MESSAGE_TYPE to application/json/badgerfish instead of setting it to application/json.
Other characteristics include the following:
Mapped JSON Convention
1. An element with no characters or child elements is represented by:
{ "element" : "" }
2. No namespaces declarations are ever written.
Note:
The Badgerfish convention does allow namespaces. If a client sends a request that contains XML namespaces, you need to bridge to the Badgerfish convention. To do this, in the Virtual REST Service's Set Headers action, set the parameter Set Headers to Header and specify the Name as Content-Type and the Value as application/json/badgerfish. Doing this will override the existing Content-Type that will be sent to the Native provider.
3. An element with multiple child elements of the same name is represented by an array.
Simple case:
<price>10.00</price>
{ "acme.price" : { "10.00" }
Array case:
<root><child>test</child><child>test</child></root>
{ "root" : { "child" : [ "test", "test" ] } }
4. The XML attributes for a message are prefixed with @ when a message is serialized (same as Badgerfish).
Badgerfish Convention
This convention is used to provide the means to translate between XML and JSON without losing any data (that is, namespaces).
1. Element names become object properties.
2. Text content of elements goes in the $ property of an object.
3. Nested elements become nested properties.
4. Multiple elements at the same level become array elements.
5. Attributes go in properties whose names begin with @.
6. Active namespaces for an element go in the element's @xmlns property.
7. The default namespace URI goes in @xmlns.$.
8. Other namespaces go in other properties of @xmlns.
9. Elements with namespace prefixes become object properties, too.
Simple example:
<price xmlns="http://acme.com">10.00</price>
{ "price": { "@xmlns": { "$": "http://acme.com" }, "$1": "10.00" } }
A more complex example:
<alice xmlns="http://some-namespace"
xmlns:charlie="http://another-namespace">
<bob>david</bob>
<charlie:edgar>frank</charlie:edgar>
</alice>
{ "alice" : { "bob" : { "$" : "david" , "@xmlns" :
{"charlie" : "http://another-namespace" , "$" : "http://some-namespace"} } ,
"charlie:edgar" : { "$" : "frank" , "@xmlns" :
{"charlie":"http://another-namespace", "$" : "http://some-namespace"} },
"@xmlns" : { "charlie" : "http://another-namespace", "$" : "http://some-nam
espace"} } }
Multiple Root Nodes in JSON REST Services
With REST Virtual REST Services, when working with requests and responses of the Content-Type application/json, the message content can contain one or more root nodes. For example, a message might have the two root nodes {“firstName": “John”, “lastName”: “Smith”}. Note the following points for messages with multiple root nodes:
The XSLT provided in the Request/Response Processing step should have the XPath start with
//, for example
//firstName. This is because during the processing of the JSON content,
Mediator will wrap the given content with system-defined elements.
webMethods IS REST Services that you invoke in the Request/Response Processing step will contain the JSON content in the variable called
JSONRESTContentString. You can update the content in the IS REST Service and put the updated content into the pipeline's input variable
UpdatedJSONRESTContentString, which will be sent to the Native REST Service.
Handling Virtual REST Services with Multiple Resources
The enhanced REST framework of CentraSite Business UI allows you to explicitly define multiple resources for a RESTful REST Service. Each resource within the REST Service exposes a unique URI for performing the CRUD operations on the resource.
CentraSite provides the resource path tokenizer to support the multiple resources handling at run-time. The tokenizer for substituting a resource path is automatically appended to the REST Service’s endpoint (base URL) by a path variable ${sys:resource_path}. When there are multiple resources defined for an REST Service, at run time, Mediator replaces the resource path tokenizer with the appropriate resource path that is defined for the particular resource call.
Important:
Beginning with version 9.7, CentraSite supports the multi-resource handling of the REST interface at run-time (in contrast, earlier versions of CentraSite supported a single resource handling). Note that the enhanced REST interface that is implemented by current version of CentraSite is not compatible with the interface that was implemented by previous versions of Mediator prior to version 9.7. However, if you still attempt to publish a Virtual REST Service with multiple resources to an earlier version of Mediator instance, Mediator throws an exception message.
Let's now learn about the usage of resource path tokenizers in CentraSite by looking at a couple of examples using our sample phone store REST Service.
Consider you have a plain REST Service PhoneStoreREST Service with a defined set of resources for performing the CRUD operations.
Assume you have the PhoneStore REST Service with the following configuration details:
Base URL:
http://www.phonestore.com/REST Service
Resource:
phones
Resource URI:
/phones
Native Endpoint:
http://www.phonestore.com/REST Service/phones
Beginning with version 9.7, on a Virtual copy of this REST Service, CentraSite appends the resource path tokenizer ${sys:resource_path} to represent its Route to endpoint like this:
http://www.phonestore.com/REST Service/${sys:resource_path}
In the aspect of this resource path tokenizer, there are two principal scenarios, when consumers attempt to model Virtual REST Services with multiple resources.
Scenario A
Consider you have a Virtual REST Service created using the current version of CentraSite, this REST Service will have the Route to endpoint of the Straight-Through/Content-Based/Content-Based Routing action, by default, appended with a resource path tokenizer. The Route to endpoint assigned by CentraSite has the format <base-url>/${sys:resource_path}, where the resource_path is the same as the original resource URI defined in the REST Service’s first resource definition.
Whenever you try to add a new resource to this REST Service, the endpoint is automatically assigned and sent to Mediator for processing inside a Virtual REST Service Definition (VSD) in the prescribed format. At run time, when a HTTP request is received for the resource, that request will be sent to the endpoint dynamically substituted with the path variable. This dynamic substitution of the endpoint indicates that the REST interface is enhanced to support multiple resources.
Scenario B
Consider you have a Virtual REST Service created in versions of CentraSite prior to 9.7, this REST Service will continue to exhibit the old REST behavior, that is, it will continue to send the HTTP requests to the Native REST Service endpoint using the resource URI defined in the earlier version.
Now consider our sample PhoneStore REST Service with two different formats of resource URIs, say, /phones, /invoke
Now, whenever you try to add a new resource to this REST Service, CentraSite performs an internal validation of the existing resource URI. Depending on the validation, CentraSite handles the HTTP request in the following way:
Endpoint exactly ends with the existing resource URI - Resource URI
/phones. In this case, the URI is automatically substituted with the tokenizer. This ensures that the
Mediator processes the HTTP request and routes the request to the appropriate Native REST Service endpoint for the requested resource.
Endpoint does not exactly end with the existing resource URI - Resource URI
/invoke. In this case, the URI is not substituted with the tokenizer and eventually results in a failure alert.
Now, based on the routing configuration for the Native REST Service, you have the following workaround options:
Straight-Through Routing Action - Straight-Through Routing Action
Workaround Option 1
Modify the Straight-Through routing action of the Native REST Service.
1. In CentraSite Business UI, access the Advanced Search panel in one of the following ways:
Click the
Browse link in the upper-left corner of the menu bar.
Click the
Search icon next to the
Scope list. The default search scope is
Assets.
A list of defined assets in CentraSite (for which you have the View permission) is displayed in the Search Results page.
2. In the Additional Search Criteria list, select Asset Types.
3. To search for the assets of type, REST Service, click Choose.
4. In the Choose Asset Types dialog box, select the Assets option button, and follow these steps:
a. Click the chevron next to Assets option button.
b. In the displayed list of asset types, select REST Service.
c. Click OK.
5. In the displayed list of REST Services, click the REST Service you want to Virtualize.
The REST Service Details page is displayed. The Actions bar displays a set of actions that are available for working with the REST Service.
6. On the Actions bar of the REST Service, click the Virtualize icon.
7. In the Virtualize <REST Service_Name> (Step 1 of 3) wizard, select the Virtual REST Service alias and it’s endpoint for reconfiguration.
8. Click Next.
9. In the Virtualize <REST Service_Name> (Step 2 of 3) wizard, locate the Straight-Through routing action in the Message Flow section.
10. Hover over the action name, and click the Configure icon next to the action name.
This opens the Straight-Through Routing dialog box.
11. In the Route to endpoint field, modify the existing endpoint. Append the resource path tokenizer ${sys:resource_path} with the base URL in the format <base-url>/${sys:resource_path}.
Thus, for our sample endpoint:
http://www.phonestore.com/REST Service/phones
The modified endpoint should be:
http://www.phonestore.com/REST Service/${sys:resource_path}
12. Click OK and save the modified REST Service.
13. If you choose to use this option, in addition to the above steps in CentraSite Business UI, you must consider one of the following:
Modify the Native REST Service implementation to reconfigure the endpoint and resource URI.
In the details page of the Native REST Service, edit the resource URI to exactly match with the endpoint. Thus for our example, modify the resource URI to read
/phones. In addition, you must inform the clients of changes that have been made to the endpoint and resource URI.
Workaround Option 2
Convert the Straight-Through Routing action of the Native REST Service to either a Context-Based Routing or Content-Based Routing action.
To convert the Straight-Through routing action
1. In CentraSite Business UI, access the Advanced Search panel in one of the following ways:
Click the
Browse link in the upper-left corner of the menu bar.
Click the
Search icon next to the
Scope list. The default search scope is
Assets.
A list of defined assets in CentraSite (for which you have the View permission) is displayed in the Search Results page.
2. In the Additional Search Criteria list, select Asset Types.
3. To search for the assets of type, REST Service, click Choose.
4. In the Choose Asset Types dialog box, select the Assets option button, and follow these steps:
a. Click the chevron next to Assets option button.
b. In the displayed list of asset types, select REST Service.
c. Click OK.
5. In the displayed list of REST Services, click the REST Service you want to Virtualize.
The REST Service Details page is displayed. The Actions bar displays a set of actions that are available for working with the REST Service.
6. On the Actions bar of the REST Service, click the Virtualize icon.
7. In the Virtualize <REST Service_Name> (Step 1 of 3) wizard, select the Virtual REST Service alias and it’s endpoint for reconfiguration.
8. Click Next.
9. In the Virtualize <REST Service_Name> (Step 2 of 3) wizard, locate the Straight-Through Routing action in the Message Flow section.
10. Hover over the action name, and click the Delete icon next to the action name.
11. Drag and drop the Content-Based Routing action or the Context-Based Routing action from the Policy Actions accordion to the Message Flow section.
12. Configure the Content-Based Routing action or the Context-Based Routing action as described later in this topic.
Content-Based Routing Action
Given the Content-Based Routing action, specify a custom routing rule. Perform the following steps:
1. In CentraSite Business UI, access the Advanced Search panel in one of the following ways:
Click the
Browse link in the upper-left corner of the menu bar.
Click the
Search icon next to the
Scope list. The default search scope is
Assets.
A list of defined assets in CentraSite (for which you have the View permission) is displayed in the Search Results page.
2. In the Additional Search Criteria list, select Asset Types.
3. To search for the assets of type, REST Service, click Choose.
4. In the Choose Asset Types dialog box, select the Assets option button, and follow these steps:
a. Click the chevron next to Assets option button.
b. In the displayed list of asset types, select REST Service.
c. Click OK.
5. In the displayed list of REST Services, click the REST Service you want to Virtualize.
The REST Service Details page is displayed. The Actions bar displays a set of actions that are available for working with the REST Service.
6. On the Actions bar of the REST Service, click the Virtualize icon.
7. In the Virtualize <REST Service_Name> (Step 1 of 3) wizard, select the Virtual REST Service alias and it’s endpoint for reconfiguration.
8. Click Next.
9. In the Virtualize <REST Service_Name> (Step 2 of 3) wizard, locate the Straight-Through Routing action in the Message Flow section.
10. Hover over the action name, and click the Configure icon next to the action name. This opens the Content-Based Routing dialog box.
11. In the Default Route to endpoint field, modify the existing endpoint. Append the resource path tokenizer ${sys:resource_path} with the base URL in the format <base-url>/${sys:resource_path}.
Thus, for our sample endpoint:
http://www.phonestore.com/REST Service/phones
The modified endpoint should be:
http://www.phonestore.com/REST Service/${sys:resource_path}
12. Click the Add Routing Rule button. In the Routing Rule dialog box, complete the following fields:
In the
XPath Expression field, specify an XPath expression unique to the resource.
Add a namespace value in the
Prefix and
URI fields.
In the
Route To field, specify the Native REST Service endpoint.
In our sample,
http://www.phonestore.com/REST Service/phones
Click
OK to save the new routing rule.
13. Click OK and save the modified REST Service.
Context-Based Routing Action
Given the Context-Based Routing action, specify a custom routing rule. Perform the following steps:
1. In CentraSite Business UI, access the Advanced Search panel in one of the following ways:
Click the
Browse link in the upper-left corner of the menu bar.
Click the
Search icon next to the
Scope list. The default search scope is
Assets.
A list of defined assets in CentraSite (for which you have the View permission) is displayed in the Search Results page.
2. In the Additional Search Criteria list, select Asset Types.
3. To search for the assets of type, REST Service, click Choose.
4. In the Choose Asset Types dialog box, select the Assets option button, and follow these steps:
a. Click the chevron next to Assets option button.
b. In the displayed list of asset types, select REST Service.
c. Click OK.
5. In the displayed list of REST Services, click the REST Service you want to Virtualize.
The REST Service Details page is displayed. The Actions bar displays a set of actions that are available for working with the REST Service.
6. On the Actions bar of the REST Service, click the Virtualize icon.
7. In the Virtualize <REST Service_Name> (Step 1 of 3) wizard, select the Virtual REST Service alias and it’s endpoint for reconfiguration.
8. Click Next.
9. In the Virtualize <REST Service_Name> (Step 2 of 3) wizard, locate the Straight-Through Routing action in the Message Flow section.
10. Hover over the action name, and click the Configure icon next to the action name. This opens the Context-Based Routing dialog box.
11. In the Default Route to endpoint field, modify the existing endpoint. Append the resource path tokenizer ${sys:resource_path} with the base URL in the format <base-url>/${sys:resource_path}.
Thus, for our sample endpoint:
http://www.phonestore.com/REST Service/phones
The modified endpoint should be:
http://www.phonestore.com/REST Service/${sys:resource_path}
12. Click the Add Routing Rule button and provide the following information:
Type a name for the new routing rule.
For the
Variable field, select
Predefined Context Variable from the drop-down list.
In the
Condition section of the dialog box, perform the following steps.
Select
String in the first
Data Type field.
Select the
Virtual REST Service Operation in the second
Predefined Context field.
Specify the
Equal To operator in the third field.
Specify the exact resource name in the
Variable Value field. In our example,
invoke.
In the
Route To field, specify the Native REST Service endpoint.
In our sample,
http://www.phonestore.com/REST Service/phones
Click
OK to save the new routing rule.
13. Click OK and save the modified REST Service.