【问题标题】:A message body writer for Java class java.util.ArrayList...and MIME media type text/xml was not found未找到 Java 类 java.util.ArrayList...和 ​​MIME 媒体类型 text/xml 的消息正文编写器
【发布时间】:2013-03-15 03:01:59
【问题描述】:

我正在使用 Jersey 构建一个 REST 服务,并希望将 Collection<String> 作为 XML 返回。

@GET
@Produces(MediaType.TEXT_XML)
@Path("/directgroups")
public Response getDirectGroupsForUser(@PathParam("userId") String userId) {
    try {
        Collection<String> result = service.getDirectGroupsForUser(userId, null, true);

//      return result; //first try
//      return result.toArray(new String[0]); //second try
        return Response.ok().type(MediaType.TEXT_XML).entity(result).build(); //third try
    } catch (UserServiceException e) {
        LOGGER.error(e);
        throw new RuntimeException(e.getMessage());
    }
}

但我的尝试失败并出现以下异常:

javax.ws.rs.WebApplicationException:com.sun.jersey.api.MessageException:Java 类 java.util.ArrayList、Java 类型类 java.util.ArrayList 和 MIME 媒体类型 text/ 的消息体编写器找不到xml

我通过 google 发现的所有异常结果都处理返回 text/json 而不是像我的情况一样的 text/xml。

谁能帮助我?我想,如果我使用响应,那将是我在 XML 中的根元素,而我的集合是其中的字符串元素列表..

【问题讨论】:

    标签: java xml rest jaxb jersey


    【解决方案1】:

    注意:虽然这个答案有效,但anar's answer 更好。

    您应该尝试使用带有 JAXB 注释的类来解决您的问题。您可以将方法更改为:

    @GET
    @Produces(MediaType.TEXT_XML)
    @Path("/directgroups")
    public Groups getDirectGroupsForUser(@PathParam("userId") String userId) {
        try {
    
            Groups groups = new Groups();
            groups.getGroup().addAll(service.getDirectGroupsForUser(userId, null, true));
            return groups;
        } catch (UserServiceException e) {
            LOGGER.error(e);
            throw new RuntimeException(e.getMessage());
        }
    }
    

    然后为您的组创建一个带有 JAXB 注释的类。我使用this answer 中描述的过程为您包含了一个生成的类。以下是它将生成的文档示例:

    <groups>
      <group>Group1</group>
      </group>Group2</group>
    </groups>
    

    这是生成的类:

    package example;
    
    import java.util.ArrayList;
    import java.util.List;
    import javax.xml.bind.annotation.XmlAccessType;
    import javax.xml.bind.annotation.XmlAccessorType;
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    import javax.xml.bind.annotation.XmlType;
    
    
    /**
     * <p>Java class for anonymous complex type.
     * 
     * <p>The following schema fragment specifies the expected content contained within this class.
     * 
     * <pre>
     * &lt;complexType>
     *   &lt;complexContent>
     *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
     *       &lt;sequence>
     *         &lt;element ref="{}group" maxOccurs="unbounded"/>
     *       &lt;/sequence>
     *     &lt;/restriction>
     *   &lt;/complexContent>
     * &lt;/complexType>
     * </pre>
     * 
     * 
     */
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "group"
    })
    @XmlRootElement(name = "groups")
    public class Groups {
    
        @XmlElement(required = true)
        protected List<String> group;
    
        /**
         * Gets the value of the group property.
         * 
         * <p>
         * This accessor method returns a reference to the live list,
         * not a snapshot. Therefore any modification you make to the
         * returned list will be present inside the JAXB object.
         * This is why there is not a <CODE>set</CODE> method for the group property.
         * 
         * <p>
         * For example, to add a new item, do as follows:
         * <pre>
         *    getGroup().add(newItem);
         * </pre>
         * 
         * 
         * <p>
         * Objects of the following type(s) are allowed in the list
         * {@link String }
         * 
         * 
         */
        public List<String> getGroup() {
            if (group == null) {
                group = new ArrayList<String>();
            }
            return this.group;
        }
    
    }
    

    【讨论】:

    【解决方案2】:

    使用

    List<String> list = new ArrayList<String>();
    GenericEntity<List<String>> entity = new GenericEntity<List<String>>(list) {};
    Response response = Response.ok(entity).build();
    

    通用实体包装器用于在使用响应构建器时获取输出。

    Reference

    【讨论】:

    【解决方案3】:

    到目前为止,唯一对我有用的是创建自己的 Wrapper 对象。

    不要忘记 @XmlRootElement 注释来解释 JAXB 如何解析它。

    请注意,这适用于任何类型的对象 - 在此示例中,我使用了 String 的 ArrayList。

    例如

    Wrapper 对象应如下所示:

    import java.util.ArrayList;
    import javax.xml.bind.annotation.XmlRootElement;
    
    @XmlRootElement
    public class ArrayListWrapper {
        public ArrayList<String> myArray = new ArrayList<String>();
    }
    

    REST 方法应该是这样的:

    @GET
    @Produces(MediaType.TEXT_XML)
    @Path("/directgroups")
    public ArrayListWrapper getDirectGroupsForUser(@PathParam("userId") String userId) {
        try {
            ArrayListWrapper w = new ArrayListWrapper();
            w.myArray = service.getDirectGroupsForUser(userId, null, true);
            return w;
        } catch (UserServiceException e) {
            LOGGER.error(e);
            throw new RuntimeException(e.getMessage());
        }
    }
    

    【讨论】:

      【解决方案4】:

      将@XmlRootElement(name = "class name") 添加到我要返回的对象,解决了我的问题

      【讨论】:

        猜你喜欢
        • 2016-10-01
        • 2018-04-20
        • 2012-01-28
        • 2013-12-05
        • 2012-08-16
        • 2018-01-26
        • 2011-12-11
        • 1970-01-01
        • 2014-03-20
        相关资源
        最近更新 更多