How to encode msgkey attribute in resfresh message in UPA 8.0 JAVA

I want to encode a msgkey attribute into a refresh message, and this msgkey is directly get from the request message. I use below way, but it will effect the refresh message body (all seriesentry will null ), could someone help check it and provide some advice?

_refreshMsg.msgClass(MsgClasses.REFRESH);
_refreshMsg.flags(RefreshMsgFlags.SOLICITED | RefreshMsgFlags.REFRESH_COMPLETE );

_refreshMsg.containerType(DataTypes.SERIES);

_refreshMsg.applyHasMsgKey();

_refreshMsg.msgKey().flags(key.flags());
_refreshMsg.msgKey().name(key.name());
_refreshMsg.msgKey().nameType(key.nameType());
_refreshMsg.msgKey().identifier(key.identifier());
_refreshMsg.msgKey().serviceId(key.serviceId());
_refreshMsg.msgKey().attribContainerType(key.attribContainerType());
_refreshMsg.msgKey().encodedAttrib(key.encodedAttrib());

ret = _refreshMsg.encodeInit(_encodeIter, 0);

/* create and initialize series structure */
Series series = CodecFactory.createSeries();
/* create a single SeriesEntry and reuse for each entry */
SeriesEntry seriesEntry = CodecFactory.createSeriesEntry();

/* encode the series */

but the encode xml like blow:

<REFRESH domainType="HISTORY" streamId="1026" containerType="SERIES" flags="0x68 (HAS_MSG_KEY|SOLICITED|REFRESH_COMPLETE)" groupId="0" State: Non-streaming/Ok/None - text: "" dataSize="400">
<key flags="0x37 (HAS_SERVICE_ID|HAS_NAME|HAS_NAME_TYPE|HAS_IDENTIFIER|HAS_ATTRIB)" serviceId="1" name="HL2_1" nameType="1" identifier="13" attribContainerType="ELEMENT_LIST">
<attrib>
<elementList flags="0x08 (HAS_STANDARD_DATA)">
<elementEntry name="QueryString" dataType="UTF8_STRING" data="*:*"/>
<elementEntry name="numresult" dataType="INT" data="1"/>
<elementEntry name="StartDtTm" dataType="DATETIME" data="29 SEP 2016 00:44:30:000"/>
<elementEntry name="User" dataType="ASCII_STRING" data="et"/>
<elementEntry name="Position" dataType="ASCII_STRING" data="127.0.0.1"/>
<elementEntry name="AppID" dataType="INT" data="170"/>
</elementList>
</attrib>
</key>
<dataBody>
<series flags="0x08 ()" countHint="0" containerType="NO_DATA">
<seriesEntry>
</seriesEntry>
<seriesEntry>
</seriesEntry>
<seriesEntry>
</seriesEntry>
<seriesEntry>
</seriesEntry>
<seriesEntry> </seriesEntry>
</series>
</dataBody>
</REFRESH>

if I remove the msgkey part, the refresh can encode the series entry correctly.

