7,540
edits
Changes
→Hibakezelés
==Hibakezelés==
===Áttekintés===Ez egy sarkalatos pontja a REST interfész implementációnak, ugyanis a kliensnek minden esetben vissza kell adni egy szabványos REST választ, ahol hiba esetén lehetőleg megmondjuk, hogy mi történt, tehát minden hibát le kell valahogy kezelni. Ezen felül előfordulhat, hogy hiba esetén más objektum típussal szeretnénk visszatérni, mint a boldog ágon. A @GET/POST/PUT annotációkkal ellátott metódusoknál csak azt tudjuk definiálni, hogy mi legyen a válasz típusa happy ágon, mikor visszatérési objektum típus meghatározására két lehetőségünk van. * Ha rest metódusnak egy POJO a kérést rendeltetés szerűen ki tudta szolgálni a szervervisszatérési értéke (vagy egy abból képzett típus) akkor sikeres futás estében, tehát a HTTP státusz kódja metódus visszatérése után a válasznak a 200JAX-as tartományba RS ebből automatikusan REST választ fog esni. Ha van visszatérési értékgenerálni, akkor feltehetően ez 200 lesza POJO-t JSON/XML-re fogja konvertálni, ha nincsés be is állítja a HTTP státuszt, akkor 204, ezt automatikusan kezeli nekünk ezzel ebben az esetben semmi dolgunk. Viszont több okból is meg van kötve a JAX-RS. kezünk:
** Ha a metódus sikeresen elfut, akkor a JAX-RS ezt mindig sikeres futásnak fogja tekinteni, és a HTTP státuszt mindig 200-ra fogja állítani, nem tudunk beavatkozni a válasz elkészítésébe.
** Ha a service metódusnak nem egy POJO a visszatérési értéke, hanem a javax.ws.rs.core.Response, akkor teljes kontrolunk van a válasz összeállításában, viszont mindent mind sikeres, mind sikertelen ágon nekünk kell kézzel a válaszba belerakni a megfelelő response JAVA objektumot és beállítani a HTTP státuszt. <br>
https://dennis-xlc.gitbooks.io/restful-java-with-jax-rs-2-0-en/cn/part1/chapter7/complex_responses.html
Alább láthatunk egy példát a teljesen manuális response összeállítására. Ha
<source lang="java">
@GET
@Path("/contract2")
public Response getBook() {
Contract contract = new Contract();
ResponseBuilder builder = Response.ok(contract);
builder.language("en").header("Some-Header", "some value").cookie(new NewCookie("adamCooke", "value"));
return builder.build();
}
</source>
azt fogja JSON/XML struktúrára mappe-elni automatikusan a JAX-RS, és a HTTP . Ennek az az előnye, hogy a válasz automatikusan előáll a boldog ágon. Azonban hiba esetén nem tudunk más objektum típust használni. Megoldás lehet, hogy olyan univerzális választ definiálunk, amiben van egy ErrorMessageResponse paraméter is, amit csak hiba estén töltünk ki, és akkor nem különbözik a válasz típusa sikeres és sikertelen futtatás estén. Ha viszont különböznie kell, akkor két lehetőségünk van:
** Hiba esetén egy saját Exception-t dobunk, amit egy Exception provider-el feldolgozunk, és egyedi hiba objektumot készítünk belőle a válaszba.
** A service metódusunknak nem egy POJO a visszatérési értéke, hanem egy javax.ws.rs.core.Response, amibe mi állítjuk
ha java csak azt tudjuk definiálni, hogy mi legyen a válasz típusa happy ágon, mikor a kérést rendeltetés szerűen ki tudta szolgálni a szerver, tehát a HTTP státusz kódja a válasznak a 200-as tartományba fog esni. Ha van visszatérési érték, akkor feltehetően ez 200 lesz, ha nincs, akkor 204, ezt automatikusan kezeli a JAX-RS.
Egy java metódusból úgy lehet az előre definiált visszatérési értéken felül más típusú választ kijuttatni, ha PL egy megfelelő exception-t eldobunk, amit elkapunk és lekezelünk. Itt is ezt fogjuk tenni.
Ahhoz hogy a hibaágakat is kezelni tudjuk, létre kell hozzunk egyedi Exception osztályokat, és hozzájuk tartozó response mapper-eket(Provider), amik az Exception eldobása estén megkapják a vezérlést, és az Exception alapján össze tudják állítani a választ. Ehhez három osztályt kell létrehozzunk:
# ErrorResponse osztály, egy egységesített struktúra, amit minden nem 200-as válaszban vár a kliens. (pl hibakódok, szöveges leírás)
# Saját Exception implementáció (WebServiceException), amibe minden olyan infónak szerepelnie kell, ami alapján az ErrorResponse osztály elkészíthető.
# Exception mapper osztály, ami megkapja a vezérlést ha WebServiceException dobódott, és a benne található információk alapján példányosítja a ErrorResponse osztályt, majd beleteszi a REST válaszba, amit a JAX-RS JSON formátumra fog hozni.
===Jax-RS provider===
A JAX-RS-ben 3 típusa létezik a provider-ekenek, melyekkel három különféle feladatot láthatunk el:
====Entity provider====
https://docs.huihoo.com/jersey/2.13/message-body-workers.html<br>
The Entity provider API contains 2 interfaces. One for handling inbound entity representation-to-Java de-serialization - '''MessageBodyReader<T>''' and the other one for handling the outbound entity Java-to-representation serialization - '''MessageBodyWriter<T>'''. A MessageBodyReader<T>, as the name suggests, is an extension that supports reading the message body representation from an input stream and converting the data into an instance of a specific Java type. A MessageBodyWriter<T> is then responsible for converting a message payload from an instance of a specific Java type into a specific representation format that is sent over the wire to the other party as part of an HTTP message exchange. Both of these providers can be used to provide message payload serialization and de-serialization support on the server as well as the client side.
====Context provider====
https://www.logicbig.com/tutorials/java-ee-tutorial/jax-rs/context-resolver.html<br>
Context providers supply a context object to resource classes or to other providers.A context provider class must implement the ContextResolver<T>interface.
====Exception provider====These providers map a checked or runtime exception to an instance of Response. They implement ExceptionMapper<T>. Számunkra ez a lényeges. Itt fogjuk az exception-t <br><br>===Megvalósítás=== Elsőként definiáljuk azt az osztályt ami alapján a nem 200-as státusz esetén a válasz objektumot létre akarjuk hozni: . Létrehoztunk egy Facory metódust is a JSON<->JAVA konverzióra, amit '''@JsonCreator''' annotációval láttunk el (a metódusnak az 'of' nevet adtuk). A '''@JsonProperty'''-val megadtuk az egyez mezők JSON nevét és Jáva típusát.
<source lang="java">
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
public class ErrorMessageResponse implements Serializable {
private String correlationId;
private String errorCodemessage; @JsonCreator public static ErrorMessageResponse of (@JsonProperty("correlationId") String correlationId, @JsonProperty("messages") String message) { return new ErrorMessageResponse(correlationId, message); }
//Getters and setters and constructor...
}
</source>
A HTTP válaszba JSON alakban ez így fog kinézni:
<pre>
{"correlationId":"XXX", "errorCodemessage":"111"}
</pre>
Hozzunk létre egy egyedi Exception implementációt, amit minden kezelt hiba estén mi fogunk dobni a webservice metódusok belsejében. Ezt az exception-t fogja elkapni a mapper osztályunk, és alakítja majd át ErrorMessageResponse objektumra.
<source lang="java">
public class WebServiceException extends IllegalArgumentException {
//HTTP status
private int status;
private String correlationId;
private String responseMessage;
public WebServiceException(String correlationId, String responseMessage, String message, Throwable cause) {
super(message, cause);
...
}
//getters...
}
</source>
<source lang="java">