The mechanism for encoding event payloads in WSRP is somewhat ambiguously defined in the WSRP 2.0 specification and could use some clarification.

Relevant statements from the specification

Event Payload Description

Section 4.1.11 of the specification contains the following descriptions:

name: A namespaced name for the event being described. If this event's payload is not carried within the NamedStringArray alternative of the EventPayload structure, this name also becomes the XML element name carrying the payload with the type field defining the type of the element.

aliases: An array of the QNames of events known to be semantically equivalent to this event. While this can provide a hint to the Consumer concerning potential items that could be correlated with this event, it remains the Consumer's responsibility do any transformations required to produce the described event.

type: A[n optional] reference to a schema-defined payload the event will carry at runtime. If the type is not supplied, the Consumer SHOULD treat this as an opaque event payload. Note that this includes those events which are signals and therefore carry no payload.

Event Descriptions

Section 4.1.24 of the specification contains the following descriptions:

eventDescriptions: This array of EventDescription structures, with unique event names, describes the events the Portlets hosted at the Producer could either generate or handle. These descriptions match events at runtime via the event name, with it being an error for an event's type to not match the type from the EventDescriptions with the matching event name. This information is provided to assist the Consumer in pre-determining the flow of events between its constituents. While this list is not required to be exhaustive (i.e. the Portlet may generate an event it has not described), not describing an event greatly reduces its ability to be distributed by some Consumers' event distribution systems.

From the wsrp-2.0-types.xsd schema

<complexType name="EventPayload">
  <sequence>
    <element name="namedStringArray"  type="types:NamedStringArray" minOccurs="0"/>
    <any     namespace="##other"      minOccurs="0" processContents="lax"/>
  </sequence>
</complexType>

<complexType name="Event">
  <sequence>
    <element name="payload"    type="types:EventPayload" minOccurs="0"/>
    <element name="extensions" type="types:Extension"    minOccurs="0" maxOccurs="unbounded"/>
  </sequence>
  <attribute name="name"       type="xsd:QName"  use="required"/>
  <attribute name="type"       type="xsd:QName"  use="optional"/>
</complexType>

Use Cases

  1. No payload
    • The event is signal only, no payload is associated with it.
  2. Simple Payload (E.g. string, int ...)
    • An event with a simple type defined as a xsd base type is sent.
  3. Complex Payload (E.g. Postal Address)
    • An event with a user or spec defined complex type is sent.
  4. Undeclared Payloads
    • An event is sent where the type attribute is not declared.
  5. Undeclared Events
    • An event is sent which was not declared in the portlet description.
  6. Consumer transformation of payloads
    1. The source and sink have the same simple type, but different QNames.
    2. The source and sink have the same complex type, but different QNames.
    3. The source and sink have different simple types and QNames.
    4. The source and sink have different complex types and QNames.

Issues

  1. Having the event name become the XML element name carrying the payload is incompatible with the schema requirement of namespace "##other" in the case where the XML element namespace is empty, as the "##other" namespace cannot be empty by XSD spec.
  2. There is a conflict between alias-induced renaming of events on the consumer and treating the event payloads as opaque if the payload type is not declared, since the payload XML element name is the event name and therefore would need to be changed by the consumer when the event was renamed to match an alias.
  3. It is likely that the most common event payload types will be "simple" types such as strings or integers, but the specification has no mechanism for recognizing these types in a manner consistent across implementations. Because these simple payload types are likely the most common event payloads, it would be very useful to have a common means of declaring these simple types so that all consumer / producer implementations could recognize them, as well as a common means of marshalling / unmarshalling these simple payload types to the WSRP event payload.
  4. The JSR286 Java Portlet specification requires that all event payloads are JAXB-bindable or are supported JAXB primitive types, the latter falling under issue #3. By default, JAXB recognizes XML representation of objects through recognition of XML element names, making it harder (but not impossible) to have JAXB unmarshal event payloads when the root element has been renamed to match the event name.

