NicholasKarl
NicholasKarl

Reputation: 253

How do I make a RESTful service handle custom object in the Response?

How do I make custom object in a restful Response look like a native type. In other words, I don't want to use a getter and setter, but rather have the object marshal and unmarshall like a string. I can use a constructor for unmarshall, but I don't know how to get the object through the Response of the service. When I run the sample, I get this result:

<data>
  <nType>123</nType>
  <myType/>
  <notMyType>
    <value>def</value>
  </notMyType>
</data>

I am trying to get myType to look like nType. Here is a short code example:

package rscust;

import java.util.HashSet;
import java.util.Set;

import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.xml.bind.annotation.XmlRootElement;

@Path("/")
public class Service extends Application {

    @XmlRootElement
    public static class Data {
        public String nType;
        public MyType myType;
        public NotMyType notMyType;
        public Data() {}
    }

    // custom class does not work in Response
    public static class MyType {
        private String value;
        public MyType() {}
        public MyType(String value) {
            this.value=value;
        }
        public String toString() {
            return value;
        }
    }

    // works with getter and setter, but I don't want that
    public static class NotMyType {
        private String value;
        public NotMyType() {}
        public NotMyType(String value) {
            this.setValue(value);
        }
        public String getValue() {
            return value;
        }
        public void setValue(String value) {
            this.value = value;
        }
    }

    @GET
    @Produces(value={MediaType.APPLICATION_XML})
    public Response get(
            @QueryParam(value = "ntype")String nType,
            @QueryParam(value = "mytype")MyType myType, 
            @QueryParam(value = "notmytype")NotMyType notMyType
    ) {
        Data data = new Data();
        data.nType = nType;
        data.myType = myType;
        data.notMyType = notMyType;
        return Response.ok().entity(data).build();

    }

    private HashSet<Object> singletons;
    public Service() {
        super();
        singletons = new HashSet<Object>();
        singletons.add(this);
    }
    public Set<Object> getSingletons() {
        return singletons;
    }
}

Upvotes: 2

Views: 1687

Answers (2)

Mark
Mark

Reputation: 18807

If you don't wont to use getter and setter, than you need set the fields 'public'. Because RESTeasy need access to the fields.

Upvotes: 0

SpacePrez
SpacePrez

Reputation: 1086

The answer is you need to add annotations to the custom class to tell it how to deserialize and serialize the different fields. Your get method looks fine, but the custom classes aren't annotated at all. MyType and NotMyType should also have @ XmlRootElement as well as annotations to mark which fields are @ Transient and which are @ JsonProperty

@XmlRootElement
    public static class Data {
        @JsonProperty
        public String nType;
        @JsonProperty
        public MyType myType;
        @JsonProperty
        public NotMyType notMyType;
        public Data() {}
    }

@XmlRootElement
public static class MyType {
        @JsonProperty
        private String value;
        public MyType() {}
        public MyType(String value) {
            this.value=value;
        }
        public String toString() {
            return value;
        }
    }

also, since you made those objects part of Data already, just request a single data object, and then you can pull the others from there.

public Response get( @QueryParam(value = "data")Data d,){
Data d = data.nType;
}

Upvotes: 3

Related Questions