简体   繁体   中英

JAX-RS consume a resource object

service with the Jersey implementation of JAX-RS. My Question is if it is possible to consume an object that is represented by an URI directly. I'm sorry if my wording is wrong but I'm a beginner when it comes to web-services, REST and Marshalling/Unmarschalling.

To illustrate my problem I've made an example web-service. First I created a POJO that will be published and consumed by the web-service

package com.test.webapp.resources;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class SomeData {

    private String name;
    private String id;
    private String description;

    public SomeData() {

    }

    public SomeData(String id, String name, String description) {

        this.id = id;
        this.name = name;
        this.description = description;
    }

    public String getName() {
        return name;
    }

    public String getId() {
        return id;
    }

    public String getDescription() {
        return description;
    }

    @Override
    public String toString() {

        return "SomeData [id=" 
               + id 
               + ", name=" 
               + name 
               + ", description=" 
               + description + "]";
    }
}

Next the web-service that will publish the data:

package com.test.webapp.resources;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.GenericType;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.json.JSONConfiguration;

@Path("/data")
public class DataResource {

    @Context
    private UriInfo uriInfo;
    @Context
    private Request request;

    private static SomeData firstData = new SomeData("1", 
                                                     "Important Data", 
                                                     "First Test Data");
    private static SomeData secondData = new SomeData("2", 
                                                      "Very Important Data", 
                                                      "Second Test Data");
    private static SomeData thirdData = new SomeData("3",  
                                                     "Some Data", 
                                                     "Third Test Data");    
    private static List<SomeData> someDataList = new ArrayList<>();

    static {

        someDataList.add(firstData);
        someDataList.add(secondData);
        someDataList.add(thirdData);        
    }

    @GET
    @Path("/someData/list")
    @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
    public List<SomeData> getSomeData() {

        return someDataList; 
    }

    @GET
    @Path("/someData/{id}")
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    public SomeData getSomeDataSingle(@PathParam("id") int id) {

        try {

            SomeData data = someDataList.get(id);

            return new SomeData(data.getId(), 
                                       data.getName(), 
                                       data.getDescription());
        }           
        catch (IndexOutOfBoundsException e){

            throw new RuntimeException("Data with id: " 
                                       + id + " was not found");
        }
    }   


    @POST
    @Path("/someSummary/create/all/uri")
    @Consumes(MediaType.APPLICATION_XML)
    public Response createSumaryFromUrl(String someDataResourceString) {

        URI someDataResource = null;

        try {

            someDataResource = new URI(someDataResourceString);
        } 
        catch (URISyntaxException e1) {

            e1.printStackTrace();
        }

        List<SomeData> theDataList = this.comsumeData(someDataResource);

        String summaryString = "";

        for(SomeData data : theDataList) {

            summaryString += data.getDescription() + " ";
        }

        return Response.status(201).entity(summaryString).build();
    }

    private List<SomeData> comsumeData(URI someDataResource) {

        ClientConfig clientConfig = new DefaultClientConfig();
        clientConfig.getFeatures()
                    .put(JSONConfiguration.FEATURE_POJO_MAPPING, 
                         Boolean.TRUE);
        Client client = Client.create(clientConfig);
        WebResource webResource = client.resource(someDataResource);

        List<SomeData> dataListFromGet = webResource
                                  .accept(MediaType.APPLICATION_JSON)                                                                            
                                  .get(new GenericType<List<SomeData>>(){});

        return dataListFromGet;

    }
}

Now I create a Jersey Client to do a post and create a summary.

package com.test.webapp.client;

import java.net.URI;

import javax.ws.rs.core.MediaType;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.json.JSONConfiguration;

public class JerseyClient {

    public static void main(String[] args) {

        try {

            ClientConfig clientConfig = new DefaultClientConfig();
            clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
            Client client = Client.create(clientConfig);
            WebResource webResource = client.resource("http://localhost:8080/WebApp");

            URI someDataListResource = new URI("http://localhost:8080/WebApp/data/someData/list");

            ClientResponse response = webResource
                    .path("data/someSummary/create/all/uri")
                    .accept(MediaType.APPLICATION_XML)
                    .type(MediaType.APPLICATION_XML)
                    .post(ClientResponse.class, someDataListResource.toString());

            if(response.getStatus() != 201) {

                throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
            }

            System.out.println(response.getEntity(String.class));
        }

        catch(Exception e) {

            e.printStackTrace();
        }
    }
}

So this works all good and well. However I think this is some kind of workaround to create a client inside the web-service to consume a resource. What I would like to do is remove the client all together inside the web-service and consume the object behind a resource directly.

Something like this:

In the web-service:

@POST
@Path("/someSummary/create/all")
@Consumes(MediaType.APPLICATION_XML)
public Response createSumary(List<SomeData> someDataList) {

    String summaryString = "";

    for(SomeData data : someDataList) {

        summaryString += data.getDescription() + " ";
    }   

    return Response.status(201).entity(summaryString).build();
}

And in the client something like this:

URI someDataListResource = new URI("http://localhost:8080/WebApp/data/someData/list");

ClientResponse response = webResource
        .path("data/someSummary/create/all/uri")
        .accept(MediaType.APPLICATION_XML)
        .type(MediaType.APPLICATION_XML)
        .post(ClientResponse.class, someDataListResource);

Is this possible or do I get something wrong?

Sorry if this is a trivial question but I did some research and couldn't find anything probably because my search therms are wrong due to my inexperience.

Thank you for your efforts in advance.

First, yes, if you want to consume URIs, you will need to do it by hand. You could write a custom class like this:

public class SomeDataList extends ArrayList<SomeData> {
   public static SomeDataList valueOf(String uri) {
       // fetch the URI & create the list with the objects, return it.
   }
   // other methods
}

And just use this specific class in your request:

@POST
@Path("/someSummary/create/all/uri")
@Consumes(MediaType.APPLICATION_XML)
public Response createSumaryFromUrl(@QueryParam("uri") SomeDataList someDataResourceString) {
   //....
}

However, it looks to me that the specific objects you want to retrieve are already in the server, so there's no need to do a round-trip over HTTP+REST - just find them directly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM