2015-04-29 1 views
10

Примечания: Весь код для воспроизведения этой проблемы можно найти на https://gist.github.com/SrikanthRao/c9fc35e6fe22a74ab40cMultiException когда заказ Джерси пары бросает исключению

http://localhost:8080/date/bean?date=2014-13-23 (с использованием BeanParam) производят «{» кода «: 500,» сообщение «:» Была ошибка обрабатывая ваш запрос. Он был зарегистрирован (ID 48be9aa43bd49547). "}" Без добавления MultiExceptionMapper в трикотаж.

Если добавить MultiExceptionMapper в джерси, приведенные выше результаты URL в

"Дата либо не формат в YYYY-MM-DD или недействителен"

http://localhost:8080/date?date=2014-13-23 (прямой параметр @QueryParam) производит " Дата является формат либо не YYYY-MM-DD или недействителен»

Пара вопросов:

  1. является ли это правильный способ справиться с проверка ввода более чистым способом?
  2. Я ожидал, что это сработает без необходимости добавления моего собственного MultiExceptionMapper. Не поддерживает ли Джерси пользовательские * Парамы внутри POJO, которые вводятся как @BeanParam в методах ресурсов?

Вот трассировка стека, создаваемая при запросе (без добавления MultiExceptionMapper в трикотаж). Конечно, удалены длинные следы. Дайте мне знать, если вам нужна полная трассировка стека.

ERROR [2015-05-04 18:48:33,366] io.dropwizard.jersey.errors.LoggingExceptionMapper: Error handling a request: 0f23e4de758653d6 
    ! javax.ws.rs.WebApplicationException: HTTP 400 Bad Request 
    ! at io.dropwizard.jersey.params.AbstractParam.<init>(AbstractParam.java:28) ~[dropwizard-jersey-0.8.1.jar:0.8.1] 
    ! at com.fun.myapp.LocalDateTimeParam.<init>(LocalDateTimeParam.java:20) ~[classes/:na] 
    ! at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_45] 
... 
... 
Causing: org.glassfish.hk2.api.MultiException: A MultiException has 3 exceptions. They are: 
! 1. javax.ws.rs.WebApplicationException: HTTP 400 Bad Request 
! 2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of com.fun.myapp.PaginationFilters errors were found 
! 3. java.lang.IllegalStateException: Unable to perform operation: resolve on com.fun.myapp.PaginationFilters 
! 
! at org.jvnet.hk2.internal.Collector.throwIfErrors(Collector.java:88) ~[hk2-locator-2.4.0-b10.jar:na] 
! at org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:252) ~[hk2-locator-2.4.0-b10.jar:na] 
! at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:360) ~[hk2-locator-2.4.0-b10.jar:na] 
! at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471) ~[hk2-locator-2.4.0-b10.jar:na] 
.... 
.... 
WARN [2015-05-04 18:48:33,401] org.glassfish.jersey.internal.Errors: The following warnings have been detected: WARNING: Unknown HK2 failure detected: 
MultiException stack 1 of 3 
javax.ws.rs.WebApplicationException: HTTP 400 Bad Request 
    at io.dropwizard.jersey.params.AbstractParam.<init>(AbstractParam.java:28) 
    at com.fun.myapp.LocalDateTimeParam.<init>(LocalDateTimeParam.java:20) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) 
... 
... 
MultiException stack 2 of 3 
java.lang.IllegalArgumentException: While attempting to resolve the dependencies of com.fun.myapp.PaginationFilters errors were found 
    at org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:249) 
    at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:360) 
    at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471) 
... 
... 
MultiException stack 3 of 3 
java.lang.IllegalStateException: Unable to perform operation: resolve on com.fun.myapp.PaginationFilters 
    at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:389) 
    at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471) 
    at org.glassfish.jersey.process.internal.RequestScope.findOrCreate(RequestScope.java:162) 

Я задал этот вопрос на dropwizard пользователей Google группы - https://groups.google.com/forum/#!topic/dropwizard-user/yW-RXSSlspY

+0

вы реализовали код, соответствующий: // возвращает правильный объект ответа здесь. –

+0

другой пункт. Исключением жалуется класс com.fun.personal.finance.params.PaginationFilters. Можете ли вы проверить, есть ли у него открытый конструктор? –

+0

Да, я применил возвращаемый правильный ответ. позвольте мне обновить сообщение, поэтому его легче понять. Еще одна вещь: я изменил классы здесь, чтобы не копировать все, что у меня есть. stacktrace ссылается на разные имена. Фиксация. Нет конструктора args. – Srikanth

ответ

3

Вопрос 1

Согласно основной документации dropwizard, я вижу два возможных реализаций для проверки входных данных:

  • через аннотацию проверки

вы можете добавить аннотации валидации полей ваших классов представления и проверки их ...

Это не похоже, подходит для вашего случая. Фактически, нет доступной аннотации для LocalDateTime, и создание одного приводит к анализу LocalDateTime дважды: для проверки и для настройки поля bean.

  • Благодаря обработке ошибок:

