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.
Please be informed that a reply has been verified as correct in answering the question, and has been marked as such.
Thanks,
AHS
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.
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.
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)
For more details regarding message encoding with pre-encoded MsgKey attribute see Developers Guide section name "Msg Encoding Example 2".
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?
Yes, you should be able to encode both ways - msg.encode() and msg.encodeInit()/msg.encodeComplete().
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).
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.