2016-11-07 8 views
7

Mam następujący zasób zużywający JSON odwzorowany na POJO.Niestandardowa aplikacja ExceptionMapper for Jersey nie działa z niepoprawnym wpisem JSON

@Path("example") 
public class ExampleResource { 

    @POST 
    @Consumes(MediaType.APPLICATION_JSON) 
    public Response addThesis(MyObject myObject) { 
     return Response.ok().entity("Test").build(); 
    } 
} 

Oto klasa POJO:

public class MyObject { 
    private String title; 

    public String getTitle() { 
     return title; 
    } 

    public void setTitle(String title) { 
     this.title = title; 
    } 
} 

Kiedy wysłać żądanie POST z ciałem { "title": "tytuł Test"} wszystko działa poprawnie. Odpowiedź: Test, zgodnie z oczekiwaniami. Jednak, kiedy zmienić wniosek do { "titlee": "Test" tytuł} serwer odpowiada z tym:

Nierozpoznany pole "titlee" (klasa com.my.package.MyObject), nie oznakowane jako niezapomniany (jedna znana właściwość: "tytuł")) w [Źródło: org.glassfish.jersey.me[email protected]6dc6a46a; linia: 2, kolumna: 11] (przez łańcuch referencyjny: com.my.package.MyObject ["titlee"])

Oczywiście jest to wyjątek wyrzucony i zwrócony przez Jersey. Jak mogę przechwycić ten wyjątek i zwrócić niestandardowy kod statusu i wiadomość?

Co próbowałem tak daleko jest do realizacji własne ExceptionMapper:

@Provider 
public class MyJsonExceptionMapper implements ExceptionMapper<JsonProcessingException> { 
    public Response toResponse(JsonProcessingException e) { 
     return Response.status(400).entity("JSON Processing Error").build(); 
    } 
} 

Niestety odpowiedź pozostaje taka sama. Kiedy implementuję ExceptionMapper dla niestandardowego wyjątku i wyrzucam odpowiedni wyjątek w metodzie zasobów, wszystko działa poprawnie. Zakładam, że ma to związek z domyślnym wyjątkiem ExceptionMapper dla JsonProcessingException przesłaniającym mój własny. Potem próbowałem stworzyć ogólny program odwzorowujący ("implementuje ExceptionMapper"), ale znowu nie ma sukcesu.

Szukałem dosłownie wszędzie i próbowałem wielu rzeczy, w tym przedłużania ResourceConfig i rejestrowania mojego programu odwzorowującego, ale nic nie zadziałało tak daleko.

Kilka dodatkowych informacji, które mogą pomóc w zmniejszeniu problemu: Używam Grizzly2 jako serwera HTTP, który wdrażam jako Fat JAR.

Część zależność mojego pom.xml wygląda następująco:

<dependencies> 
    <dependency> 
     <groupId>org.glassfish.jersey.media</groupId> 
     <artifactId>jersey-media-json-jackson</artifactId> 
     <version>2.24</version> 
    </dependency> 
    <dependency> 
     <groupId>org.glassfish.jersey.containers</groupId> 
     <artifactId>jersey-container-grizzly2-http</artifactId> 
     <version>2.24</version> 
    </dependency> 
</dependencies> 

Każda rada jest bardzo ceniona.

+0

Z tego co pamiętam, myślę, że implementując program odwzorowujący JsonMappingException i JsonParseException, powinien on zastąpić domyślne. Nie jestem do końca pewien, jak je wyłączyć. –

+0

Implementacja programu odwzorowującego dla 'Throwable' powinna zastąpić/wszystkie/istniejące elementy odwzorowujące. Ale to nie działa. W dodatku ResourceConfig nie można również poprawić właściwości 'ExceptionMapper ' explicity. – BadZen

+0

(Również implementacja 'ExtendedExceptionMapper', jak sugerują dokumenty również nie działa ...) – BadZen

Odpowiedz

5

Ok, to jest głupie i hack-owski, ale pracował dla mnie:

register(JacksonJaxbJsonProvider.class);

Wynika to z następujących "ładne zachowanie domyślne" w punkcie Jackson wejściowej cecha:

if (!config.isRegistered(JacksonJaxbJsonProvider.class)) { // add the default Jackson exception mappers context.register(JsonParseExceptionMapper.class); context.register(JsonMappingExceptionMapper.class);

:(

Ale to wciąż wolą odpowiedź, która rozwiązuje problem „dla rea kłamstwo. bez wstępnej rejestracji komponentów, aby funkcja nie mogła ich poprawnie skonfigurować ...

+0

(i tak, aby rozszerzony program odwzorowujący mógł odrzucić wyjątek i wysłać go do domyślnego programu odwzorowującego ...) – BadZen

0

Używamy JAX-RS na Wildfly do realizacji naszych usług internetowych i korzystania z następujących elementów, aby osiągnąć to, co próbujesz zrobić z Jersey na Glassfish. Może ma podobne cechy, które możesz sprawdzić. Nasze kroki:

  • Usługa jest bezpaństwowcem EJB, wykorzystanie EJB przechwytujących do pułapki wyjątkiem i wypełnić wniosek o zakresie obiektu ze szczegółami
  • Wdrożenie PostProcessInterceptor który odczytuje z życzeniem określania zakresów obiektu i modyfikuje odpowiedź zanim zwrotów serwisowych. (To jest specyficzne dla JAX-RS)
2

Miałem także do czynienia z tym problemem. Jeśli zarejestrowano numer JacksonFeature, można po prostu zarejestrować się jako obejście JacksonJaxbJsonProvider.


Gdy JacksonFeature jest w ścieżce klasy, to jest automatycznie wykrywane przez Jersey. Innym sposobem naprawy jest wyłączenie automatycznego wykrywania przez ustawienie ServerProperties.FEATURE_AUTO_DISCOVERY_DISABLE na true. W związku z tym konieczne będzie ręczne zarejestrowanie innych funkcji.


Alternatywnie można pozbyć się jersey-media-json-jackson artefaktu i używać jackson-jaxrs-json-provider zamiast. Dzięki temu pozbędziesz się JacksonFeature, a następnie będziesz mógł zarejestrować swoich własnych maperów wyjątków.


ostatnia opcja i prawdopodobnie to, co wydaje się być poprawne rozwiązanie (jak wskazano w Kysil Iwana answer) można napisać własny mapowania wyjątku, a następnie nadać jej wysoki priorytet, takich jak 1. Jeśli używasz auto odkrycie, tylko opisywanie go @Provider i @Priority:

@Provider 
@Priority(1) 
public class JsonParseExceptionMapper implements ExceptionMapper<JsonParseException> { 
    ... 
} 

Jeśli ręcznie zarejestrować się z operatorem, można give your provider a binding priority:

@ApplicationPath("/") 
public class MyResourceConfig extends ResourceConfig { 

    public MyResourceConfig() { 
     register(JsonParseExceptionMapper.class, 1); 
    } 
} 

Zobacz ten answer więcej szczegółów.

Powiązane problemy