Если вы хотите больше контроля, вы можете также объявить JerseyProviders в вашей среде на карте исключения для определенных ответов по телефону JerseyEnvironment # регистр (Object) с реализацией javax.ws.rs.ext.ExceptionMapper ...

Чтобы ответить на ваш первый вопрос, я бы сказал, что использование устройства отображения исключений отлично подходит для вашего случая.

Вопрос 2 Отладка как isValidDate методов показывает, что версия @BeanParam использует ClazzCreator.java пока @QueryParam нет. Этот класс отвечает за создание экземпляра класса bean. Если вы проверите строку 226 из the class, вы увидите, что она собирает несколько исключений при анализе ввода с несколькими ошибками. Это должно позволить сообщать о нескольких ошибках, связанных с различными полями бобов, включая некоторые последующие исключения.

Ответ заключается в том, что Jeysey поддерживает * Params внутри POJO. Однако связанное исключение инкапсулируется в MultiException в контексте @BeanParam. Следовательно, если вы планируете добавлять другие поля в PaginationFilters, вам следует подумать о том, чтобы сообщить о нескольких ошибках в отображаемом сообщении об исключении.

+0

У меня создается впечатление, что механизм проверки ограничений выполняется после того, как Джерси преобразует QueryParam из запроса в класс * Param. Для простоты я не приводил несколько аргументов внутри PaginationFilters. Но у этого есть возможность получить несколько параметров, добавленных к нему. Если я хочу объединить несколько ошибок, я не понимаю, как это сделать. Если вы видите MultiExceptionMapper, он обнаруживает первую ошибку, которая имеет тип WebApplicationException и возвращает ее ответ. Этот ответ имеет правильную ошибку. Например, я могу иметь полезную нагрузку определенного формата. Когда у меня есть несколько ответов, я не уверен, как объединиться. – Srikanth

+0

Это разные проблемы. Он был рассмотрен в другом ответе: http://stackoverflow.com/questions/28858450/handling-multiexception-of-jersey. Вы должны уметь адаптировать его к своим требованиям. –

0

1/для подтверждения даты, я предпочитаю самостоятельно разбирать «даты». Это просто и чисто. Вот некоторые рабочий код:

package com.rizze.stackoverflow; 

import java.text.ParseException; 
import java.text.SimpleDateFormat; 
import java.util.Date; 

import javax.ws.rs.GET; 
import javax.ws.rs.Path; 
import javax.ws.rs.Produces; 
import javax.ws.rs.QueryParam; 
import javax.ws.rs.core.Response; 



@Path("/test") 
public class TestRessource { 


    @GET  
    @Path("is") 
    @Produces({"application/json"}) 
    public Response isDateValid(@QueryParam("date") String dateString){ 

     if(dateString == null) 
      return Response.status(400).entity("date is null").build(); 
     Date thedate =null; 
     try { 
      thedate = new SimpleDateFormat("yyyy-mm-dd").parse(dateString); 
     } 
     catch (ParseException e) { 
      return Response.status(400).entity("date malformed").build(); 
     } 
     System.out.println("time:"+thedate.getTime()); 
     return Response.ok() 
       .entity("{\"time\":"+ thedate.getTime() +"}") 
       .header("source", "com.rizze") 
       .build(); 
    } 
} 

в этом коде вы будете называть

http://localhost:8080/test/is?date=2014-12-12 

вернется:

{"time":1389496320000} 

взглянуть на суть: https://gist.github.com/jeorfevre/6e46ae8d9232f7f9d7cc

2/в чтобы ловить исключения, хорошая практика заключается в том, чтобы поймать исключение на уровне сервера с Провайдерами (по регистру провайдера для вашего приложения). И для исключения на уровне приложения используйте свое исключение самостоятельно, используя response.status (статус исключения) .....

Пожалуйста, взгляните на мой вилочный указатель, я добавил _ServerError.class и я ' ве зарегистрировали его в приложении:

//register a mapper by rizze 
     environment.jersey().register(_ServerError.class); 

пожалуйста, смотрите на официальном документ, который Cristal ясно: official jersey representation doc

+0

Для простоты мой пример показывает только один параметр в PaginationFilters. API REST, обслуживающий множество методов ресурсов, будет иметь аналогичный ввод (я имею в виду дату, используемую несколькими методами и т. Д.), Но многие из них. Я хочу как можно больше отделить валидацию и не переписывать проверку каждый раз. Эта цель заставила меня использовать Джерси-Парамс. Я думаю, что это их цель. Я знаю обо всех исключениях. Я использую существующие механизмы проверки ограничений. Моя забота - это MultiException, когда пользовательский параметр находится внутри @BeanParam pojo. – Srikanth

+0

Это решение приводит к множеству дубликатов кода, если LocalDateTimeParam BeanParam используется во многих ресурсах. – ChrisO