mirror of https://github.com/apache/kafka.git
				
				
				
			MINOR: Catch InvocationTargetException explicitly and propagate underlying cause (#12230)
Catch InvocationTargetException explicitly and propagate underlying cause Reviewers: Ismael Juma <mlists@juma.me.uk>, Matthew de Detrich <mdedetrich@gmail.com>, Kvicii, Luke Chen <showuon@gmail.com>
This commit is contained in:
		
							parent
							
								
									add4ca6c7f
								
							
						
					
					
						commit
						9aef992118
					
				| 
						 | 
				
			
			@ -21,6 +21,7 @@ import org.slf4j.LoggerFactory;
 | 
			
		|||
 | 
			
		||||
import java.lang.reflect.Constructor;
 | 
			
		||||
import java.lang.reflect.InvocationHandler;
 | 
			
		||||
import java.lang.reflect.InvocationTargetException;
 | 
			
		||||
import java.lang.reflect.Method;
 | 
			
		||||
import java.lang.reflect.Proxy;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
| 
						 | 
				
			
			@ -75,8 +76,12 @@ public class LoggingSignalHandler {
 | 
			
		|||
    private Object createSignalHandler(final Map<String, Object> jvmSignalHandlers) {
 | 
			
		||||
        InvocationHandler invocationHandler = new InvocationHandler() {
 | 
			
		||||
 | 
			
		||||
            private String getName(Object signal) throws ReflectiveOperationException {
 | 
			
		||||
                return (String) signalGetNameMethod.invoke(signal);
 | 
			
		||||
            private String getName(Object signal) throws Throwable {
 | 
			
		||||
                try {
 | 
			
		||||
                    return (String) signalGetNameMethod.invoke(signal);
 | 
			
		||||
                } catch (InvocationTargetException e) {
 | 
			
		||||
                    throw e.getCause();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private void handle(Object signalHandler, Object signal) throws ReflectiveOperationException {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -463,8 +463,7 @@ public final class Utils {
 | 
			
		|||
            throw new ClassNotFoundException(String.format("Unable to access " +
 | 
			
		||||
                "constructor of %s", className), e);
 | 
			
		||||
        } catch (InvocationTargetException e) {
 | 
			
		||||
            throw new ClassNotFoundException(String.format("Unable to invoke " +
 | 
			
		||||
                "constructor of %s", className), e);
 | 
			
		||||
            throw new KafkaException(String.format("The constructor of %s threw an exception", className), e.getCause());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -122,6 +122,14 @@ public class KafkaFutureTest {
 | 
			
		|||
        assertEquals(CancellationException.class, cancellationException.getClass());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Object invokeOrThrow(final Method method, final Object obj, final Object... args) throws Throwable {
 | 
			
		||||
        try {
 | 
			
		||||
            return method.invoke(obj, args);
 | 
			
		||||
        } catch (InvocationTargetException e) {
 | 
			
		||||
            throw e.getCause();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testCompleteFutures() throws Exception {
 | 
			
		||||
        KafkaFutureImpl<Integer> future123 = new KafkaFutureImpl<>();
 | 
			
		||||
| 
						 | 
				
			
			@ -591,7 +599,7 @@ public class KafkaFutureTest {
 | 
			
		|||
 | 
			
		||||
    @Test
 | 
			
		||||
    @SuppressWarnings("unchecked")
 | 
			
		||||
    public void testLeakCompletableFuture() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
 | 
			
		||||
    public void testLeakCompletableFuture() throws Throwable {
 | 
			
		||||
        final KafkaFutureImpl<String> kfut = new KafkaFutureImpl<>();
 | 
			
		||||
        CompletableFuture<String> comfut = kfut.toCompletionStage().toCompletableFuture();
 | 
			
		||||
        assertThrows(UnsupportedOperationException.class, () -> comfut.complete(""));
 | 
			
		||||
| 
						 | 
				
			
			@ -600,44 +608,20 @@ public class KafkaFutureTest {
 | 
			
		|||
        // so test reflectively
 | 
			
		||||
        if (Java.IS_JAVA9_COMPATIBLE) {
 | 
			
		||||
            Method completeOnTimeout = CompletableFuture.class.getDeclaredMethod("completeOnTimeout", Object.class, Long.TYPE, TimeUnit.class);
 | 
			
		||||
            assertThrows(UnsupportedOperationException.class, () -> {
 | 
			
		||||
                try {
 | 
			
		||||
                    completeOnTimeout.invoke(comfut, "", 1L, TimeUnit.MILLISECONDS);
 | 
			
		||||
                } catch (InvocationTargetException e) {
 | 
			
		||||
                    throw e.getCause();
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            assertThrows(UnsupportedOperationException.class, () -> invokeOrThrow(completeOnTimeout, comfut, "", 1L, TimeUnit.MILLISECONDS));
 | 
			
		||||
 | 
			
		||||
            Method completeAsync = CompletableFuture.class.getDeclaredMethod("completeAsync", Supplier.class);
 | 
			
		||||
            assertThrows(UnsupportedOperationException.class, () -> {
 | 
			
		||||
                try {
 | 
			
		||||
                    completeAsync.invoke(comfut, (Supplier<String>) () -> "");
 | 
			
		||||
                } catch (InvocationTargetException e) {
 | 
			
		||||
                    throw e.getCause();
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            assertThrows(UnsupportedOperationException.class, () -> invokeOrThrow(completeAsync, comfut, (Supplier<String>) () -> ""));
 | 
			
		||||
 | 
			
		||||
            Method obtrudeValue = CompletableFuture.class.getDeclaredMethod("obtrudeValue", Object.class);
 | 
			
		||||
            assertThrows(UnsupportedOperationException.class, () -> {
 | 
			
		||||
                try {
 | 
			
		||||
                    obtrudeValue.invoke(comfut, "");
 | 
			
		||||
                } catch (InvocationTargetException e) {
 | 
			
		||||
                    throw e.getCause();
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            assertThrows(UnsupportedOperationException.class, () -> invokeOrThrow(obtrudeValue, comfut, ""));
 | 
			
		||||
 | 
			
		||||
            Method obtrudeException = CompletableFuture.class.getDeclaredMethod("obtrudeException", Throwable.class);
 | 
			
		||||
            assertThrows(UnsupportedOperationException.class, () -> {
 | 
			
		||||
                try {
 | 
			
		||||
                    obtrudeException.invoke(comfut, new RuntimeException());
 | 
			
		||||
                } catch (InvocationTargetException e) {
 | 
			
		||||
                    throw e.getCause();
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            assertThrows(UnsupportedOperationException.class, () -> invokeOrThrow(obtrudeException, comfut, new RuntimeException()));
 | 
			
		||||
 | 
			
		||||
            // Check the CF from a minimal CompletionStage doesn't cause completion of the original KafkaFuture
 | 
			
		||||
            Method minimal = CompletableFuture.class.getDeclaredMethod("minimalCompletionStage");
 | 
			
		||||
            CompletionStage<String> cs = (CompletionStage<String>) minimal.invoke(comfut);
 | 
			
		||||
            CompletionStage<String> cs = (CompletionStage<String>) invokeOrThrow(minimal, comfut);
 | 
			
		||||
            cs.toCompletableFuture().complete("");
 | 
			
		||||
 | 
			
		||||
            assertFalse(kfut.isDone());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,7 +78,7 @@ public class RecordTestUtils {
 | 
			
		|||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } catch (InvocationTargetException e) {
 | 
			
		||||
                throw new RuntimeException(e);
 | 
			
		||||
                throw new RuntimeException(e.getCause());
 | 
			
		||||
            } catch (IllegalAccessException e) {
 | 
			
		||||
                throw new RuntimeException(e);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue