Enterprise Java Development@TOPIC@
An asset to be exposed to the web
Document, set of properties, method, nearly anything
Web has limited methods but an unlimited number of resources
Example
Products
Categories
Customers
An address to access a particular resource
Can be expressed relative
index.html /rest/products /rest/categories /rest/customers
Can be expressed fully qualified
http://127.0.0.1:8080/jaxrsInventoryWAR/index.html http://127.0.0.1:8080/jaxrsInventoryWAR/rest/products http://127.0.0.1:8080/jaxrsInventoryWAR/rest/categories http://127.0.0.1:8080/jaxrsInventoryWAR/rest/customers
May have query parameters
http://127.0.0.1:8080/jaxrsInventoryWAR/rest/categories?name=&offset=0&limit=0
May have nested path parameters
http://127.0.0.1:8080/jaxrsInventoryWAR/rest/products/1
Building URIs with JAX-RS URIBuilder
//start with the URI for the WAR deployed to the server //that ends with the context-root return UriBuilder.fromUri(appURI) //add path info from the //javax.ws.rs.core.Application @ApplicationPath .path("rest") //add in @Path added by resource class .path(resourceClass) //add in @Path added by resource class' method .path(resourceClass,method); //marshall @PathParm into the URI .build(id);
Bounded ("uniform interface")
Primary Set
GET - non-destructive read
POST - create and other methods
PUT - create or update
DELETE - delete
Secondary Set
HEAD - a GET without the data - metadata only
OPTIONS - lists which methods supported
Example: Get Product ID=1
GET http://127.0.0.1:8080/jaxrsInventoryWAR/rest/products/1
Standardized
2xx - success
3xx - success/redirect
4xx - client error
5xx - server error
Common Set
200 - OK
201 - CREATED
400 - BAD_REQUEST
404 - NOT_FOUND
500 - INTERNAL_ERROR
Annotated with @Path
Injected with implementation details and call context
@Path("/products")
public class ProductsResource {
private static final Log log = LogFactory.getLog(ProductsResource.class);
@Inject
private InventoryMgmtEJB ejb;
@Context
private Request request;
@Context
private UriInfo uriInfo;
...
Create new resource or tunnel service
Returns CREATED and URO of created resource
@POST @Path("")
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
public Response addCustomer(Customer customer) {
log.debug(String.format("%s %s", request.getMethod(), uriInfo.getAbsolutePath()));
try {
Customer c = ejb.addCustomer(customer);
URI uri = UriBuilder.fromUri(uriInfo.getAbsolutePath())
.path(CustomersResource.class, "getCustomer")
.build(c.getId());
return Response.created(uri)
.entity(c)
.build();
} catch (Exception ex) {
return serverError(log, "creating person", ex).build();
}
}
Non-destructive read
Returns OK with payload
@GET @Path("{id}")
@Produces(MediaType.APPLICATION_XML)
public Response getProduct(@PathParam("id")int id) {
log.debug(String.format("%s %s", request.getMethod(), uriInfo.getAbsolutePath()));
try {
Product product = ejb.getProduct(id);
if (product != null) {
return Response.ok(product)
.build();
}
else {
return Response.status(Response.Status.NOT_FOUND)
.entity(String.format("unable to locate product %d", id))
.type(MediaType.TEXT_PLAIN)
.build();
}
} catch (Exception ex) {
return ResourceHelper.serverError(log, "getting product", ex).build();
}
}
Create new or update existing
Optional results
@PUT @Path("{id}")
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
public Response updateProduct(@PathParam("id") int id, Product product) {
log.debug(String.format("%s %s", request.getMethod(), uriInfo.getAbsolutePath()));
try {
Product p = ejb.updateProduct(product);
return Response.ok(p)
.build();
} catch (Exception ex) {
return ResourceHelper.serverError(log, "update product", ex).build();
}
}
Deletes specified resource
Optional results
@DELETE @Path("{id}")
@Produces(MediaType.APPLICATION_XML)
public Response deleteCustomer(@PathParam("id") int id) {
log.debug(String.format("%s %s", request.getMethod(), uriInfo.getAbsolutePath()));
try {
ejb.deleteCustomer(id);
return Response.ok()
.build();
} catch (Exception ex) {
return serverError(log, "deleting person", ex).build();
}
}
Request supplies method, URI, optional payload, and other properties
GET /jaxrsInventoryWAR/rest/categories?name=snacks&offset=0&limit=0 HTTP/1.1 Accept: application/xml Host: 127.0.0.1:7080 Connection: Keep-Alive User-Agent: Apache-HttpClient/4.1.3 (java 1.5)
Response provides status code, optional entity, and other properties]
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Content-Type: application/xml Transfer-Encoding: chunked Date: Tue, 06 Nov 2012 07:32:18 GMT <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <ns2:catageories xmlns:ns2="http://webejb.ejava.info/inventory" count="1" limit="0" offset="0" version="0"> <categories id="4" name="snacks" version="1"> <productCount>1</productCount> </categories> </ns2:catageories>