2013-03-25 7 views
13

Im utilizza Jersey per creare un servizio REST e desidera restituire uno Collection<String> come XML.Un writer del corpo del messaggio per la classe Java java.util.ArrayList ... e il tipo di supporto MIME text/xml non è stato trovato

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

ma i miei tentativi non riescono, con la seguente eccezione:

javax.ws.rs.WebApplicationException: com.sun.jersey.api.MessageException: Uno scrittore corpo del messaggio per Java di classe java.util .ArrayList, e il tipo di classe Java java.util.ArrayList, e MIME tipo di supporto text/xml non è stato trovato

e tutti i risultati di tale eccezione ho trovato tramite Google affrontato il ritorno del testo/jSON invece di text/xml come nella mia situazione.

Qualcuno può aiutarmi? Ho pensato che, se io uso una risposta, che sarebbe stato il mio elemento principale in XML e la mia collezione un elenco di elementi stringa in esso ..

risposta

11

NOTA: Anche se questa risposta funziona, anar's answer è meglio.

Si dovrebbe provare a utilizzare una classe annotata JAXB per risolvere il problema. Si potrebbe cambiare il metodo a questo:

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

E poi creare una classe annotata JAXB per i gruppi. Ho incluso una classe generata per te, utilizzando la procedura descritta in this answer. Ecco un esempio dei documenti che produrrà:

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

E qui è la classe generata:

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

} 
+0

Non c'è altro modo? Pensavo che Response avrebbe fatto il lavoro per quello che hai creato i gruppi di classe.-> fornire un contenitore per la lista un atto come elemento radice – lrxw

+0

Al minimo, qualcosa deve dire a Jersey il nome dell'elemento XML radice. Sembra che tu possa utilizzare un [wrapper generico e JAXB] (http://stackoverflow.com/a/1603484/1818625) o la [biblioteca XStream] (http://stackoverflow.com/a/8427694/1818625). –

+0

http://stackoverflow.com/questions/17342218/getting-error-a-message-body-writer-for-java-class-java-util-arraylist-listjava .. puoi risolvere questo problema ?? – user2416728

40

Usa

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

L'entità involucro generico funziona per ottenere il risultato quando si utilizza il generatore di risposte.

Reference

+0

Ha funzionato benissimo per LinkedList - grazie! – remrick

+0

purtroppo il link a cui fai riferimento qui è morto, ma sarebbe stato davvero utile – Toadfish

+1

http://docs.oracle.com/javaee/6/api/javax/ws/rs/core/GenericEntity.html – OhadR

0

L'unica cosa che ha funzionato per me finora è quello di creare il mio oggetto wrapper.

non dimenticare il @XmlRootElement annotazione di spiegare JAXB come analizzare esso.

Nota che questo funzionerà per qualsiasi tipo di oggetto: in questo esempio ho usato ArrayList of String.

ad es.

L'oggetto wrapper dovrebbe essere così:

import java.util.ArrayList; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class ArrayListWrapper { 
    public ArrayList<String> myArray = new ArrayList<String>(); 
} 

E il metodo resto dovrebbe assomigliare a questo:

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