#7152 Classes with @ConstructorProperties for Reflection

This commit is contained in:
Johannes
2020-02-13 18:48:47 +01:00
parent 6d5eeea9da
commit 3236502ca8
4 changed files with 180 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
package io.quarkus.deployment;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.DotName;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.MethodInfo;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
/**
* Registers all classes for reflection,
* that contain a constructor annotated with <code>@java.beans.ConstructorProperties</code>.
*/
public class ConstructorPropertiesProcessor {
private static final DotName CONSTRUCTOR_PROPERTIES = DotName.createSimple("java.beans.ConstructorProperties");
@BuildStep
void build(BuildProducer<ReflectiveClassBuildItem> reflectiveClass, CombinedIndexBuildItem indexBuildItem) {
IndexView index = indexBuildItem.getIndex();
for (AnnotationInstance annotationInstance : index.getAnnotations(CONSTRUCTOR_PROPERTIES)) {
registerInstance(reflectiveClass, annotationInstance);
}
}
private void registerInstance(BuildProducer<ReflectiveClassBuildItem> reflectiveClass, AnnotationInstance instance) {
AnnotationTarget annotationTarget = instance.target();
if (annotationTarget instanceof MethodInfo) {
MethodInfo methodInfo = (MethodInfo) annotationTarget;
String classname = methodInfo.declaringClass().toString();
reflectiveClass.produce(asReflectiveClassBuildItem(classname));
}
}
private ReflectiveClassBuildItem asReflectiveClassBuildItem(String annotatedClass) {
return new ReflectiveClassBuildItem(true, false, annotatedClass);
}
}

View File

@@ -0,0 +1,86 @@
package io.quarkus.it.rest;
import java.beans.ConstructorProperties;
import javax.json.bind.JsonbBuilder;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.sse.OutboundSseEvent;
import javax.ws.rs.sse.Sse;
import javax.ws.rs.sse.SseEventSink;
@Path("/constructorproperties")
public class TestResourceForConstructorProperties {
@Context
Sse sse;
@GET
@Path("/direct")
@Produces(MediaType.APPLICATION_JSON)
public VanillaJavaImmutableData direct() {
return new VanillaJavaImmutableData("direct", "directvalue");
}
@GET
@Path("/jsonb")
@Produces(MediaType.APPLICATION_JSON)
public String jsonb() {
VanillaJavaImmutableData entity = new VanillaJavaImmutableData("jsonb", "jsonbvalue");
return JsonbBuilder.create().toJson(entity);
}
@GET
@Path("/response")
@Produces(MediaType.APPLICATION_JSON)
public Response response() {
VanillaJavaImmutableData entity = new VanillaJavaImmutableData("response", "responsevalue");
return Response.ok(entity).build();
}
@GET
@Path("/sse")
@Produces(MediaType.SERVER_SENT_EVENTS + ";element-type=" + MediaType.APPLICATION_JSON)
public void serverSentEvents(@Context SseEventSink sink) {
VanillaJavaImmutableData data = new VanillaJavaImmutableData("sse", "ssevalue");
try {
OutboundSseEvent.Builder builder = sse.newEventBuilder();
builder.id(String.valueOf(1))
.mediaType(MediaType.APPLICATION_JSON_TYPE)
.data(data)
.name("stream of json data");
sink.send(builder.build());
} finally {
sink.close();
}
}
public static class VanillaJavaImmutableData {
private final String name;
private final String value;
@ConstructorProperties({ "name", "value" })
public VanillaJavaImmutableData(String name, String value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
@Override
public String toString() {
return "ConstructorPropertiesAnnotatedImmutableData [name=" + name + ", value=" + value + "]";
}
}
}

View File

@@ -0,0 +1,8 @@
package io.quarkus.it.main;
import io.quarkus.test.junit.NativeImageTest;
@NativeImageTest
public class JaxRsConstructorPropertiesITCase extends JaxRsConstructorPropertiesTestCase {
}

View File

@@ -0,0 +1,44 @@
package io.quarkus.it.main;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.RestAssured;
import io.restassured.specification.RequestSender;
@QuarkusTest
public class JaxRsConstructorPropertiesTestCase {
@Test
public void testReturnedDirectly() {
when().get("/constructorproperties/direct").then()
.body("name", is("direct"),
"value", is("directvalue"));
}
@Test
public void testConvertedWithJsonbAndReturnedAsString() {
when().get("/constructorproperties/jsonb").then()
.body("name", is("jsonb"),
"value", is("jsonbvalue"));
}
@Test
public void testWrappedInResponse() {
when().get("/constructorproperties/response").then()
.body("name", is("response"),
"value", is("responsevalue"));
}
@Test
public void testWrappedInServerSentEventMessage() {
when().get("/constructorproperties/sse").then().body(containsString("ssevalue"));
}
private static RequestSender when() {
return RestAssured.when();
}
}