Sono di fronte a un problema di marshalling/unmarshalling che coinvolge ereditarietà e polimorfismo utilizzando l'implementazione JAXB di MOXy e il file di binding di metadati esterno.eclipselink/Moxy: ereditarietà e attributo del nome attributo basato sul tipo
ho alcun controllo sui file XML o le classi del modello.
Non ci sono più classi all'interno del modello che ereditano altre classi DTO. . Ecco un esempio di ambiente di cui sto lavorando in questo esempio è qui solo per qualche scopo della sintassi, l'ambiente reale comporta eredità nidificato, collezioni ecc:
Qui è la classe che verrà ereditato
class A {
private String name;
public String getName(){
return name;
}
public void setName(String value){
name = value;
}
}
Qui è una classe ereditata
class B extends A {
private String attrFromB;
public String getAttrFromB(){
return attrFromB;
}
public void setAttrFromB(String value){
attrFromB = value;
}
}
E un altro
class C extends A {
private String attrFromC;
public String getAttrFromC(){
return attrFromC;
}
public void setAttrFromC(String value){
attrFromC= value;
}
}
Ecco una classe contenitore
class MyContainerClass{
private A myObject;
public A getMyObject(){
return myObject;
}
public void setMyObject(A value){
myObject = value;
}
}
Ecco l'XML che dovrebbe produrre nel caso di myContainer contenente A myContainer
<MyContainer>
<MyObject nameA="foo" />
</MyContainer>
contenente B
<MyContainer>
<MyObject nameB="foo" attrFromB="bar" />
</MyContainer>
E myContainer contenente C
<MyContainer>
<MyObject nameC="foo" attrFromC="bar" />
</MyContainer>
Così si può già vedere problemi all'orizzonte ...
Ecco il file di mapping che avrei scritto:
<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="com.test.example"
version="2.1">
<java-type name="A" xml-accessor-type="NONE">
<xml-root-element name="MyObject" />
<java-attributes>
<xml-element java-attribute="name" xml-path="@nameA" />
</java-attributes>
</java-type>
<java-type name="B" xml-accessor-type="NONE">
<xml-root-element name="MyObject" />
<xml-see-also>
com.test.example.A
</xml.see.also>
<java-attributes>
<xml-element java-attribute="name" xml-path="@nameB" />
<xml-element java-attribute="attrFromB" xml-path="@attrFromB" />
</java-attributes>
</java-type>
<java-type name="C" xml-accessor-type="NONE">
<xml-root-element name="MyObject" />
<xml-see-also>
com.test.example.A
</xml.see.also>
<java-attributes>
<xml-element java-attribute="name" xml-path="@nameC" />
<xml-element java-attribute="attrFromC" xml-path="@attrFromC" />
</java-attributes>
</java-type>
<java-type name="MyContainer" xml-accessor-type="NONE">
<xml-root-element name="MyContainer" />
<java-attributes>
<xml-element java-attribute="myObject" type="com.test.example.A" xml-path="MyObject" />
</java-attributes>
</java-type>
</xml-bindings>
Il primo problema è che se mi legano le classi come che, ottengo la seguente eccezione:
[Exception [EclipseLink-44] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Missing class indicator field from database row [UnmarshalRecord()].
prima domanda: capisco che questo è normale , Jaxb ha bisogno di un modo per determinare il tipo di attributo MyContaioner.myObject. Il problema è che non ho accesso ai file XML in arrivo, quindi non posso aggiungere xsi: digita i campi su di loro. C'è un modo per determinare una classe in base alla presenza di un attributo specifico in essa? indipendentemente dal suo valore. Se la sorgente XML contiene un attributo @attrFromC, so l'oggetto deve essere di tipo C. Se contiene attrFromB, è B.
Il secondo problema è che il "name" non esiste all'interno B e C, quindi jaxb ignora em.
--Ignoring attribute [name] on class [com.test.example.B] as no Property was generated for it.
--Ignoring attribute [name] on class [com.test.example.C] as no Property was generated for it.
seconda domanda: L'altro problema è che non so se JAXB è in grado di sovrascrivere i nomi degli attributi XML, come ci si aspetta all'interno del file XML (@nameA, @nameB e nameC tutto riferiscono a A. nome), c'è un modo per farlo?
Grazie in anticipo per il vostro tempo.
Leggendo la prima parte della sua risposta, questo è già stato veramente utile. Grazie. Non posso aspettare la seconda parte. – Drewman
Giusto per sicurezza, se all'interno di ClassExtractor, voglio testare la presenza di un nodo e non un attributo. Posso usare record.get ("SomeNodeName") o record.get ("SomeNodeName/text()")? – Drewman
@ user1121108 - Ho aggiunto una risposta per la seconda parte. Nell'estrattore di classe sarai in grado di testare solo la presenza di attributi. A quel punto dell'esecuzione gli elementi secondari non sono ancora stati elaborati. –