question

Upvotes
Accepted
1 0 1 2

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.

elektronelektron-sdkrrteta-apielektron-transport-apiencoding
icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

@Tina Zhang

Please be informed that a reply has been verified as correct in answering the question, and has been marked as such.

Thanks,

AHS

Upvotes
Accepted
1.9k 7 10 16

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.

icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Upvotes
36 0 0 1

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.

icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

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)

Upvotes
36 0 0 1

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

icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

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).

code.txt

encodexml.txt

code.txt (45.1 KiB)
encodexml.txt (89.8 KiB)

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.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.