You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by or...@apache.org on 2015/08/24 08:30:23 UTC
svn commit: r1697319 - in /qpid/java/trunk/broker-plugins:
management-http/src/main/java/org/apache/qpid/server/management/plugin/
management-http/src/main/java/org/apache/qpid/server/management/plugin/filter/
management-http/src/main/java/org/apache/q...
Author: orudyy
Date: Mon Aug 24 06:30:22 2015
New Revision: 1697319
URL: http://svn.apache.org/r1697319
Log:
QPID-6707: [Java Broker] Kill the Broker on invocation of store mutation operation ending with ServerScopedRuntimeException
work by Lorenz Quack <qu...@gmail.com> and Alex Rudyy <or...@apache.org>
Added:
qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/filter/ExceptionHandlingFilter.java
Modified:
qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
qpid/java/trunk/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java
Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java?rev=1697319&r1=1697318&r2=1697319&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java Mon Aug 24 06:30:22 2015
@@ -43,6 +43,7 @@ import javax.servlet.http.HttpServletReq
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import org.apache.qpid.server.management.plugin.filter.ExceptionHandlingFilter;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
@@ -239,6 +240,8 @@ public class HttpManagement extends Abst
root.getServletContext().setAttribute(HttpManagementUtil.ATTR_BROKER, getBroker());
root.getServletContext().setAttribute(HttpManagementUtil.ATTR_MANAGEMENT_CONFIGURATION, this);
+ root.addFilter(new FilterHolder(new ExceptionHandlingFilter()), "/*", EnumSet.allOf(DispatcherType.class));
+
FilterHolder loggingFilter = new FilterHolder(new LoggingFilter());
root.addFilter(loggingFilter, "/api/*", EnumSet.of(DispatcherType.REQUEST));
root.addFilter(loggingFilter, "/service/*", EnumSet.of(DispatcherType.REQUEST));
Added: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/filter/ExceptionHandlingFilter.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/filter/ExceptionHandlingFilter.java?rev=1697319&view=auto
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/filter/ExceptionHandlingFilter.java (added)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/filter/ExceptionHandlingFilter.java Mon Aug 24 06:30:22 2015
@@ -0,0 +1,85 @@
+/*
+ * 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.qpid.server.management.plugin.filter;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.server.util.ServerScopedRuntimeException;
+
+public class ExceptionHandlingFilter implements Filter
+{
+ private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionHandlingFilter.class);
+
+ private Thread.UncaughtExceptionHandler _uncaughtExceptionHandler;
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException
+ {
+ _uncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
+ if (_uncaughtExceptionHandler == null)
+ {
+ throw new IllegalStateException("no uncaught exception handler set");
+ }
+ }
+
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException
+ {
+ try
+ {
+ filterChain.doFilter(servletRequest, servletResponse);
+ }
+ catch (ServerScopedRuntimeException | Error e)
+ {
+ if (_uncaughtExceptionHandler == null)
+ {
+ throw e;
+ }
+ _uncaughtExceptionHandler.uncaughtException(Thread.currentThread(), e);
+ }
+ catch (IOException | ServletException e)
+ {
+ LOGGER.debug("Exception in servlet '{}': ", ((HttpServletRequest)servletRequest).getRequestURI(), e);
+ throw e;
+ }
+ catch (RuntimeException e)
+ {
+ LOGGER.error("Unexpected exception in servlet '{}': ", ((HttpServletRequest)servletRequest).getRequestURI(), e);
+ throw e;
+ }
+ }
+
+ @Override
+ public void destroy()
+ {
+ // noop
+ }
+}
Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java?rev=1697319&r1=1697318&r2=1697319&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java Mon Aug 24 06:30:22 2015
@@ -38,6 +38,8 @@ import java.util.Set;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
@@ -354,7 +356,6 @@ public class RestServlet extends Abstrac
@Override
protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
- try
{
String[] pathInfoElements = getPathInfoElements(request);
if (pathInfoElements != null && pathInfoElements.length == _hierarchy.length + 1)
@@ -420,10 +421,6 @@ public class RestServlet extends Abstrac
sendCachingHeaders);
}
}
- catch (RuntimeException e)
- {
- setResponseStatus(request, response, e);
- }
}
private boolean isSingleObjectRequest(HttpServletRequest request)
@@ -465,6 +462,21 @@ public class RestServlet extends Abstrac
performCreateOrUpdate(request, response);
}
+ @Override
+ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ try
+ {
+ super.service(request, response);
+ }
+ catch (IllegalArgumentException | IllegalConfigurationException | IllegalStateException | AccessControlException
+ | ExchangeExistsException | QueueExistsException | IntegrityViolationException
+ | IllegalStateTransitionException | NoClassDefFoundError e)
+ {
+ setResponseStatus(request, response, e);
+ }
+ }
+
private void performCreateOrUpdate(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
response.setContentType("application/json");
@@ -474,7 +486,6 @@ public class RestServlet extends Abstrac
boolean isPostToFullURL = isFullObjectURL && "POST".equalsIgnoreCase(request.getMethod());
final String[] pathInfoElements = getPathInfoElements(request);
boolean isOperation = pathInfoElements != null && pathInfoElements.length == _hierarchy.length + 1 && isPostToFullURL;
- try
{
if(!isOperation)
{
@@ -533,11 +544,6 @@ public class RestServlet extends Abstrac
doOperation(request, response);
}
}
- catch (RuntimeException | NoClassDefFoundError e)
- {
- setResponseStatus(request, response, e);
- }
-
}
private void doOperation(final HttpServletRequest request,
@@ -935,16 +941,28 @@ public class RestServlet extends Abstrac
}
responseCode = SC_UNPROCESSABLE_ENTITY;
}
+ else if (e instanceof NoClassDefFoundError)
+ {
+ message = "Not found: " + message;
+ LOGGER.warn("Unexpected exception processing request ", e);
+ }
else
{
- if (e instanceof NoClassDefFoundError)
+ // This should not happen
+ if (e instanceof RuntimeException)
{
- message = "Not found: " + message;
+ throw (RuntimeException)e;
+ }
+ else if (e instanceof Error)
+ {
+ throw (Error)e;
+ }
+ else
+ {
+ throw new RuntimeException("Unexpected Exception", e);
}
- LOGGER.warn("Unexpected exception processing request ", e);
}
-
sendJsonErrorResponse(request, response, responseCode, message);
}
@@ -953,7 +971,6 @@ public class RestServlet extends Abstrac
@Override
protected void doDeleteWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
- try
{
Collection<ConfiguredObject<?>> allObjects = getObjects(request);
if(allObjects != null)
@@ -971,10 +988,6 @@ public class RestServlet extends Abstrac
sendJsonErrorResponse(request, response, HttpServletResponse.SC_NOT_FOUND, "Not Found");
}
}
- catch(RuntimeException e)
- {
- setResponseStatus(request, response, e);
- }
}
@Override
Modified: qpid/java/trunk/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java?rev=1697319&r1=1697318&r2=1697319&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java (original)
+++ qpid/java/trunk/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java Mon Aug 24 06:30:22 2015
@@ -37,9 +37,11 @@ import javax.management.MBeanOperationIn
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.RuntimeErrorException;
+import javax.management.RuntimeMBeanException;
import javax.management.remote.MBeanServerForwarder;
import javax.security.auth.Subject;
+import org.apache.qpid.server.util.ServerScopedRuntimeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -59,6 +61,7 @@ public class MBeanInvocationHandlerImpl
private static final Logger _logger = LoggerFactory.getLogger(MBeanInvocationHandlerImpl.class);
private final static String DELEGATE = "JMImplementation:type=MBeanServerDelegate";
+ private final Thread.UncaughtExceptionHandler _uncaughtExceptionHandler;
private MBeanServer _mbs;
private final boolean _managementRightsInferAllAccess;
@@ -68,6 +71,11 @@ public class MBeanInvocationHandlerImpl
{
_managementRightsInferAllAccess = Boolean.valueOf(System.getProperty(BrokerProperties.PROPERTY_MANAGEMENT_RIGHTS_INFER_ALL_ACCESS, "true"));
_broker = broker;
+ _uncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
+ if (_uncaughtExceptionHandler == null)
+ {
+ throw new IllegalStateException("no uncaught exception handler set");
+ }
}
public static MBeanServerForwarder newProxyInstance(Broker<?> broker)
@@ -165,13 +173,12 @@ public class MBeanInvocationHandlerImpl
}
catch (InvocationTargetException e)
{
- Throwable targetException = e.getCause();
- logTargetException(method, args, targetException);
- throw targetException;
+ handleTargetException(method, args, e.getCause());
+ throw e.getCause();
}
}
- private void logTargetException(Method method, Object[] args, Throwable targetException)
+ private void handleTargetException(Method method, Object[] args, Throwable targetException)
{
Throwable error = null;
if (targetException instanceof RuntimeErrorException)
@@ -190,6 +197,21 @@ public class MBeanInvocationHandlerImpl
{
_logger.error("Unexpected error occurred on invoking of " + method + " with arguments " + Arrays.toString(args), targetException);
}
+
+ if (targetException instanceof ServerScopedRuntimeException)
+ {
+ error = targetException;
+ }
+ else if (targetException instanceof RuntimeMBeanException)
+ {
+ // unwrap RuntimeMBeanException
+ error = ((RuntimeMBeanException)targetException).getTargetException();
+ }
+
+ if (error instanceof Error || error instanceof ServerScopedRuntimeException)
+ {
+ _uncaughtExceptionHandler.uncaughtException(Thread.currentThread(), error);
+ }
}
private Object authoriseAndInvoke(final Method method, final Object[] args) throws Exception
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org