This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git


The following commit(s) were added to refs/heads/master by this push:
     new 1acfe7d  [SCB-2186] fix bug of ExceptionConverter throw exception 
(#2219)
1acfe7d is described below

commit 1acfe7d06d420795c47b3e6ab6013242cabe7a9d
Author: wujimin <[email protected]>
AuthorDate: Thu Jan 28 09:07:40 2021 +0800

    [SCB-2186] fix bug of ExceptionConverter throw exception (#2219)
---
 .../servicecomb/core/exception/Exceptions.java     | 20 +++++++++--
 .../servicecomb/core/exception/ExceptionsTest.java | 40 ++++++++++++++++++++++
 .../foundation/common/utils/ReflectUtils.java      | 11 ------
 .../metrics/core/OsMetersInitializer.java          | 11 +++++-
 .../metrics/core/TestOsMeterInitializer.java       | 20 ++---------
 ...g.apache.servicecomb.core.filter.FilterProvider | 18 ----------
 6 files changed, 70 insertions(+), 50 deletions(-)

diff --git 
a/core/src/main/java/org/apache/servicecomb/core/exception/Exceptions.java 
b/core/src/main/java/org/apache/servicecomb/core/exception/Exceptions.java
index 7166d6b..c3f6059 100644
--- a/core/src/main/java/org/apache/servicecomb/core/exception/Exceptions.java
+++ b/core/src/main/java/org/apache/servicecomb/core/exception/Exceptions.java
@@ -18,6 +18,7 @@ package org.apache.servicecomb.core.exception;
 
 import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
 import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
+import static org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace;
 import static 
org.apache.servicecomb.core.exception.ExceptionCodes.GENERIC_CLIENT;
 import static 
org.apache.servicecomb.core.exception.ExceptionCodes.GENERIC_SERVER;
 import static 
org.apache.servicecomb.swagger.invocation.InvocationType.CONSUMER;
@@ -35,6 +36,7 @@ import 
org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
 import org.apache.servicecomb.foundation.common.utils.ExceptionUtils;
 import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
 import org.apache.servicecomb.swagger.invocation.Response;
+import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData;
 import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory;
 import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
 import org.slf4j.Logger;
@@ -141,9 +143,23 @@ public final class Exceptions {
 
   public static InvocationException convert(@Nullable Invocation invocation, 
Throwable throwable,
       StatusType genericStatus) {
+    return convert(invocation, throwable, genericStatus, CACHE);
+  }
+
+  public static InvocationException convert(@Nullable Invocation invocation, 
Throwable throwable,
+      StatusType genericStatus, Map<Class<?>, ExceptionConverter<Throwable>> 
cache) {
     Throwable unwrapped = unwrap(throwable);
-    return CACHE.computeIfAbsent(unwrapped.getClass(), clazz -> 
findConverter(unwrapped))
-        .convert(invocation, unwrapped, genericStatus);
+    try {
+      return cache.computeIfAbsent(unwrapped.getClass(), clazz -> 
findConverter(unwrapped))
+          .convert(invocation, unwrapped, genericStatus);
+    } catch (Exception e) {
+      LOGGER.error("BUG: ExceptionConverter.convert MUST not throw exception, 
please fix it.\n"
+              + "original exception:{}converter exception:{}",
+          getStackTrace(throwable),
+          getStackTrace(e));
+      return new InvocationException(INTERNAL_SERVER_ERROR,
+          new CommonExceptionData(GENERIC_SERVER, 
INTERNAL_SERVER_ERROR.getReasonPhrase()));
+    }
   }
 
   private static ExceptionConverter<Throwable> findConverter(Throwable 
throwable) {
diff --git 
a/core/src/test/java/org/apache/servicecomb/core/exception/ExceptionsTest.java 
b/core/src/test/java/org/apache/servicecomb/core/exception/ExceptionsTest.java
index fa6783f..9350ae1 100644
--- 
a/core/src/test/java/org/apache/servicecomb/core/exception/ExceptionsTest.java
+++ 
b/core/src/test/java/org/apache/servicecomb/core/exception/ExceptionsTest.java
@@ -21,6 +21,15 @@ import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
 import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
 import static org.assertj.core.api.Assertions.assertThat;
 
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+import javax.ws.rs.core.Response.StatusType;
+
+import org.apache.servicecomb.core.Invocation;
+import 
org.apache.servicecomb.foundation.test.scaffolding.exception.RuntimeExceptionWithoutStackTrace;
+import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector;
 import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData;
 import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
 import org.junit.jupiter.api.Test;
@@ -61,4 +70,35 @@ class ExceptionsTest {
     assertThat(Json.encode(invocationException.getErrorData()))
         .isEqualTo("{\"code\":\"SCB.50000000\",\"message\":\"msg\"}");
   }
+
+  static class ThrowExceptionWhenConvert implements 
ExceptionConverter<Throwable> {
+    @Override
+    public boolean canConvert(Throwable throwable) {
+      return true;
+    }
+
+    @Override
+    public InvocationException convert(@Nullable Invocation invocation, 
Throwable throwable, StatusType genericStatus) {
+      throw new RuntimeExceptionWithoutStackTrace("mock exception when 
convert");
+    }
+  }
+
+  @Test
+  void should_protect_when_converter_throw_exception() {
+    try (LogCollector logCollector = new LogCollector()) {
+      Map<Class<?>, ExceptionConverter<Throwable>> cache = new HashMap<>();
+      cache.put(RuntimeExceptionWithoutStackTrace.class, new 
ThrowExceptionWhenConvert());
+      InvocationException exception = Exceptions
+          .convert(null, new RuntimeExceptionWithoutStackTrace("exception need 
convert"), BAD_REQUEST, cache);
+
+      assertThat(exception.getStatus())
+          .isSameAs(INTERNAL_SERVER_ERROR);
+      assertThat(exception.getErrorData().toString())
+          .isEqualTo("CommonExceptionData{code='SCB.50000000', 
message='Internal Server Error', dynamic={}}");
+      
assertThat(logCollector.getLastEvents().getRenderedMessage().replace("\r\n", 
"\n"))
+          .isEqualTo("BUG: ExceptionConverter.convert MUST not throw 
exception, please fix it.\n"
+              + "original 
exception:org.apache.servicecomb.foundation.test.scaffolding.exception.RuntimeExceptionWithoutStackTrace:
 exception need convert\n"
+              + "converter 
exception:org.apache.servicecomb.foundation.test.scaffolding.exception.RuntimeExceptionWithoutStackTrace:
 mock exception when convert\n");
+    }
+  }
 }
\ No newline at end of file
diff --git 
a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/ReflectUtils.java
 
b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/ReflectUtils.java
index 9730eda..1b4d3f1 100644
--- 
a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/ReflectUtils.java
+++ 
b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/ReflectUtils.java
@@ -21,7 +21,6 @@ import java.lang.reflect.Array;
 import java.lang.reflect.Field;
 import java.lang.reflect.GenericArrayType;
 import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 
@@ -31,13 +30,6 @@ import org.springframework.util.ReflectionUtils;
 import com.google.common.reflect.TypeToken;
 
 public final class ReflectUtils {
-  private static final Field MODIFIERS_FIELD =
-      ReflectionUtils.findField(Field.class, "modifiers");
-
-  static {
-    MODIFIERS_FIELD.setAccessible(true);
-  }
-
   private ReflectUtils() {
 
   }
@@ -49,9 +41,6 @@ public final class ReflectUtils {
   public static void setField(Class<?> cls, Object instance, String fieldName, 
Object value) {
     Field field = ReflectionUtils.findField(cls, fieldName);
     try {
-      if ((field.getModifiers() & Modifier.FINAL) != 0) {
-        MODIFIERS_FIELD.setInt(field, field.getModifiers() & ~Modifier.FINAL);
-      }
       field.setAccessible(true);
       field.set(instance, value);
     } catch (Exception e) {
diff --git 
a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/OsMetersInitializer.java
 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/OsMetersInitializer.java
index 783d0cc..88f0139 100644
--- 
a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/OsMetersInitializer.java
+++ 
b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/OsMetersInitializer.java
@@ -24,6 +24,7 @@ import org.apache.servicecomb.metrics.core.meter.os.OsMeter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.eventbus.EventBus;
 import com.netflix.spectator.api.Registry;
 import com.netflix.spectator.api.SpectatorUtils;
@@ -33,9 +34,17 @@ public class OsMetersInitializer implements 
MetricsInitializer {
 
   private OsMeter osMeter;
 
+  private boolean isOsLinux = SystemUtils.IS_OS_LINUX;
+
+  @VisibleForTesting
+  OsMetersInitializer setOsLinux(boolean osLinux) {
+    isOsLinux = osLinux;
+    return this;
+  }
+
   @Override
   public void init(GlobalRegistry globalRegistry, EventBus eventBus, 
MetricsBootstrapConfig config) {
-    if (!SystemUtils.IS_OS_LINUX) {
+    if (!isOsLinux) {
       LOGGER.info("only support linux os to collect cpu and net info");
       return;
     }
diff --git 
a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java
 
b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java
index 2514934..440176a 100644
--- 
a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java
+++ 
b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java
@@ -25,17 +25,13 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang3.SystemUtils;
-import org.apache.servicecomb.foundation.common.utils.ReflectUtils;
 import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.metrics.core.meter.os.CpuMeter;
 import org.apache.servicecomb.metrics.core.meter.os.NetMeter;
 import org.apache.servicecomb.metrics.core.meter.os.OsMeter;
 import org.apache.servicecomb.metrics.core.meter.os.cpu.CpuUtils;
 import org.apache.servicecomb.metrics.core.meter.os.net.InterfaceUsage;
-import org.junit.After;
 import org.junit.Assert;
-import org.junit.Before;
 import org.junit.Test;
 
 import com.google.common.eventbus.EventBus;
@@ -54,19 +50,11 @@ public class TestOsMeterInitializer {
 
   Registry registry = new DefaultRegistry(globalRegistry.getClock());
 
-  private boolean isLinux;
-
   @Mocked
   EventBus eventBus;
 
-  @Before
-  public void beforeTest() {
-    isLinux = SystemUtils.IS_OS_LINUX;
-  }
-
   @Test
   public void init(@Mocked Runtime runtime, @Mocked RuntimeMXBean mxBean) {
-    ReflectUtils.setField(SystemUtils.class, null, "IS_OS_LINUX", true);
     List<String> list = new ArrayList<>();
     list.add("13  1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1");
     list.add("useless");
@@ -111,6 +99,7 @@ public class TestOsMeterInitializer {
     };
     globalRegistry.add(registry);
     OsMetersInitializer osMetersInitializer = new OsMetersInitializer();
+    osMetersInitializer.setOsLinux(true);
     osMetersInitializer.init(globalRegistry, eventBus, null);
     OsMeter osMeter = osMetersInitializer.getOsMeter();
     Assert.assertNotNull(osMeter);
@@ -149,13 +138,8 @@ public class TestOsMeterInitializer {
   @Test
   public void initFail() {
     OsMetersInitializer osMetersInitializer = new OsMetersInitializer();
-    ReflectUtils.setField(SystemUtils.class, null, "IS_OS_LINUX", false);
+    osMetersInitializer.setOsLinux(false);
     osMetersInitializer.init(null, eventBus, null);
     Assert.assertNull(osMetersInitializer.getOsMeter());
   }
-
-  @After
-  public void afterTest() {
-    ReflectUtils.setField(SystemUtils.class, null, "IS_OS_LINUX", isLinux);
-  }
 }
diff --git 
a/transports/transport-highway/src/main/resources/META-INF/services/org.apache.servicecomb.core.filter.FilterProvider
 
b/transports/transport-highway/src/main/resources/META-INF/services/org.apache.servicecomb.core.filter.FilterProvider
deleted file mode 100644
index 950dcb7..0000000
--- 
a/transports/transport-highway/src/main/resources/META-INF/services/org.apache.servicecomb.core.filter.FilterProvider
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# 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.
-#
-
-org.apache.servicecomb.transport.highway.HighwayFilterProvider
\ No newline at end of file

Reply via email to