Hello Karsten,
On 02/22/2011 10:09 AM, Knese, Karsten wrote:
> Hey Folks.
>
> Currently I am working on a restful webservice and want to return a array of primitives, e.g. a simple string-array.
> Unfortunately I am not able to fulfill this task. I tried several methods:
>
> Simple Method:
> @GET
> @Path("stringarray")
> @Produces(MediaType.APPLICATION_JSON)
> public String[] test(){
> return new String[]{"one","two","three"};
> }
>
this won't work. Jersey does not support String[] out-of-the-box, but
you could write your own MessageBodyReader/Writer to do that. You can
use ByteArrayProvider [1] as inspiration (or other jaxb related
readers/writers if you want xml output).
>
> Return List:
> @GET
> @Path("stringarray")
> @Produces(MediaType.APPLICATION_JSON)
> public List<String> blub(){
>
> ArrayList<String> list = new ArrayList<String>();
> list.add("one");
> list.add("two");
> list.add("three");
> GenericEntity<List<String>> entity = new GenericEntity<List<String>>(list){};
> return entity.getEntity();
> }
>
>
> What I expect is the following:
> <strings>
> <string>one</string>
> <string>two</string>
> <string>three</string>
> </strings>
>
>
> What I get:
> Feb 21, 2011 4:59:21 PM com.sun.jersey.spi.container.ContainerResponse logException
> SEVERE: Mapped exception to response: 500 (Internal Server Error)
> javax.ws.rs.WebApplicationException: com.sun.jersey.api.MessageException: A message body writer for Java class java.util.ArrayList, and Java type java.util.List<java.lang.String>, and MIME media type text/xml was not found
> at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:285)
> at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1316)
> at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1229)
> at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1219)
> at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:419)
>
yes, thats expected too. If you really want JSON output, you should do
something like this:
@GET
@Path("/a")
@Produces("application/json")
public JSONArray getMessages() {
List<String> l = new ArrayList<String>();
l.add("a");
l.add("b");
l.add("c");
return new JSONArray(l);
}
if you want XML, you'll have to do some additional work because JAXB
needs to have some information about type and currently, Jersey creates
envelope element and serializes List items one by one using JAXB. And
that is the problem here, you can't call
Marshaller.marshal("somestring");. Basically When you are returning
List<Sometype> in xml representation, Sometype should have
@XmlRootElement or @XmlType annotation.
So, in this case, you would need to implement your own MessageBodyWriter
again and do marshalling by yourself.. Other solution is to wrap
everything in some class (which you already did below), but it
introduces another element in your ouput.
>
>
> But now one things works fine, when I encapsulate the array in a PoJo:
>
> import java.util.ArrayList;
> import java.util.Collection;
>
> import javax.xml.bind.annotation.XmlAccessType;
> import javax.xml.bind.annotation.XmlAccessorType;
> import javax.xml.bind.annotation.XmlElement;
> import javax.xml.bind.annotation.XmlElementWrapper;
> import javax.xml.bind.annotation.XmlRootElement;
>
>
> @XmlRootElement
> @XmlAccessorType(XmlAccessType.FIELD)
> public class Car {
>
> public Car() {
> }
>
> @XmlElement
> private String id;
> @XmlElement
> private int counter;
> @XmlElement
> @XmlElementWrapper(name="StringArray")
> private Collection<String> array = new ArrayList<String>();
>
> public Car(String id) {
> this.id = id;
> counter++;
> array.add("one");
> array.add("two");
> }
>
> public void add(){
> counter++;
> }
>
> public int getCounter(){
> return counter;
> }
>
> public String getSession() {
> return id;
> }
>
> }
>
>
>
> <cars>
> −
> <car>
> <id>one</id>
> <counter>1</counter>
> −
> <StringArray>
> <array>one</array>
> <array>two</array>
> </StringArray>
> </car>
> −
> <car>
> <id>two</id>
> <counter>1</counter>
> −
> <StringArray>
> <array>one</array>
> <array>two</array>
> </StringArray>
> </car>
> −
> <car>
> <id>three</id>
> <counter>1</counter>
> −
> <StringArray>
> <array>one</array>
> <array>two</array>
> </StringArray>
> </car>
> </cars>
>
>
>
> What I am doing wrong? I really run out of ideas. Caused by the lack of this feature, I went on with x-stream. Which works quite fine, but that I have to add a new technology...
>
Regards,
Pavel
[1]
http://java.net/projects/jersey/sources/svn/content/trunk/jersey/jersey-core/src/main/java/com/sun/jersey/core/impl/provider/entity/ByteArrayProvider.java?rev=4643
> Cheers,
> Karsten