Apama 10.3 | Apama Documentation | Connecting Apama Applications to External Components | Working with Connectivity Plug-ins | Developing Connectivity Plug-ins | Map contents used by the apama.eventMap host plug-in
Map contents used by the apama.eventMap host plug-in
The payloads that the apama.eventMap generates for transportward messages and that it requires for hostward messages are maps. For Java chains, this is java.util.Map<Object, Object>. For C++ chains, this is a map_t.
Each key in the map is the name of a field in the EPL event definition and the value the corresponding EPL value. Each event containing other events is represented as a Map value within the top-level field, allowing nesting of events, dictionaries and sequences. For events sent from chains into the correlator, all fields must have non-empty values and must be present as keys in the map, unless the configuration setting allowMissing is set to true. Keys that do not correspond to fields are ignored by default. There is an exception: an empty value that maps to an optional<type> or any in EPL is permitted even if allowMissing is false (see also the descriptions of the optional and any types in the API Reference for EPL (ApamaDoc) ).
Events can be annotated with the com.softwareag.connectivity.ExtraFieldsDict annotation (see Adding predefined annotations) which names a dictionary field, in which case any unmapped keys are placed into this dictionary field. This can be disabled with the extraFields configuration property. The dictionary must be one of:
*dictionary<string,string> - Keys and values are coerced into strings. Lists generate the string form of sequence<string>. Maps generate the string form of dictionary<string,string>.
*dictionary<any,any> - Values are mapped to the corresponding EPL type, or sequence<any> for lists and dictionary<any,any> for maps without names.
*dictionary<string,any> - Keys are coerced into strings. Values are mapped as described above.
The types are converted as described below:
EPL type
Transportward events will contain Java or C++ type
Hostward events can also convert from types
java.util.Map or map_t
java.util.Map or map_t
java.util.List or list_t
java.util.Map or map_t (keys are x1, y1, x2, y2)
java.lang.String or const char* (if it is a string channel)
java.lang.String or const char*
all numeric types, boolean
java.lang.Long or int64_t
all numeric types (except NaN float values), strings if they can be parsed as an integer
java.lang.Double or double
all numeric types, strings if they can be parsed as a float
java.math.BigDecimal (but see the notes below) or decimal_t
all numeric types, strings if they can be parsed as a float
java.lang.Boolean or bool
string, if true or false
EPL values of type optional<T> translate into one of the following:
*null or corresponding Java type (see the above conversions), or
*a data_t that is either empty or of type T (see the above conversions).
A Java object or data_t that corresponds to an EPL value of type optional<T> is translated if
*the Java object is null or of type T,
*data_t is empty or of type T.
EPL values of type any translate into one of the following:
*null or corresponding Java type (see the above conversions), or
*a data_t that is either empty or of the underlying concrete type (see the above conversions).
See also the note below for Event mappings.
A Java object or data_t that corresponds to an EPL value of type any is translated if
*the Java object is null or of a concrete type (see above),
*data_t is empty or of a concrete type (see above).
See also the note below for Event mappings.
Note: An any type containing an Event is represented as either com.softwareag.connectivity.NamedMap or map_t and the name field is set to the event type.
Non-native conversions (a floating point to integer conversion or vice versa) may lose precision, and conversions to/from strings or decimals are more expensive than float or integer conversions. If anything other than an exact match is found, a debug-level log message is generated; you may wish to verify that there are none if the conversion is performance-sensitive.
The following applies to Java only: an EPL decimal value which is NaN (not a number) or an infinity is mapped to/from a Double representation of NaN or infinity, as the BigDecimal Java type does not support them.
Events containing the following types cannot be sent into the correlator, as they cannot be serialized:
*action variables
Events containing the following can be sent in, provided allowMissing is set to true in the host plug-in configuration and no value is provided for that field:
Events containing cycles cannot be sent into or out of the correlator, but arbitrary nesting is permitted. Aliases will be flattened.
For Java plug-ins, handling messages from the apama.eventMap plug-in thus involves casting the payload of the message from Object to Map, and then accessing members of that, casting as necessary (or, for flexibility, introspecting their types by using the instanceof operator). For example, for the following event definition, the CustomerOrder is translated to a map with deliveryAddress, userId and items keys, and items will be a list of maps containing itemId, price and qty.
event LineItem {
string itemId;
float price;
integer qty;
event CustomerOrder {
string deliveryAddress;
string userId;
sequence<LineItem> items;
To print the total cost of an order (sum of product of qty and price for each item), the Java code would be as follows:
public void deliverMessageTowardsTransport(Message message) {
Map payload = (Map) message.getPayload();
List<Map> items = (List<Map>) payload.get("items");
double total = 0.0;
for(Map item : items) {
double price = MapHelper.getDouble(item, "price");
long qty = MapHelper.getInteger(item, "qty");
total = total + price * qty;
logger.info("Order value is "+total);
Note that due to type erasure, the type parameters on Map or List are not checked or guaranteed. In the above example, it is convenient to cast the list representing EPL field sequence<LineItems> to List<Map> to avoid having to cast the entries within it. The Map, however, is still treated as a map of objects as it has different types (String, Double, Long) in it.
For C++ plug-ins, handling messages from the apama.eventMap plug-in involves using the get<map_t> function and accessing the members of that, using get<> as necessary. If code needs to be flexible as to which type it accepts, then use the visitor pattern (see C++ data types). For example, using the event definition above, the following C++ code will print the total cost of the order:
virtual void deliverMessageTowardsTransport(Message &message) {
map_t &payload = get<map_t>(message.getPayload());
list_t &items = get<list_t>(payload[data_t("items")]);
double total = 0.0;
for(auto it = items.begin(); it != items.end(); it++) {
map_t &item = get<map_t>(*it);
double price = MapHelper::getDouble(item, "price");
long qty = MapHelper::getInteger(item, "qty");
total = total + price * qty;
logger.info("Order value is %f", total);
The following constructs and sends an order with one line item into the correlator:
Map<String,Object> payload = new HashMap<>();
payload.put("deliveryAddress", "1 Roadsworth Avenue");
payload.put("userId", "jbloggs");
List<Map> items = new ArrayList<>();
Map<String,Object> item = new HashMap<String,Object>();
item.put("itemId", "item1");
item.put("price", 3.14);
item.put("qty", 10);
payload.put("items", items);

Map<String, String> metadata = new HashMap<String, String>();
metadata.put(Message.HOST_MESSAGE_TYPE, "CustomerOrder");
Message msg = new Message(payload, metadata);
The above can also be written more compactly:
This would typically be done in a more automated fashion, translating data from some other form, rather than laboriously setting each field as needed - though some combination will often be needed.
The equivalent C++code is:
map_t payload;
payload.insert(data_t("deliveryAddress"), data_t("1 Roadsworth Avenue"));
payload.insert(data_t("userId"), data_t("jbloggs"));
list_t items;
map_t item;
item.insert(data_t("itemId"), data_t("item1"));
item.insert(data_t("price"), data_t(3.14));
item.insert(data_t("qty"), data_t((int64_t) 10));
payload[data_t("items")] = data_t(std::move(items));

Message msg(data_t(std::move(payload)));
msg.putMetadataValue(Message::HOST_MESSAGE_TYPE(), "CustomerOrder");
hostSide->sendBatchTowardsHost(&msg, (&msg)+1);

Copyright © 2013-2018 | Software AG, Darmstadt, Germany and/or Software AG USA, Inc., Reston, VA, USA, and/or its subsidiaries and/or its affiliates and/or their licensors.