What can I do to ignore the <envelope> and <body> tags in unmarshall process using Castor?
Xml examole:
<?xml version="1.0" encoding="UTF-8"?>
<envelope>
<header>
<message>consultaTelefonosVigentesSocios</message>
</header>
<body>
<datosTelefonosVigentesSocios>
<listaTelefonosVigentesSocios>
<nroInterlocutor>2000393451672</nroInterlocutor>
<nroContrato>S6125345450573001</nroContrato>
<nroTelefono>011-4454451-8293</nroTelefono>
<tipoTelefono>T</tipoTelefono>
<claseDireccion>Z001</claseDireccion>
<descClaseDireccion>Correspondencia</descClaseDireccion>
<marcaEstandar>X</marcaEstandar>
<nroInterlocutorAsociadoDomicilio>200053945351672</nroInterlocutorAsociadoDomicilio>
</listaTelefonosVigentesSocios>
<listaTelefonosVigentesSocios>
<nroInterlocutor>200053435391672</nroInterlocutor>
<nroContrato>S612535430573001</nroContrato>
<nroTelefono>011-44453551-8299</nroTelefono>
<tipoTelefono>T</tipoTelefono>
<claseDireccion>Z001</claseDireccion>
<descClaseDireccion>Correspondencia</descClaseDireccion>
<marcaEstandar/>
<nroInterlocutorAsociadoDomicilio>20005543391672</nroInterlocutorAsociadoDomicilio>
</listaTelefonosVigentesSocios>
</datosTelefonosVigentesSocios>
</body>
<fault>
<faultactor>servicios.page:consultaTelefonosVigentesSocios</faultactor>
</fault>
</envelope>
castor mapping file:
<?xml version="1.0"?>
<mapping>
<class
name="ar.com.telefonosSocioByNroContratoService.backend.service.TelefonosVigentesSocios">
<map-to xml="datosTelefonosVigentesSocios" />
<field name="listaTelefonosVigentesSocios"
type="ar.com.telefonosSocioByNroContratoService.backend.service.TelefonoVigenteSocio"
collection="arraylist">
<bind-xml name="listaTelefonosVigentesSocios" />
</field>
</class>
<class
name="ar.com.telefonosSocioByNroContratoService.backend.service.TelefonoVigenteSocio">
<map-to xml="listaTelefonosVigentesSocios" />
<field name="nroInterlocutor" type="java.lang.String">
<bind-xml name="nroInterlocutor" node="element" />
</field>
<field name="nroContrato" type="java.lang.String">
<bind-xml name="nroContrato" node="element" />
</field>
<field name="nroTelefono" type="java.lang.String">
<bind-xml name="nroTelefono" node="element" />
</field>
<field name="tipoTelefono" type="java.lang.String">
<bind-xml name="tipoTelefono" node="element" />
</field>
<field name="marcaEstandar" type="java.lang.String">
<bind-xml name="marcaEstandar" node="element" />
</field>
<field name="descClaseDireccion" type="java.lang.String">
<bind-xml name="descClaseDireccion" node="element" />
</field>
<field name="nroInterlocutorAsociadoDomicilio" type="java.lang.String">
<bind-xml name="nroInterlocutorAsociadoDomicilio" node="element" />
</field>
</class>
</mapping>
Test Class:
public class TelefonosSocioByNroContratoServiceTest {
#Test
public void testUsuarioIntranetListfromXML() throws Exception{
Mapping mapping= new Mapping();
ClassPathResource mappingResource =
new ClassPathResource("/ar/com/telefonosSocioByNroContratoService/backend/service/telefonosVigenteSocios.map.xml");
mapping.loadMapping(mappingResource.getURL());
ClassPathResource inputExample= new ClassPathResource("ar/com/test/castor/consultaTelefonosVigentesSocios.xml");
Reader reader = new FileReader(inputExample.getFile());
Unmarshaller unmarshaller = new Unmarshaller(TelefonosVigentesSocios.class);
unmarshaller.setMapping(mapping);
TelefonosVigentesSocios telefonosVigentesSocios = (TelefonosVigentesSocios) unmarshaller.unmarshal(reader);
reader.close();
Assert.assertNotNull(telefonosVigentesSocios);
Assert.assertNotNull(telefonosVigentesSocios.getListaTelefonosVigentesSocios());
Assert.assertTrue("se esperaba not empty telefonos",!telefonosVigentesSocios.getListaTelefonosVigentesSocios().isEmpty());
}
}
Instead of using an input stream, you could use an XMLStreamReader (StAX) as your input. Then advance the XMLStreamReader to the start element event for the content you mapped to. Then have Castor unmarshal from the XMLStreamReader.
If Castor does not support StAX then I can show you how to do it with JAXB. I lead the EclipseLink JAXB implementation (MOXy).
Related
I am trying to capture- SecurityList message(35= y)
Receiving message in log file as:
8=FIXT.1.19=000036635=y49=XXXXXX56=XXXXXX34=352=20190204-10:41:59.758369=2320=1322=R1560=0393=951301=DGCX_PRECIOUS_METALS1300=GOLD_FUTURES893=N146=255=[N/A]48=546822=8167=FUT200=201906541=20190529231=32107=DG-20190529562=1561=115=USD120=USD7555=26555=[N/A]48=546922=8167=FUT200=201904541=20190327231=32107=DG-20190327562=1561=115=USD120=USD7555=26510=180
8=FIXT.1.19=9735=j34=349=XXXXXX52=20190204-10:42:00.29356=XXXXXX45=258=Unsupported Message Type372=y380=310=178
First thing - Not able to capture this message in fromApp() method.
Second- Using message cracker, cracking it as, but not coming in this method:
public void onMessage(SecurityList message, SessionID sessionId)
throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue {
log.info("Recieved SecurityList");
}
XML file looks like which has same sequence of message coming as this :
<message name='SecurityList' msgtype='y' msgcat='app'>
<component name='ApplicationSequenceControl' required='N' />
<field name='SecurityReportID' required='N' />
<field name='ClearingBusinessDate' required='N' />
<field name='SecurityReqID' required='N' />
<field name='SecurityResponseID' required='N' />
<field name='SecurityRequestResult' required='N' />
<field name='TotNoRelatedSym' required='N' />
<field name='MarketID' required='N' />
<field name='MarketSegmentID' required='N' />
<field name='LastFragment' required='N' />
<component name='SecListGrp' required='N' />
<field name='SecurityListID' required='N' />
<field name='SecurityListRefID' required='N' />
<field name='SecurityListDesc' required='N' />
<field name='EncodedSecurityListDescLen' required='N' />
<field name='EncodedSecurityListDesc' required='N' />
<field name='SecurityListType' required='N' />
<field name='SecurityListTypeSource' required='N' />
<field name='TransactTime' required='N' />
</message>
Conf file :
UseDataDictionary=Y
AppDataDictionary=C:\conf\FIX50SP2.xml
What can be the reason for this.
A message is cracked using Message Cracker, need to check if MessageCracker class is cracking that particular message.
The older version might miss out on some messages.
Using newer version quickfix-messages-fix50sp2-2.0.0 jar where MessageCracker class was cracking this message solved the problem.
I am trying to capture MarketDataIncrementalRefresh messages.
It got a group noMDEntries, I am trying to parse over it.
I have two problems:
1st - I have printed the message that is coming in the fromApp method which is different from what I am getting in my file created through FileStorePath.
How is this possible? Then I am cracking through message cracker but even after cracking it is the same message as received in fromApp
Message from fromApp:
8=FIX.4.29=7535=X34=3649=XXXXXXXX52=2019011605:09:51.00056=XXXXXXXX262=1268=110=223
Message received in file :
8=FIX.4.29=0019435=X49=XXXXXXXX56=XXXXXXXX34=3652=20190116-05:09:51.000262=1268=1279=1269=055=ES167=FUT200=201903541=20190315205=1518211=M207=CME100=XCME461=F15=USD270=249375271=20290=110=123
2nd - While iterating through the group I am getting an error as :
quickfix.FieldNotFound: 268, index=1
at quickfix.FieldMap.getGroup(FieldMap.java:633)
but as you can see field 268 is set, also I have checked it again through message.isSetField(268) which results in true, just after it tried :
MarketDataIncrementalRefresh.NoMDEntries mdEntriesGroup = new MarketDataIncrementalRefresh.NoMDEntries();
message.getGroup(1, mdEntriesGroup);
it gives the above error.
FIX42.xml looks like which has same order of fields as in my message received.:
<message name='MarketDataIncrementalRefresh' msgtype='X' msgcat='app'>
<field name='MDReqID' required='Y' />
<field name='PriceFeedStatus' required='N' />
<group name='NoMDEntries' required='Y'>
<field name='MDUpdateAction' required='Y' />
<field name='MDEntryType' required='Y' />
<field name='Symbol' required='N' />
<field name='SecurityType' required='N' />
<field name='SecuritySubType' required='N' />
<field name='MaturityMonthYear' required='N' />
<field name='MaturityDate' required='N' />
<field name='MaturityDay' required='N' />
<field name='PutOrCall' required='N' />
<field name='StrikePrice' required='N' />
<field name='OptAttribute' required='N' />
<field name='DeliveryTerm' required='N' />
<field name='DeliveryDate' required='N' />
<field name='SecurityID' required='N' />
<field name='SecurityExchange' required='N' />
<field name='ExDestination' required='N' />
<field name='CFICode' required='N' />
<field name='Currency' required='N' />
<field name='MDEntryPx' required='N' />
<field name='MDEntrySize' required='N' />
<field name='MDEntryDate' required='N' />
<field name='MDEntryTime' required='N' />
<field name='MDEntryPositionNo' required='N' />
<field name='SecondaryOrderID' required='N' />
<field name='NumberOfOrders' required='N' />
</group>
<field name='ExchangeSendingTime' required='N' />
<field name='ExchangeTransactTime' required='N' />
<field name='ExchangeSeqNum' required='N' />
</message>
Always trust the message log over FromApp() and FromAdmin(). The log is recorded before the engine attempts to parse the message; the callbacks happen after. If an error happens in parsing (like in your case), what you see in the callback will be wrong (which you are seeing).
I've seen your issue before. What is probably happening is that your configuration has a mistake, or your configured DD xml file does not accurately match your counterparty's specification.
First, your config file should have these lines:
UseDataDictionary=Y
# for FIX4
DataDictionary=path/to/your/dd.xml
# for FIX5+
AppDataDictionary=path/to/your/FIX5whatever.xml
TransportDataDictionary=path/to/your/FIXT1.1.xml
Second, check your message against the DD file that's in your config. Probably something in the repeating group definition is not correct. For instance, a field could be missing from the group definition and the parser is exiting the group early when it hits it. Make sure your config points to the correct xml file.
(If you fix your message paste above to include visible field separators, I'll come back and help take a look.)
I have a self referential table that I am mapping with kodo jdo 4 (supplied from weblogic server 10.3.4.) The code I have will get through the enhancer, but when I try to use it I get the error:
<openjpa-1.1.1-SNAPSHOT-r422266:965591 fatal user error> kodo.jdo.FatalUserException: Missing table name for field "com.[...].jdo.Branch.branches". This field cannot reside in the owning class table.
at org.apache.openjpa.jdbc.meta.FieldMapping.mapJoin(FieldMapping.java:529)
the table is:
CREATE TABLE branch
(
id VARCHAR2(10) NOT NULL,
parentId VARCHAR2(10) NOT NULL,
[other fields deleted ...]
CONSTRAINT branch_pk PRIMARY KEY(id),
CONSTRAINT branch_fk_parent FOREIGN KEY(parentId) REFERENCES branch(id)
);
the class is :
public class Branch implements MenuPart, Serializable
{
private Branch parent;
private Set<Branch> branches = new HashSet<Branch> ();
private String id;
private Set<Leaf> leafs = new HashSet<Leaf> ();
private long ordering;
private String title;
//methods removed.
}
the package.jdo file is:
<class name="Branch" objectid-class="BranchId" table="SCHEMA.BRANCH">
<version strategy="none"/>
<field name="parent" table="SCHEMA.BRANCH">
<column name="SCHEMA.BRANCH.PARENTID" target="ID" />
</field>
<field name="branches" table="SCHEMA.BRANCH" >
<collection element-type="Branch"/>
<join>
<column name="SCHEMA.BRANCH.PARENTID" target="ID" />
</join>
</field>
<field name="id" column="ID" primary-key="true"/>
<field name="leafs" table="SCHEMA.LEAF">
<collection element-type="Leaf"/>
<join>
<column name="ID" target="BRANCHID" />
</join>
</field>
<field name="ordering" column="ORDERING"/>
<field name="title" column="TITLE"/>
</class>
I have gotten the functionality to work in kodo jdo 3.4 but now the syntax is different and the friendly manual isn't that helpful that I can find.
Perhaps its objecting to you defining the join-table for that relation to be the table for the class itself (which is obviously wrong).
Obviously Kodo is not fully JDO-compliant, and is dead as a project, so if you hit issues then you've got problems ...
Can you try
<class name="Branch" objectid-class="BranchId" table="SCHEMA.BRANCH">
<version strategy="none"/>
<field name="parent" table="SCHEMA.BRANCH">
<column name="SCHEMA.BRANCH.PARENTID" target="ID" />
</field>
<field name="branches" table="SCHEMA.BRANCH" >
<collection element-type="Branch"/>
<extension vendor-name="kodo" key="inverse-owner" value="parent"/>
</field>
<field name="id" column="ID" primary-key="true"/>
</class>
here is what finally worked
<class name="Branch" objectid-class="BranchId" table="EBIGP.BRANCH">
<version strategy="none"/>
<field name="parent">
<column name="EBIGP.BRANCH.PARENTID" target="ID" />
</field>
<field name="branches" mapped-by="parent" />
<field name="id" column="ID" primary-key="true"/>
<field name="leafs" default-fetch-group="true">
<collection element-type="Leaf"/>
<element column="BRANCHID"/>
</field>
<field name="ordering" column="ORDERING"/>
<field name="title" column="TITLE"/>
</class>
Apparently all it needed was a mapped-by="parent" attribute.
I'm using Castor to write out a map of user ID's to time intervals. I'm using it to save and resume progress in a lengthy task, and I'm trying to make the XML as compact as possible. My map is from string userID's to a class that contains the interval timestamps, along with additional transient data that I don't need to serialize.
I'm able to use a nested class mapping:
...
<field name="userIntervals" collection="map">
<bind-xml name="u">
<class name="org.exolab.castor.mapping.MapItem">
<field name="key" type="string"><bind-xml name="n" node="attribute"/></field>
<field name="value" type="my.package.TimeInterval"/>
</class>
</bind-xml>
</field>
...
<class name="my.package.TimeInterval">
<map-to xml="ti"/>
<field name="intervalStart" type="long"><bind-xml name="s" node="attribute"/></field>
<field name="intervalEnd" type="long"><bind-xml name="e" node="attribute"/></field>
</class>
...
And get output that looks like:
<u n="36164639"><value s="1292750896000" e="1292750896000"/></u>
What I'd like is the name, start, and end of the user in a single node like this.
<u n="36164639" s="1292750896000" e="1292750896000"/>
But I can't seem to finagle it so the start and end attributes in the "value" go in the same node as the "key". Any ideas would be greatly appreciated.
Nash,
I think to arrange the castor mapping is bit tricky.
If you want to have structure like
<u n="36164639" s="1292750896000" e="1292750896000"/>
Then you need to create a new pojo file where it will be having
all the three fields Key,intervalStart,intervalEnd.
And let the File name as KeyTimeInterval
And map it like the below.
<field name="userIntervals" collection="map">
<class name="org.exolab.castor.mapping.MapItem">
<field name="u" type="my.package.KeyTimeInterval">
<bind-xml name="u" node="element"/>
</field>
</class>
</field>
<class name="my.package.KeyTimeInterval">
<field name="key" type="String">
<bind-xml name="n" node="attribute"/></field>
<field name="intervalStart" type="long">
<bind-xml name="s" node="attribute"/></field>
<field name="intervalEnd" type="long">
<bind-xml name="e" node="attribute"/></field>
</class>
I think you should be able to use location on s and e. Try this:-
...
<class name="my.package.TimeInterval">
<map-to xml="ti"/>
<field name="intervalStart" type="long">
<bind-xml name="s" location="u" node="attribute"/>
</field>
<field name="intervalEnd" type="long">
<bind-xml name="e" location="u" node="attribute"/>
</field>
</class>
Am answering my own question here, since there is a solution that does exactly what I want, and there's actually an error in the explanation at http://www.castor.org/xml-mapping.html#Sample-3:-Using-the-container-attribute - the container attribute is exactly what's needed here.
Changing one line in the mapping:
<field name="value" type="my.package.TimeInterval" container="true"/>
did exactly what I wanted, it didn't create a subelement for the value, just mapped the fields into the existing parent element. Since then, I've used this quite a few times to map multiple-value classes into their parent.
The error of course is the documentation states you do this by setting the container attribute to false. Of course, it should be true.
I don't manage to persist a many-to-many link with DataNucleus using JDO. I have two classes Book and Shop. This is the orm mapping file:
<?xml version="1.0"?>
<!DOCTYPE orm PUBLIC
"-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN"
"http://java.sun.com/dtd/orm_2_0.dtd">
<orm>
<package name="com.mypackage.pojo">
<class name="Book" identity-type="datastore">
<datastore-identity>
<column name="BOOK_ID" />
</datastore-identity>
<field name="name">
<column length="100" jdbc-type="VARCHAR" />
</field>
<field name="shops" persistence-modifier="persistent"
table="BOOKS_SHOPS">
<collection element-type="com.mypackage.pojo.Shop" />
<join>
<column name="BOOK_ID" />
</join>
<element>
<column name="SHOP_ID" />
</element>
</field>
</class>
<class name="Shop" identity-type="datastore">
<datastore-identity>
<column name="SHOP_ID" />
</datastore-identity>
<field name="name">
<column length="50" jdbc-type="VARCHAR" />
</field>
<field name="books" persistence-modifier="persistent"
table="BOOKS_SHOPS">
<collection element-type="com.mypackage.pojo.Book" />
<join>
<column name="SHOP_ID" />
</join>
<element>
<column name="BOOK_ID" />
</element>
</field>
</class>
</package>
</orm>
I try to link a book to a shop and the other way around, like this:
shop.addBook(book);
book.addShop(shop);
Making these two objects persistent again doesn't do anything. Both before and after the little code snippet above, their ObjectState is detached-clean.
What could I be doing wrong?
I have a working solution, but have to admit I do not fully understand everything. Things work when the last field element is not defined as
<field name="books" persistence-modifier="persistent" table="BOOKS_SHOPS">
but as
<field name="books" persistence-modifier="persistent" mapped-by="shops">
This solved my problem.
See also the DataNucleus manual on JDO M-N Relationships. However, leaving the join and the element elements out, as is done in this example, didn't work for me. Another relevant link on the DataNucleus site is JDO Guides : M-N Relation. The code for this last example can be found on SourceForge. Unfortunately, this example also didn't work for me.
This is not really a good answer, but all that I have to offer for now...