Commit f132a963 by Patryk Czarnik

Odpowiedzi jako Response

parent 11b2fe2e
package sklep.rest;
import java.math.BigDecimal;
import java.net.URI;
import java.util.List;
import javax.ws.rs.Consumes;
......@@ -11,6 +12,9 @@ import javax.ws.rs.PUT;
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.Response;
import javax.ws.rs.core.UriInfo;
import sklep.db.DBConnection;
import sklep.db.DBException;
......@@ -117,22 +121,24 @@ public class RProducts {
// Powszechnie przyjętą praktyką w REST jest to, że
// zapytanie typu POST przysłane pod adres katalogu (np. /products)
// jest traktowane jako polecenie dodania nowego rekordu.
// W tej wersji w odpowiedzi odsyłany jest cały rekord Product uzupełniony o pole ID.
// W tej wersji zwracamy kod "201 Created" ze wskazaną lokalizacją nowoutworzonego rekordu.
// Jest to przykład sesnownego użycia klasy Response.
@POST
@Consumes({"application/json", "application/xml"})
@Produces("application/json")
public Product addProduct(Product product) throws DBException {
public Response zapisz(Product product,
@Context UriInfo uriInfo) throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
if(product.getProductId() != null) {
throw new IllegalArgumentException("Nowy produkt nie może mieć ustawionego ID");
}
productDAO.insertNew(product);
productDAO.save(product);
db.commit();
return product;
URI location = uriInfo.getBaseUriBuilder() // bazowy adres aplikacji
.path(RProducts.class) // krok obejmujący katalog produktów /products
.path("/{id}") // krok obejmujcy id produktu, np. /2
.build(product.getProductId()); // podstawienie ID tego konkretnego produktu w miejsce {}
return Response.created(location).build();
}
}
@DELETE
@Path("/{id}")
public void removeProduct(@PathParam("id") int productId) throws DBException, RecordNotFound {
......
package sklep.rest;
import java.net.URI;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
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.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import sklep.db.DBConnection;
import sklep.db.DBException;
import sklep.db.ProductDAO;
import sklep.db.RecordNotFound;
import sklep.model.Product;
import sklep.model.ProductList;
import sklep.photo.PhotoUtil;
// W tej wersji pokazuję, że odpowiedzi na zapytania mogą być zwracane w postaci obiektów klasy Response
// - daje nam to pełną kontrolę nad odpowiedzią (nagłówki, ciasteczka, ...)
// i pozwala dynamicznie podejmować decyzje np. co do formatu danych - czego nie da się w pełni opisać w adnotacjach.
@Path("/products.r")
public class RProductsResponse {
@GET
@Produces({"application/json", "application/xml", "text/plain"})
public Response readAll() {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
ProductList lista = new ProductList(productDAO.readAll());
return Response.ok(lista).build();
} catch (DBException e) {
return Response.serverError()
.type("text/plain")
.entity("Starszny błąd: " + e)
.build();
}
}
@GET
@Produces({"application/json", "application/xml", "text/plain"})
@Path("/{id}")
public Response readOne(@PathParam("id") int productId) {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
Product product = productDAO.findById(productId);
return Response.ok()
.entity(product)
.build();
} catch (DBException e) {
return Response.serverError()
.type("text/plain")
.entity("Starszny błąd: " + e)
.build();
} catch (RecordNotFound e) {
String html = "<html><body><h1>Nie znaleziono</h1><p style='color:red'>" + e.getMessage() + "</p></body></html>";
return Response.status(404)
.type("text/html")
.entity(html)
.build();
}
}
@POST
@Consumes({"application/json", "application/xml"})
public Response addProduct(Product product, @Context UriInfo uriInfo) throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
if(product.getProductId() != null) {
throw new IllegalArgumentException("Nowy produkt nie może mieć ustawionego ID");
}
productDAO.insertNew(product);
db.commit();
URI location = uriInfo.getBaseUriBuilder() // bazowy adres aplikacji
.path(RProductsResponse.class) // krok obejmujący katalog produktów /products
.path("/{id}") // krok obejmujcy id produktu, np. /2
.build(product.getProductId()); // podstawienie ID tego konkretnego produktu w miejsce {}
return Response.created(location).build();
}
}
@DELETE
@Path("/{id}")
public Response removeProduct(@PathParam("id") int productId) {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
if(productDAO.delete(productId)) {
db.commit();
return Response.noContent().build();
} else {
String html = "<html><body><h1>Nie znaleziono</h1><p style='color:red'>Nie ma produktu nr " + productId + "</p></body></html>";
return Response.status(404)
.type("text/html")
.entity(html)
.build();
}
} catch (DBException e) {
throw new WebApplicationException("Straszny błąd");
}
}
@GET
@Path("/{id}/photo")
@Produces("image/jpeg")
public Response getPhoto(@PathParam("id") int productId) {
try {
byte[] bytes = PhotoUtil.readBytes(productId);
return Response.ok(bytes).build();
} catch (DBException | RecordNotFound e) {
return Response.status(404).build();
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment