0% found this document useful (0 votes)
5 views25 pages

Usługi Restful

Uploaded by

valyrix
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views25 pages

Usługi Restful

Uploaded by

valyrix
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 25

Usługi RESTful

Technologia tworzenia rozproszonych, lekkich komponentów usługowych, które komunikują się


poprzez HTTP z wykorzystaniem konwencji typowych dla aplikacji www. W architekturze REST
(Representational State Transfer) centralna rolę stanowi transfer różnych reprezentacji (formatów)
zasobów z użyciem żądań i odpowiedzi.

Główne cechy to:



identyfikacja zasobów poprzez adresy URI – analogicznie jak w zwykłych aplikacjach www,
żądania wysyłane są pod określony adres, który określa udostępnianą przez usługę operację

jednolity interfejs dostępu (HTTP) – operacje wykonywane są poprzez wysłanie odpowiedniego
typu żądania HTTP na adres zasobu (URI):

GET – pozyskanie zasobu (np.: pobranie danych książki)

POST – dodanie nowego zasobu (np.: dodanie nowej książki)

PUT – aktualizacja stanu zasobu (np.: modyfikacja danych książki)

DELETE – usunięcie zasobu (np.: usunięcie książki)

oddzielenie zasobu od jego reprezentacji – dany zasób może mieć wiele reprezentacji (formatów),
w których jest udostępniany, np.: zwykły tekst, HTML, XML, JSON, PDF, JPEG, ...

bezstanowość – każde żądanie od klienta zawiera pełną informację, która jest potrzebna do
wykonania zadania i zwrócenia odpowiedzi. Klient powinien przechowywać informację o
ewentualnym stanie sesji (np: poprzez odpowiedni identyfikator). Serwer obsługę stanu może
przekazać do innej usługi (np: bazy, która przechowuje stan i dane do uwierzytelniania)
Usługi RESTful

Wsparcie dla REST na platformach Java SE/Java EE/jakarta EE,


podstawowe pakiety to:

jakarta.ws.rs – interfejsy wysokiego poziomu i adnotacje używane do tworzenia usług RESTful

jakarta.ws.rs.client – JAX-RS API dla klienta usług RESTful

jakarta.ws.rs.container – JAX-RS API specyficzne dla kontenera

jakarta.ws.rs.core – interfejsy i adnotacje niskiego poziomu używane do tworzenia zasobów
RESTful

jakarta.ws.rs.ext – API rozszerzające typy obsługiwane przez JAX-RS API

Referencyjna implementacja to Jersey, inne przykłady implementacji to:CXF (Apache), RESTEasy


(JBoss), i Restlet
Usługi RESTful

Przykład prostej usługi, model danych



adnotacje JAXB określają jak klasy ma być odwzorowana na XML, odwzorowanie na JSON jest
wykonywane automatycznie z użyciem JSON-B
package webws1.model;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlRootElement;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Book {
@XmlAttribute
private Integer id;
@XmlAttribute
private String title;
@XmlAttribute
private Double price;

public Book() {
}
set/get...
}
Usługi RESTful

Przykład prostej usługi, implementacja


@Path("/book")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public class BookRestService {
@Inject
private BookDao bookDao;
@Context
private UriInfo uriInfo;
@GET @Path("{id}")
public Response getBook(@PathParam("id") String id) {
Book book = bookDao.find(Integer.parseInt(id));
return Response.ok(book).build();
}
@POST
public Response createBook(Book book) {
bookDao.save(book);
URI bookUri = uriInfo.getAbsolutePathBuilder().path(book.getId().toString()).build();
return Response.created(bookUri).build();
}
@PUT
public Response updateBook(Book book) {
bookDao.update(book);
return Response.ok().build();
}
@DELETE @Path("{id}")
public Response deleteBook(@PathParam("id") String id) {
bookDao.remove(book.getId());
return Response.noContent().build();
}
}
Usługi RESTful

Przykład prostej usługi, konfiguracja



URI protokół://serwer:port/aplikacja/sciezka_globalna/sciezka_zasobu/parametry_sciezki?parametr_url=…
np.: http://localhost:8080/restdemo/resources/book/1

import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;
@ApplicationPath("resources")
public class ApplicationConfig extends Application {
}
Usługi RESTful

Wymagania dla klasy usługi



musi mieć adnotację @javax.ws.rs.Path

powinna być publiczna, nie może być finalna ani abstrakcyjna

Klasa z adnotacja @Path powinna mieć publiczny bezparametrowy konstruktor

nie może definiwoać metody finalize()

usługa może być też klasą EJB (@Stateless lub @Singleton)

