Java JAX-B:子元素上缺少XML属性

Java JAX-B:子元素上缺少XML属性,java,xml,web-services,jaxb,moxy,Java,Xml,Web Services,Jaxb,Moxy,编辑:我最初在问题中遗漏了一个重要的细节——返回要封送的Java对象的服务方法返回的是接口类型(Foo),而不是类实现类型(FooImpl) 我有一个简单的Java类,其中包含几个元素和属性的JAX-B注释: @XmlRootElement(name = "foo") public class FooImpl { private String id; private String name; @XmlElement public String getName()

编辑:我最初在问题中遗漏了一个重要的细节——返回要封送的Java对象的服务方法返回的是接口类型(
Foo
),而不是类实现类型(
FooImpl

我有一个简单的Java类,其中包含几个元素和属性的JAX-B注释:

@XmlRootElement(name = "foo")
public class FooImpl {
    private String id;
    private String name;

    @XmlElement
    public String getName() {
            return name;
    }

    public void setName(final String name) {
            this.name = name;
    }

    @XmlAttribute
    public String getId() {
            return Id;
    }

    public void setId(final String id) {
            this.id = id;
    }
}
编辑:FooImpl类有一个名为
Foo
的接口:

public interface Foo {
    public String getName();
    public void setName(final String name);

    public String getId();
    public void setId(final String id);
}
当我有一个返回
Foo
的服务方法时,我得到了我所期望的:

<foo id="abc123">
  <name>bar</name>
</foo>
保存列表的类如下所示:

@XmlRootElement(name = "foos")
public class Foos {

    private List<Foo> foos;

    @XmlElement(name = "foo")
    public List<Foo> getFoos() {
        return foos;
    }

    public void setFoos(List<Foo> foos) {
        this.foos = foos;
    }

}
@XmlRootElement(name=“foos”)
公共类食品{
私人名单;
@xmlement(name=“foo”)
公共列表getFoos(){
返回foos;
}
公共void setFoos(列出foos){
this.foos=foos;
}
}

我碰巧使用MOXy作为我的JAX-B实现,但我认为这并不重要。

注意:我是专家组的负责人和成员

由于您有一个类型为接口的属性,因此需要在
@xmlement
注释上指定实现类型:

@XmlElement(name = "foo", type=FooImpl.class)
public List<Foo> getFoos() {
   return foos;
}
FoomImpl

package forum9137171;

import javax.xml.bind.annotation.*;

@XmlRootElement(name = "foo")
public class FooImpl implements Foo {
    private String id;
    private String name;

    @XmlElement
    public String getName() {
            return name;
    }

    public void setName(final String name) {
            this.name = name;
    }

    @XmlAttribute
    public String getId() {
            return id;
    }

    public void setId(final String id) {
            this.id = id;
    }
}
演示

package forum9137171;

public interface Foo {
    public String getName();
    public void setName(final String name);

    public String getId();
    public void setId(final String id);
}
package forum9137171;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Foos.class);
        System.out.println(jc);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum9137171/input.xml");
        Foos foos = (Foos) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(foos, System.out);
    }

}
输入/输出

org.eclipse.persistence.jaxb.JAXBContext@16a786
<?xml version="1.0" encoding="UTF-8"?>
<foos>
   <foo id="abc123">
      <name>bar1</name>
   </foo>
   <foo id="def456">
      <name>bar2</name>
   </foo>
</foos>
org.eclipse.persistence.jaxb。JAXBContext@16a786
bar1
bar2
了解更多信息


注意:我是专家组的负责人和成员

由于您有一个类型为接口的属性,因此需要在
@xmlement
注释上指定实现类型:

@XmlElement(name = "foo", type=FooImpl.class)
public List<Foo> getFoos() {
   return foos;
}
FoomImpl

package forum9137171;

import javax.xml.bind.annotation.*;

@XmlRootElement(name = "foo")
public class FooImpl implements Foo {
    private String id;
    private String name;

    @XmlElement
    public String getName() {
            return name;
    }

    public void setName(final String name) {
            this.name = name;
    }

    @XmlAttribute
    public String getId() {
            return id;
    }

    public void setId(final String id) {
            this.id = id;
    }
}
演示

package forum9137171;

public interface Foo {
    public String getName();
    public void setName(final String name);

    public String getId();
    public void setId(final String id);
}
package forum9137171;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Foos.class);
        System.out.println(jc);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum9137171/input.xml");
        Foos foos = (Foos) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(foos, System.out);
    }

}
输入/输出

org.eclipse.persistence.jaxb.JAXBContext@16a786
<?xml version="1.0" encoding="UTF-8"?>
<foos>
   <foo id="abc123">
      <name>bar1</name>
   </foo>
   <foo id="def456">
      <name>bar2</name>
   </foo>
</foos>
org.eclipse.persistence.jaxb。JAXBContext@16a786
bar1
bar2
了解更多信息


是否确定内存中的对象(编组之前)包含
id
属性的非空值?是。我可以自行返回任何一个
Foo
对象并查看属性值。但是当同一个对象是
Foos
集合的一部分时,我不能。我正在通过HTTP4E直接从Eclipse测试web服务,以便能够准确地看到有效负载。您确定内存中的对象(编组之前)包含
id
属性的非空值吗?是的。我可以自行返回任何一个
Foo
对象并查看属性值。但是当同一个对象是
Foos
集合的一部分时,我不能。我正在通过HTTP4E直接从Eclipse测试web服务,以便能够准确地看到有效负载。谢谢您的快速回复。知道我的注释或期望没有错是很有帮助的。这一定是我周围的环境。我将尝试创建一个可复制的测试用例。在创建一个可复制的测试用例的过程中,我发现我的代码和原始问题中缩小的代码之间存在一个潜在的重要差异。请看我的编辑上面。Foo是由FooImpl类实现的接口。然而,我只有FooImpl上的JAX-B注释。还请注意,返回
Foo
的服务方法有效…但返回
List
的服务方法无效。您的回答非常有效…谢谢。我想这确实让我感到疑惑,为什么JAXB不能自己找出支持接口的实现类型。这也让我想知道,为什么返回一个
Foo
就可以了?!谢谢你的快速回复。知道我的注释或期望没有错是很有帮助的。这一定是我周围的环境。我将尝试创建一个可复制的测试用例。在创建一个可复制的测试用例的过程中,我发现我的代码和原始问题中缩小的代码之间存在一个潜在的重要差异。请看我的编辑上面。Foo是由FooImpl类实现的接口。然而,我只有FooImpl上的JAX-B注释。还请注意,返回
Foo
的服务方法有效…但返回
List
的服务方法无效。您的回答非常有效…谢谢。我想这确实让我感到疑惑,为什么JAXB不能自己找出支持接口的实现类型。这也让我想知道,为什么返回一个
Foo
就可以了?!