Jaxb, Class tem duas propriedades com o mesmo nome

120

com jaxb, tento ler um arquivo xml, apenas alguns elementos no arquivo xml são interessantes, então eu gostaria de pular muitos elementos

conteúdo xml

xml eu tento ler

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

minha 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 tento ler o arquivo xlm, recebo

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

eu não entendo esse erro

editar: eu uso jaxb-impl-2.1.12

ok agora eu não tenho nenhum erro, mas quando eu verifico meu objeto, timeSeries é nulo ...

então talvez jaxb pareça ter problemas com flx?

redfox26
fonte

Respostas:

204

Eu também enfrentei problemas como esse e configurei isso.

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

Isso vai funcionar 100%

user2067376
fonte
8
Eu tive o mesmo problema. E até funciona quando adicionamos apenas @XmlAccessorType (XmlAccessType.FIELD)
Ram Dutt Shukla
2
Resolvi o problema removendo a @XmlAccessorType(XmlAccessType.FIELD)anotação
Hans Wouters
Parece estranho, mas também me livrei dessa exceção reduzindo o par de anotações \ @XmlRootElement @XmlAccessorType (XmlAccessType.FIELD) para apenas \ @XmlRootElement
Alex InTechno
3
Encontrou o mesmo problema com classes Inner para anotação JAXB. Colocar @XmlAccessorType (XmlAccessType.FIELD) nas classes internas funcionou!
Shoaib Khan
Incrível, muito obrigado. Em combinação com Lombok muito útil
Michael Hegner
25

Você não especificou qual versão do JAXB-IMPL está usando, mas uma vez eu tive o mesmo problema (com jaxb-impl 2.0.5) e resolvi usando a anotação no nível getter em vez de usá-la no nível do membro.

megator
fonte
Isso é correto, acabei de remover a anotação do membro e colocá-la no nível de setter e funcionou.
Varun
22

Eu também vi alguns problemas semelhantes como este.

Acho que é por causa do lugar onde usamos a anotação " @XMLElement " na classe (bean).

E eu acho que o JAXB (processador de anotação) considera o campo membro e método getter do mesmo elemento de campo como propriedades diferentes, quando usamos a anotação @XMLElement no nível do campo e lança a exceção IllegalAnnotationExceptions .

Mensagem de exceção:

A classe tem duas propriedades com o mesmo nome "timeSeries"

No Método Getter:

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

No campo do membro:

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

Solução: em vez de usar @XmlElement no campo , use-o no método getter .

Sriram
fonte
16

acabei de adicionar isso à minha classe

@XmlAccessorType(XmlAccessType.FIELD)

trabalhou como um cham

Ismael Ozil
fonte
Funciona junto com a anotação @Data de lombok também.
digz6666
16

Existem várias soluções, mas basicamente se você anota na declaração de variável, então você precisa @XmlAccessorType(XmlAccessType.FIELD), mas se você preferir anotar um método get- ou set, então você não precisa .

Então você pode fazer:

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

Ou:

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

    @XmlElement(name = "STATUS")         
    public int getStatus()
    {
    }
}
Assado em Nome
fonte
Maravilhoso. Obrigado :) +1
Anish B.
11

Seu JAXB está olhando para o getTimeSeries()método e o membro timeSeries. Você não diz qual implementação JAXB está usando ou sua configuração, mas a exceção é bastante clara.

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

e

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

Você precisa configurar seu material JAXB para usar anotações (conforme seu @XmlElement(name="TimeSeries")) e ignorar métodos públicos.

ptomli
fonte
eu já faço: @XmlElement (name = "TimeSeries") protected List <TimeSeries> timeSeries;
redfox26
4
também eu mudo (XmlAccessType.FIELD) para (XmlAccessType.NONE), posso manter XmlElement no nível do membro
redfox26
Também precisei adicionar @XmlTransient à variável
HomeIsWhereThePcIs
8

Você precisa configurar a classe ModeleREPtão bem @XmlAccessorType(XmlAccessType.FIELD)quanto fez com a classe TimeSeries.

Dê uma olhada no OOXS

Mike
fonte
8

Se usarmos as anotações abaixo e removermos a anotação "@XmlElement", o código deve funcionar corretamente e o XML resultante terá os nomes dos elementos semelhantes aos do membro da classe.

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

Caso o uso de "@XmlElement" seja realmente necessário, defina-o como nível de campo e o código deve funcionar perfeitamente. Não defina a anotação na parte superior do método getter.

Tentei as duas abordagens acima mencionadas e consegui resolver o problema.

Naveen Rahangdale
fonte
7

"Classe tem duas propriedades de exceção com o mesmo nome" pode acontecer quando você tem um membro de classe x com um nível de acesso público e um getter / setter para o mesmo membro.

Como regra prática do java, não é recomendado usar um nível de acesso público junto com getters e setters.

Verifique isto para obter mais detalhes: Propriedade pública VS Propriedade privada com getter?

Para consertar isso:

  1. Mude o nível de acesso de seu membro para privado e mantenha seu getter / setter
  2. Remova o getter e setter do membro
Naor Bar
fonte
6

Estas são as duas propriedades que o JAXB está examinando.

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

e

protected java.util.List testjaxp.ModeleREP.timeSeries

