Closed FrankConstructor closed 4 years ago
FieldEntry is a public interface which can accessed by client, and can be implemented by client with their own implementation. FieldEntryImpl is internal impl provided by EMA, not intentional for client use.
May I ask what do you try to do? Can you provide us a use case detail? Do you try to access an encoded data in a FieldEntry?
We simulate in our tests complex scenarios including exceptional situations. One very simple example is the need that an entry returns a specific name. This is not easily possible without accessing internal data of FieldEntryImpl (created via the EmaFactory):
public String name() {
return (_rsslDictionaryEntry == null) ? DataImpl.EMPTY_STRING : _rsslDictionaryEntry.acronym().toString();
}
This internal variable can only be written (without hacks) using this package local method:
FieldEntryImpl entryValue(FieldListImpl fieldList, com.thomsonreuters.upa.codec.DictionaryEntry rsslDictionaryEntry, DataImpl load) {
_load = load;
_fieldList = fieldList;
_rsslDictionaryEntry = rsslDictionaryEntry;
return this;
}
Now, a developer may have the idea to create an own implementation for FieldEntry to solve that:
public static MyFieldEntry implements FieldEntry {
// ...
}
Then ones creates the message, invokes the application service that processes the message and ... you get an exception.
See below class that demonstrates this:
import com.thomsonreuters.ema.access.*;
public class Test {
public static void main(String[] args) {
FieldList list = EmaFactory.createFieldList();
list.add(new MyFieldEntry());
RefreshMsg msg = EmaFactory.createRefreshMsg();
msg.payload(list);
msg.payload(); // boom
}
public static MyFieldEntry implements FieldEntry {
// tons of overrides
}
}
The result is:
java.lang.ClassCastException: Test$1MyFieldEntry cannot be cast to com.thomsonreuters.ema.access.FieldEntryImpl
at com.thomsonreuters.ema.access.FieldListImpl.encodedData(FieldListImpl.java:420)
at com.thomsonreuters.ema.access.MsgImpl.msgPayload(MsgImpl.java:789)
at com.thomsonreuters.ema.access.RefreshMsgImpl.payload(RefreshMsgImpl.java:337)
FieldEntry and other EMA entry interface provide two part of functionality. One part is accessors to allow client to retrieve all field entry information which are decoded from a msg such as an refreshMsg/updateMsg, usually they are off from wire inside a consumer application. This part of “Get” functions are not designed to be used in encoding side such as provider side application. Your app is encoding a FieldList, then immediately turn around to access the name and other properties of an encoded field entry, right?
But there may be a way to allow you to access name (other properties) of an encoded Field entry. You need to convert your encoded data into decoded data, then access their properties. JunitTestConnect.java inside the package is a public class which provides functionalities to help you to do the conversion. The EMA junit test (more specific FieldListTest.java, testFieldList_EncodeEMA_DecodeEMA_DecodeAll()) shipped can show you how to use those conversion interface.
public void testFieldList_EncodeEMA_DecodeEMA_DecodeAll() throws UnsupportedEncodingException
{
TestUtilities.printTestHead("testFieldList_EncodeEMA_DecodeEMA_DecodeAll", "Encode FieldList with EMA and Decode FieldList with EMA");
// load dictionary
com.thomsonreuters.upa.codec.DataDictionary dictionary = com.thomsonreuters.upa.codec.CodecFactory
.createDataDictionary();
TestUtilities.upa_encodeDictionaryMsg(dictionary);
//EMA Encode FieldList
FieldList flEnc = EmaFactory.createFieldList();
flEnc.info( dictionary.infoDictionaryId(), 65 );
try {
//EMA Encoding
//first entry (fid not found case)
flEnc.add(EmaFactory.createFieldEntry().uintValue( -100, 64 ));
//second entry
…add more entry data here
FieldList flDec = JUnitTestConnect.createFieldList();
//this function converts flEnc (encoded fieldlist) to flDec (decoded fieldlist), you can access name of a field entry on flDec.
JUnitTestConnect.setRsslData(flDec, flEnc, Codec.majorVersion(), Codec.minorVersion(), dictionary, null);
TestUtilities.checkResult("FieldList with all data types - hasInfo()" , flDec.hasInfo());
TestUtilities.checkResult("FieldList with all data types - infoDictionaryId()", flDec.infoDictionaryId() == dictionary.infoDictionaryId() );
TestUtilities.checkResult("FieldList with all data types - infoFieldListNum()", flDec.infoFieldListNum() == 65 );
Iterator<FieldEntry> iter = flDec.iterator();
…
FieldEntry fe2 = iter.next();
TestUtilities.checkResult("FieldEntry.fieldId()", fe2.fieldId() == 1 );
TestUtilities.checkResult("FieldEntry.name()", fe2.name().equals( "PROD_PERM") );
If you also can go further to define your own converting function in JUnitTestConnect.java by passing EMA DataDictionary (not use eta DataDictionary interface) such as
public static void setRsslData(Data data, Data dataEncoded, int majVer, int minVer, com.thomsonreuters.rdm.DataDictionary emaDictionary) { ((CollectionDataImpl) data).decode(((DataImpl)dataEncoded).encodedData(), majVer, minVer, ((DataDictionaryImpl)DataDictionary).rsslDateDictionary(), null); }
If you do provide your own implementation for FieldEntry, you properly need to pay lots of effort to change all related FieldEntryImpl Casting to use your own in the package to avoid crashes you saw.
import com.thomsonreuters.ema.access.*; public class Test { public static void main(String[] args) { FieldList list = EmaFactory.createFieldList(); list.add(new MyFieldEntry()); //incorrect list.add (EmaFactory.createMyFieldEntry()) //correct list.infoDictionaryId(); RefreshMsg msg = EmaFactory.createRefreshMsg(); msg.payload(list); ... } public static MyFieldEntry implements FieldEntry { // tons of overrides } }
The package is sealed by design. Closing this issue as maydu has provided details on how to write tests (see junits) above. Please let us know if you have further questions.
The manifest declares that the package is sealed:
All implementation classes in com.thomsonreuters.ema.access are package private. The method
FieldListImpl.encodedData()
expects that each FieldEntry can be casted to FieldEntryImpl:In effect:
This makes it impossible to build advanced JUnit tests simulating specific scenarios in applications (apart from using Mockito or similar).
Furthermore, it is not possible to capture a real live message and serialize/deserialize it so that it can be replayed in tests.