Jaxb, Class ha due proprietà con lo stesso nome


120

con jaxb, provo a leggere un file xml solo pochi elementi nel file xml sono interessanti, quindi vorrei saltare molti elementi

contenuto xml

xml provo a leggere

<?xml version="1.0" encoding="UTF-8"?>
<!--Sample XML file generated by XMLSpy v2010 rel. 3 sp1 (http://www.altova.com)-->
<flx:ModeleREP xsi:schemaLocation="urn:test:mod_rep.xsd mod_rep.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:flx="urn:test:mod_rep.xsd">
<flx:DocumentHeader>
    <flx:Identification v="04489"/>
</flx:DocumentHeader>
<flx:TimeSeries>
    <flx:Identification v="test1a"/>
    <flx:BusinessType v="A01"/>
    <flx:Product v="123a"/>
    <flx:ResourceObject codingScheme="N" v="testa"/>
    <flx:Period>
        <flx:TimeInterval v="2011-07-02T00:00/2011-07-16T00:00"/>
        <flx:Resolution v="PT2H"/>
        <flx:Pt>
            <flx:P v="1"/>
            <flx:Q unitCode="String" v="1.0"/>
            <flx:A currencyIdentifier="String" v="195.0"/>
        </flx:Pt>
    </flx:Period>
</flx:TimeSeries>
<flx:TimeSeries>
    <flx:Identification v="test2a"/>
    <flx:BusinessType v="A01"/>
    <flx:Product v="a123b"/>
    <flx:ResourceObject codingScheme="N" v="test2"/>
    <flx:Period>
        <flx:TimeInterval v="2011-07-02T00:00/2011-07-16T00:00"/>
        <flx:Resolution v="PT2H"/>
        <flx:Pt>
            <flx:P v="1"/>
            <flx:Q unitCode="String" v="1.0"/>
            <flx:A currencyIdentifier="String" v="195.0"/>
        </flx:Pt>
        <flx:Pt>
            <flx:P v="2"/>
            <flx:Q unitCode="String" v="1.0"/>
            <flx:A currencyIdentifier="String" v="195.0"/>
        </flx:Pt>
    </flx:Period>
</flx:TimeSeries>
</flx:ModeleREP>

la mia classe

@XmlRootElement(name="ModeleREP", namespace="urn:test:mod_rep.xsd")
public class ModeleREP {

  @XmlElement(name="TimeSeries")
  protected List<TimeSeries> timeSeries;

  public List<TimeSeries> getTimeSeries() {
  if (this.timeSeries == null) {
      this.timeSeries = new ArrayList<TimeSeries>();
  }
  return this.timeSeries;
  }

  public void setTimeSeries(List<TimeSeries> timeSeries) {
  this.timeSeries = timeSeries;
  }

}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "TimeSeries")
public class TimeSeries {

@XmlElement(name="ResourceObject")
protected RessourceObject resourceObject;

@XmlElement(name = "Period")
protected Period period;

public RessourceObject getResourceObject() {
    return this.resourceObject;
}

public void setResourceObject(RessourceObject resourceObject) {
    this.resourceObject = resourceObject;
}

public Period getPeriod() {
    return this.period;
}

public void setPeriod(Period period) {
    this.period = period;
}

}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "ResourceObject")

public class RessourceObject {
@XmlAttribute(name = "codingScheme")
protected String codingScheme;

@XmlAttribute(name = "v")
protected String v;

public String getCodingScheme() {
    return this.codingScheme;
}

public void setCodingScheme(String codingScheme) {
    this.codingScheme = codingScheme;
}

public String getV() {
    return this.v;
}

public void setV(String v) {
    this.v = v;
}
}