Isso pode ser evitado usando a anotação JAXB no método get, conforme mencionado abaixo.

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

apenas declare as variáveis ​​de membro como privadas na classe que você deseja converter para XML. Boa codificação

Tayab Hussain
fonte
Esta deve ser a solução aceita. Se você declarar sua variável de membro pública, o JABX irá analisá-la além dos métodos anotados getter / setter e cuspir a exceção. É um ótimo exemplo em que o (s) designer (s) da biblioteca jabx foram uma milha extra na reflexão tentando criar flexibilidade e acabaram facilitando configurações inválidas. Corrigi o problema sozinho, alterando uma linha de código por vez, rastreando de volta à variável de membro.
Vortex
4

Mesmo problema que enfrentei, acrescentei

@XmlRootElement(name="yourRootElementName")

@XmlAccessorType(XmlAccessType.FIELD)

e agora está funcionando.

Anil
fonte
3

Isso funcionará quando você colocar sua anotação antes dos getters e removê-la dos atributos protegidos:

protected String codingScheme;

@XmlAttribute(name = "codingScheme")
public String getCodingScheme() {
    return this.codingScheme;
}
Lilia
fonte
Eu também estou enfrentando o mesmo problema. Eu também observei que, quando a anotação é marcada sobre os atributos, vejo isso. Isso significa que sempre deve ser colocado antes dos getters ?.
Pavan Dittakavi de
@Pavan Sim, acho que sim. Caso contrário, isso me causa os mesmos problemas que você
Lilia
2

Acabei de encontrar esse problema e resolvi-o.

A origem do problema é que você tem XmlAccessType.FIELD e pares de getters e setters. A solução é remover setters e adicionar um construtor padrão e um construtor que leva todos os campos.

Slava Imeshev
fonte
Eu tive o mesmo erro e a anotação que você mencionou resolveu, obrigado!
gyorgyabraham
1

Tive uma aula de serviço com a assinatura abaixo "

@WebMethod
public FetchIQAStatusResponseVO fetchIQAStatus(FetchIQAStatusRequest fetchIQAStatusRequest) {

Na execução, obtive o mesmo erro para os FetchIQAStatusResponseVOcampos. Acabei de adicionar uma linha em cima de FetchIQAStatusResponseVO:

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

e isso resolveu o problema.

S Agrawal
fonte
1

ModeleREP#getTimeSeries()tem que estar com @Transientanotação. Isso ajudaria.

Armer B.
fonte
0

Anotar com @XmlTransientresolve esse problema

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

Consulte http://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/XmlTransient.html para obter mais detalhes

Kmaziarz
fonte
1
Acho que isso é mais um hack do que uma solução. Isso diz a jaxb para ignorar o método, em vez de torná-lo ciente de que é a mesma coisa.
Hans Wouters
Hack ou não esta É a melhor solução para contornar algo que não pode ser descrito como nada menos que um bug. Usei @XmlAccessorType (XmlAccessType.FIELD) que foi quase totalmente ignorado e adicionar @XmlTransient a cada propriedade foi a única maneira de repare este problema. Obrigado!
Ralph Ritoch,
0

Uma maneira rápida e simples de corrigir esse problema é remover o @XmlElement(name="TimeSeries")do início da instrução de declaração da variável protected List<TimeSeries> timeSeries;para o início de seu getter public List<TimeSeries> getTimeSeries(),.

Portanto, sua ModeleREPclasse será semelhante 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;
  }
}

Espero que ajude!

Sourav Purakayastha
fonte
Você mencionou 'Uma maneira simples'. Curioso, existe alguma outra maneira de sair disso - não, outra anotação que poderia ser aproveitada ?.
Pavan Dittakavi de
0

Eu fiz tentativa e erro e cheguei à conclusão de que, você só precisa usar um dos dois @XMLElementou @XmlAccessorType(XmlAccessType.FIELD).

Quando usar qual?

caso 1 : se os nomes dos campos e o nome do elemento que deseja usar no arquivo xml forem diferentes, você deve usar @XMLElement(name="elementName"). Como isso irá vincular campos com esse nome de elemento e exibir no arquivo XML.

caso 2 : se os nomes dos campos e o respectivo nome do elemento em xml forem iguais, você pode simplesmente usar@XmlAccessorType(XmlAccessType.FIELD)

Nilam Dhami
fonte
0

Muitas soluções foram fornecidas, e os internos são brevemente tocados por @Sriram e @ptomli também. Só quero adicionar algumas referências ao código-fonte para ajudar a entender o que está acontecendo nos bastidores.

Por padrão (ou seja, nenhuma anotação extra usada, exceto @XmlRootElementna classe raiz), o JABX tenta empacotar as coisas expostas de duas maneiras:

  1. campos públicos
  2. métodos getter que são nomeados de acordo com a convenção e têm um método setter correspondente.

Observe que se um campo é (ou retorna o método) null , ele não será escrito na saída.

Agora se @XmlElement for usado, coisas não públicas (podem ser campos ou métodos getter) também podem ser empacotadas.

Mas as duas formas, isto é, campos e métodos getter, não devem entrar em conflito uma com a outra. Caso contrário, você obterá a exceção .

wlnirvana
fonte