java jframe - JAX-RS / Jersey Wie kann man die Fehlerbehandlung anpassen?




example gui (9)

Dies ist das richtige Verhalten tatsächlich. Jersey wird versuchen, einen Handler für Ihre Eingabe zu finden und wird versuchen, ein Objekt aus der bereitgestellten Eingabe zu konstruieren. In diesem Fall wird versucht, ein neues Date-Objekt mit dem Wert X zu erstellen, der dem Konstruktor übergeben wird. Da dies ein ungültiges Datum ist, wird Jersey per Konvention 404 zurückgeben.

Was Sie tun können, ist neu schreiben und Geburtsdatum als String setzen, dann versuchen Sie zu analysieren und wenn Sie nicht bekommen, was Sie wollen, können Sie jede Ausnahme von einem der Ausnahme Mapping-Mechanismen werfen (es gibt mehrere ).

Ich lerne JAX-RS (alias JSR-311) mit Jersey. Ich habe erfolgreich eine Root-Ressource erstellt und spiele mit Parametern:

@Path("/hello")
public class HelloWorldResource {

    @GET
    @Produces("text/html")
    public String get(
        @QueryParam("name") String name,
        @QueryParam("birthDate") Date birthDate) {

         // Return a greeting with the name and age
    }
}

Das funktioniert gut und behandelt jedes Format im aktuellen Gebietsschema, das vom Konstruktor Date (String) verstanden wird (wie JJJJ / MM / TT und MM / TT / JJJJ). Aber wenn ich einen Wert gebe, der ungültig oder nicht verstanden ist, bekomme ich eine 404 Antwort.

Beispielsweise:

GET /hello?name=Mark&birthDate=X

404 Not Found

Wie kann ich dieses Verhalten anpassen? Vielleicht ein anderer Antwortcode (wahrscheinlich "400 Bad Request")? Was ist mit der Protokollierung eines Fehlers? Fügen Sie möglicherweise eine Beschreibung des Problems ("falsches Datumsformat") in einen benutzerdefinierten Header ein, um die Fehlerbehebung zu erleichtern. Oder gib eine ganze Fehlerantwort mit Details zurück, zusammen mit einem 5xx Statuscode?


abtrack class Responce
{
private String message ;
private int code ;

public String getMessage(){
 return this.message ;
}
public void setMessage(String message){
this.message =message ;
}


public String getCode(){
 return this.code ;
}
public void setCode(String code){
this.code =code ;
}

}

@XmlRootElement(name='MyResponce')
class MyResponce extends Responce {

}

@Path("/hello")
public class HelloWorldResource {

    @GET
    @Produces("text/html")
    public MyResponce  get(
      MyResponce  myResponce = new MyResponce ();
        @QueryParam("name") String name,
        @QueryParam("birthDate") Date birthDate) throw WSException {
          try {
}catch(Exception)
myResponce.setCode(400);
myResponce.setMessage("Exception")
   }
return myResponce ;

}

Ich mag auch StaxMan würde wahrscheinlich das QueryParam als String implementieren, dann die Konvertierung übernehmen und bei Bedarf neu starten.

Wenn das länderspezifische Verhalten das gewünschte und erwartete Verhalten ist, verwenden Sie Folgendes, um den 400 BAD REQUEST-Fehler zurückzugeben:

throw new WebApplicationException(Response.Status.BAD_REQUEST);

Weitere Informationen finden Sie in der JavaDoc-Datei für javax.ws.rs.core.Response.Status .


Wenn es fehlschlägt, die Parameter zu demarmarshall, löst Jersey eine com.sun.jersey.api.ParamException aus, so dass eine Lösung darin besteht, einen ExceptionMapper zu erstellen, der diese Arten von Ausnahmen behandelt:

@Provider
public class ParamExceptionMapper implements ExceptionMapper<ParamException> {
    @Override
    public Response toResponse(ParamException exception) {
        return Response.status(Status.BAD_REQUEST).entity(exception.getParameterName() + " incorrect type").build();
    }
}

@Provider
public class BadURIExceptionMapper implements ExceptionMapper<NotFoundException> {

public Response toResponse(NotFoundException exception){

    return Response.status(Response.Status.NOT_FOUND).
    entity(new ErrorResponse(exception.getClass().toString(),
                exception.getMessage()) ).
    build();
}
}

Erstellen Sie über Klasse. Dies wird 404 (NotFoundException) behandeln und hier in ToResponse-Methode können Sie Ihre benutzerdefinierte Antwort geben. In ähnlicher Weise gibt es ParamException usw., die Sie zuordnen müssen, um angepasste Antworten bereitzustellen.


Sie könnten auch eine wiederverwendbare Klasse für mit QueryParam gekennzeichnete Variablen schreiben

public class DateParam {
  private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

  private Calendar date;

  public DateParam(String in) throws WebApplicationException {
    try {
      date = Calendar.getInstance();
      date.setTime(format.parse(in));
    }
    catch (ParseException exception) {
      throw new WebApplicationException(400);
    }
  }
  public Calendar getDate() {
    return date;
  }
  public String format() {
    return format.format(value.getTime());
  }
}

dann benutze es so:

private @QueryParam("from") DateParam startDateParam;
private @QueryParam("to") DateParam endDateParam;
// ...
startDateParam.getDate();

Obwohl die Fehlerbehandlung in diesem Fall trivial ist (eine 400-Antwort wird ausgelöst), ermöglicht Ihnen die Verwendung dieser Klasse die Parameterbehandlung im Allgemeinen, die Protokollierung usw. beinhalten könnte.


@QueryParam-Dokumentation sagt

"Der Typ T des annotierten Parameters, Felds oder der Eigenschaft muss entweder