Options

  1. Keep the existing specification wording with further clarifications
    • To solve issue 1, requires modifying the wsrp-2.0-types schema to allow any namespace for event payload elements, with a statement that the payload element namespace MUST NOT be the WSRP 2.0 namespace.
    • To solve issue 2, requires clarification that the consumer is allowed and expected to rename event payload elements when renaming an event for alias-matching.
    • To solve issue 3, requires:
      • additional declaration of simple payload types that consumers and producers can recognize if they so choose.
      • additional declaration of how the simple types are marshalled to XML elements.
      • Require xsi:type on the payload's child element. This will help the receiving container to parse the event.
    • No real solution for issue 4 (although it is solvable through more complex JAXB configuration).
  2. Declare that the event payload root element is a "wrapper" for the actual payload which is contained within.
    • To solve issue 1, requires modifying the wsrp-2.0-types schema to allow any namespace for event payload elements, with a statement that the payload element namespace MUST NOT be the WSRP 2.0 namespace.
    • To solve issue 2, declare that the consumer may change the name of the "wrapper" payload element when renaming an event for alias-matched delivery.
    • To solve issue 3, a declaration of simple payload type schema types could be made, with the simple type marshalled as the appropriate XML type directly within the "wrapper" element.
    • Solves issue 4, as JAXB can be pointed at the element within the "wrapper" for unmarshalling.
  3. Remove the requirement that the event payload XML root element name is the same as the event name.
    • Solves issue 1 as long as the consumer / producer creating the event payload root element does not use an empty namespace.
    • Solves issue 2 as there is no need for the consumer to rename an event payload root element when renaming an event for alias-matched delivery.
    • To solve issue 3, a declaration of simple payload type schema types could be made, with the simple type marshalled as the appropriate XML type directly within a well-known "wrapper" root payload element.
    • Solves issue 4 as JAXB can recognize the event payload based on element name alone.

Samples

Use Case 2: Simple Type

Send an event named {urn:producer1}hello with a string payload.

Option 1:

   1   <v2:event xmlns:p1="urn:producer1" name="p1:hello" type="xsd:string">
   2    <v2:payload>
   3      <p1:hello xsi:type="xsd:string">World</p1:hello>
   4    </v2:payload>
   5   </v2:event>

Option 2:

   1   <v2:event xmlns:p1="urn:producer1" name="p1:hello" type="xsd:string">
   2    <v2:payload>
   3      <p1:hello><extra:string>World</extra:string></p1:hello>
   4    </v2:payload>
   5   </v2:event>

Option 3:

   1   <v2:event xmlns:p1="urn:producer1" name="p1:hello" type="xsd:string">
   2    <v2:payload>
   3      <extra:string>World</extra:string>
   4    </v2:payload>
   5   </v2:event>

Use Case 3: Complex Type

Send an event named {urn:producer1}foundIt with a Postal payload.

XSD:

   1 <schema targetNamespace="urn:oasis:wsrp:sample"
   2         xmlns:sample="urn:oasis:wsrp:sample"
   3 
   4         xmlns="http://www.w3.org/2001/XMLSchema"
   5         xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   6         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   7 
   8         elementFormDefault="qualified">
   9   <import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd" />
  10 
  11   <complexType name="Postal">
  12     <sequence>
  13       <element name="name"         type="xsd:string"      minOccurs="0"/>
  14       <element name="street"       type="xsd:string"      minOccurs="0"/>
  15       <element name="city"         type="xsd:string"      minOccurs="0"/>
  16       <element name="stateprov"    type="xsd:string"      minOccurs="0"/>
  17       <element name="postalcode"   type="xsd:string"      minOccurs="0"/>
  18       <element name="country"      type="xsd:string"      minOccurs="0"/>
  19       <element name="organization" type="xsd:string"      minOccurs="0"/>
  20       <element name="extensions"   type="types:Extension" minOccurs="0" maxOccurs="unbounded"/>
  21     </sequence>
  22     <attribute name="ref" type="xsd:string"/>
  23   </complexType>
  24 
  25   <element name="postal" type="sample:Postal"/>
  26 </schema>

