Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DynamoDB Enhanced Client for DynamoDB Annotations #255

Merged
merged 1 commit into from
Sep 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@
<artifactId>quarkus-amazon-dynamodb-deployment</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkiverse.amazonservices</groupId>
<artifactId>quarkus-amazon-dynamodb-enhanced</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkiverse.amazonservices</groupId>
<artifactId>quarkus-amazon-dynamodb-enhanced-deployment</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkiverse.amazonservices</groupId>
<artifactId>quarkus-amazon-devservices-iam</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion docs/modules/ROOT/pages/includes/attributes.adoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
:quarkus-version: 2.12.2.Final
:quarkus-version: 2.13.0.Final
:quarkus-amazon-services-version: 1.2.0
:maven-version: 3.8.1+

Expand Down
464 changes: 417 additions & 47 deletions docs/modules/ROOT/pages/includes/quarkus-amazon-cognitouserpools.adoc

Large diffs are not rendered by default.

469 changes: 422 additions & 47 deletions docs/modules/ROOT/pages/includes/quarkus-amazon-dynamodb.adoc

Large diffs are not rendered by default.

464 changes: 417 additions & 47 deletions docs/modules/ROOT/pages/includes/quarkus-amazon-iam.adoc

Large diffs are not rendered by default.

464 changes: 417 additions & 47 deletions docs/modules/ROOT/pages/includes/quarkus-amazon-kms.adoc

Large diffs are not rendered by default.

508 changes: 459 additions & 49 deletions docs/modules/ROOT/pages/includes/quarkus-amazon-s3.adoc

Large diffs are not rendered by default.

464 changes: 417 additions & 47 deletions docs/modules/ROOT/pages/includes/quarkus-amazon-secretsmanager.adoc

Large diffs are not rendered by default.

464 changes: 417 additions & 47 deletions docs/modules/ROOT/pages/includes/quarkus-amazon-ses.adoc

Large diffs are not rendered by default.

464 changes: 417 additions & 47 deletions docs/modules/ROOT/pages/includes/quarkus-amazon-sns.adoc

Large diffs are not rendered by default.

464 changes: 417 additions & 47 deletions docs/modules/ROOT/pages/includes/quarkus-amazon-sqs.adoc

Large diffs are not rendered by default.

464 changes: 417 additions & 47 deletions docs/modules/ROOT/pages/includes/quarkus-amazon-ssm.adoc

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions dynamodb-enhanced/deployment/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>io.quarkiverse.amazonservices</groupId>
<artifactId>quarkus-amazon-dynamodb-enhanced-parent</artifactId>
<version>999-SNAPSHOT</version>
</parent>

<artifactId>quarkus-amazon-dynamodb-enhanced-deployment</artifactId>
<name>Quarkus - Amazon Services - DynamoDB Enhanced - Deployment</name>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-netty-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkiverse.amazonservices</groupId>
<artifactId>quarkus-amazon-dynamodb-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkiverse.amazonservices</groupId>
<artifactId>quarkus-amazon-dynamodb-enhanced</artifactId>
</dependency>
<dependency>
<groupId>io.quarkiverse.amazonservices</groupId>
<artifactId>quarkus-amazon-common-deployment</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
package io.quarkus.amazon.dynamodb.enhanced.deployment;

import java.util.function.BiFunction;
import java.util.function.Consumer;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import io.quarkus.amazon.dynamodb.enhanced.runtime.BeanTableSchemaSubstitutionImplementation;
import io.quarkus.amazon.dynamodb.enhanced.runtime.DynamodbEnhancedClientProducer;
import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.BytecodeTransformerBuildItem;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.pkg.steps.NativeBuild;
import io.quarkus.gizmo.Gizmo;
import software.amazon.awssdk.enhanced.dynamodb.DefaultAttributeConverterProvider;
import software.amazon.awssdk.enhanced.dynamodb.internal.mapper.BeanTableSchemaAttributeTags;
import software.amazon.awssdk.enhanced.dynamodb.mapper.BeanTableSchema;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;

