Reputation: 199
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.
Upvotes: 2
Views: 3354
Reputation: 16142
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.
Upvotes: 1