7,540
edits
Changes
→Service osztály definiálása
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>hu.otp.authadam.loginHelper.jaxrs.service</param-value>
</init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
hu.otp.authadam.loginHelper.jaxrs.mapper.AppExceptionMapper; hu.otp.authadam.loginHelper.jaxrs.mapper.ErrorMessage; hu.otp.authadam.loginHelper.jaxrs.mapper.WebServiceExceptionMapper
</param-value>
</init-param>
<source lang="java">
import javax.ws.rs.POST;
import javax.ws.rs.Path;
@Path("/login/")
@Consumes({ "application/json" })
@Produces({ "application/json" })
public class LoginService {
}
return contract;
}
</source>
A válaszban ez így fog megjelenni:
<pre>
response code: HTTP 404
response boy: {"correlationId":"111", "message":"service-error"}
</pre>
==Cookie kezelés==
https://www.logicbig.com/tutorials/java-ee-tutorial/jax-rs/cookie-param.html
=JAX-RS kliens=
https://dennis-xlc.gitbooks.io/restful-java-with-jax-rs-2-0-en/cn/part1/chapter8/building_and_invoking_requests.html
==Kliens bemutatása==
Maven dependecia:
<source lang="java">
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.28</version>
</dependency>
</source>
A JAX-RS kliens használata magáért beszél, elég intuitív. A ClientBuilder-el csinálunk egy globális kliens példányt, majd a klienssel készítünk sorban egy target-et, hozzáadunk path-t, request-et, metódust stb... A post(), put() metódusok két paramétert várnak, az első a request body objektum (ha van ilyen az interfészen), a második a válasz típusa. A get() csak egy paramétert vár, a válasz típusát. A JSON<->Java mappelést a JAX-RS automatikusan el fogja végezni.
===Request és Response megadása===
Nézzünk egy példát ahol a kliens meghívja a POST:login interfészt, a request body JSON stukturáját a LoginRequest objektum írja le, a választ pedig a LoginResponse.
<source lang="java">
public class LoginResponse {
private String user;
private String pass;
//getters and setters ...
}
public class LoginResponse {
private String userId;
private String token;
//getters and setters ...
}
</source>
Ekkor a request így fog kinézni:
<pre>
$ curl -XPOST 'localhost:8080/rest/login?' -H 'Content-Type: application/json' -d'
{ "user":"adam", "pass":"1234" }
</pre>
<source lang="java">
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
private static Client client = ClientBuilder.newClient();
LoginRequst loginRequest = new LoginRequest();
LoginResponse loginResponse = client.target(baseUrl).path("login").
request(MediaType.APPLICATION_JSON).post(Entity.json(loginRequest), LoginResponse.class);
</source>
A válaszban az alábbi JSON fog visszaérkezni:
<pre>
{ "userId":"11111", "token":"XXXXXX"}
</pre>
Amit a JAX-RS mappelni fog egy LoginResponse objektumba.
===Templét használata a request-ben===
A request URL-ben használhatunk PATH és request paramétereket is, amikhez a JAX-RS kliens behelyettesítő metódusokat biztosít. A PAHT paramétereket a resolveTemplate() metódussal, míg a QUERY paramétereket a queryParam() metódussal helyettesíthetjük be:
<source lang="java">
WebTarget target = client.target("http://commerce.com/customers/{id}")
.resolveTemplate("id", "123")
.queryParam("verbose", true);
</source>
===Listák kezelése a válaszban===
Ha az interfész válaszában egy POJO listát kapunk vissza, akkor a válasz típusának a megadását az alábbiak szerint kell megadni: ű
<source lang="java">
Client client = ClientBuilder.newClient();
List<Book> books = client.target(url)
.request(MediaType.APPLICATION_JSON).get(new GenericType<List<Book>>(){});
</source>
==Hibakezelés==
A hibák kezelésére három megközelítést fogunk alkalmazni, amik egybevágnak a server implementációnál tárgyalt megközelítésekkel.
# Exception kezelés: A get(), put(), post().. metódusoknál továbbra is megadjuk a válasz objektum típusát. 200 -as válasz esetében a JAX-RS automatikusan mappelni fogja a választ a megadott objektumba, így ha nem volt hiba, egy Java objektumban megkapjuk a választ. Ha bármilyen hiba dobódik az interfész hívása közben, akkor a JAX-RS kivétel típusából tudhatjuk, hogy milyen hiba történt. A kivételből ki tudjuk szedni a válasz body-ban esetlegesen küldött objektumot.
# A get(), post().. HTTP metódusokban nem mondjuk meg a válasz típusát. Ekkor a kliens a HTTP státusztól függetlenül egy '''javax.ws.rs.core.Response''' objektummal fog visszatérni ha volt hiba hanem. Ekkor a Response-ból nekünk kell kiszedni a válasz objektumot a '''readEntity(Class<T> entityType)''' metódussal és a HTTP státuszt a '''getStatus()''' metódussal.
# A harmadik megközelítés egy változata a másodiknak. Ahelyett, hogy a readEntity() hívással a JAX-RS -e bíznánk a parszolást, a JSON/XML String reprezentációját kérjük el a válaszból, és azt manuálisan parszoljuk.
===Exception kezelés===
https://dennis-xlc.gitbooks.io/restful-java-with-jax-rs-2-0-en/cn/part1/chapter7/exception_handling.html<br>
Talán ez a legtisztább megközelítés, megadjuk a HTTP metódusban a válasz objektum típusát, amit sikeres futás esetén (HTTP 200) meg fogunk kapni a megadott JAVA objektumban out-of-the-box.
<source lang="java">
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.Response;
private static Client client = ClientBuilder.newClient();
LoginRequst loginRequest = new LoginRequest();
try {
LoginRequst loginRequest = client.target(baseUrl).path("login").
request(MediaType.APPLICATION_JSON).post(Entity.json(loginRequest), LoginRequst.class);
// 400-as hibák
} catch (ClientErrorException e) {
ErrorMessageResponse errorMessageResponse = e.getResponse().readEntity(ErrorMessageResponse.class);
int status = e.getResponse().getStatus();
// 500-as hibák
} catch (ServerErrorException e) {
...
// 300-as redirekt hibák
} catch (RedirectionException e) {
...
}
</source>
{| class="wikitable"
! style="font-weight:bold; background-color:#c0c0c0;" | Base Exception
! style="font-weight:bold; background-color:#c0c0c0;" | Status code range
! style="font-weight:bold; background-color:#c0c0c0;" | Description
|-
| ClientErrorException
| 4XX
| Client side error
|-
| ServerErrorException
| 5XX
| Server side error
|-
| RedirectionException
| 3XX
| Redirect
|}
{| class="wikitable"
! style="font-weight:bold; background-color:#c0c0c0;" | Exception
! style="font-weight:bold; background-color:#c0c0c0;" | Status code
! style="font-weight:bold; background-color:#c0c0c0;" | Description
|-
| BadRequestException
| 400
| Malformed message
|-
| NotAuthorizedException
| 401
| Authentication failure
|-
| ForbiddenException
| 403
| Not permitted to access
|-
| NotFoundException
| 404
| Couldn’t find resource
|-
| NotAllowedException
| 405
| HTTP method not supported
|-
| NotAcceptableException
| 406
| Client media type requested not supported
|-
| NotSupportedException
| 415
| Client posted media type not supported
|-
| InternalServerErrorException
| 500
| General server error
|-
| ServiceUnavailableException
| 503
| Server is temporarily unavailable or busy
|}
===Response objektum használata===
<source lang="java">
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.Response;
private static Client client = ClientBuilder.newClient();
LoginRequst loginRequest = new LoginRequest();
Response response = client.target(baseUrl).path("login").
request(MediaType.APPLICATION_JSON).post(Entity.json(loginRequest));
int status = e.getResponse().getStatus();
if (status < 300) {
LoginResponse loginResponse = response.readEntity(LoginResponse.class);
} else {
ErrorMessageResponse errorMessageResponse = response.readEntity(ErrorMessageResponse.class);
}
</source>
===Response as String===
<source lang="java">
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.8</version>
</dependency>
</source>
<source lang="java">
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.Response;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
private static Client client = ClientBuilder.newClient();
private static ObjectMapper objectMapper = new ObjectMapper();
LoginRequst loginRequest = new LoginRequest();
Response response = client.target(baseUrl).path("login").
request(MediaType.APPLICATION_JSON).post(Entity.json(loginRequest));
String responseString = response.readEntity(String.class);
int status = e.getResponse().getStatus();
LoginResponse loginResponse = objectMapper.readValue(responseString,LoginResponse.class);
</source>