Commit 447cbe44 by Patryk Czarnik

Przykłady klienta REST z wykorzystamiem klas modelu

parent 3658628b
package rest_klient;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.Invocation;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.Response;
// Ten i kolejne przykłady pokazują jak aplikacja kliencka napisana w Javie może wysyłać
// zapytania do usługi REST-owej (głównie GET, jest też gdzieś POST)
// korzystając z technologii JAX-RS "po stronie klienta".
// Aby z tego skorzystać, do projektu trzeba dodać bibliotekę z implementacją JAX-RS.
// Tutaj jest to resteasy-client.
public class Klient11_RestClient {
public static void main(String[] args) {
System.out.println("Startujemy");
Client client = ClientBuilder.newClient();
System.out.println("Przygotowuję zapytanie");
WebTarget target = client.target(Ustawienia.ADRES_USLUGI).path("products.json");
Invocation invocation = target.request().buildGet();
System.out.println("Wysyłam zapytanie");
Response response = invocation.invoke();
// Wynikiem jest obiekt klasy Response - tej samej, co na serwerze (używaliśmy np. do generowania kodów 404).
// W obiekcie można sprawdzić informacji o odpowiedzi: media type, status code.
System.out.println("Mam odpowiedź: " + response);
System.out.println("Status: " + response.getStatus());
System.out.println("C-Type: " + response.getMediaType());
System.out.println("Length: " + response.getLength());
// Aby odczytać zawartość zwróconą przez serwer, używamy metody readEntity.
// (przy domyślnych ustawieniach) tę metodę można wywołać tylko raz.
// Dopiero w tym momencie podajemy typ, na który zostanie skonwertowana treść odpowiedzi
// (w miarę możliwości - po prostu niektóre typy zadziałają, a niektóre nie).
byte[] dane = response.readEntity(byte[].class);
System.out.println("Dane mają " + dane.length + " bajtów.");
client.close();
try {
Files.write(Paths.get("wynik11.json"), dane);
System.out.println("Zapisałem w pliku");
} catch (IOException e) {
System.err.println(e);
}
System.out.println("Koniec");
}
}
package rest_klient;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.core.Response;
public class Klient12_RestClient_String {
public static void main(String[] args) {
try(Client client = ClientBuilder.newClient()) {
// Taki styl programowania to "fluent API". Przy okazji - zarówno Client, jak i Response są "zamykalne.
try(Response response = client.target(Ustawienia.ADRES_USLUGI)
.path("products.json")
.request()
.buildGet()
.invoke()) {
System.out.println("Mam odpowiedź: " + response);
System.out.println("Status: " + response.getStatus());
System.out.println("C-Type: " + response.getMediaType());
System.out.println("Length: " + response.getLength());
// readEntity(OKREŚLENIE TYPU) stara się odczytać tresc odpowiedzi jako obiekt podanego typu
// Obsługiwane typy to m.in: byte[], String, InputStream, File
// Dodając odpowiednie "MeassgeBodyReader", możemy obsługiwać dowolne typy.
// W szczególności, gdy dodamy do projektu obsługę XML lub JSON (zob. zależności Mavena),
// będziemy mogli odczytywać dane w postaci obiektów naszego modelu, np. Product.
String dane = response.readEntity(String.class);
System.out.println("Otrzymane dane:");
System.out.println(dane);
}
}
}
}
package rest_klient;
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 javax.swing.JOptionPane;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.core.Response;
public class Klient13_RestClient_Multiformat {
public static void main(String[] args) {
try(Client client = ClientBuilder.newClient()) {
String[] formaty = {"txt", "json", "xml", "html", "pdf"};
String format = (String) JOptionPane.showInputDialog(null, "Wybierz format danych", "Wybór",
JOptionPane.QUESTION_MESSAGE, null, formaty, "txt");
if(format == null) {
return;
}
String mediaType = switch(format) {
case "txt" -> "text/plain";
case "json" -> "application/json";
case "xml" -> "application/xml";
case "html" -> "text/html";
case "pdf" -> "application/pdf";
default -> throw new IllegalArgumentException();
};
// Klient może wybrać format (mediaType), w jakim oczekuje odpowiedzi - to wpływa na nagłówek Accept
try(Response response = client.target(Ustawienia.ADRES_USLUGI)
.path("products")
.request(mediaType)
.buildGet()
.invoke()) {
JOptionPane.showMessageDialog(null, String.format("""
Status: %d
C-Type: %s
Length: %d""", response.getStatus(), response.getMediaType(), response.getLength()));
Path plik = Paths.get("wynik13." + format);
InputStream stream = response.readEntity(InputStream.class);
Files.copy(stream, plik, StandardCopyOption.REPLACE_EXISTING);
JOptionPane.showMessageDialog(null, "Zapisano plik " + plik);
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
package rest_klient;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
public class Klient14_RestClient_PDF {
private static final MediaType PDF_TYPE = new MediaType("application", "pdf");
public static void main(String[] args) {
int productId = 1;
System.out.println("Startujemy...");
try(Client client = ClientBuilder.newClient()) {
WebTarget root = client.target(Ustawienia.ADRES_USLUGI);
try(Response response = root
.path("products")
.path("{id}")
.resolveTemplate("id", productId)
.request()
.accept(PDF_TYPE)
.buildGet()
.invoke()) {
System.out.println("Otrzymałem response: " + response);
System.out.println("Status: " + response.getStatus());
System.out.println("Content-Type: " + response.getMediaType());
if (response.getStatus() != 200) {
System.out.println("Chyba coś nie tak, więc przerywam.");
return;
}
String nazwaPliku = "wynik.pdf";
String contentDisposition = response.getHeaderString("Content-Disposition");
if (contentDisposition != null && contentDisposition.contains(";filename=")) {
nazwaPliku = contentDisposition.split(";filename=")[1];
}
try (InputStream strumienDanych = response.readEntity(InputStream.class)) {
long ileBajtow = Files.copy(strumienDanych, Paths.get(nazwaPliku), StandardCopyOption.REPLACE_EXISTING);
System.out.printf("Zapisano %d bajtów do pliku %s\n", ileBajtow, nazwaPliku);
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("Gotowe");
}
}
package rest_klient;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.core.Response;
import sklep.model.Product;
import sklep.model.ProductList;
public class Klient21_RestClient_JAXB {
public static void main(String[] args) {
try (Client client = ClientBuilder.newClient();
Response response = client.target(Ustawienia.ADRES_USLUGI)
.path("products.xml")
.request()
.buildGet()
.invoke()) {
System.out.println("Mam odpowiedź: " + response);
System.out.println("Status: " + response.getStatus());
System.out.println("C-Type: " + response.getMediaType());
System.out.println("Length: " + response.getLength());
ProductList products = response.readEntity(ProductList.class);
System.out.println("Otrzymane dane:");
for (Product product : products.getProducts()) {
System.out.println(product);
}
}
}
}
package rest_klient;
import java.util.List;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.core.GenericType;
import jakarta.ws.rs.core.Response;
import sklep.model.Product;
public class Klient22_RestClient_JSON {
public static void main(String[] args) {
try(Client client = ClientBuilder.newClient();
Response response = client.target(Ustawienia.ADRES_USLUGI)
.path("products.json")
.request()
.buildGet()
.invoke()) {
System.out.println("Mam odpowiedź: " + response);
System.out.println("Status: " + response.getStatus());
System.out.println("C-Type: " + response.getMediaType());
System.out.println("Length: " + response.getLength());
// Ponieważ wersja JSON na serwerze zwraca wynik typu List<Product>, to tutaj musimy podać "typ generyczny",
// a nie wystarczy zwykła klasa.
// Nie zadziała:
// List<Product> products = response.readEntity(List.class);
GenericType<List<Product>> typListy = new GenericType<>() {
};
List<Product> products = response.readEntity(typListy);
// albo jednolinijkowo:
// List<Product> products = response.readEntity(new GenericType<List<Product>>() {});
for (Product product : products) {
System.out.println(product);
}
}
}
}
package rest_klient;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import sklep.model.Product;
import java.util.Scanner;
public class Klient23_RestClient_JSON_JedenProdukt {
public static void main(String[] args) {
try(Client client = ClientBuilder.newClient();
Scanner scanner = new Scanner(System.in)) {
final WebTarget path = client.target(Ustawienia.ADRES_USLUGI)
.path("products")
.path("{id}");
while (true) {
System.out.print("Podaj id produktu (-1 kończy): ");
int id = Integer.parseInt(scanner.nextLine());
if (id == -1) {
break;
}
try (Response response = path
.resolveTemplate("id", id)
.request()
.accept(MediaType.APPLICATION_JSON)
.buildGet()
.invoke()) {
System.out.println("Mam odpowiedź: " + response);
System.out.println("Status: " + response.getStatus());
System.out.println("C-Type: " + response.getMediaType());
System.out.println("Length: " + response.getLength());
Product product = response.readEntity(Product.class);
System.out.println("Odczytany produkt: " + product);
}
}
}
}
}
package rest_klient;
import java.math.BigDecimal;
import java.util.Scanner;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import sklep.model.Product;
public class Klient24_Interaktywna_Edycja {
public static void main(String[] args) {
System.out.println("Startujemy...");
try (Scanner scanner = new Scanner(System.in);
Client client = ClientBuilder.newClient()) {
WebTarget path = client.target(Ustawienia.ADRES_USLUGI)
.path("products")
.path("{id}");
System.out.println("Przygotowana ścieżka: " + path);
while (true) {
System.out.print("\nPodaj id: ");
int id = scanner.nextInt();
if (id == 0) break;
try(Response response = path
.resolveTemplate("id", id)
.request(MediaType.APPLICATION_JSON)
.get()) {
System.out.println("Status: " + response.getStatus());
System.out.println("Content-Type: " + response.getMediaType());
if (response.getStatus() == 200) {
Product product = response.readEntity(Product.class);
System.out.println("Mam produkt:");
System.out.println(" Nazwa: " + product.getProductName());
System.out.println(" Cena: " + product.getPrice());
System.out.println(" Opis: " + product.getDescription());
System.out.println();
System.out.println("Podaj zmianę ceny (0 aby nie zmieniać):");
BigDecimal zmianaCeny = scanner.nextBigDecimal();
if (zmianaCeny.compareTo(BigDecimal.ZERO) != 0) {
BigDecimal newPrice = product.getPrice().add(zmianaCeny);
System.out.println("PUT nowej ceny...");
Response odpPut = path.path("price").resolveTemplate("id", id).request()
.put(Entity.entity(newPrice, MediaType.TEXT_PLAIN_TYPE));
System.out.println("PUT zakończył się kodem " + odpPut.getStatus());
}
} else {
System.out.println("nie mogę odczytać");
}
}
}
}
}
}
package sklep.model;
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
import java.time.LocalDateTime;
public class AdapterDaty extends XmlAdapter<String, LocalDateTime> {
@Override
public LocalDateTime unmarshal(String s) {
return LocalDateTime.parse(s);
}
@Override
public String marshal(LocalDateTime dt) {
return dt.toString();
}
}
package sklep.model;
import jakarta.xml.bind.annotation.XmlRootElement;
import java.util.Objects;
@XmlRootElement
public class Customer {
private String email;
private String name;
private String phoneNumber;
private String address;
private String postalCode;
private String city;
public Customer() {
}
public Customer(String email, String name, String phone, String address, String postalCode, String city) {
this.email = email;
this.name = name;
this.phoneNumber = phone;
this.address = address;
this.postalCode = postalCode;
this.city = city;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phone) {
this.phoneNumber = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "Customer [email=" + email + ", name=" + name + ", phone=" + phoneNumber + ", address=" + address
+ ", postalCode=" + postalCode + ", city=" + city + "]";
}
@Override
public int hashCode() {
return Objects.hash(email, name, address, city, phoneNumber, postalCode);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Customer other = (Customer) obj;
return Objects.equals(email, other.email) && Objects.equals(name, other.name)
&& Objects.equals(address, other.address) && Objects.equals(city, other.city)
&& Objects.equals(phoneNumber, other.phoneNumber) && Objects.equals(postalCode, other.postalCode);
}
}
package sklep.model;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlElementWrapper;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@XmlRootElement
public class Order {
@XmlAttribute(name="id")
private Integer orderId;
@XmlElement(name="customer-email")
private String customerEmail;
@XmlElement(name="order-date")
@XmlJavaTypeAdapter(AdapterDaty.class)
private LocalDateTime orderDate;
@XmlAttribute(name="status")
private Status orderStatus;
@XmlElementWrapper(name="products")
@XmlElement(name="product")
public final List<OrderProduct> products = new ArrayList<>();
public Order() {
}
public Order(Integer orderId, String customerEmail, LocalDateTime orderDate, Status orderStatus) {
this.orderId = orderId;
this.customerEmail = customerEmail;
this.orderDate = orderDate;
this.orderStatus = orderStatus;
}
public static Order ofDbFields(int orderId, String customerEmail, java.sql.Timestamp orderDate, String orderStatus) {
return new Order(orderId, customerEmail,
orderDate.toLocalDateTime(),
Status.valueOf(orderStatus.toUpperCase()));
}
public Integer getOrderId() {
return orderId;
}
public void setOrderId(Integer orderId) {
this.orderId = orderId;
}
public String getCustomerEmail() {
return customerEmail;
}
// public void setCustomerEmail(String customerEmail) {
// this.customerEmail = customerEmail;
// }
public LocalDateTime getOrderDate() {
return orderDate;
}
public void setOrderDate(LocalDateTime orderDate) {
this.orderDate = orderDate;
}
public Status getOrderStatus() {
return orderStatus;
}
public void setOrderStatus(Status orderStatus) {
this.orderStatus = orderStatus;
}
public List<OrderProduct> getProducts() {
return Collections.unmodifiableList(products);
}
public void addProduct(OrderProduct product) {
this.products.add(product);
}
public void addProducts(Collection<OrderProduct> products) {
this.products.addAll(products);
}
public void setProducts(Collection<OrderProduct> products) {
this.products.clear();
this.products.addAll(products);
}
@Override
public String toString() {
return "Order [orderId=" + orderId + ", customerEmail=" + customerEmail + ", orderDate=" + orderDate
+ ", orderStatus=" + orderStatus + "]";
}
@Override
public int hashCode() {
return Objects.hash(customerEmail, orderDate, orderId, orderStatus);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Order other = (Order) obj;
return Objects.equals(customerEmail, other.customerEmail) && Objects.equals(orderDate, other.orderDate)
&& Objects.equals(orderId, other.orderId) && orderStatus == other.orderStatus;
}
public enum Status {
NEW,
CONFIRMED,
PAID,
SHIPPED,
CLOSED,
RETURNED,
;
}
}
package sklep.model;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import java.math.BigDecimal;
import java.util.Objects;
public class OrderProduct {
@XmlAttribute(name="order-id")
private Integer orderId;
@XmlAttribute(name="product-id")
private Integer productId;
private int quantity;
@XmlElement(name="price")
private BigDecimal actualPrice;
public OrderProduct() {
}
public OrderProduct(Integer orderId, Integer productId, int quantity, BigDecimal actualPrice) {
this.orderId = orderId;
this.productId = productId;
this.quantity = quantity;
this.actualPrice = actualPrice;
}
public static OrderProduct of(Integer orderId, Product product, int quantity) {
return new OrderProduct(orderId, product.getProductId(), quantity, product.getPrice());
}
public Integer getOrderId() {
return orderId;
}
public void setOrderId(Integer orderId) {
this.orderId = orderId;
}
public Integer getProductId() {
return productId;
}
public void setProductId(Integer productId) {
this.productId = productId;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public BigDecimal getActualPrice() {
return actualPrice;
}
public void setActualPrice(BigDecimal actualPrice) {
this.actualPrice = actualPrice;
}
@Override
public String toString() {
return "OrderProduct [orderId=" + orderId + ", productId=" + productId + ", quantity=" + quantity
+ ", actualPrice=" + actualPrice+ "]";
}
@Override
public int hashCode() {
return Objects.hash(orderId, productId, quantity, actualPrice);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
OrderProduct other = (OrderProduct) obj;
return Objects.equals(orderId, other.orderId) && Objects.equals(productId, other.productId)
&& quantity == other.quantity
&& Objects.equals(actualPrice, other.actualPrice);
}
}
package sklep.model;
import java.math.BigDecimal;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlValue;
@XmlRootElement
public class Price {
@XmlValue
private BigDecimal value;
public Price() {
this.value = BigDecimal.ZERO;
}
public Price(BigDecimal value) {
this.value = value;
}
public BigDecimal getValue() {
return value;
}
public void setValue(BigDecimal value) {
this.value = value;
}
@Override
public String toString() {
return value.toString();
}
}
package sklep.model;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
import java.math.BigDecimal;
import java.util.Objects;
@XmlRootElement
public class Product {
@XmlAttribute(name="id")
private Integer productId;
@XmlElement(name="product-name")
private String productName;
private BigDecimal price;
private BigDecimal vat;
private String description;
public Product() {
}
public Product(Integer productId, String productName, BigDecimal price, BigDecimal vat, String description) {
this.productId = productId;
this.productName = productName;
this.price = price;
this.vat = vat;
this.description = description;
}
public Integer getProductId() {
return productId;
}
public void setProductId(Integer productId) {
this.productId = productId;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public BigDecimal getVat() {
return vat;
}
public void setVat(BigDecimal vat) {
this.vat = vat;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public int hashCode() {
return Objects.hash(description, price, vat, productId, productName);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Product other = (Product) obj;
return Objects.equals(productId, other.productId) && Objects.equals(productName, other.productName)
&& Objects.equals(price, other.price)
&& Objects.equals(vat, other.vat)
&& Objects.equals(description, other.description);
}
@Override
public String toString() {
return "Product [productId=" + productId + ", productName=" + productName + ", price=" + price + ", vat=" + vat
+ ", description=" + description + "]";
}
public String toHtml() {
return String.format("<div class='product'>"
+ "<h2>%s</h2>"
+ "<p>(nr %d)</p>"
+ "<p>Cena: <strong>%,.2f PLN</strong></p>"
+ "<p>%s</p>"
+ "</div>",
getProductName(),
getProductId(),
getPrice(),
getDescription());
}
}
package sklep.model;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="products")
public class ProductList {
@XmlElement(name="product")
private final List<Product> products = new ArrayList<>();
public ProductList() {
// zostawia pustą listę
}
public ProductList(Collection<Product> products) {
this.products.addAll(products);
}
public List<Product> getProducts() {
return Collections.unmodifiableList(this.products);
}
public void setProducts(Collection<Product> products) {
this.products.clear();
this.products.addAll(products);
}
@Override
public String toString() {
return this.products.toString();
}
}
@XmlAccessorType(XmlAccessType.FIELD)
package sklep.model;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
\ No newline at end of file
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