usługa powinna być obiektem bezstanowym, który nie przechowuje informacji specyficznych dla
klienta pomiędzy wywołaniami jej metod
Usługi RESTful

Przykład klienta

public class App {


public static void main(String[] args) {
URI uri = UriBuilder.fromUri("http://localhost:8080/appname/rest/book").port(8080).build();
Client client = ClientBuilder.newClient();
Book book = new Book(1,"title1",1.99);

// dodanie książki (POST)


Response response = client.target(uri).request().post(Entity.entity(book,
MediaType.APPLICATION_XML));
System.out.println("Status code 1:"+response.getStatusInfo().getStatusCode());
URI bookURI = response.getLocation();

// pobranie (GET)
response = client.target(bookURI).request().get();
book = response.readEntity(Book.class);
System.out.println("Status code 2:"+response.getStatusInfo().getStatusCode());
System.out.println(book);

// usunięce (DELETE
String bookId = bookURI.toString().split("/")[6];
response = client.target(uri).path(bookId).request().delete();
System.out.println("Status code 3:"+response.getStatusInfo().getStatusCode());
}
}
Usługi RESTful

Przykład klienta

zależności maven

….
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>ver</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-jaxb</artifactId>
<version>ver.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-processing</artifactId>
<version>ver1</version>
</dependency>
</dependencies>
...
Usługi RESTful

Obsługa wyjątków


metody klas implementujących usługę REST mogą wyrzucać wyjątki (unchecked i checked)

wyjątki mogą być obsłużone przez środowisko JAX-RS z użyciem klas odwzorowujących wyjątek
na odpowiedź HTTP, która będzie wysłana do klienta

klasa odpowiedzialna za odwzorowanie wyjątku powinna implementować interfejs
javax.ws.rs.ext.ExceptionMapper i mieć adnotację @jakarta.ws.rs.ext.Provider

Przykład

@Provider
public class ServiceExceptionMapper implements ExceptionMapper<UnsupportedOperationException> {
@Override
public Response toResponse(UnsupportedOperationException e) {
return Response.status(Response.Status.SERVICE_UNAVAILABLE).build();
}
}

@Path("book")
public class BookService {
@GET
public List<Book> findAll() {
throw new UnsupportedOperationException();

}
}
Usługi RESTful

Obsługa wyjątków

JAX-RS posiada też własną hierarchię wyjątków, które są automatycznie zamieniane na
odpowiednie odpowiedzi HTTP – nie wymagają tworzenia własnych klas odwzorowujących

bazową klasą dla wyjątków JAX-RS, które metody usług mogą wyrzucać jest
javax.ws.rs.WebApplicationException

dla standardowych typów błędów są też dostępne podklasy, np.: ,
BadRequestExceptionNotFoundException, NotAuthorizedException,
ServiceUnavailableException, ...

Przykład
@Path("book")
public class BookService {
@GET
public List<Book> findAll() {
// użycie bazowego typu wyjątku
throw new
WebApplicationException(Response.status(Response.Status.SERVICE_UNAVAILABLE).build());
// lub skorzystanie z podklasy
throw new ServiceUnavailableException();

}
}
Usługi RESTful

Uwierzytelnianie klienta przez HTTP Basic/Digest z użyciem referencyjnej implementacji JAX_RS:


Jersey

Przykład
public class App {
public static void main(String[] args) {
URI uri = UriBuilder.fromUri("http://localhost:8080/appname/rest/book").port(8080).build();
// HTTP Basic
HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic("user", "secretPassword");
// lub HTTP Digest
HttpAuthenticationFeature feature = HttpAuthenticationFeature.digest("user", "secretPassword");
client.register(feature);
… client.target(uri).get() ….
}
}
Usługi RESTful

Uwierzytelnianie klienta per żądanie przez HTTP Basic/Digest z użyciem referencyjnej implementacji
JAX_RS: Jersey

Przykład
public class App {
public static void main(String[] args) {
URI uri = UriBuilder.fromUri("http://localhost:8080/appname/rest/book").port(8080).build();
// HTTP Basic
Response response = client.target("http://localhost:8080/rest/homer/contact").request()
.property(HTTP_AUTHENTICATION_BASIC_USERNAME, "user")
.property(HTTP_AUTHENTICATION_BASIC_PASSWORD, "secretPassword").get();

// lub HTTP Digest


Response response = client.target("http://localhost:8080/rest/homer/contact").request()
.property(HTTP_AUTHENTICATION_DIGEST_USERNAME, "user")
.property(HTTP_AUTHENTICATION_DIGEST_PASSWORD, "secretPassword").get();

}
}
Web Services (usługi webowe)

Technologia do tworzenia rozproszonych komponentów usługowych, które komunikują się z użyciem


