Jaxb, Class tiene dos propiedades del mismo nombre


120

con jaxb, trato de leer un archivo xml, solo algunos elementos en el archivo xml son interesantes, así que me gustaría omitir muchos elementos

contenido xml

xml trato de leer

<?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>

mi clase

@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;
}
}

cuando intento leer el archivo xlm, obtengo, obtengo

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

no entiendo este error

editar: uso jaxb-impl-2.1.12

ok, ahora no tengo ningún error, pero cuando verifico mi objeto, timeSeries es nulo ...

Entonces, ¿tal vez jaxb parece tener problemas con flx?

Respuestas:


204

También enfrenté un problema como este y configuré esto.

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

Esto funcionará al 100%


8
Tuve el mismo problema. E incluso funciona cuando agregamos solo @XmlAccessorType (XmlAccessType.FIELD)
Ram Dutt Shukla

2
Resolví el problema eliminando la @XmlAccessorType(XmlAccessType.FIELD)anotación
Hans Wouters

Suena extraño, pero también me deshice de esta excepción reduciendo el par de anotaciones \ @XmlRootElement @XmlAccessorType (XmlAccessType.FIELD) a solo \ @XmlRootElement
Alex InTechno

3
Me encontré con el mismo problema con las clases internas para la anotación JAXB. ¡Colocar @XmlAccessorType (XmlAccessType.FIELD) en clases internas funcionó!
Shoaib Khan

Impresionante, muchas gracias. En combinación con Lombok muy útil
Michael Hegner

25

No especificó qué versión de JAXB-IMPL está usando, pero una vez tuve el mismo problema (con jaxb-impl 2.0.5) y lo resolví usando la anotación en el nivel de captador en lugar de usarla en el nivel de miembro.


Eso es correcto. Simplemente eliminé la anotación del miembro y la puse en el nivel del setter y funcionó.
Varun

22

También he visto algunos problemas similares como este.

Creo que se debe al lugar donde usamos la anotación " @XMLElement " en la clase (bean).

Y creo que el JAXB (procesador de anotaciones) considera el campo miembro y el método getter del mismo elemento de campo como propiedades diferentes, cuando usamos la anotación @XMLElement en el nivel de campo y lanza la excepción IllegalAnnotationExceptions .

Mensaje de excepción:

La clase tiene dos propiedades del mismo nombre "timeSeries"

En el método Getter:

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

En el campo de miembros:

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

Solución: en lugar de usar @XmlElement en el campo , utilícelo en el método getter .


16

acabo de agregar esto a mi clase

@XmlAccessorType(XmlAccessType.FIELD)

trabajó como un cham


También funciona junto con la anotación @Data de lombok.
digz6666

16

Hay varias soluciones, pero básicamente si anota en la declaración de variable, entonces lo necesita @XmlAccessorType(XmlAccessType.FIELD), pero si prefiere anotar un método get o set, entonces no lo hace.

Entonces puedes hacer:

@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()
    {
    }
}

Maravilloso. Gracias :) +1
Anish B.

11

Su JAXB está mirando tanto el getTimeSeries()método como el miembro timeSeries. No dice qué implementación de JAXB está usando, o su configuración, pero la excepción es bastante clara.

en público java.util.List testjaxp.ModeleREP.getTimeSeries ()

y

en protegido java.util.List testjaxp.ModeleREP.timeSeries

Debe configurar sus cosas JAXB para usar anotaciones (según su @XmlElement(name="TimeSeries")) e ignorar los métodos públicos.


Ya lo hago: @XmlElement (name = "TimeSeries") protected List <TimeSeries> timeSeries;
redfox26

4
también cambio (XmlAccessType.FIELD) a (XmlAccessType.NONE), puedo mantener XmlElement a nivel de miembro
redfox26

También necesitaba agregar @XmlTransient a la variable
HomeIsWhereThePcIs

8

Debe configurar la clase ModeleREPtanto @XmlAccessorType(XmlAccessType.FIELD)como lo hizo con la clase TimeSeries.

Eche un vistazo a OOXS


8

Si usamos las siguientes anotaciones y eliminamos la anotación "@XmlElement", el código debería funcionar correctamente y el XML resultante tendría los nombres de los elementos similares al miembro de la clase.

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

En caso de que el uso de "@XmlElement" sea realmente necesario, defínalo como nivel de campo y el código debería funcionar perfectamente. No defina la anotación en la parte superior del método getter.

Intenté los dos enfoques mencionados anteriormente y resolví el problema.


7

"La clase tiene dos propiedades con el mismo nombre de excepción" puede ocurrir cuando tienes un miembro de clase x con un nivel de acceso público y un getter / setter para el mismo miembro.

Como regla general de Java, no se recomienda utilizar un nivel de acceso público junto con getters y setters.

Verifique esto para más detalles: Propiedad pública VS Propiedad privada con captador?

Para arreglar eso:

  1. Cambie el nivel de acceso de su miembro a privado y mantenga su getter / setter
  2. Eliminar el getter y setter del miembro

