Repository: metron Updated Branches: refs/heads/master d69101a8d -> a8fd8ea0c
METRON-1218 Metron REST should return better error messages (merrimanr) closes apache/metron#779 Project: http://git-wip-us.apache.org/repos/asf/metron/repo Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/a8fd8ea0 Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/a8fd8ea0 Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/a8fd8ea0 Branch: refs/heads/master Commit: a8fd8ea0c37ffe0fdd87a54e9be9808fba16acfb Parents: d69101a Author: merrimanr <[email protected]> Authored: Wed Oct 4 08:50:07 2017 -0500 Committer: merrimanr <[email protected]> Committed: Wed Oct 4 08:50:07 2017 -0500 ---------------------------------------------------------------------- .../rest/controller/RestExceptionHandler.java | 3 +- .../controller/RestExceptionHandlerTest.java | 74 ++++++++++++++++++++ .../elasticsearch/dao/ElasticsearchDao.java | 6 ++ 3 files changed, 82 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metron/blob/a8fd8ea0/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/RestExceptionHandler.java ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/RestExceptionHandler.java b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/RestExceptionHandler.java index fa73dab..5e6f7e7 100644 --- a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/RestExceptionHandler.java +++ b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/RestExceptionHandler.java @@ -17,6 +17,7 @@ */ package org.apache.metron.rest.controller; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.metron.rest.RestException; import org.apache.metron.rest.model.RestError; import org.springframework.http.HttpStatus; @@ -35,7 +36,7 @@ public class RestExceptionHandler extends ResponseEntityExceptionHandler { @ResponseBody ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) { HttpStatus status = getStatus(request); - return new ResponseEntity<>(new RestError(status.value(), ex.getMessage(), ex.getMessage()), status); + return new ResponseEntity<>(new RestError(status.value(), ex.getMessage(), ExceptionUtils.getRootCauseMessage(ex)), status); } private HttpStatus getStatus(HttpServletRequest request) { http://git-wip-us.apache.org/repos/asf/metron/blob/a8fd8ea0/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/controller/RestExceptionHandlerTest.java ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/controller/RestExceptionHandlerTest.java b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/controller/RestExceptionHandlerTest.java new file mode 100644 index 0000000..b934481 --- /dev/null +++ b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/controller/RestExceptionHandlerTest.java @@ -0,0 +1,74 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package org.apache.metron.rest.controller; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import javax.servlet.http.HttpServletRequest; +import org.apache.commons.lang.exception.ExceptionUtils; +import org.apache.metron.rest.model.RestError; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +public class RestExceptionHandlerTest { + + private RestExceptionHandler restExceptionHandler; + private HttpServletRequest request; + + @Before + public void setUp() throws Exception { + restExceptionHandler = new RestExceptionHandler(); + request = mock(HttpServletRequest.class); + } + + @Test + public void handleControllerExceptionShouldProperlyReturnRestError() throws Exception { + when(request.getAttribute("javax.servlet.error.status_code")).thenReturn(401); + Throwable throwable = new RuntimeException("unauthorized"); + + ResponseEntity responseEntity = restExceptionHandler.handleControllerException(request, throwable); + assertEquals(HttpStatus.UNAUTHORIZED, responseEntity.getStatusCode()); + RestError actualRestError = (RestError) responseEntity.getBody(); + assertEquals("unauthorized", actualRestError.getMessage()); + assertEquals("RuntimeException: unauthorized", actualRestError.getFullMessage()); + assertEquals(401, actualRestError.getResponseCode()); + } + + @Test + public void handleControllerExceptionShouldDefaultTo500() throws Exception { + when(request.getAttribute("javax.servlet.error.status_code")).thenReturn(null); + Throwable throwable = new RuntimeException("some error"); + + ResponseEntity responseEntity = restExceptionHandler.handleControllerException(request, throwable); + assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode()); + } + + @Test + public void handleControllerExceptionShouldReturnRootCause() throws Exception { + when(request.getAttribute("javax.servlet.error.status_code")).thenReturn(500); + Throwable throwable = new RuntimeException("some error", new RuntimeException("some root cause")); + + ResponseEntity responseEntity = restExceptionHandler.handleControllerException(request, throwable); + assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, responseEntity.getStatusCode()); + RestError actualRestError = (RestError) responseEntity.getBody(); + assertEquals("some error", actualRestError.getMessage()); + assertEquals("RuntimeException: some root cause", actualRestError.getFullMessage()); + assertEquals(500, actualRestError.getResponseCode()); + } +} http://git-wip-us.apache.org/repos/asf/metron/blob/a8fd8ea0/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchDao.java ---------------------------------------------------------------------- diff --git a/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchDao.java b/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchDao.java index 62706e3..e097a99 100644 --- a/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchDao.java +++ b/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchDao.java @@ -20,6 +20,7 @@ package org.apache.metron.elasticsearch.dao; import com.google.common.base.Splitter; import com.google.common.collect.Iterables; import java.io.IOException; +import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -95,8 +96,12 @@ import java.util.Map; import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ElasticsearchDao implements IndexDao { + + private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private transient TransportClient client; private AccessConfig accessConfig; private List<String> ignoredIndices = new ArrayList<>(); @@ -167,6 +172,7 @@ public class ElasticsearchDao implements IndexDao { elasticsearchResponse = client.search(new org.elasticsearch.action.search.SearchRequest(wildcardIndices) .source(searchSourceBuilder)).actionGet(); } catch (SearchPhaseExecutionException e) { + LOG.error("Could not execute search", e); throw new InvalidSearchException("Could not execute search", e); } SearchResponse searchResponse = new SearchResponse();
