Skip to content

Commit

Permalink
Merge pull request #19609 from Ladicek/fix-fault-tolerance-buildtime-…
Browse files Browse the repository at this point in the history
…classloading

Fix SmallRye Fault Tolerance build-time class loading
  • Loading branch information
Ladicek authored Aug 24, 2021
2 parents 413a7f0 + e5a688f commit de32b2e
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 134 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.quarkus.deployment.util;

import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -377,55 +376,4 @@ public ClassNotIndexedException(DotName dotName) {
}
}

public static Class<?> loadRawType(Type type) {
switch (type.kind()) {
case VOID:
return void.class;
case PRIMITIVE:
switch (type.asPrimitiveType().primitive()) {
case BOOLEAN:
return boolean.class;
case CHAR:
return char.class;
case BYTE:
return byte.class;
case SHORT:
return short.class;
case INT:
return int.class;
case LONG:
return long.class;
case FLOAT:
return float.class;
case DOUBLE:
return double.class;
default:
throw new IllegalArgumentException("Unknown primitive type: " + type);
}
case CLASS:
return load(type.asClassType().name());
case PARAMETERIZED_TYPE:
return load(type.asParameterizedType().name());
case ARRAY:
Class<?> component = loadRawType(type.asArrayType().component());
int dimensions = type.asArrayType().dimensions();
return Array.newInstance(component, new int[dimensions]).getClass();
case WILDCARD_TYPE:
return loadRawType(type.asWildcardType().extendsBound());
case TYPE_VARIABLE:
return load(type.asTypeVariable().name());
case UNRESOLVED_TYPE_VARIABLE:
return Object.class; // can't do better here
default:
throw new IllegalArgumentException("Unknown type: " + type);
}
}