public class DynamodbEnhancedProcessor {
private static final String FEATURE = "amazon-dynamodb-enhanced";

@BuildStep
FeatureBuildItem feature() {
return new FeatureBuildItem(FEATURE);
}

@BuildStep
AdditionalBeanBuildItem producer() {
return AdditionalBeanBuildItem.unremovableOf(DynamodbEnhancedClientProducer.class);
}

@BuildStep(onlyIf = NativeBuild.class)
public void registerClassesForReflectiveAccess(
CombinedIndexBuildItem combinedIndexBuildItem,
BuildProducer<ReflectiveClassBuildItem> reflectiveClass) {

//Discover all DynamoDbBean annotated classes and register them
for (AnnotationInstance i : combinedIndexBuildItem
.getIndex()
.getAnnotations(DotName.createSimple(DynamoDbBean.class.getName()))) {
ClassInfo classInfo = i.target().asClass();
reflectiveClass.produce(
new ReflectiveClassBuildItem(true, false, classInfo.name().toString()));
}

// Register classes which are used by BeanTableSchema but are not found by the classloader
reflectiveClass.produce(
new ReflectiveClassBuildItem(true, false, DefaultAttributeConverterProvider.class.getName()));
reflectiveClass.produce(
new ReflectiveClassBuildItem(true, false, BeanTableSchemaAttributeTags.class.getName()));

}

@BuildStep
private void applyClassTransformation(BuildProducer<BytecodeTransformerBuildItem> transformers) {
// We rewrite the bytecode to avoid native-image issues (runtime generated lambdas not supported)
// and class loader issues (that are only problematic in test and dev mode).
transformers.produce(
new BytecodeTransformerBuildItem(
BeanTableSchema.class.getName(), new MethodCallRedirectionVisitor()));
}

private static class MethodCallRedirectionVisitor
implements BiFunction<String, ClassVisitor, ClassVisitor> {

public static final String TARGET_METHOD_OWNER = BeanTableSchemaSubstitutionImplementation.class.getName().replace('.',
'/');

@Override
public ClassVisitor apply(String className, ClassVisitor outputClassVisitor) {
return new ClassVisitor(Gizmo.ASM_API_VERSION, outputClassVisitor) {

@Override
public MethodVisitor visitMethod(
int access, String name, String descriptor, String signature, String[] exceptions) {
// https://stackoverflow.com/questions/45180625/how-to-remove-method-body-at-runtime-with-asm-5-2
MethodVisitor originalMethodVisitor = super.visitMethod(access, name, descriptor, signature, exceptions);
if (name.equals("newObjectSupplierForClass")) {
return new ReplaceMethodBody(
originalMethodVisitor,
getMaxLocals(descriptor),
visitor -> {
visitor.visitCode();
visitor.visitVarInsn(Opcodes.ALOAD, 0);
Type type = Type.getType(descriptor);
visitor.visitMethodInsn(
Opcodes.INVOKESTATIC, TARGET_METHOD_OWNER, name, type.getDescriptor(), false);
visitor.visitInsn(Opcodes.ARETURN);
});
} else if (name.equals("getterForProperty")) {
return new ReplaceMethodBody(
originalMethodVisitor,
getMaxLocals(descriptor),
visitor -> {
visitor.visitCode();
visitor.visitVarInsn(Opcodes.ALOAD, 0);
visitor.visitVarInsn(Opcodes.ALOAD, 1);
Type type = Type.getType(descriptor);
visitor.visitMethodInsn(
Opcodes.INVOKESTATIC, TARGET_METHOD_OWNER, name, type.getDescriptor(), false);
visitor.visitInsn(Opcodes.ARETURN);
});
} else if (name.equals("setterForProperty")) {
return new ReplaceMethodBody(
originalMethodVisitor,
getMaxLocals(descriptor),
visitor -> {
visitor.visitCode();
visitor.visitVarInsn(Opcodes.ALOAD, 0);
visitor.visitVarInsn(Opcodes.ALOAD, 1);
Type type = Type.getType(descriptor);
visitor.visitMethodInsn(
Opcodes.INVOKESTATIC, TARGET_METHOD_OWNER, name, type.getDescriptor(), false);
visitor.visitInsn(Opcodes.ARETURN);
});
} else {
return originalMethodVisitor;
}
}

private int getMaxLocals(String descriptor) {
return (Type.getArgumentsAndReturnSizes(descriptor) >> 2) - 1;
}
};
}
}

private static class ReplaceMethodBody extends MethodVisitor {
private final MethodVisitor targetWriter;
private final int newMaxLocals;
private final Consumer<MethodVisitor> code;

public ReplaceMethodBody(
MethodVisitor writer, int newMaxL, Consumer<MethodVisitor> methodCode) {
super(Opcodes.ASM5);
this.targetWriter = writer;
this.newMaxLocals = newMaxL;
this.code = methodCode;
}

@Override
public void visitMaxs(int maxStack, int maxLocals) {
targetWriter.visitMaxs(0, newMaxLocals);
}

@Override
public void visitCode() {
code.accept(targetWriter);
}

@Override
public void visitEnd() {
targetWriter.visitEnd();
}

@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
return targetWriter.visitAnnotation(desc, visible);
}

@Override
public void visitParameter(String name, int access) {
targetWriter.visitParameter(name, access);
}
}
}
21 changes: 21 additions & 0 deletions dynamodb-enhanced/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>io.quarkiverse.amazonservices</groupId>
<artifactId>quarkus-amazon-services-build-parent</artifactId>
<version>999-SNAPSHOT</version>
<relativePath>../build-parent/pom.xml</relativePath>
</parent>

<artifactId>quarkus-amazon-dynamodb-enhanced-parent</artifactId>
<name>Quarkus - Amazon Services - DynamoDB Enhanced</name>
<packaging>pom</packaging>

<modules>
<module>runtime</module>
<module>deployment</module>
</modules>

</project>
71 changes: 71 additions & 0 deletions dynamodb-enhanced/runtime/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>io.quarkiverse.amazonservices</groupId>
<artifactId>quarkus-amazon-dynamodb-enhanced-parent</artifactId>
<version>999-SNAPSHOT</version>
</parent>

<artifactId>quarkus-amazon-dynamodb-enhanced</artifactId>
<name>Quarkus - Amazon Services - DynamoDB Enhanced - Runtime</name>
<description>Connect to Amazon DynamoDB datastore</description>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-netty</artifactId>
</dependency>
<dependency>
<groupId>io.quarkiverse.amazonservices</groupId>
<artifactId>quarkus-amazon-common</artifactId>
</dependency>
<dependency>
<groupId>io.quarkiverse.amazonservices</groupId>
<artifactId>quarkus-amazon-dynamodb</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>dynamodb-enhanced</artifactId>
hamburml marked this conversation as resolved.
Show resolved Hide resolved
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>commons-logging-jboss-logging</artifactId>
</dependency>
<dependency>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>svm</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bootstrap-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>