Best Answer

  • According to the message which is similar to the output that you expected:

    <!-- rwfMajorVer="14" rwfMinorVer="1" -->
    <REFRESH domainType="255" streamId="3" containerType="SERIES" flags="0x1E8 (HAS_MSG_KEY|SOLICITED|REFRESH_COMPLETE|HAS_QOS|CLEAR_CACHE)"
    groupId="0" Qos: Realtime / TickByTick / Static - timeInfo: 0 rateInfo: 0 State: Open / Ok / None - text: " Item Refresh Completed "
    dataSize="35">
    <key flags="0x27 (HAS_SERVICE_ID|HAS_NAME|HAS_NAME_TYPE|HAS_ATTRIB)" serviceId="1" name="IBM.N" nameType="1" attribContainerType="ELEMENT_LIST">
    <attrib>
    <elementList flags="0x08 (HAS_STANDARD_DATA)">
    <elementEntry name="Name" dataType="ASCII_STRING" data="test1" />
    <elementEntry name="Text" dataType="ASCII_STRING" data="test2" />
    </elementList>
    </attrib>
    </key>
    <dataBody>
    <series flags="0x05 (HAS_SET_DEFS|HAS_TOTAL_COUNT_HINT)" countHint="1" containerType="FIELD_LIST">
    <fieldSetDefs>
    <fieldSetDef setId="3">
    <fieldSetDefEntry fieldId="22" dataType="REAL" />
    <fieldSetDefEntry fieldId="25" dataType="REAL" />
    </fieldSetDef>
    </fieldSetDefs>
    <seriesEntry>
    <fieldList flags="0x0C (HAS_SET_ID|HAS_STANDARD_DATA)">
    <fieldEntry fieldId="22" dataType="REAL" data="22.0" />
    <fieldEntry fieldId="25" dataType="REAL" data="25.0" />
    </fieldList>
    </seriesEntry>
    </series>
    </dataBody>
    </REFRESH>

    Here this is the snippet code that generates the result above:

    RefreshMsg refreshMsg = (RefreshMsg)CodecFactory.createMsg();
    refreshMsg.clear();


    refreshMsg.msgClass(MsgClasses.REFRESH);


    // Stream ID
    refreshMsg.streamId(itemReqInfo.streamId);


    if (itemReqInfo.isStreamingRequest)
    {
    refreshMsg.state().streamState(StreamStates.OPEN);
    }
    else
    {
    refreshMsg.state().streamState(StreamStates.NON_STREAMING);
    }


    // State
    refreshMsg.state().dataState(DataStates.OK);
    refreshMsg.state().code(StateCodes.NONE);
    refreshMsg.state().text().data("Item Refresh Completed");
    refreshMsg.applyRefreshComplete();


    if (itemReqInfo.isPrivateStreamRequest)
    {
    refreshMsg.applyPrivateStream();
    }


    // For Solicited Refresh Message
    if (true)
    {
    refreshMsg.applySolicited();

    // clear cache for solicited refresh messages.
    refreshMsg.applyClearCache();
    }


    // Qos
    refreshMsg.applyHasQos();
    refreshMsg.qos().dynamic(false);
    refreshMsg.qos().rate(QosRates.TICK_BY_TICK);
    refreshMsg.qos().timeliness(QosTimeliness.REALTIME);

    // StreamId
    refreshMsg.streamId(itemReqInfo.streamId);
    refreshMsg.applyHasMsgKey();

    // Service Id
    refreshMsg.msgKey().applyHasServiceId();
    refreshMsg.msgKey().serviceId(serviceId());

    // ItemName
    refreshMsg.msgKey().name(itemReqInfo.itemName);
    refreshMsg.msgKey().applyHasName();
    refreshMsg.msgKey().nameType(InstrumentNameTypes.RIC);
    refreshMsg.msgKey().applyHasNameType();

    // Set Encoder Version
    encodeIter.clear();
    ret = encodeIter.setBufferAndRWFVersion(msgBuf, itemReqInfo.channel.majorVersion(), itemReqInfo.channel.minorVersion());
    if (ret != CodecReturnCodes.SUCCESS)
    {
    error.text("EncodeIterator.setBufferAndRWFVersion() failed with return code: " + CodecReturnCodes.toString(ret));
    return ret;
    }


    refreshMsg.domainType(255);
    refreshMsg.containerType(DataTypes.SERIES);


    refreshMsg.msgKey().applyHasAttrib();
    refreshMsg.msgKey().attribContainerType(DataTypes.ELEMENT_LIST);


    ret = refreshMsg.encodeInit(encodeIter, 0);
    if (ret < CodecReturnCodes.SUCCESS)
    {
    return ret;
    }


    /* Begin MsgKey > ElementList */
    elementList.clear();
    elementEntry.clear();
    tempBuffer.clear();
    elementList.applyHasStandardData();


    ret = elementList.encodeInit(encodeIter, null, 0);
    if (ret != 0) {
    return ret;
    }

    /* Begin MsgKey > ElementList > ElementEntry(0) */
    tempBuffer.data("test1");
    elementEntry.dataType(DataTypes.ASCII_STRING);
    elementEntry.name(ElementNames.NAME);
    ret = elementEntry.encode(encodeIter, tempBuffer);
    if (ret != 0) {
    return ret;
    }
    /* End MsgKey > ElementList > ElementEntry(0) */


    /* Begin MsgKey > ElementList > ElementEntry(1) */
    tempBuffer.data("test2");
    elementEntry.dataType(DataTypes.ASCII_STRING);
    elementEntry.name(ElementNames.TEXT);
    ret = elementEntry.encode(encodeIter, tempBuffer);
    if (ret != 0) {
    return ret;
    }
    /* Begin MsgKey > ElementList > ElementEntry(1) */


    ret = elementList.encodeComplete(encodeIter, true);
    if(ret < CodecReturnCodes.SUCCESS)
    return ret;
    /* End MsgKey > ElementList */


    ret = refreshMsg.encodeKeyAttribComplete(encodeIter, true);
    if (ret < 0) {
    return ret;
    }


    series.clear();
    seriesEntry.clear();
    series.containerType(DataTypes.FIELD_LIST);
    series.applyHasTotalCountHint();
    series.totalCountHint(1);
    series.applyHasSetDefs();


    /* Begin Payload > Series */
    ret = series.encodeInit(encodeIter, 0, 0);
    if (ret != 0) {
    return ret;
    }


    /* Begin Payload > Series > FieldSetDef */
    FieldSetDefEntry[] fieldSetDefEntries = new FieldSetDefEntry[2];

    fieldSetDefEntries[0] = CodecFactory.createFieldSetDefEntry();
    dictionaryEntry = _dictionaryHandler.dictionary().entry(MarketPriceItem.BID_FID);
    if (dictionaryEntry != null)
    {
    fieldSetDefEntries[0].dataType(dictionaryEntry.rwfType());
    fieldSetDefEntries[0].fieldId(22);
    }

    fieldSetDefEntries[1] = CodecFactory.createFieldSetDefEntry();
    dictionaryEntry = _dictionaryHandler.dictionary().entry(MarketPriceItem.ASK_FID);
    if (dictionaryEntry != null)
    {
    fieldSetDefEntries[1].dataType(dictionaryEntry.rwfType());
    fieldSetDefEntries[1].fieldId(25);
    }


    fieldSetDefDb.definitions()[3].setId(3);
    fieldSetDefDb.definitions()[3].count(2);
    fieldSetDefDb.definitions()[3].entries(fieldSetDefEntries);

    ret = fieldSetDefDb.encode(encodeIter);
    if (ret != 0) {
    return ret;
    }

    ret = series.encodeSetDefsComplete(encodeIter, true);
    if (ret != 0) {
    return ret;
    }
    /* End Payload > Series > FieldSetDef */

    /* Begin Payload > Series > SeriesEntry (0) */
    ret = seriesEntry.encodeInit(encodeIter, 0);
    if (ret != 0) {
    return ret;
    }

    fieldList.clear();
    fieldEntry.clear();

    tempUInt.clear();
    tempReal.clear();

    fieldList.applyHasStandardData();
    fieldList.applyHasSetId();
    fieldList.setId(3);

    /* Begin Payload > Series > FieldList */
    ret = fieldList.encodeInit(encodeIter, fieldSetDefDb, 0);
    if (ret < CodecReturnCodes.SUCCESS)
    {
    return ret;
    }

    /* Begin Payload > Series > FieldList > FieldEntry (0) */
    // BID
    fieldEntry.clear();
    fieldEntry.fieldId(MarketPriceItem.BID_FID);
    fieldEntry.dataType(DataTypes.REAL);
    tempReal.clear();
    tempReal.value(22.0, RealHints.EXPONENT_2);
    ret = fieldEntry.encode(encodeIter, tempReal);
    if (ret < CodecReturnCodes.SUCCESS)
    {
    return ret;
    }
    /* End Payload > Series > FieldList > FieldEntry (0) */

    /* Begin Payload > Series > FieldList > FieldEntry (1) */
    // ASK
    fieldEntry.clear();
    fieldEntry.fieldId(MarketPriceItem.ASK_FID);
    fieldEntry.dataType(DataTypes.REAL);
    tempReal.clear();
    tempReal.value(25.0, RealHints.EXPONENT_2);
    ret = fieldEntry.encode(encodeIter, tempReal);
    if (ret < CodecReturnCodes.SUCCESS)
    {
    return ret;
    }
    /* End Payload > Series > FieldList > FieldEntry (1) */

    // complete encode field list
    ret = fieldList.encodeComplete(encodeIter, true);
    if (ret < CodecReturnCodes.SUCCESS)
    {
    return ret;
    }
    /* End Payload > Series > FieldList */

    seriesEntry.encodeComplete(encodeIter, true);
    if(ret < CodecReturnCodes.SUCCESS)
    return ret;
    /* End Payload > Series > SeriesEntry (0) */

    series.encodeComplete(encodeIter, true);
    if(ret < CodecReturnCodes.SUCCESS)
    return ret;
    /* End Payload > Series */




    refreshMsg.encodeComplete(encodeIter, true);
    if (ret < CodecReturnCodes.SUCCESS)
    {
    return ret;
    }

    Hope this helps.