6

Estas son las dos propiedades que JAXB está considerando.

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

y

protected java.util.List testjaxp.ModeleREP.timeSeries

Esto se puede evitar usando la anotación JAXB en el método get como se menciona a continuación.

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

5

simplemente declare las variables miembro como privadas en la clase que desea convertir a XML. Codificación feliz


Esta debería ser la solución aceptada. Si declara pública su variable miembro, JABX la analizará además de los métodos anotados de getter / setter y escupirá la excepción. Es un gran ejemplo en el que los diseñadores de bibliotecas jabx hicieron un esfuerzo adicional en la reflexión tratando de crear flexibilidad y terminaron facilitando configuraciones no válidas. Solucioné el problema por mi cuenta cambiando una línea de código a la vez, rastreando hasta la variable miembro.
Vortex

4

El mismo problema que enfrenté, agregué

@XmlRootElement(name="yourRootElementName")

@XmlAccessorType(XmlAccessType.FIELD)

y ahora está funcionando.


3

Funcionará cuando coloque su anotación antes de los captadores y la elimine de los atributos protegidos:

protected String codingScheme;

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

Yo también me encuentro con el mismo problema. Yo también he observado que cuando la anotación está marcada sobre los atributos, veo esto. ¿Significa esto que siempre debe colocarse antes que los getters ?.
Pavan Dittakavi

@Pavan Sí, eso creo. De lo contrario, me causa los mismos problemas que tú
Lilia

2

Me encontré con este problema y lo resolví.

La fuente del problema es que tiene tanto XmlAccessType.FIELD como pares de captadores y definidores. La solución es eliminar los establecedores y agregar un constructor predeterminado y un constructor que tome todos los campos.


Tuve el mismo error y la anotación que mencionaste lo resolvió, ¡gracias!
gyorgyabraham

1

Tenía una clase de servicio con la firma de la siguiente manera "

@WebMethod
public FetchIQAStatusResponseVO fetchIQAStatus(FetchIQAStatusRequest fetchIQAStatusRequest) {

Al ejecutar, obtuve el mismo error para los FetchIQAStatusResponseVOcampos. Acabo de agregar una línea encima de FetchIQAStatusResponseVO:

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

y esto resolvió el problema.


1

ModeleREP#getTimeSeries()tiene que estar con @Transientanotación. Eso podría ayudar.


0

Anotar con @XmlTransientresuelve ese problema

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

Mire http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/XmlTransient.html para obtener más detalles


1
Creo que esto es más un truco que una solución. Esto le dice a jaxb que ignore el método, en lugar de hacerle saber que es lo mismo.
Hans Wouters

Hackear o no, esta ES la mejor solución para evitar algo que no se puede describir como un error, utilicé @XmlAccessorType (XmlAccessType.FIELD) que se ignoró en su mayoría y agregar @XmlTransient a cada propiedad era la única forma de repare este problema. ¡Gracias!
Ralph Ritoch

0

Una forma rápida y sencilla de solucionar este problema es eliminar el @XmlElement(name="TimeSeries")de la parte superior de la declaración de declaración de variables protected List<TimeSeries> timeSeries;a la parte superior de su comprador, public List<TimeSeries> getTimeSeries().

Por lo tanto, su ModeleREPclase se verá así:

@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;
  }
}

¡Espero eso ayude!


Mencionas "Una forma sencilla". Curioso, ¿hay alguna otra forma de salir de esto? ¿No hay otra anotación que pueda aprovecharse?
Pavan Dittakavi

0

Hice prueba y error y llegué a la conclusión de que solo tienes que usar ambos @XMLElemento @XmlAccessorType(XmlAccessType.FIELD).

¿Cuándo usar cuál?

caso 1 : si los nombres de campo y el nombre del elemento que desea usar en el archivo xml son diferentes, entonces debe usar @XMLElement(name="elementName"). Como esto vinculará campos con ese nombre de elemento y se mostrará en un archivo XML.

caso 2 : si los nombres de los campos y el nombre del elemento respectivo en xml son iguales, simplemente puede usar@XmlAccessorType(XmlAccessType.FIELD)


0

Se han dado muchas soluciones, y @Sriram y @ptomli también tocan brevemente los aspectos internos. Solo quiero agregar algunas referencias al código fuente para ayudar a comprender lo que está sucediendo bajo el capó.

De forma predeterminada (es decir, no se utilizan anotaciones adicionales excepto @XmlRootElementen la clase raíz), JABX intenta ordenar las cosas expuestas de dos maneras:

  1. campos públicos
  2. métodos getter que se nombran siguiendo la convención y tienen un método setter correspondiente.

Tenga en cuenta que si un campo es (o un método devuelve) null, no se escribirá en la salida.

Ahora, si @XmlElementse usa, las cosas no públicas (podrían ser campos o métodos getter) también se pueden ordenar.

Pero las dos formas, es decir, los campos y los métodos getter, no deben entrar en conflicto entre sí. De lo contrario, obtienes la excepción .

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.