2016-07-31 44 views
8

In einem meiner Projekte habe ich Jersey von Version 2.14 auf 2.23 aktualisiert. Aber ich habe viele Stunden mit einem Problem zu kämpfen. Mein Projekt definiert seine eigenen ExceptionMapper für eine ValidationException, aber leider Jersey hat bereits eine eingebaute Ausnahme Mapper für diese Ausnahme und ich kann es nicht überschreiben.Wie überschreiben Sie eine integrierte Ausnahme-Mapper in Jersey 2.23?

Ich habe richtig registriert (ich habe es) meine eigenen Mapper, die im folgenden dargestellt:

@Provider 
public class ValidationExceptionMapper implements 
     ExceptionMapper<ValidationException> { 

    @Override 
    public Response toResponse(ValidationException exception) { 
     return Response.status(Status.BAD_REQUEST).build(); 
    } 
} 

aber es wird nie aufgerufen wird. Jersey immer die org.glassfish.jersey.server.validation.internal.ValidationExceptionMapper abholen. Ich habe auch versucht, @Priority Annotation für meine benutzerdefinierte Mapper zu verwenden, aber leider berücksichtigt Jersey es nicht.

Also, was ist los? Es funktionierte perfekt in der vorherigen Jersey-Version, also scheint es ein Regression Bug zu sein.

Ich gebe auf. Irgendwelche Hinweise?

+0

Sie könnten 'ConstraintViolationException' (das ist der tatsächliche Typ der Validierungsausnahmen) als eine Arbeit umgehen. Es ist spezifischer als 'ValidationException' und hat Vorrang. Ich habe nie herausgefunden, wie man diesen einen Mapper deaktiviert, ohne _alle_ Meta-Inf-Provider zu deaktivieren (keine spaßige Lösung). Meine Arbeit war, einfach einen Mapper für 'ConstraintViolationException' zu verwenden. –

+0

Danke, ich weiß das, aber das löst das Problem überhaupt nicht. Weil die Anwendung auf 'ValidationException' reagieren muss. –

+0

'ConstraintViolationException' erweitert' ValidationException'. Der mit der Bean-Validierung in Jersey geworfene Ausnahmetyp ist immer eine 'ConstraintViolationException'. Es funktioniert für 'ValidationException', weil Super-Typ-Mapper Sub-Typ-Ausnahmen behandeln können, gibt es keinen Mapper für den Subtyp –

Antwort

4

Es stellte sich wirklich ein Regressions Fehler in Jersey sein aus 2015 eingeführt im Januar wird

Bug mit zwei Erweiterungen des Jersey bezogen werden: für Weld und Bohnen Validierung. Da ohne Weld-Container gestartet, hat meine benutzerdefinierte ValidationExceptionMapper Mapper Vorrang vor der eingebauten jersey-bean-validation-Modul, so dass mein Ziel erreicht wird.

Ich habe einen Fehlerbericht unter JERSEY-3153 gefüllt.

Um ehrlich zu sein, werde ich nie wieder Weld + Jersey benutzen ... Ich bin so müde mit dieser Kombination. In den letzten zwei Jahren habe ich bereits 10 Bugs entdeckt. Ich bin echt müde.

Wie auch immer, ich hoffe, es wird jemandem helfen.

UPDATE: Wie @ Jose Jose in den Kommentaren unten bemerkt, gibt es auch eine andere Abhilfe für den genannten Fehler. Wir können HK2 Bindungen, verwenden Sie den problematischen Einbau-Mapper außer Kraft zu setzen:

register(new AbstractBinder() { 
    @Override 
    protected void configure() { 
     bind(my.custom.ValidationExceptionMapper.class).to(ExceptionMapper.class) 
       .in(Singleton.class); 
    } 
}); 
0

fand ich einen Weg, um es zu bekommen mit neuerem Jersey arbeitet wieder freigibt, die ich auch unter dem Bug-Report geschrieben.

Man muss Jersey lokal mit dem geänderten Code, speziell dem jersey-bean-validation Artefakt, bauen.

Finde org.glassfish.jersey.server.validation.internal.ValidationBinder und kommentieren Sie die folgenden zwei Zeilen in configure():

bind(ValidationExceptionMapper.class).to(ExceptionMapper.class).in(Singleton.class); 
bind(ValidationErrorMessageBodyWriter.class).to(MessageBodyWriter.class).in(Singleton.class); 

Es ist irgendwie ironisch, dass der Quellcode Kommentar über diesen Zeilen sagt, dass sie angeblich Benutzern zu ermöglichen, ihre eigenen Provider zu registrieren.

+0

Danke Hein, aber ich würde in Erwägung ziehen, eine Bibliothek als letzten Ausweg zu patchen ... –

4

Der integrierte ValidationExceptionMapper von Jersey wird über ValidationFeature registriert. Vermutlich kann das Ersetzen von Trikes ValidationFeature mit Ihrer eigenen Version den Trick bewirken. Es kann wie folgt gemacht werden.

Zum einen Auto-Erkennbar ValidationFeature

property(ServerProperties.BV_FEATURE_DISABLE, true); 

Der nächste Schritt ist ein Klon von Jersey Validierungsfunktion

public static class ValidationFeatureClone implements Feature { 

    @Override 
    public boolean configure(FeatureContext context) { 
     context.register(new ValidationBinder()); 
     context.register(NewValidationExceptionMapper.class); 
     context.register(ValidationErrorMessageBodyWriter.class); 
     return true; 
    } 
} 

Im Klon registrieren deaktivieren, sollten Sie Ihren neuen ExceptionMapper angeben.

Schließlich registrieren Sie Ihr neues Feature-

register(ValidationFeatureClone.class) 

UPDATE:

Von Jersey 2.20 ab, default ValidationExceptionMapper können HK2 überschrieben mit Bindung unten gezeigt.

register(new AbstractBinder() { 
@Override 
protected void configure() { 
    bind(NewValidationExceptionMapper.class).to(ExceptionMapper.class) 
      .in(Singleton.class).ranked(10‌​); 
} 

});

+0

Bitte überprüfen Sie Ihre Lösung. Ich habe es vor einer Minute mit Jersey 2.23.1 überprüft und es löst das ursprüngliche Problem überhaupt nicht. Außerdem ist 'ValidationErrorMessageBodyWriter' keine öffentlich verfügbare Klasse. –

+0

Ich verwende Jersey 2.19 in unserer Anwendung und die Lösung hat für uns gearbeitet. Es sieht so aus, als ob "ValidationErrorMessageBodyWriter" ab 2.20 in eine package-private Klasse geändert wird. Ich habe Ihre Erwähnung von 2.23 in Ihrer ursprünglichen Frage nicht bemerkt. Können Sie bitte versuchen, einen Klon von 'ValidationErrorMessageBodyWriter' zu erstellen? –

+0

Es sieht so aus, als ob in den neuesten Versionen ein benutzerdefinierter 'ValidationExceptionMapper' unter Verwendung der HK2-Bindung registriert werden kann und es nicht notwendig ist, einen Klon der Validierungsfunktion zu registrieren, wie ich in meiner ursprünglichen Antwort erwähnt habe. Können Sie bitte versuchen Sie das Hinzufügen 'registrieren (neu AbstractBinder() { \t \t \t \t \t \t @Override \t \t \t protected void configure() { \t \t \t \t bind (NewValidationExceptionMapper.class) .to (ExceptionMapper.class) .in (Singleton.class) .ranked (10); \t \t \t \t \t \t \t } \t \t}); ' –