otwartych protokołów, podstawowe składowe to:

SOAP (Simple Object Access Protocol) – protokół używany do wywołań, określa format
wiadomości

WDSL (Web Services Description Language) – język opisu interfejsu, definiuje protokół, interfejsy,
typy wiadomości przekazywane pomiędzy klientem i usługą

UDDI (Universal Description Discovery and Integration) – rejestr usług pozwalający na dodawanie
informacji o dostępnych usługach i ich wyszukiwanie

Opiera się na innych technologiach:



XML (Extensible Markup Language) – podstawowy format dla wiadomości SOAP i opisu interfejsu
WSDL

XML Schema – język definiowania dokumentów XML

HTTP (Hypertext Transfer Protocol) – protokół używany do transportu wiadomości, inne opcje to
np.: SMTP, FTP, JMS
Web Services (usługi webowe)

Wsparcie dla web services na platformach Java SE/Java EE/Jakarta EE jest oparte głównie na
następujących specyfikacjach:

JAX-WS – API umożliwiające tworzenie i komunikowanie się z usługami webowymi

Web Services – określa model programowania, format dystrybucji i zachowanie usług w
kontenerach EE

Web Services Metadata ( – udostępnia adnotacje ułatwiające definicję usług webowych

JAXB – ułatwia odwzorowanie pomiędzy obiektami a formatem XML

Powyższy zestaw specyfikacji jest nazywany Java Web Services (JWS)

Referencyjna implementacja to Metro, inne przykłady implementacji to:Apache CXF i Apache Axis2
Web Services (usługi webowe)

Przykład prostej usługi, model danych



adnotacje JAXB określają jak klasy ma być odwzorowana na XML

package webws1.model;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlRootElement;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Message implements Serializable {
@XmlAttribute
private Integer id;
@XmlAttribute
private String title;
@XmlAttribute
private String body;
public Message() {
}
… get.../set...
}
Web Services (usługi webowe)

Przykład prostej usługi, interfejs i implementacja



adnotacje JAXB określają jak klasy ma być odwzorowana na XML

package webws1.api;
import jakarta.jws.WebService;
import webws1.model.Message;
@WebService
public interface MessageProviderAPI {
Message getMessage(String name);
}

import jakarta.jws.WebService;
import webws1.api.MessageProviderAPI;
import webws1.model.Message;
@WebService(endpointInterface = "webws1.api.MessageProviderAPI")
public class MessageProvider implements MessageProviderAPI {
@Override
public Message getMessage(String name) {
return new Message(1, "Hello", "Hi "+name+", this is message from MessageProvider");
}
}
Web Services (usługi webowe)

Wymagania dla klasy usługi



musi mieć adnotację @WebService lub być skonfigurowana w deskryptorze webservices.xml

może implementować zero lub więcej interfejsów usługi (endpoint interfeces), które powinny mieć
również adnotację @WebService

powinna być publiczna, nie może być finalna ani abstrakcyjna

powinna posiadać publiczny bezparametrowy konstruktor

nie może definiwoać metody finalize()

klasy EJB, które maja być udostępniane jako usługa web, powinny mieć adnotację @Stateless lub
@Singleton

usługa powinna być obiektem bezstanowym, który nie przechowuje informacji specyficznych dla
klienta pomiędzy wywołaniami jej metod
Web Services (usługi webowe)

Przykład prostej usługi, instalacja



klasę modelu, interfejs i implementację należy dodać do modułu web, który może być budowany
do osobnej aplikacji w formacie war lub być częścią większej aplikacji Enterprise Application
(*.ear)

po wydaniu na serwerze aplikacyjnym, automatycznie tworzony jest deskryptor WSDL (dostępny
pod adresem ...nazwa_aplikacji/MessageProviderService?wsdl , który opisuje interfejs usługi,
model danych i sposób dostępu.

wygenerowany plik WSDL (http://localhost:8080/WebWS1/MessageProviderService?wsdl):
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:tns="http://api.webws1/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://api.webws1/">
<types>
<xsd:schema>
<xsd:import namespace="http://api.webws1/" schemaLocation="http://localhost:8080/WebWS1/MessageProviderService?xsd=1"/>
</xsd:schema>
</types>
<message name="getMessage">
<part name="parameters" element="tns:getMessage"/>
</message>
<message name="getMessageResponse">
<part name="parameters" element="tns:getMessageResponse"/>
</message>
<portType name="MessageProviderAPI">
<operation name="getMessage">
<input xmlns:ns1="http://www.w3.org/2007/05/addressing/metadata" ns1:Action="http://api.webws1/MessageProviderAPI/getMessageRequest"
message="tns:getMessage"/>
<output xmlns:ns2="http://www.w3.org/2007/05/addressing/metadata" ns2:Action="http://api.webws1/MessageProviderAPI/getMessageResponse"
message="tns:getMessageResponse"/>
</operation>
</portType>
</definitions>
Web Services (usługi webowe)

Przykład prostej usługi, instalacja



wygenerowany plik XSD (http://localhost:8080/WebWS1/MessageProviderService?xsd=1) z
definicją typów danych:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:tns="http://api.webws1/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://api.webws1/">
<xs:element name="getMessage" type="tns:getMessage"/>
<xs:element name="getMessageResponse" type="tns:getMessageResponse"/>
<xs:element name="message" type="tns:message"/>
<xs:complexType name="getMessage">
<xs:sequence>
<xs:element name="arg0" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="getMessageResponse">
<xs:sequence>
<xs:element name="return" type="tns:message" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="message">
<xs:sequence/>
<xs:attribute name="id" type="xs:int"/>
<xs:attribute name="title" type="xs:string"/>
<xs:attribute name="body" type="xs:string"/>
</xs:complexType>
</xs:schema>
Web Services (usługi webowe)

Przykład klienta

wywołanie metody usługi z klienta odbywa się zazwyczaj z użyciem obiektu proxy, który lokalnie
udostępnia interfejs usługi i wykonuje niezbędne operacje do wywołania usługi web (konwertuje
wywołanie i parametry do wiadomości SOAP, wysyła żądanie na serwer, odbiera i parsuje
odpowiedź, tworzy obiekty reprezentujące wynik i je zwraca)

proxy oraz klasy modelu danych można wygenerować na podstawie plików WSDL oraz XSD,
które opisują interfejs usługi i struktury danych z użyciem narzędzia wsimport - dostępne w JDK i
implementacji JWS; w przypadku projektu Maven wystarczy użyć odpowiedniego plugin’a, który
pobierze wymagane pliki WSDL/XSD i wygeneruje odpowiednie klasy
Web Services (usługi webowe)

Przykład klienta

konfiguracja Maven, która tworzy w fazie generate-sources tworzy odpowiednie klasy w projekcie
klienta:
….
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.4.1</version>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<wsdlUrls>
<wsdlUrl>
http://localhost:8080/WebWS1/MessageProviderService?wsdl
</wsdlUrl>
</wsdlUrls>
<!-- Needed with JAXP 1.5 -->
<vmArgs>
<vmArg>-Djavax.xml.accessExternalSchema=all</vmArg>
</vmArgs>
<keep>true</keep>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
Web Services (usługi webowe)

Przykład klienta, użycie



typy wygenerowane po stronie klienta to m.in.: Message, MessageProviderAPI,
MessageProviderService

public class App {


public static void main(String[] args) {
MessageProviderAPI ms = new MessageProviderService().getMessageProviderPort();
Message m = ms.getMessage("Joe");
System.out.println("Message id:"+m.getId()+", title:"+m.getTitle()+", body:"+m.getBody());
}
}
Web Services (usługi webowe)

Przykład uwierzytelnienia HTTP Basic



typy wygenerowane po stronie klienta to m.in.: Message, MessageProviderAPI,
MessageProviderService

import javax.xml.ws.BindingProvider;
public class App {
public static void main(String[] args) {
MessageProviderAPI ms = new MessageProviderService().getMessageProviderPort();

BindingProvider provider = (BindingProvider)ms;


provider.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "user");
provider.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "secredPassword");

Message m = ms.getMessage("Joe");
System.out.println("Message id:"+m.getId()+", title:"+m.getTitle()+", body:"+m.getBody());
}
}
Web Services (usługi webowe)

Przykład klienta w kontenerze, użycie



typy wygenerowane po stronie klienta to m.in.: Message, MessageProviderAPI,
MessageProviderService

public class InContainer {


@WebServiceRef
MessageProviderService service;
public static void main(String[] args) {
MessageProviderAPI ms = service.getMessageProviderPort();
Message m = ms.getMessage("Joe");
System.out.println("Message id:"+m.getId()+", title:"+m.getTitle()+", body:"+m.getBody());
}
}
Web Services (usługi webowe)

Obsługa wyjątków

Wyjątki wyrzucane przez metody komponentu WebService są komunikat błędu wysyłany do
klienta (SOAP fault message)

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>java.lang.NullPointerException</faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>

try {
...
}
} catch (ServerSOAPFaultException ex) {
System.out.println(ex.getMessage());
System.out.println( ex.getFault().getFaultCode());
System.out.println(ex.getFault().getFaultString());

You might also like