The JSON codec connectivity plug-in
The JSON codec can be used if you have a transport that is dealing with messages in the JSON format and you want your EPL application to be able to interact with it by sending and listening for events. It does not matter whether the transport
takes JSON-formatted data from an external system and sends it towards the host, or
wants to be given JSON-formatted data from the direction of the host, and then sends it to an external system, or
even does both of the above.
The JSON codec does bidirectional translation between JSON documents in the payload of a message (transport side) and an object in the payload of a message (host side). If the JSON codec is adjacent to the eventMap plug-in, then the JSON document on the transportwards side should be an object with fields for the event members. The Mapper codec can help move fields to match the event structure, map parts of the metadata into the payload, and support JSON values other than objects.
For example, a JSON document like
{"a":2,"b":["x","y","z"]}
on the transport side corresponds to a java.util.Map (Java) or map_t (C++) on the host side. This java.util.Map or map_t maps a string to an integer for one map entry and a string to a list of strings for the other entry. When the apama.eventMap host plug-in sees an object like this, it will be able to map it to/from an EPL event type such as the following:
event E {
integer a;
sequence<string> b;
}
The above assumes that either
metadata.sag.type is set to
E (see also
Metadata values) or the
apama.eventMap host plug-in has been configured with
defaultEventType: E. Remember that this is completely bidirectional.
Taking a closer look at the inbound response, a typical chain would start with the HTTP client transport (see also
The HTTP Client Transport Connectivity Plug-in). This transport returns a byte array containing the response body which is normally transformed into a UTF-8 string using the String codec (see also
The String codec connectivity plug-in). This UTF-8 string, held in the payload, is then passed to the JSON codec and transformed into a data structure that the JSON represents. At this point, the
metadata.http map holds the headers and other elements of the HTTP response, and is used to set the
metadata.sag.type and add to the response payload. After the mapping rules have been applied, the payload is passed to the
apama.eventMap host plug-in and converted to the event that is defined in the
metadata.sag.type.
The apama.eventMap host plug-in can convert a map into an event. This map will either be created from the JSON if it contains an object, or it will need to be created by mapping in the chain. In the example below, we get a JSON object in the response and it maps to the EPL event shown:
// Example response payload contains a JSON object.
response = {"hostname":"host","name":"correlator","value":"expected value"}
// Maps to HTTPResponse event putting "value" into extra fields dictionary
// and adding the id from metadata.
HTTPResponse(id,"host","correlator",{value:"expected value"})
The top-level value in the JSON will normally be an object, which can be mapped directly to an Apama event. However, it is also possible to use other JSON types such as string, array, boolean or number. In those cases, you will need to map the decoded payload before it can be received by Apama. For example:
// Other valid JSON responses that require mapping
// payload = "valid"
// payload = 3.14
// payload = []
HTTPResponse:
towardsHost:
mapFrom:
- payload.contents: payload
// The event can define a field or use @ExtraFieldsDict
// and provide a map for the contents.
event MyEvent{ any contents; }
It is not supported to have a JSON null as the top-level value in the payload. Empty payloads are treated as special control messages in connectivity chains and the JSON codec will ignore such messages. Nulls can occur elsewhere in the JSON structure and will be mapped to the empty any type in EPL.
The content of the event that forms the JSON request will be transformed similarly, so care needs to be taken over how the content will end up in the request JSON:
event Example{}
// Creates an empty JSON object in the payload.
{}
// Any and Optional need careful handling if the values
// are not set. They default to null.
event Example{ optional<string> test1; any test2 }
// Maps to
{"test1":null,"test2":null}
Since the JSON standard does not permit floating point
special values such as Infinity and NaN (see
Support for IEEE 754 special values), float fields containing such values are represented as strings when generating JSON using this codec. For example, this is represented as
[1.2, 3.4, "Infinity", "NaN"] in the generated JSON. If you need different handling of special values (for example, representing them as a JSON
null), add a custom codec to your connectivity chain before the JSON codec to make any necessary conversions. In the other direction, when parsing JSON, the codec gives an error if requested to parse one of these special values that is not wrapped as a string.
There are two identically behaving versions of the JSON codec, one implemented using C++ and the other implemented using Java. The C++ version of the codec has the same behavior as the Java version, but it usually gives a better performance. In particular, changing between Java and C++ is expensive, so you should match the implementation language of the codec to that of the adjacent codecs. See
Deploying plug-in libraries for more information.
A Java sample is provided in the samples/connectivity_plugin/java/JSON-Codec directory of your Apama installation. This provides a more detailed end-to-end example of this codec (along with the source code to this codec), which allows an EPL application to consume and emit JSON as EPL events.
To reference the JSON codec, an entry such as the one below is required in the
connectivityPlugins section of the configuration file (see also
Configuration file for connectivity plug-ins). You can then just have a JSON codec in a chain in between the host and a transport. No configuration is required for this plug-in.
Configuration file entry for Java:
jsonCodec:
directory: ${APAMA_HOME}/lib/
classpath:
- json-codec.jar
class: com.softwareag.connectivity.plugins.JSONCodec
Configuration file entry for C++:
jsonCodec:
libraryName: connectivity-json-codec
class: JSONCodec
The following configuration option is available for the JSON codec:
Configuration option | Description |
filterOnContentType | This option can be used in chains which have multiple messages of different types through the chain with a transport or mapper configuration which is setting the metadata.contentType field in the messages. It allows the JSON codec to only process messages which (hostwards) are correctly encoded in JSON or (transportwards) should be encoded in JSON. Other messages need to be handled by another codec in the chain which will handle non-JSON-encoded messages. If set to true and the metadata.contentType is set to anything that does not match the pattern "^application/([^/]*[+])?json(;[^=;]+=(\".*\"|[^=;]+))*$", or if it is not set, then the codec will ignore the event in either direction and pass it on unmodified. If set to false, then the codec will attempt to process the message no matter what the value of metadata.contentType is. Default: false. |
Note:
Equivalent functionality is available with the JSON EPL plug-in. See
Using the JSON plug-in for detailed information.