Answers

  • Two things I can think of that would cause strange behavior.

    1) Refresh message does not have state set properly. It cannot be default. It must be set to something like below. If not, encodeInit() will fail.

    msg.state().streamState(StreamStates.OPEN);
    msg.state().dataState(DataStates.OK);
    msg.state().code(StateCodes.NONE);

    2) MsgKey flags are not set properly. Make sure MsgKeyFlags.HAS_ATTRIB is set. Otherwise, encodeInit() will skip it and encoding will be incorrect.

  • For more details regarding message encoding with pre-encoded MsgKey attribute see Developers Guide section name "Msg Encoding Example 2".

  • Thanks for your comments Bill.

    I have set the state info(just not post on the description), and set the key.flags() contains the MsgKeyFlags.HAS_ATTRIB, you can see in the encode xml , it flag list it.

    key flags="0x37 (HAS_SERVICE_ID|HAS_NAME|HAS_NAME_TYPE|HAS_IDENTIFIER|HAS_ATTRIB)

  • Hi Bill,

    I reviewed the example2, if I use refreshMsg.msgKey().encodedAttrib(encodedAttrib) this way to encode the msgkey, then I must encode the msg by encodedDataBody(encodedPayload)? Can't I use _refreshMsg.encodeInit(_encodeIter, 0)/ _refreshMsg.encodeComplete(_encodeIter, true)?

    Could you please help confirm this?

  • Hi Bill, I used encodeInit() and encodedDataBody() separately for the refresh message encode, but I got same result when I set the msgKey part. I attached the code and encodeXml result , could you please help check where I am wrong?

    the encodeResponse() method uses encodedDataBody() way, and encodeResponseWithInit() uses msg.encodeInit() way.

    if I remove Line 651-658 msgKey part, seriese body can encode correct(second xml in encodexml.txt).

    code.txt

    encodexml.txt

  • Yes, you should be able to encode both ways - msg.encode() and msg.encodeInit()/msg.encodeComplete().

  • Just by looking at the code I noticed that return values are not checked for every encode()/encodeInit()/encodeComplete() call. Make sure you check every return value since this could show where the problem is.

  • If you still have problems after checking return values, you can contact the support channels so they can help with deeper
    troubleshooting.