Как поймать оригинальное исключение при использовании WebServices? - PullRequest
0 голосов
/ 25 сентября 2018

После поисков в течение нескольких дней и прочтения почти всего, что с этим связано, я наконец-то разместил здесь свой вопрос, поскольку не смог найти решение для своей конкретной проблемы.

Я хочу, чтобы мои REST WebServices возвращали исходное исключение, которое было выброшено, или, по крайней мере, правильный StackTrace.Чтобы проверить это, я использую тесты интеграции JUnit и Wildfly 13 в качестве сервера приложений.После исследования я нашел 2 возможных решения.

1.Использование картографирования исключений

В то время как эта волшебная вещь захватывает все мои исключения и позволяет мне возвращать ответ, я 'Я заметил, что мой StackTrace изменился, если я использую его, как в примере.Например, «com.test.TestClass» превращается в «null.thread» или «null.interceptor».Кажется, что каким-то образом исключение меняется на пути, и пути к классу теряются или подвергаются цензуре, но я не могу понять это.Также я не смог найти никаких ограничений для Response.entity, будь то размер, тип данных или безопасность.

Насколько я понимаю, вы можете перехватить ExceptionMapper Response ИЛИ WebApplicationException, которая содержит ответ.В моем случае ответ в исключении WebApplicationEx содержит все соответствующие данные, кроме (правильного) StackTrace.

2.Использование исключения WebApplicationException

Другим решением было бы просто вызвать исключение WebApplicationException вместо ECEException и не использовать маппер.Если я это сделаю и поймаю, исключение будет пустым.Он не содержит никакого набора данных, он всегда равен 500 - InternalServerError (я думаю, тогда Wildfly не смог обработать его и сам выдал исключение).

Или он не должен быть перехвачен / брошенкак это?Нужно ли мне конвертировать его в JSon или можно ожидать, что он просто будет работать «из коробки» с моими аннотациями в WebServiceInterface и MediaType Response?Имеет ли смысл помещать полный ответ в исключение WebApplicationException?Я имею в виду, что оба содержат поля для ErrorCode, который кажется избыточным и даже при том, что есть конструктор для этого подхода.

Короче говоря: Какой лучший подход для перехвата всех возможных исключений иполучить полную трассировку стека? Читая этот пост , я думаю, что перехватывать все "Исключения" - это нормально, и они всегда возвращаются как WebApplicationExceptions, но трассировка стека все еще пропала / искажена ... ваши мысли?

    **JUnitTest** 
    @Test
    public void testCreateTask_ClusterInvalid() throws IOException {

        final RPETask taskToCreate = new RPETask();;

        try 
        {
            final long tid = taskManagerWebService.createTask(taskToCreate);
        } 
        catch (WebApplicationException e) //Responses are ALWAYS catched as WebApplicationException
        {

            Response response = e.getResponse();  
            String emString = response.readEntity(String.class);

            Gson gson = new Gson(); 

            ECEWebErrorMessage errorMessage = gson.fromJson(emString, ECEWebErrorMessage.class);       
            errorMessage.displayErrorInformationOnConsole();
        }
    }




    **WebServiceInterface**
    @POST
    @Path(URI_CREATE_TASK)
    @Consumes(WebServiceNames.JSON)
    @Produces(WebServiceNames.JSON)
    long createTask(final RPETask task) throws ECEException;




    **WebService**
    @Override
    public long createTask(final RPETask task) throws ECEException {
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("createTask(" + task + ")");
        }
        return taskManager.createTask(task);
    }




    **ManagerBeanInterface**
    long createTask(RPETask task) throws ECEException;




    **ManagerBean**
    @Override
    public long createTask(final RPETask task) throws ECEException {
        final ClusterEngineBean cluster = find(ClusterEngineBean.class, task.getCluster());
        if (cluster == null) {
            throw new ECEObjectNotFoundException(ClusterEngineBean.class, task.getCluster());
        }
    }




    **ExceptionMapper**
    @Provider
    public class GenericWebExceptionMapper implements ExceptionMapper<Exception> {
    final Log logger = LogFactory.getLog(getClass());

    @Override
    public Response toResponse(Exception ex) {

        //At this point, the Exception is fully available -> Sending it as Response breaks it!
        logger.error("GenericWebExceptionMapper -> toResponse(Throwable ex)", ex);

        ECEWebErrorMessage errorMessage = new ECEWebErrorMessage(500, 
                                                                 ex.getMessage(), 
                                                                 ex.getClass().getCanonicalName(),
                                                                 ex.getStackTrace());
        return Response.status(Status.INTERNAL_SERVER_ERROR)
                .entity(errorMessage)
                .type(MediaType.APPLICATION_JSON)
                .build();
        }
    }

1 Ответ

0 голосов
/ 26 сентября 2018

После дальнейших исследований я наконец-то нашел решение для себя.

Почему StackTrace пропал / поврежден?

Это из соображений безопасности.Wildfly автоматически обнаруживает исходящие StackTraces и подвергает их цензуре, используя перехватчики.Я не уверен, что вы можете что-то с этим сделать, но, полагаю, вам все равно не следует этого делать.

Каков наилучший подход?

Использование Exception Mappers сработалодля меня.Вместо того, чтобы отлавливать их как WebApplicationException, вы всегда можете ожидать ответ с кодом ошибки присвоения и обрабатывать их таким образом.Например, код ошибки 200 = OK, сделайте это ... код ошибки 404 = NOTFOUND, сделайте это ... В этом случае ваши WebServices всегда должны возвращать Response и содержать объект, который вы хотите получить в поле сущности Response.

Не стесняйтесь добавлять дополнительную информацию к этому решению.

...