1) Sei ein primitiver Typ
2) Haben Sie einen Konstruktor, der ein einzelnes String-Argument akzeptiert
3) Haben Sie eine statische Methode namens valueOf oder fromString, die ein einzelnes String-Argument akzeptiert (siehe zB Integer.valueOf (String))
4) Habe eine registrierte Implementierung von jaxx.ws.rs.ext.ParamConverterProvider JAX-RS Extension SPI, die eine javax.ws.rs.ext.ParamConverter Instanz zurückliefert, die eine "from string" Konvertierung für den Typ ausführen kann.
5) Sei List, Set oder SortedSet, wobei T die obigen 2, 3 oder 4 erfüllt. Die resultierende Sammlung ist schreibgeschützt. "

Wenn Sie steuern möchten, welche Antwort an den Benutzer gesendet wird, wenn der Abfrageparameter im String-Formular nicht in den Typ T konvertiert werden kann, können Sie WebApplicationException auslösen. Dropwizard kommt mit folgenden * Param-Klassen, die Sie für Ihre Bedürfnisse verwenden können.

BooleanParam, DateTimeParam, IntParam, LongParam, LocalDateParam, NonEmptyStringParam, UUIDParam. Siehe https://github.com/dropwizard/dropwizard/tree/master/dropwizard-jersey/src/main/java/io/dropwizard/jersey/params

Wenn Sie Joda DateTime benötigen, verwenden Sie einfach DropWizard github.com/dropwizard/dropwizard/blob/master/dropwizard-jersey/… .

Wenn die obige Liste nicht Ihren Bedürfnissen entspricht, definieren Sie Ihre eigene, indem Sie AbstractParam erweitern. Überschreiben Sie die Parse-Methode. Wenn Sie die Kontrolle über den Fehlerreaktionskörper benötigen, überschreiben Sie die Fehlermethode.

Guter Artikel von Coda Hale zu diesem Thema ist http://codahale.com/what-makes-jersey-interesting-parameter-classes/

import io.dropwizard.jersey.params.AbstractParam;

import java.util.Date;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

public class DateParam extends AbstractParam<Date> {

    public DateParam(String input) {
        super(input);
    }

    @Override
    protected Date parse(String input) throws Exception {
        return new Date(input);
    }

    @Override
    protected Response error(String input, Exception e) {
        // customize response body if you like here by specifying entity
        return Response.status(Status.BAD_REQUEST).build();
    }
}

Der Konstruktor "Date (String arg)" ist veraltet. Ich würde Java 8-Datumsklassen verwenden, wenn Sie auf Java 8 sind. Ansonsten wird Joda Date Time empfohlen.


Es gibt mehrere Ansätze, um das Fehlerbehandlungsverhalten mit JAX-RS anzupassen. Hier sind drei der leichteren Möglichkeiten.

Der erste Ansatz besteht darin, eine Exception-Klasse zu erstellen, die WebApplicationException erweitert.

Beispiel:

public class NotAuthorizedException extends WebApplicationException {
     public NotAuthorizedException(String message) {
         super(Response.status(Response.Status.UNAUTHORIZED)
             .entity(message).type(MediaType.TEXT_PLAIN).build());
     }
}

Und um diese neu zu erstellen erstellen Sie einfach:

@Path("accounts/{accountId}/")
    public Item getItem(@PathParam("accountId") String accountId) {
       // An unauthorized user tries to enter
       throw new NotAuthorizedException("You Don't Have Permission");
}

Beachten Sie, dass Sie die Ausnahme nicht in einer throws-Klausel deklarieren müssen, weil WebApplicationException eine Laufzeitausnahme ist. Dies wird eine 401-Antwort an den Client zurückgeben.

Der zweite und einfachere Ansatz besteht darin, einfach eine Instanz der WebApplicationException direkt in Ihrem Code zu erstellen. Dieser Ansatz funktioniert, solange Sie keine eigenen Anwendungsausnahmen implementieren müssen.

Beispiel:

@Path("accounts/{accountId}/")
public Item getItem(@PathParam("accountId") String accountId) {
   // An unauthorized user tries to enter
   throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}

Dieser Code gibt auch eine 401 an den Client zurück.

Das ist natürlich nur ein einfaches Beispiel. Sie können die Exception bei Bedarf viel komplexer machen und Sie können den HTTP-Antwortcode generieren, den Sie benötigen.

Ein anderer Ansatz besteht darin, eine vorhandene Exception, möglicherweise eine ObjectNotFoundException, mit einer kleinen Wrapper-Klasse zu umbrechen, die die ExceptionMapper-Schnittstelle implementiert, die mit einer @Provider-Annotation versehen ist. Dies teilt der JAX-RS-Laufzeit mit, dass, wenn die umbrochene Exception ausgelöst wird, der im ExceptionMapper definierte Antwortcode zurückgegeben wird.


Sie müssen Ihren Inhaltstyp auf application / json setzen. -d sendet jedoch die Content-Type- application/x-www-form-urlencoded , die von Spring nicht akzeptiert wird.

Wenn ich die curl-Manpage betrachte , denke ich, kannst du -H :

-H "Content-Type: application/json"

Vollständiges Beispiel:

curl --header "Content-Type: application/json" \
  --request POST \
  --data '{"username":"xyz","password":"xyz"}' \
  http://localhost:3000/api/login

( -H steht für --header , -d für --data )

Beachten Sie, dass -request POST optional ist, wenn Sie -d , da das Flag -d eine POST-Anforderung impliziert.

Unter Windows sind die Dinge etwas anders. Siehe den Kommentarthread.







java rest error-handling jersey jax-rs