@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name = "Period")
public class Period {

@XmlElement(name = "TimeInterval")
protected TimeInterval timeInterval;

@XmlElement(name = "Pt")
protected List<Pt> pt;

public TimeInterval getTimeInterval() {
    return this.timeInterval;
}

public void setTimeInterval(TimeInterval timeInterval) {
    this.timeInterval = timeInterval;
}

public List<Pt> getPt() {
    if (this.pt == null) {
    this.pt = new ArrayList<Pt>();
    }
    return this.pt;
}

public void setPt(List<Pt> pt) {
    this.pt=pt;
}

}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "TimeInterval")
public class TimeInterval {

@XmlAttribute(name = "v")
private String timeIntervalPeriod;

public String getTimeIntervalPeriod() {
    return this.timeIntervalPeriod;
}

public void setTimeIntervalPeriod(String timeIntervalPeriod) {
    this.timeIntervalPeriod = timeIntervalPeriod;
}

}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Pt")
public class Pt {

@XmlElement(name = "P")
protected P p;

@XmlElement(name = "A")
protected A a;

public P getP() {
    return this.p;
}

public void setP(P p) {
    this.p = p;
}

public A getA() {
    return this.a;
}

public void setA(A a) {
    this.a = a;
}
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "P")
public class P {
@XmlAttribute(name = "v")
protected String position;


public String getPosition(){
    return this.position;
}

public void setPosition(String position){
    this.position=position;
}
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "A")
public class A {
@XmlAttribute(name = "v")
protected String calculatedAmount;

public String getCalculatedAmount() {
    return this.calculatedAmount;
}

public void setCalculatedAmount(String calculatedAmount) {
    this.calculatedAmount = calculatedAmount;
}
}

quando provo a leggere il file xlm che ottengo ottengo

com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Class has two properties of the same name "timeSeries"
    this problem is related to the following location:
        at public java.util.List testjaxp.ModeleREP.getTimeSeries()
        at testjaxp.ModeleREP
    this problem is related to the following location:
        at protected java.util.List testjaxp.ModeleREP.timeSeries
        at testjaxp.ModeleREP

non capisco questo errore

modifica: io uso jaxb-impl-2.1.12

ok ora non ho alcun errore, ma quando controllo il mio oggetto, timeSeries è nullo ...

quindi forse jaxb sembra avere problemi con flx?

Risposte:


204

Ho anche affrontato problemi come questo e l'ho impostato.

@XmlRootElement(name="yourRootElementName")
@XmlAccessorType(XmlAccessType.FIELD)

Questo funzionerà al 100%


8
Ho avuto lo stesso problema. E funziona anche quando aggiungiamo solo @XmlAccessorType (XmlAccessType.FIELD)
Ram Dutt Shukla

2
Ho risolto il problema rimuovendo l' @XmlAccessorType(XmlAccessType.FIELD)annotazione
Hans Wouters

Sembra strano, ma mi sono anche sbarazzato di questa eccezione riducendo la coppia di annotazioni \ @XmlRootElement @XmlAccessorType (XmlAccessType.FIELD) solo a \ @XmlRootElement
Alex InTechno

3
Ho riscontrato lo stesso problema con le classi interne per l'annotazione JAXB. Posizionare @XmlAccessorType (XmlAccessType.FIELD) sulle classi interne ha funzionato!
Shoaib Khan

Fantastico, grazie mille. In combinazione con Lombok molto utile
Michael Hegner

25

Non hai specificato quale versione JAXB-IMPL stai usando, ma una volta ho avuto lo stesso problema (con jaxb-impl 2.0.5) e l'ho risolto usando l'annotazione a livello getter invece di usarla a livello di membro.


È corretto, ho appena rimosso l'annotazione dal membro e l'ho messa a livello di setter e ha funzionato.
Varun

22

Ho anche visto alcuni problemi simili come questo.

Penso che sia a causa del luogo in cui usiamo l' annotazione " @XMLElement " nella classe (bean).

E penso, il JAXB (processore di annotazione) considera il campo membro e il metodo getter dello stesso elemento di campo come proprietà diverse, quando usiamo l' annotazione @XMLElement a livello di campo e genera l' eccezione IllegalAnnotationExceptions .

Messaggio di eccezione:

La classe ha due proprietà con lo stesso nome "timeSeries"

Al metodo Getter:

    at public java.util.List testjaxp.ModeleREP.getTimeSeries()

Nel campo membri:

    at protected java.util.List testjaxp.ModeleREP.timeSeries

Soluzione: invece di usare @XmlElement nel campo , usalo nel metodo getter .


16

l'ho appena aggiunto alla mia classe

@XmlAccessorType(XmlAccessType.FIELD)

ha funzionato come un cham


Funziona anche con l'annotazione @Data di lombok.
digz6666

16

Esistono più soluzioni, ma fondamentalmente se annoti sulla dichiarazione di una variabile, allora ne hai bisogno @XmlAccessorType(XmlAccessType.FIELD), ma se preferisci annotare un metodo get o set, allora non lo fai.

Quindi puoi fare:

@XmlRootElement(name="MY_CLASS_A")
@XmlAccessorType(XmlAccessType.FIELD)
public class MyClassA
{
    @XmlElement(name = "STATUS")   
    private int status;
   //.. and so on
}

O:

