Reputation: 225
I'm trying to solidify my understanding of Rest.
1) How does this function get called when there's no @Path, specifically, what triggers getCustomers to get called? "public StreamingOutput getCustomers(final @QueryParam("start") int start, final @QueryParam("size") @DefaultValue("2") int size)"
Source:
package com.restfully.shop.services;
import com.restfully.shop.domain.Customer;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.StreamingOutput;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
@Path("/customers")
public class CustomerResource
{
private Map<Integer, Customer> customerDB = Collections.synchronizedMap(new LinkedHashMap<Integer, Customer>());
public CustomerResource()
{
Customer customer;
int id = 1;
customer = new Customer();
customer.setId(id);
customer.setFirstName("Bill");
customer.setLastName("Burke");
customerDB.put(id++, customer);
customer = new Customer();
customer.setId(id);
customer.setFirstName("Joe");
customer.setLastName("Burke");
customerDB.put(id++, customer);
}
@GET
@Produces("application/xml")
public StreamingOutput getCustomers(final @QueryParam("start") int start,
final @QueryParam("size") @DefaultValue("2") int size)
{
return new StreamingOutput()
{
public void write(OutputStream outputStream) throws IOException, WebApplicationException
{
PrintStream writer = new PrintStream(outputStream);
writer.println("<customers>");
synchronized (customerDB)
{
int i = 0;
for (Customer customer : customerDB.values())
{
if (i >= start && i < start + size) outputCustomer(" ", writer, customer);
i++;
}
}
writer.println("</customers>");
}
};
}
@GET
@Produces("application/xml")
@Path("uriinfo")
public StreamingOutput getCustomers(@Context UriInfo info)
{
int start = 0;
int size = 2;
if (info.getQueryParameters().containsKey("start"))
{
start = Integer.valueOf(info.getQueryParameters().getFirst("start"));
}
if (info.getQueryParameters().containsKey("size"))
{
size = Integer.valueOf(info.getQueryParameters().getFirst("size"));
}
return getCustomers(start, size);
}
protected void outputCustomer(String indent, PrintStream writer, Customer cust) throws IOException
{
writer.println(indent + "<customer id=\"" + cust.getId() + "\">");
writer.println(indent + " <first-name>" + cust.getFirstName() + "</first-name>");
writer.println(indent + " <last-name>" + cust.getLastName() + "</last-name>");
writer.println(indent + "</customer>");
}
}
2) As for the second getCustomers function, Am I correct that it is the the existence of the path* @Path("uriinfo") that matches the URL that triggers the call? Note #1 has no @path at all. I know there's the precedence rules, but what happens if I had an almost identical method that has the same path, then will BOTH methods get called?
Let's say I also have this- note the 2 in getCustomers2:
@GET
@Produces("application/xml")
@Path("uriinfo")
public StreamingOutput getCustomers2(@Context UriInfo info)
{
int start = 0;
int size = 2;
if (info.getQueryParameters().containsKey("start"))
{
start = Integer.valueOf(info.getQueryParameters().getFirst("start"));
}
if (info.getQueryParameters().containsKey("size"))
{
size = Integer.valueOf(info.getQueryParameters().getFirst("size"));
}
return getCustomers(start, size);
}
I got a compilation error.
Sorry, I made an error previously, what if I had these two methods in the class:
@GET
@Produces("application/xml")
public StreamingOutput getCustomers3(final @QueryParam("start") int start,
final @QueryParam("size") @DefaultValue("2") int size)
{
return new StreamingOutput()
{
public void write(OutputStream outputStream) throws IOException, WebApplicationException
{
PrintStream writer = new PrintStream(outputStream);
writer.println("<customers>");
synchronized (customerDB)
{
int i = 0;
for (Customer customer : customerDB.values())
{
if (i >= start && i < start + size) outputCustomer(" ", writer, customer);
i++;
}
}
writer.println("</customers>");
}
};
}
@GET
@Produces("application/xml")
public StreamingOutput getCustomers4(final @QueryParam("start") int start,
final @QueryParam("size") @DefaultValue("2") int size)
{
return new StreamingOutput()
{
public void write(OutputStream outputStream) throws IOException, WebApplicationException
{
PrintStream writer = new PrintStream(outputStream);
writer.println("<customers>");
synchronized (customerDB)
{
int i = 0;
for (Customer customer : customerDB.values())
{
if (i >= start && i < start + size) outputCustomer(" ", writer, customer) ;
i++;
}
}
writer.println("</customers>");
}
};
}
Upvotes: 1
Views: 320
Reputation: 13410
The getCustomers
method will be called when an HTTP GET
request is sent for /customers
and the client is requesting application/xml
as the desired content type of the request.
If a JAX-RS method is not annotated with an @Path
annotation it inherits the path specified by the class level annotation.
The second getCustomers
method will be called when an HTTP GET
request is sent for /customers/uriinfo
, as the paths are additive, and the client is requesting application/xml
as the desired content type of the request.
No, it is not true that the @Path
value must be unique. What must be unique is the combination of HTTP method (@GET
, @POST
, @DELETE
, etc), @Path
value, and the content type defined by @Produces
and @Consumes
for a method.
Upvotes: 1