On this blog I am collecting information that might hopefully be useful to other java developers. My profile can be found on my website. Please feel free to comment and discuss any topic if you like.
Dieses Blog durchsuchen
Posts mit dem Label REST werden angezeigt. Alle Posts anzeigen
Posts mit dem Label REST werden angezeigt. Alle Posts anzeigen
Freitag, 6. Januar 2017
REST Service Exception Handling
Bei der Implementierung von REST-Services stellt sich der Entwickler früher oder später die Frage, wie eigentlich mit Exceptions umgegangen werden soll. Denn anders als bei der Implementierung von SOAP Services muss sich der Entwickler hier eine eigene Strategie überlegen, wie aufgetretene Fehler dem nutzenden System übermittelt werden sollen.
An dieser Stelle möchte ich eine Variante aus der Praxis vorstellen, die sich bewährt hat. Und zwar wird dazu die Klasse javax.ws.rs.ext.ExceptionMapper implementiert und mit der @Provider Annotation versehen. Eine weitergehende Konfiguration oder Aktivierung des Mappers ist nicht notwendig. Indem nun die Methode toResponse überschrieben wird, kann definiert werden, wie die Antwort des Servers im Falle einer Exception konkret aussehen soll.
Das Beispiel zeigt den Aufbau einer Nachricht bestehend aus einleitendem Text "An Error occured!", dem aktuellen Datum, dem Namen der Exception-Klasse und der Nachricht. Falls die Exception einen root cause hat, wird auch dieser noch mit ausgegeben.
Zusätzlich ist es sinnvoll, einen passenden HTTP-Status-Code mitzugeben, in diesem Fall Status Code 500 für "Internal Server Error", denn viele Clients fragen diesen Status-Code ab, um entsprechend reagieren zu können.
@Provider
public class RestThrowableExceptionMapper implements ExceptionMapper<Throwable> {
@Context
private HttpHeaders headers;
@Override
public Response toResponse(Throwable throwable) {
int status = Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(); //defaults to internal server error 500;
StringBuilder messageBuilder = new StringBuilder();
messageBuilder.append("An Error occured! ");
messageBuilder.append(new Date());
messageBuilder.append(": ");
messageBuilder.append("Cause -> ");
messageBuilder.append(throwable.getClass().getName());
messageBuilder.append(": ");
messageBuilder.append(throwable.getMessage());
// also append root cause of exception if present
Throwable rootCause = ExceptionUtils.getRootCause(throwable);
if (rootCause != null) {
messageBuilder.append("; Root Cause -> ");
messageBuilder.append(rootCause.getClass().getName());
messageBuilder.append(": ");
messageBuilder.append(rootCause.getMessage());
}
return Response.status(status).
entity(messageBuilder.toString()).
type(headers.getMediaType()).build();
}
}
Dienstag, 27. Dezember 2016
Eigener Authenticator für Basic Authentication in Kombination mit Proxy-Authentifizierung
Sofern ein REST-Client (oder auch SOAP-Client) sich zunächst über einen Proxy authentifizieren soll und anschließend eine Basic-Authentifizierung
durchführen muss, bietet es sich an, einen eigenen Authenticator zu schreiben.
Dieser Authenticator muss von der Klasse java.net.Authenticator ableiten und die Methode getPasswordAuthentication() überschreiben. Erwähnenswert ist nun, wie die implementierung dieser Methode konkret aussieht:
Zu sehen ist, wie mithilfe der geerbten Methode getRequestingHost()zunächst der Host ermittelt wird, der eine Authentifizierungsanfrage stellt. Sofern dies der Proxy ist, wird entsprechend der Nutzer und das Passwort des Proxys gesetzt. Handelt es sich jedoch um den Zielserver, werden die Credentials entsprechend für diesen verwendet.
Über die statische Methode Authenticator.setDefault(new MyAuthenticator()); wird der Authenticator schließlich JVM-weit gesetzt und beginnt mit der Arbeit, sobald die ersten Authentifizierungsanfragen eintreffen.
Dieser Authenticator muss von der Klasse java.net.Authenticator ableiten und die Methode getPasswordAuthentication() überschreiben. Erwähnenswert ist nun, wie die implementierung dieser Methode konkret aussieht:
@Override protected PasswordAuthentication getPasswordAuthentication() { String requestingHost = getRequestingHost(); if (proxyEnabled && requestingHost.equals(proxyHost)) { return new PasswordAuthentication(proxyUserName, proxyPassword); } else { return new PasswordAuthentication(serverUserName, serverPassword); }
}
Zu sehen ist, wie mithilfe der geerbten Methode getRequestingHost()zunächst der Host ermittelt wird, der eine Authentifizierungsanfrage stellt. Sofern dies der Proxy ist, wird entsprechend der Nutzer und das Passwort des Proxys gesetzt. Handelt es sich jedoch um den Zielserver, werden die Credentials entsprechend für diesen verwendet.
Über die statische Methode Authenticator.setDefault(new MyAuthenticator()); wird der Authenticator schließlich JVM-weit gesetzt und beginnt mit der Arbeit, sobald die ersten Authentifizierungsanfragen eintreffen.
Montag, 8. November 2010
REST Client in Java
In der ORDIX News habe ich vor längerer Zeit beschrieben, wie mit Hilfe der Referenz Implementierung Jersey ein REST Service bereitgestellt werden kann.
Nach wie vor gefällt mir der REST-Ansatz sehr gut, da er (im Gegensatz zu Web Services auf Basis von SOAP) schlank und verständlich ist. Mehr und mehr Anbieter, wie z. B. Alfresco, ein Open Source ECM-System, stellen einen Großteil ihrer Funktionalitäten über REST-Services bereit.
Glücklicherweise bietet die Referenzimplementierung Jersey neben der im o.g. Artikel beschriebenen Server API auch eine Client API an, um komfortabel auf REST Services zugreifen zu können. Wie zu erwarten, ist es nicht weiter kompliziert, einen Service zu konsumieren, ein schlanker Dreizeiler reicht aus:
Nach wie vor gefällt mir der REST-Ansatz sehr gut, da er (im Gegensatz zu Web Services auf Basis von SOAP) schlank und verständlich ist. Mehr und mehr Anbieter, wie z. B. Alfresco, ein Open Source ECM-System, stellen einen Großteil ihrer Funktionalitäten über REST-Services bereit.
Glücklicherweise bietet die Referenzimplementierung Jersey neben der im o.g. Artikel beschriebenen Server API auch eine Client API an, um komfortabel auf REST Services zugreifen zu können. Wie zu erwarten, ist es nicht weiter kompliziert, einen Service zu konsumieren, ein schlanker Dreizeiler reicht aus:
Client client = Client.create();
WebResource webResource = client.resource(http://server/restService);
String response = webResource.get(String.class);
Schon kann die Antwort des Services ("response") verarbeitet werden. Ab und zu ist es notwendig, sich für einen Web Service zu authentifizieren. Nichts einfacher als das, bei Verwendung der HTTP Basic Authentifizierung vor dem Aufruf des Services:
client.addFilter(new HTTPBasicAuthFilter("nutzer", "passwort"));
Abonnieren
Posts (Atom)