Commit 9be2e02b by Patryk Czarnik

moduł rest

parent f1d2ac60
......@@ -16,5 +16,6 @@
<modules>
<module>wielomodulowy-model</module>
<module>wielomodulowy-baza</module>
<module>wielomodulowy-rest</module>
</modules>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>pl.alx.kjava</groupId>
<artifactId>Wielomodulowy</artifactId>
<version>1.0</version>
</parent>
<artifactId>wielomodulowy-rest</artifactId>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>jakarta.ws.rs</groupId>
<artifactId>jakarta.ws.rs-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>wielomodulowy-model</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>wielomodulowy-baza</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.4.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package rest;
import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;
/* Ten projekt jest zrobiony w technologii JAX-RS - implementacja usług RESTowych w ramach Java EE.
*
* Ta klasa pełni rolę "aktywatora" tej technologii na serwerze. Gdy serwer (WildFly / Glassfish / WebLogic)
* zauważy w projekcie taką klasę, to wie, że ma skonfigurować usługę REST pod podanym adresem.
* Adres / (albo pusty String) oznacza, że cały projekt jest "jedną wielką aplikacją RESTową",
* ale można też podać jakiś podkatalog na serwerze.
*
* Domyślnie w skład aplikacji RESTowej będą wchodzić wszystkie klasy w projekcie, które mają adnotację @Path (+ rozszerzenia @Provider i @Interceptor, ale to inny temat...)
* To zachowanie można zmienić nadpisując metody getClasses i getSingletons - pokażę to w innym projekcie...
*/
@ApplicationPath("/")
public class AplikacjaRestowa extends Application {
}
package rest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import sklep.db.DBException;
import sklep.db.DBSettings;
import sklep.db.RecordNotFound;
public class PhotoUtil {
private static final String EXT = ".jpg";
public static File getFile(int productId) throws DBException, RecordNotFound {
Path path = getPath(productId);
File file = path.toFile();
if(file.exists()) {
return file;
} else {
throw new RecordNotFound("Cannot read photo for product id = " + productId);
}
}
public static byte[] readBytes(int productId) throws DBException, RecordNotFound {
Path path = getPath(productId);
try {
return Files.readAllBytes(path);
} catch (IOException e) {
// System.err.println(e);
throw new RecordNotFound("Cannot read photo for product id = " + productId);
}
}
public static void writeStream(int productId, InputStream inputStream) {
try {
Path path = getPath(productId);
Files.copy(inputStream, path, StandardCopyOption.REPLACE_EXISTING);
} catch (Exception e) {
// wypisujemy błąd, ale metoda kończy się normalnie
e.printStackTrace();
}
}
public static void writeBytes(int productId, byte[] bytes) {
try {
Path path = getPath(productId);
Files.write(path, bytes, StandardOpenOption.CREATE);
} catch (Exception e) {
// wypisujemy błąd, ale metoda kończy się normalnie
e.printStackTrace();
}
}
private static Path getPath(int productId) throws DBException {
String dir = DBSettings.load().getProperty("photo_dir");
String fileName = productId + EXT;
return Paths.get(dir, fileName);
}
}
package rest;
import java.net.URI;
import java.util.List;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriBuilder;
import sklep.db.CustomerDAO;
import sklep.db.DBConnection;
import sklep.db.DBException;
import sklep.db.RecordNotFound;
import sklep.model.Customer;
@Path("/customers")
@Produces(MediaType.APPLICATION_JSON)
public class RCustomers {
@GET
@Path("/{id}")
public Customer findById(@PathParam("id") final String email) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
CustomerDAO customerDAO = db.customerDAO();
return customerDAO.findByEmail(email);
}
}
@GET
public List<Customer> listAll() throws DBException {
try(DBConnection db = DBConnection.open()) {
CustomerDAO customerDAO = db.customerDAO();
return customerDAO.readAll();
}
}
@POST
public Response save(final Customer customer) throws DBException {
try(DBConnection db = DBConnection.open()) {
CustomerDAO customerDAO = db.customerDAO();
customerDAO.save(customer);
db.commit();
URI uri = UriBuilder
.fromResource(RCustomers.class)
.path(String.valueOf(customer.getEmail()))
.build();
return Response.created(uri).build();
}
}
@PUT
@Path("/{id}")
public Response update(@PathParam("id") String email, final Customer customer) throws DBException {
try(DBConnection db = DBConnection.open()) {
CustomerDAO customerDAO = db.customerDAO();
customer.setEmail(email);
customerDAO.save(customer);
db.commit();
}
return Response.noContent().build();
}
@DELETE
@Path("/{id}")
public Response deleteById(@PathParam("id") String email) throws DBException {
try(DBConnection db = DBConnection.open()) {
CustomerDAO customerDAO = db.customerDAO();
customerDAO.delete(email);
db.commit();
}
return Response.noContent().build();
}
}
package rest;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
@Path("/hello")
public class RHello {
@GET
public String hello() {
return "Hello <b>REST</b>";
}
}
package rest;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import sklep.db.DBConnection;
import sklep.db.DBException;
import sklep.db.ProductDAO;
import sklep.db.RecordNotFound;
import sklep.model.Product;
@Path("/products.html")
public class RHtmlZaPomocaWritera {
// Ta klasa służy do przetestowania własnego MessageBodyWritera,
// który potrafi zamieniać pojedyncze produkty na HTML.
@GET
@Produces("text/html")
@Path("{id}")
public Product readOne(@PathParam("id") int productId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return productDAO.findById(productId);
}
}
}
package rest;
import java.net.URI;
import java.util.List;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import jakarta.ws.rs.core.UriBuilder;
import sklep.db.DBConnection;
import sklep.db.DBException;
import sklep.db.OrderDAO;
import sklep.db.RecordNotFound;
import sklep.model.Order;
@Path("/orders")
@Produces(MediaType.APPLICATION_JSON)
public class ROrders {
@GET
public List<Order> listAll() throws DBException {
try(DBConnection db = DBConnection.open()) {
OrderDAO orderDAO = db.orderDAO();
return orderDAO.readAll();
}
}
@GET
@Path("/{id:[0-9]+}")
public Response findById(@PathParam("id") final Integer id) {
// Klasa Response pozwala nam z pełną precyzją przygotować odpowiedź, która ma zostać odesłana klientowi.
// W przypadku pozytywnym (ok) zostanie odesłany obiekt przetłumaczony na XML lub JSON, a kod wynikowy to będzie 200.
// Ale w przypadku błędów możemy sami zdecydować co odsyłami (tutaj odpowiednie kody HTTP).
try(DBConnection db = DBConnection.open()) {
OrderDAO orderDAO = db.orderDAO();
Order order = orderDAO.findById(id);
return Response.ok(order).build();
} catch (DBException e) {
e.printStackTrace();
return Response.status(Status.INTERNAL_SERVER_ERROR).build();
} catch (RecordNotFound e) {
return Response.status(Status.NOT_FOUND).build();
}
}
/*
// Metoda, która ma obsłużyć pobranie info o właścicielu zamówienia:
// /orders/1/customer
// W tej wersji metoda zwraca bezpośrednio dane klienta.
// Wada tego podejścia: ten sam rekord (konkretny klient) jest widoczny pod różnymi adresami URL.
@GET
@Path("/{id:[0-9][0-9]*}/customer")
public Customer getCustomer(@PathParam("id") Integer orderId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
OrderDAO orderDAO = db.orderDAO();
CustomerDAO customerDAO = db.customerDAO();
Order order = orderDAO.findById(orderId);
Customer customer = customerDAO.findByEmail(order.getCustomerEmail());
return customer;
}
}
*/
// W tej wersji w odpowiedzi na zapytanie o dane klienta, który złożył zamówienie,
// wyślemy przekierowanie pod adres tego klienta.
// To jest lepsze z punktu widzenia "dobrych praktyk REST".
@GET
@Path("/{id:[0-9]+}/customer")
public Response getCustomer(@PathParam("id") Integer orderId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
OrderDAO orderDAO = db.orderDAO();
Order order = orderDAO.findById(orderId);
URI customerURI = UriBuilder
.fromResource(RCustomers.class)
.path("/{email}")
.build(order.getCustomerEmail());
return Response.seeOther(customerURI).build();
}
}
}
package rest;
import java.math.BigDecimal;
import java.net.URI;
import java.util.List;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.UriBuilder;
import sklep.db.DBConnection;
import sklep.db.DBException;
import sklep.db.ProductDAO;
import sklep.db.RecordNotFound;
import sklep.model.Product;
import sklep.model.ProductList;
@Path("/products")
public class RProducts {
@GET
@Produces({"application/xml", "text/plain"})
public ProductList readAll() throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return new ProductList(productDAO.readAll());
}
}
// Żeby w JSON nie było dodatkowego poziomu w strukturze, zwracam bezpośrednio listę rekordów:
@GET
@Produces({"application/json"})
public List<Product> readAllJSON() throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return productDAO.readAll();
}
}
// Może też być tak, że kilka metod działa pod tym samym adresem, ale służą one do tworzenia odpowiedzi w różnych formatach.
// Przykład: tworzenie HTML w oddzielnej metodzie
@GET
@Produces("text/html;charset=UTF-8")
public String readAllHTML() throws DBException {
List<Product> products = readAll().getProducts();
StringBuilder txt = new StringBuilder("<!DOCTYPE html>\n<html><body>\n");
txt.append("<h1>Lista produktów</h1>\n");
for(Product product : products) {
txt.append(product.toHtml()).append('\n');
}
txt.append("</body></html>");
return txt.toString();
}
@GET
@Path("/{id}")
@Produces({"application/json", "application/xml", "text/plain"})
public Product readOne(@PathParam("id") int productId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return productDAO.findById(productId);
}
}
@GET
@Produces("text/html;charset=UTF-8")
@Path("/{id}")
public String readOneHTML(@PathParam("id") int productId) throws DBException, RecordNotFound {
Product product = readOne(productId);
return "<!DOCTYPE html>\n<html><body>" + product.toHtml() + "</body></html>";
}
@POST
@Consumes({"application/json", "application/xml"})
// W metodach typu POST i PUT powinien znajdować się dokładnie jeden parametr nieozanczony żadną adnotacją.
// Do tego parametru zostanie przekazana wartość utworzona na podstawie treści zapytania (content / body / entity).
// W adnotacji @Consumes określamy format, w jakim te dane mają być przysłane.
public Response saveProduct(Product product) throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
productDAO.save(product);
db.commit();
// Zwracamy informację, pod jakim adresem został zapisany rekord.
URI uri = UriBuilder
.fromResource(RProducts.class)
.path(String.valueOf(product.getProductId()))
.build();
return Response.created(uri).build();
}
}
// Ta metoda zwraca wartość wybranego pola w rekordzie.
// W praktyce rzadko kiedy twozy się takie metody, ale gdybyśmy wiedzieli, że klient akurat takiej rzeczy może potrzebować,
// to można taką dodatkową meotdę stworzyć.
// Właściwą strukturą adresu będzie wtedy np. products/3/price
@GET
@Path("/{id}/price")
@Produces({"application/json", "text/plain"})
public BigDecimal getPrice(@PathParam("id") int productId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return productDAO.findById(productId).getPrice();
}
}
// Metoda PUT służy w HTTP do zapisywania danych DOKŁADNIE POD PODANYM ADRESEM
@PUT
@Path("/{id}/price")
@Consumes({"application/json", "text/plain"})
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.update(product);
db.commit();
}
}
@DELETE
@Path("/{id}")
public void delete(@PathParam("id") int productId) throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
productDAO.delete(productId);
db.commit();
}
}
@GET
@Path("/{id}/photo")
@Produces("image/jpeg")
public byte[] getPhoto(@PathParam("id") int productId) throws DBException, RecordNotFound {
return PhotoUtil.readBytes(productId);
}
}
package rest;
import java.math.BigDecimal;
import java.util.List;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import sklep.db.DBConnection;
import sklep.db.DBException;
import sklep.db.ProductDAO;
import sklep.db.RecordNotFound;
import sklep.model.Product;
@Path("/products.json")
@Produces("application/json")
@Consumes("application/json")
// Adnotacje @Produces / @Consumes na poziomie klasy mówią co domyślnie produkują i konsumują metody.
// - metoda może nadpisać te ustawienia (np. metody dot. zdjęć)
// - adnotacje dotyczą tylko tych metod, które faktycznie coś pobierają lub zwracają
// Np. metoda, która niczego nie konsumuje, nie zwróci uwagi na te adnotacje z poziomu klasy.
// Metoda typu void nie zwraca uwagi na adnotację Produces
public class RProductsJSON {
@GET
public List<Product> readAll() throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return productDAO.readAll();
}
}
@GET
@Path("/{id}")
public Product readOne(@PathParam("id") int productId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return productDAO.findById(productId);
}
}
@POST
// W metodach typu POST i PUT powinien znajdować się dokładnie jeden parametr nieozanczony żadną adnotacją.
// Do tego parametru zostanie przekazana wartość utworzona na podstawie treści zapytania (content / body / entity).
// W adnotacji @Consumes określamy format, w jakim te dane mają być przysłane.
public InformacjaZwrotna saveProduct(Product product) throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
productDAO.save(product);
db.commit();
return new InformacjaZwrotna(product.getProductId());
}
}
// klasa definiująca, co jest zwracane w wyniku POST po zapisaniu produktu
public static class InformacjaZwrotna {
private int noweId;
public InformacjaZwrotna() {
}
public InformacjaZwrotna(int noweId) {
this.noweId = noweId;
}
public int getNoweId() {
return noweId;
}
public void setNoweId(int noweId) {
this.noweId = noweId;
}
}
// Ta metoda zwraca wartość wybranego pola w rekordzie.
// W praktyce rzadko kiedy twozy się takie metody, ale gdybyśmy wiedzieli, że klient akurat takiej rzeczy może potrzebować,
// to można taką dodatkową meotdę stworzyć.
// Właściwą strukturą adresu będzie wtedy np. products/3/price
@GET
@Path("/{id}/price")
public BigDecimal getPrice(@PathParam("id") int productId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return productDAO.findById(productId).getPrice();
}
}
// Metoda PUT służy w HTTP do zapisywania danych DOKŁADNIE POD PODANYM ADRESEM
@PUT
@Path("/{id}/price")
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.update(product);
db.commit();
}
}
@DELETE
@Path("/{id}")
public void delete(@PathParam("id") int productId) throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
productDAO.delete(productId);
db.commit();
}
}
@GET
@Path("/{id}/photo")
@Produces("image/jpeg")
public byte[] getPhoto(@PathParam("id") int productId) throws DBException, RecordNotFound {
return PhotoUtil.readBytes(productId);
}
}
package rest;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.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.model.ProductList;
@Path("/products.pdf")
@Produces("application/pdf")
public class RProductsPDF {
@GET
public ProductList readAll() throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return new ProductList(productDAO.readAll());
}
}
@GET
@Path("/{id}")
public Product readOne(@PathParam("id") int productId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return productDAO.findById(productId);
}
}
}
package rest;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import sklep.db.DBConnection;
import sklep.db.DBException;
import sklep.db.ProductDAO;
import sklep.db.RecordNotFound;
import sklep.model.Price;
import sklep.model.Product;
import sklep.model.ProductList;
@Path("/products.xml")
@Produces("application/xml")
@Consumes("application/xml")
public class RProductsXML {
@GET
public ProductList readAll() throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return new ProductList(productDAO.readAll());
}
}
@GET
@Path("/{id}")
public Product readOne(@PathParam("id") int productId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return productDAO.findById(productId);
}
}
@POST
public void saveProduct(Product product) throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
productDAO.save(product);
db.commit();
}
}
@GET
@Path("/{id}/price")
public Price getPrice(@PathParam("id") int productId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return new Price(productDAO.findById(productId).getPrice());
}
}
@PUT
@Path("/{id}/price")
public void setPrice(@PathParam("id") int productId, Price newPrice) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
Product product = productDAO.findById(productId);
product.setPrice(newPrice.getValue());
productDAO.update(product);
db.commit();
}
}
@DELETE
@Path("/{id}")
public void delete(@PathParam("id") int productId) throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
productDAO.delete(productId);
db.commit();
}
}
@GET
@Path("/{id}/photo")
@Produces("image/jpeg")
public byte[] getPhoto(@PathParam("id") int productId) throws DBException, RecordNotFound {
return PhotoUtil.readBytes(productId);
}
}
package rest;
import java.time.LocalDateTime;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
@Path("/dt")
public class RTime {
// Obiekt tej klasy jest tworzony za każdym razem do obsługi każdego pojedynczego zapytania.
private LocalDateTime dt = LocalDateTime.now();
{ System.out.println("Jest tworzony obiekt RTime , dt = " + dt); }
// działa pod adresem: /dt
@GET
public String getDateTime() {
return dt.toString();
}
// działa pod adresem: /dt/date
@GET
@Path("/date")
public String getDate() {
return dt.toLocalDate().toString();
}
@GET
@Path("/time")
public String getTime() {
return dt.toLocalTime().toString();
}
@GET
@Path("/time/second")
public int getSecond() {
return dt.getSecond();
}
}
package rest.ext;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.ext.MessageBodyWriter;
import jakarta.ws.rs.ext.Provider;
import sklep.model.Product;
@Provider
public class Product2HtmlWriter implements MessageBodyWriter<Product> {
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
System.out.println("Sprawdzam isWriteable " + type + " " + mediaType);
// Na podstawie informacji odczytanych z kodu zw. z metodą zwracającą wynik
// mamy odpowiedzieć na pytanie "czy ten writer sobie z tym poradzi".
return type == Product.class && mediaType.isCompatible(MediaType.TEXT_HTML_TYPE);
}
@Override
public void writeTo(Product product, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders, OutputStream out)
throws IOException, WebApplicationException {
System.out.println("Wykonuję writeTo " + type + " " + mediaType + " dla obiektu " + product);
// Dla konkretnego obiektu mamy go wypisać w podanym formacie przez przekazany nam OutputStream.
String html = "<!DOCTYPE html>\n<html><body>" + product.toHtml() + "</body></html>";
httpHeaders.add("Content-Type", "text/html;charset=utf-8");
out.write(html.getBytes("utf-8"));
}
}
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