Option 1:

   1   <v2:event xmlns:p1="urn:producer1" xmlns:sample="urn:oasis:wsrp:sample" name="p1:foundIt" type="sample:Postal">
   2    <v2:payload>
   3      <p1:foundIt xsi:type="sample:Postal" ref="myHouse">
   4        <sample:name>My House</sample:name>
   5        <sample:country>US</sample:country>
   6      </p1:foundIt>
   7    </v2:payload>
   8   </v2:event>

Option 2:

   1   <v2:event xmlns:p1="urn:producer1" xmlns:sample="urn:oasis:wsrp:sample" name="p1:foundIt" type="sample:Postal">
   2    <v2:payload>
   3      <p1:foundIt>
   4        <sample:postal ref="myHouse">
   5         <sample:name>My House</sample:name>
   6         <sample:country>US</sample:country>
   7        </sample:postal>
   8      </p1:foundIt>
   9    </v2:payload>
  10   </v2:event>

Option 3:

   1   <v2:event xmlns:p1="urn:producer1" xmlns:sample="urn:oasis:wsrp:sample" name="p1:foundIt" type="sample:Postal">
   2    <v2:payload>
   3        <sample:postal ref="myHouse">
   4         <sample:name>My House</sample:name>
   5         <sample:country>US</sample:country>
   6        </sample:postal>
   7    </v2:payload>
   8   </v2:event>

Proposal

  1. Remove this sentence:
    • If this event's payload is not carried within the NamedStringArray alternative of the EventPayload structure, this name also becomes the XML element name carrying the payload with the type field defining the type of the element.

  2. To maximize interoperability:
    1. Portlets SHOULD NOT use event names without a namespace.
    2. Event Payloads SHOULD use an element defined in the event description's xsd.
      1. The xsd SHOULD be defined in the eventDescription's schemaType or schemaLocation.
        1. The xsd SHOULD define exactly one element per type. However:
          1. If multiple elements are defined, the event generator MAY choose any such element.
          2. If no element is defined, the event generator MAY choose any element name.
    3. The event element's type attribute SHOULD be set.
    4. The payload's element SHOULD have the xsi:type attribute.
    5. When the payload is a simple type use the wsrp-extra schema and one of the following elements:
      1. The event's type MUST be from the xsd namespace. Example: xsd:string
      2. The event description's schemaLocation or schemaType SHOULD refer the wsrp-extra.xsd which imports the xsd namespace.

   1   <!-- Elements defined for holding simple data in event payloads and/or properties -->
   2   <element name="string" type="xsd:string" nillable="true"/>
   3   <element name="integer" type="xsd:integer" nillable="true"/>
   4   <element name="int" type="xsd:int" nillable="true"/>
   5   <element name="long" type="xsd:long" nillable="true"/>
   6   <element name="short" type="xsd:short" nillable="true"/>
   7   <element name="decimal" type="xsd:decimal" nillable="true"/>
   8   <element name="float" type="xsd:float" nillable="true"/>
   9   <element name="double" type="xsd:double" nillable="true"/>
  10   <element name="boolean" type="xsd:boolean" nillable="true"/>
  11   <element name="byte" type="xsd:byte" nillable="true"/>
  12   <element name="QName" type="xsd:QName" nillable="true"/>
  13   <element name="dateTime" type="xsd:dateTime" nillable="true"/>
  14   <element name="binary" type="xsd:hexBinary" nillable="true"/>
  15   <element name="time" type="xsd:time" nillable="true"/>
  16   <element name="date" type="xsd:date" nillable="true"/>
  17   <element name="duration" type="xsd:duration" nillable="true"/>
  18   <element name="unsignedInt" type="xsd:unsignedInt" nillable="true"/>
  19   <element name="unsignedShort" type="xsd:unsignedShort" nillable="true"/>
  20   <element name="unsignedByte" type="xsd:unsignedByte" nillable="true"/>

Event Payloads (last edited 2009-12-18 22:56:23 by nathan.lipke)