Commit 5d0ab57d by Patryk Czarnik

Oddzielna obsługa JSON i XML

parent 7b78c9c3
package rest;
import java.math.BigDecimal;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import sklep.db.DBConnection;
import sklep.db.DBException;
import sklep.db.ProductDAO;
import sklep.db.RecordNotFound;
import sklep.model.Product;
import sklep.photo.PhotoUtil;
@Path("/products.json")
@Consumes("application/json")
@Produces("application/json")
public class RProductJSON {
// @Produces i @Consumes na poziomie klasy są domyślnymi ustawieniami dla wszystkich metod.
// Metoda może to ustawienie zmienić - tak jest w foto.
// Inaczej niż w Springu, ustawienie Produces/Consumes na poziomie klasy dotyczy tylko tych metod,
// które coś produkują lub konsumują. Metody typu GET nie zwracają uwagi na Consumes,
// a metody typu void są poprawne mimo tego, że nie produkują JSONa.
@GET
public List<Product> readAllProducts() throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return productDAO.readAll();
}
}
@Path("/{id}")
@GET
public Product readOneProduct(@PathParam("id") int productId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return productDAO.findById(productId);
}
}
@Path("/{id}/foto")
@GET
@Produces("image/jpeg")
public byte[] foto(@PathParam("id") int productId) throws DBException, RecordNotFound {
return PhotoUtil.readBytes(productId);
}
@Path("/{id}/price")
@GET
public BigDecimal getPrice(@PathParam("id") int productId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
Product product = productDAO.findById(productId);
return product.getPrice();
}
}
// W metodach HTTP POST i PUT klient przysyła dane na serwer (tzw. body / entity / content).
// Adnotacja @Consumes mówi w jakim formacie powinny być te dane.
// Metoda w JAX-RS może posiadać co najwyżej jeden parametr nieoznaczony żadną adnotacją.
// Właśnie poprzez ten parametr przekazywane są dane przysłane w treści zapytania (w praktyce: POST i PUT).
@Path("/{id}/price")
@PUT
public void setPrice(@PathParam("id") int productId, BigDecimal newPrice) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
Product product = productDAO.findById(productId);
product.setPrice(newPrice);
productDAO.save(product);
db.commit();
}
}
@Path("/{id}")
@PUT
public void updateProduct(@PathParam("id") int productId, Product product) throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
if(product.getProductId() == null) {
// jeśli przysłany rekord nie posiada ID, to utawiam ID z adresu
// w szczególności pozwalam na zapisanie nowego produktu, ale pod określonym adresem
product.setProductId(productId);
} else if(product.getProductId() != productId) {
// ale jeśli ID było ustawione, ale było inne niż w adresie, to jest to podejrzana sytuacja i takie zapytania nie wykonamy
throw new IllegalArgumentException("ID produktu nie zgodne z adresem URL");
}
productDAO.save(product);
db.commit();
}
}
// za pomocą POST będzie można przysłać wyłącznie nowe produkty be określonego ID,
// a aplikacja sama wybierze nowe ID z sekwencjii
// w wyniku zostanie odesłany uzupełniony produkt
@POST
public Product addProduct(Product product) 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();
return product;
}
}
@DELETE
@Path("/{id}")
public void removeProduct(@PathParam("id") int productId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
if(productDAO.delete(productId)) {
db.commit();
} else {
throw new RecordNotFound("Nie ma produktu nr " + productId);
}
}
}
}
package rest;
import java.math.BigDecimal;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import sklep.db.DBConnection;
import sklep.db.DBException;
import sklep.db.ProductDAO;
import sklep.db.RecordNotFound;
import sklep.model.Product;
import sklep.photo.PhotoUtil;
@Path("/products.xml")
@Consumes("application/xml")
@Produces("application/xml")
public class RProductXML {
@GET
public List<Product> readAllProducts() throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return productDAO.readAll();
}
}
@Path("/{id}")
@GET
public Product readOneProduct(@PathParam("id") int productId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return productDAO.findById(productId);
}
}
@Path("/{id}/foto")
@GET
@Produces("image/jpeg")
public byte[] foto(@PathParam("id") int productId) throws DBException, RecordNotFound {
return PhotoUtil.readBytes(productId);
}
@Path("/{id}/price")
@GET
public BigDecimal getPrice(@PathParam("id") int productId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
Product product = productDAO.findById(productId);
return product.getPrice();
}
}
// W metodach HTTP POST i PUT klient przysyła dane na serwer (tzw. body / entity / content).
// Adnotacja @Consumes mówi w jakim formacie powinny być te dane.
// Metoda w JAX-RS może posiadać co najwyżej jeden parametr nieoznaczony żadną adnotacją.
// Właśnie poprzez ten parametr przekazywane są dane przysłane w treści zapytania (w praktyce: POST i PUT).
@Path("/{id}/price")
@PUT
public void setPrice(@PathParam("id") int productId, BigDecimal newPrice) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
Product product = productDAO.findById(productId);
product.setPrice(newPrice);
productDAO.save(product);
db.commit();
}
}
@Path("/{id}")
@PUT
public void updateProduct(@PathParam("id") int productId, Product product) throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
if(product.getProductId() == null) {
// jeśli przysłany rekord nie posiada ID, to utawiam ID z adresu
// w szczególności pozwalam na zapisanie nowego produktu, ale pod określonym adresem
product.setProductId(productId);
} else if(product.getProductId() != productId) {
// ale jeśli ID było ustawione, ale było inne niż w adresie, to jest to podejrzana sytuacja i takie zapytania nie wykonamy
throw new IllegalArgumentException("ID produktu nie zgodne z adresem URL");
}
productDAO.save(product);
db.commit();
}
}
// za pomocą POST będzie można przysłać wyłącznie nowe produkty be określonego ID,
// a aplikacja sama wybierze nowe ID z sekwencjii
// w wyniku zostanie odesłany uzupełniony produkt
@POST
public Product addProduct(Product product) 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();
return product;
}
}
@DELETE
@Path("/{id}")
public void removeProduct(@PathParam("id") int productId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
if(productDAO.delete(productId)) {
db.commit();
} else {
throw new RecordNotFound("Nie ma produktu nr " + productId);
}
}
}
}
...@@ -5,7 +5,9 @@ import java.util.Objects; ...@@ -5,7 +5,9 @@ import java.util.Objects;
import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Product { public class Product {
@XmlAttribute(name="id") @XmlAttribute(name="id")
private Integer productId; private Integer productId;
......
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