@XmlRootElement(name="MY_CLASS_A")
public class MyClassA
{
    private int status;

    @XmlElement(name = "STATUS")         
    public int getStatus()
    {
    }
}

Meraviglioso. Grazie :) +1
Anish B.

11

Il tuo JAXB sta esaminando sia il getTimeSeries()metodo che il membro timeSeries. Non dici quale implementazione JAXB stai utilizzando o la sua configurazione, ma l'eccezione è abbastanza chiara.

in public java.util.List testjaxp.ModeleREP.getTimeSeries ()

e

in protected java.util.List testjaxp.ModeleREP.timeSeries

Devi configurare le tue cose JAXB per usare le annotazioni (come da te @XmlElement(name="TimeSeries")) e ignorare i metodi pubblici.


lo faccio già: @XmlElement (name = "TimeSeries") protected List <TimeSeries> timeSeries;
redfox26

4
inoltre cambio (XmlAccessType.FIELD) in (XmlAccessType.NONE), posso mantenere XmlElement a livello di membro
redfox26

Avevo anche bisogno di aggiungere @XmlTransient alla variabile
HomeIsWhereThePcIs

8

È necessario configurare classe ModeleREPe con @XmlAccessorType(XmlAccessType.FIELD)come avete fatto con classe TimeSeries.

Dai un'occhiata a OOXS


8

Se usiamo le annotazioni seguenti e rimuoviamo l'annotazione "@XmlElement", il codice dovrebbe funzionare correttamente e l'XML risultante avrebbe i nomi degli elementi simili al membro della classe.

@XmlRootElement(name="<RootElementName>")
@XmlAccessorType(XmlAccessType.FIELD)

Nel caso in cui l'uso di "@XmlElement" sia veramente richiesto, definiscilo come livello di campo e il codice dovrebbe funzionare perfettamente. Non definire l'annotazione nella parte superiore del metodo getter.

Ho provato entrambi gli approcci sopra menzionati e sono riuscito a risolvere il problema.


7

"La classe ha due proprietà con lo stesso nome eccezione" può verificarsi quando si dispone di un membro della classe x con un livello di accesso pubblico e un getter / setter per lo stesso membro.

Come regola pratica java, non è consigliabile utilizzare un livello di accesso pubblico insieme a getter e setter.

Controlla questo per maggiori dettagli: Proprietà pubblica VS Proprietà privata con getter?

Per risolvere questo problema:

  1. Cambia il livello di accesso del tuo membro in privato e mantieni il tuo getter / setter
  2. Rimuovi il getter e il setter del membro

6

Queste sono le due proprietà che JAXB sta esaminando.

public java.util.List testjaxp.ModeleREP.getTimeSeries()  

e

protected java.util.List testjaxp.ModeleREP.timeSeries

Questo può essere evitato utilizzando l'annotazione JAXB nel metodo get proprio come indicato di seguito.

@XmlElement(name="TimeSeries"))  
public java.util.List testjaxp.ModeleREP.getTimeSeries()

5

dichiarare semplicemente private le variabili membro nella classe che si desidera convertire in XML. Buona codifica


Questa dovrebbe essere la soluzione accettata. Se dichiari pubblica la tua variabile membro, JABX la analizzerà oltre ai metodi annotati getter / setter e sputerà l'eccezione. È un ottimo esempio in cui i progettisti di librerie jabx hanno fatto un passo in più nella riflessione cercando di creare flessibilità e hanno finito per facilitare le configurazioni non valide. Ho risolto il problema da solo modificando una riga di codice alla volta, risalendo alla variabile membro.
Vortex

4

Lo stesso problema che ho dovuto affrontare, ho aggiunto

@XmlRootElement(name="yourRootElementName")

@XmlAccessorType(XmlAccessType.FIELD)

e ora funziona.


3

Funzionerà quando metti la tua annotazione prima dei getter e la rimuovi dagli attributi protetti:

protected String codingScheme;

@XmlAttribute(name = "codingScheme")
public String getCodingScheme() {
    return this.codingScheme;
}

Anch'io sto incontrando lo stesso problema. Anch'io ho osservato che quando l'annotazione è contrassegnata sugli attributi, vedo questo. Questo significa che dovrebbe essere sempre posizionato prima dei getter ?.
Pavan Dittakavi

@Pavan Sì, penso di sì. Altrimenti, mi causa gli stessi problemi di te
Lilia

2

Ho appena incontrato questo problema e l'ho risolto.

