Skip to content

Commit

Permalink
Merge pull request #255 from hamburml/feature/AddDynamoDbEnhancedClient
Browse files Browse the repository at this point in the history
Add DynamoDB Enhanced Client for DynamoDB Annotations
  • Loading branch information
gsmet committed Sep 23, 2022
2 parents 1b8ed05 + 9a8ac37 commit 5a06043
Show file tree
Hide file tree
Showing 24 changed files with 4,898 additions and 473 deletions.
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>
</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>

0 comments on commit 5a06043

Please sign in to comment.