private static Class<?> load(DotName name) {
try {
return Thread.currentThread().getContextClassLoader().loadClass(name.toString());
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.Index;
import org.jboss.jandex.Indexer;
Expand Down Expand Up @@ -305,72 +302,6 @@ public static class MultiBoundedRepo<X extends A & B> implements Repo<X> {
public static class ErasedRepo2 extends MultiBoundedRepo {
}

@Test
public void testLoadRawType() {
Index index = index(TestMethods.class);
ClassInfo clazz = index.getClassByName(DotName.createSimple(TestMethods.class.getName()));

assertEquals(void.class, JandexUtil.loadRawType(clazz.method("aaa").returnType()));
assertEquals(int.class, JandexUtil.loadRawType(clazz.method("bbb").returnType()));
assertEquals(String.class, JandexUtil.loadRawType(clazz.method("ccc").returnType()));
assertEquals(List.class, JandexUtil.loadRawType(clazz.method("ddd").returnType()));
assertEquals(String[][].class, JandexUtil.loadRawType(clazz.method("eee").returnType()));
assertEquals(Object.class, JandexUtil.loadRawType(clazz.method("fff").returnType()));
assertEquals(Number.class, JandexUtil.loadRawType(clazz.method("ggg").returnType()));
assertEquals(Number.class, JandexUtil.loadRawType(clazz.method("hhh").returnType()));
assertEquals(Comparable.class, JandexUtil.loadRawType(clazz.method("iii").returnType()));
assertEquals(Comparable.class, JandexUtil.loadRawType(clazz.method("jjj").returnType()));
assertEquals(Serializable.class, JandexUtil.loadRawType(clazz.method("kkk").returnType()));
assertEquals(Object.class, JandexUtil.loadRawType(clazz.method("lll").returnType()
.asParameterizedType().arguments().get(0)));
assertEquals(Number.class, JandexUtil.loadRawType(clazz.method("mmm").returnType()
.asParameterizedType().arguments().get(0)));
assertEquals(Object.class, JandexUtil.loadRawType(clazz.method("nnn").returnType()
.asParameterizedType().arguments().get(0)));
assertEquals(Object.class, JandexUtil.loadRawType(clazz.method("ooo").returnType()
.asParameterizedType().arguments().get(0)));
assertEquals(Number.class, JandexUtil.loadRawType(clazz.method("ppp").returnType()
.asParameterizedType().arguments().get(0)));
assertEquals(Object.class, JandexUtil.loadRawType(clazz.method("qqq").returnType()
.asParameterizedType().arguments().get(0)));
}

public interface TestMethods<X> {
void aaa();

int bbb();

String ccc();

List<String> ddd();

String[][] eee();

X fff();

<Y extends Number> Y ggg();

<Y extends Number & Comparable<Y>> Y hhh();

<Y extends Comparable<Y>> Y iii();

<Y extends Comparable<Y> & Serializable> Y jjj();

<Y extends Serializable & Comparable<Y>> Y kkk();

List<?> lll();

List<? extends Number> mmm();

List<? super String> nnn();

List<? extends X> ooo();

<Y extends Number> List<? extends Y> ppp();

<Y extends Number> List<? super Y> qqq();
}

private static Index index(Class<?>... classes) {
Indexer indexer = new Indexer();
for (Class<?> clazz : classes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
<artifactId>quarkus-resteasy-reactive-jackson-deployment</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-fault-tolerance-deployment</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package io.quarkus.rest.client.reactive.ft;

import static io.quarkus.rest.client.reactive.RestClientTestUtil.setUrlForClass;
import static java.util.concurrent.CompletableFuture.completedFuture;
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;

import org.eclipse.microprofile.faulttolerance.Asynchronous;
import org.eclipse.microprofile.faulttolerance.ExecutionContext;
import org.eclipse.microprofile.faulttolerance.Fallback;
import org.eclipse.microprofile.faulttolerance.FallbackHandler;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;

public class AsyncRestClientFallbackTest {
@RegisterExtension
static final QuarkusUnitTest TEST = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(TestEndpoint.class, Client.class, MyFallback.class)
.addAsResource(new StringAsset(setUrlForClass(Client.class)), "application.properties"));

@Inject
@RestClient
Client client;

@Test
public void testFallbackWasUsed() throws ExecutionException, InterruptedException {
assertEquals("pong", client.ping().toCompletableFuture().get());
}

@Path("/test")
public static class TestEndpoint {
@GET
public String get() {
throw new WebApplicationException(404);
}
}

@RegisterRestClient
public interface Client {
@GET
@Path("/test")
@Asynchronous
@Fallback(MyFallback.class)
CompletionStage<String> ping();
}

public static class MyFallback implements FallbackHandler<CompletionStage<String>> {
@Override
public CompletionStage<String> handle(ExecutionContext context) {
return completedFuture("pong");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package io.quarkus.rest.client.reactive.ft;

import static io.quarkus.rest.client.reactive.RestClientTestUtil.setUrlForClass;
import static org.junit.jupiter.api.Assertions.assertEquals;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;

import org.eclipse.microprofile.faulttolerance.ExecutionContext;
import org.eclipse.microprofile.faulttolerance.Fallback;
import org.eclipse.microprofile.faulttolerance.FallbackHandler;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;

public class RestClientFallbackTest {
@RegisterExtension
static final QuarkusUnitTest TEST = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(TestEndpoint.class, Client.class, MyFallback.class)
.addAsResource(new StringAsset(setUrlForClass(Client.class)), "application.properties"));

@Inject
@RestClient
Client client;

@Test
public void testFallbackWasUsed() {
assertEquals("pong", client.ping());
}

@Path("/test")
public static class TestEndpoint {
@GET
public String get() {
throw new WebApplicationException(404);
}
}

@RegisterRestClient
public interface Client {
@GET
@Path("/test")
@Fallback(MyFallback.class)
String ping();
}

public static class MyFallback implements FallbackHandler<String> {
@Override
public String handle(ExecutionContext context) {
return "pong";
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package io.quarkus.rest.client.reactive.ft;

import static io.quarkus.rest.client.reactive.RestClientTestUtil.setUrlForClass;
import static org.junit.jupiter.api.Assertions.assertEquals;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;

import org.eclipse.microprofile.faulttolerance.ExecutionContext;
import org.eclipse.microprofile.faulttolerance.Fallback;
import org.eclipse.microprofile.faulttolerance.FallbackHandler;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.smallrye.mutiny.Uni;

public class UniRestClientFallbackTest {
@RegisterExtension
static final QuarkusUnitTest TEST = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(TestEndpoint.class, Client.class, MyFallback.class)
.addAsResource(new StringAsset(setUrlForClass(Client.class)), "application.properties"));

@Inject
@RestClient
Client client;

@Test
public void testFallbackWasUsed() {
assertEquals("pong", client.ping().await().indefinitely());
}

@Path("/test")
public static class TestEndpoint {
@GET
public String get() {
throw new WebApplicationException(404);
}
}

@RegisterRestClient
public interface Client {
@GET
@Path("/test")
@Fallback(MyFallback.class)
Uni<String> ping();
}

public static class MyFallback implements FallbackHandler<Uni<String>> {
@Override
public Uni<String> handle(ExecutionContext context) {
return Uni.createFrom().item("pong");
}
}
}
Loading

0 comments on commit de32b2e

Please sign in to comment.