L'origine del problema è che hai sia XmlAccessType.FIELD che coppie di getter e setter. La soluzione è rimuovere i setter e aggiungere un costruttore predefinito e un costruttore che accetta tutti i campi.


Ho avuto lo stesso errore e l'annotazione che hai citato lo ha risolto, grazie!
gyorgyabraham

1

Ho seguito un corso di servizio con la firma come sotto "

@WebMethod
public FetchIQAStatusResponseVO fetchIQAStatus(FetchIQAStatusRequest fetchIQAStatusRequest) {

Durante l'esecuzione ho ricevuto lo stesso errore per i FetchIQAStatusResponseVOcampi. Ho appena aggiunto una riga sopra FetchIQAStatusResponseVO:

@XmlAccessorType(XmlAccessType.FIELD) //This line added
public class FetchIQAStatusResponseVO {

e questo ha risolto il problema.


1

ModeleREP#getTimeSeries()deve essere con @Transientannotazione. Ciò aiuterebbe.


0

L'annotazione con @XmlTransientrisolve il problema

@XmlTransient
public void setTimeSeries(List<TimeSeries> timeSeries) {
   this.timeSeries = timeSeries;
}

Guarda http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/XmlTransient.html per maggiori dettagli


1
Penso che questo sia più un trucco che una soluzione. Questo dice a jaxb di ignorare il metodo, invece di renderlo consapevole che è la stessa cosa.
Hans Wouters

Hack o no questa È la soluzione migliore per aggirare qualcosa che non può essere descritto come qualcosa di meno che un bug, ho usato @XmlAccessorType (XmlAccessType.FIELD) che è stato per lo più ignorato e l'aggiunta di @XmlTransient a ciascuna proprietà era l'unico modo per riparare questo problema. Grazie!
Ralph Ritoch

0

Un modo rapido e semplice per risolvere questo problema è quello di rimuovere l' @XmlElement(name="TimeSeries")dall'alto della dichiarazione di dichiarazione delle variabili protected List<TimeSeries> timeSeries;al top della sua getter, public List<TimeSeries> getTimeSeries().

Così la tua ModeleREPclasse sarà simile a:

@XmlRootElement(name="ModeleREP", namespace="urn:test:mod_rep.xsd")
public class ModeleREP {


  protected List<TimeSeries> timeSeries;

  @XmlElement(name="TimeSeries")
  public List<TimeSeries> getTimeSeries() {
    if (this.timeSeries == null) {
      this.timeSeries = new ArrayList<TimeSeries>();
    }
    return this.timeSeries;
  }

  public void setTimeSeries(List<TimeSeries> timeSeries) {
    this.timeSeries = timeSeries;
  }
}

Spero che sia d'aiuto!


Hai menzionato "Un modo semplice". Curioso, c'è qualche altra via d'uscita da questo - anzi un'altra annotazione che potrebbe essere sfruttata ?.
Pavan Dittakavi

0

Ho fatto tentativi ed errori e sono giunto alla conclusione che devi solo usare entrambi @XMLElemento @XmlAccessorType(XmlAccessType.FIELD).

Quando usarlo?

caso 1 : se i nomi dei campi e il nome dell'elemento che desideri utilizzare nel file xml sono diversi, devi usare @XMLElement(name="elementName"). Poiché questo legherà i campi con quel nome di elemento e verranno visualizzati nel file XML.

caso 2 : se i nomi dei campi e il rispettivo nome dell'elemento in xml sono entrambi uguali, puoi semplicemente usare@XmlAccessorType(XmlAccessType.FIELD)


0

Sono state fornite molte soluzioni e gli interni sono stati toccati brevemente anche da @Sriram e @ptomli. Voglio solo aggiungere alcuni riferimenti al codice sorgente per aiutare a capire cosa sta succedendo sotto il cofano.

Per impostazione predefinita (ovvero nessuna annotazione aggiuntiva utilizzata ad eccezione @XmlRootElementdella classe radice), JABX tenta di eseguire il marshalling delle cose esposte in due modi:

  1. campi pubblici
  2. metodi getter che sono denominati in base alla convenzione e hanno un metodo setter corrispondente.

Notare che se un campo è (o il metodo restituisce) null , non verrà scritto nell'output.

Ora se @XmlElement viene utilizzato, è possibile eseguire il marshalling anche di elementi non pubblici (potrebbero essere campi o metodi getter).

Ma i due modi, cioè campi e metodi getter, non devono entrare in conflitto tra loro. Altrimenti ottieni l'eccezione .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.