From 39c42a3c1c6291a6b30a22125cd704d7e4f70cd8 Mon Sep 17 00:00:00 2001 From: Matthias Kay Date: Thu, 9 Jun 2022 09:57:37 +0200 Subject: [PATCH] feat: add annotation for SQS producer (#36) --- README.md | 9 ++++ .../annotation/VisualizeSqsProducer.java | 24 ++++++++++ .../annotation/VisualizeSqsProducers.java | 18 +++++++ .../AbstractCommunicationModelVisitor.java | 1 + .../analyzer/model/CommunicationModel.java | 17 +++++-- .../analyzer/model/EndpointFactory.java | 4 ++ .../commvis/analyzer/model/SqsProducer.java | 48 +++++++++++++++++++ .../model/CommunicationModelTest.java | 7 ++- .../analyzer/model/EndpointFactoryTest.java | 10 ++++ .../analyzer/model/HttpConsumerTest.java | 4 +- .../analyzer/model/HttpProducerTest.java | 4 +- .../analyzer/model/JmsReceiverTest.java | 4 +- .../analyzer/model/SqsConsumerTest.java | 2 +- .../analyzer/model/SqsProducerTest.java | 21 ++++++++ 14 files changed, 161 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/hlag/tools/commvis/analyzer/annotation/VisualizeSqsProducer.java create mode 100644 src/main/java/com/hlag/tools/commvis/analyzer/annotation/VisualizeSqsProducers.java create mode 100644 src/main/java/com/hlag/tools/commvis/analyzer/model/SqsProducer.java create mode 100644 src/test/java/com/hlag/tools/commvis/analyzer/model/SqsProducerTest.java diff --git a/README.md b/README.md index a7fcf24..227d807 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,15 @@ This project contains some API classes to allow users to define their own scanners. This way the [Distributed Communication Visualizer](https://github.com/Hapag-Lloyd/dist-comm-vis) can be extended. +# Maven Dependency +``` + + com.hlag.tools.commvis + api + 2.5.5 + provided + +``` ## Writing A User-Defined Scanner Before writing your own/private scanner: If you are solving a general use cases, please think about contributing to https://github.com/Hapag-Lloyd/dist-comm-vis to help the community. Thanks! diff --git a/src/main/java/com/hlag/tools/commvis/analyzer/annotation/VisualizeSqsProducer.java b/src/main/java/com/hlag/tools/commvis/analyzer/annotation/VisualizeSqsProducer.java new file mode 100644 index 0000000..3d7eeff --- /dev/null +++ b/src/main/java/com/hlag/tools/commvis/analyzer/annotation/VisualizeSqsProducer.java @@ -0,0 +1,24 @@ +package com.hlag.tools.commvis.analyzer.annotation; + +import com.google.gson.annotations.SerializedName; +import com.hlag.tools.commvis.analyzer.model.AbstractCommunicationModelVisitor; + +/** + * Marks a producer for AWS SQS messages. + */ +public @interface VisualizeSqsProducer { + /** + * @return name of the SQS queue messages are sent to + */ + String queueName(); + + /** + * @return the id of the project called, usually the Gitlab project id or similar + */ + String projectId(); + + /** + * @return the name of the project called. Just for a better visibility in the code. The value isn't used. + */ + String projectName() default ""; +} diff --git a/src/main/java/com/hlag/tools/commvis/analyzer/annotation/VisualizeSqsProducers.java b/src/main/java/com/hlag/tools/commvis/analyzer/annotation/VisualizeSqsProducers.java new file mode 100644 index 0000000..58af298 --- /dev/null +++ b/src/main/java/com/hlag/tools/commvis/analyzer/annotation/VisualizeSqsProducers.java @@ -0,0 +1,18 @@ +package com.hlag.tools.commvis.analyzer.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Used to group multiple {@link VisualizeSqsProducer} annotations on one element. + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface VisualizeSqsProducers { + /** + * @return all grouped {@link VisualizeSqsProducer} annotations + */ + VisualizeSqsProducer[] value(); +} diff --git a/src/main/java/com/hlag/tools/commvis/analyzer/model/AbstractCommunicationModelVisitor.java b/src/main/java/com/hlag/tools/commvis/analyzer/model/AbstractCommunicationModelVisitor.java index 65e28f8..e50fcbc 100644 --- a/src/main/java/com/hlag/tools/commvis/analyzer/model/AbstractCommunicationModelVisitor.java +++ b/src/main/java/com/hlag/tools/commvis/analyzer/model/AbstractCommunicationModelVisitor.java @@ -12,4 +12,5 @@ public abstract class AbstractCommunicationModelVisitor { public abstract void visit(JmsReceiver jmsReceiver); public abstract void visit(SqsConsumer sqsConsumer); + public abstract void visit(SqsProducer sqsProducer); } \ No newline at end of file diff --git a/src/main/java/com/hlag/tools/commvis/analyzer/model/CommunicationModel.java b/src/main/java/com/hlag/tools/commvis/analyzer/model/CommunicationModel.java index 49cdb95..0fd44db 100644 --- a/src/main/java/com/hlag/tools/commvis/analyzer/model/CommunicationModel.java +++ b/src/main/java/com/hlag/tools/commvis/analyzer/model/CommunicationModel.java @@ -17,6 +17,8 @@ @RequiredArgsConstructor @ToString public class CommunicationModel { + private static final String NOT_SET = "not-set"; + /** * Identifier for the current project, e.g. gitlab project id */ @@ -58,11 +60,17 @@ public class CommunicationModel { @SerializedName(value = "sqs_consumers") private Collection sqsConsumers = new HashSet<>(); + /** + * All SQS producers. + */ + @SerializedName(value = "sqs_producers") + private Collection sqsProducers = new HashSet<>(); + private CommunicationModel() { // for GSON deserialize - projectId = "not-set"; - projectName = "not-set"; - modelVersion = "not-set"; + projectId = NOT_SET; + projectName = NOT_SET; + modelVersion = NOT_SET; } public void addSenderReceiver(T endpoint) { @@ -74,6 +82,8 @@ public void addSenderReceiver(T endpoin jmsConsumers.add((JmsReceiver) endpoint); } else if (endpoint instanceof SqsConsumer) { sqsConsumers.add((SqsConsumer) endpoint); + } else if (endpoint instanceof SqsProducer) { + sqsProducers.add((SqsProducer) endpoint); } else { throw new IllegalStateException(String.format("We have no endpoints of type %s", endpoint.getClass().getCanonicalName())); } @@ -86,5 +96,6 @@ public void visit(AbstractCommunicationModelVisitor visitor) { httpProducers.forEach(e -> e.visit(visitor)); jmsConsumers.forEach(e -> e.visit(visitor)); sqsConsumers.forEach(e -> e.visit(visitor)); + sqsProducers.forEach(e -> e.visit(visitor)); } } diff --git a/src/main/java/com/hlag/tools/commvis/analyzer/model/EndpointFactory.java b/src/main/java/com/hlag/tools/commvis/analyzer/model/EndpointFactory.java index 5f57d41..c97aabb 100644 --- a/src/main/java/com/hlag/tools/commvis/analyzer/model/EndpointFactory.java +++ b/src/main/java/com/hlag/tools/commvis/analyzer/model/EndpointFactory.java @@ -24,4 +24,8 @@ public JmsReceiver createJmsReceiver(String className, String destinationType, S public SqsConsumer createSqsReceiver(String className, String methodName, String queueName) { return new SqsConsumer(className, methodName, queueName, identityGenerator.generateUniqueId()); } + + public SqsProducer createSqsProducer(String className, String methodName, String queueName, String destinationProjectId) { + return new SqsProducer(className, methodName, queueName, destinationProjectId, identityGenerator.generateUniqueId()); + } } diff --git a/src/main/java/com/hlag/tools/commvis/analyzer/model/SqsProducer.java b/src/main/java/com/hlag/tools/commvis/analyzer/model/SqsProducer.java new file mode 100644 index 0000000..c24627e --- /dev/null +++ b/src/main/java/com/hlag/tools/commvis/analyzer/model/SqsProducer.java @@ -0,0 +1,48 @@ +package com.hlag.tools.commvis.analyzer.model; + +import com.google.gson.annotations.SerializedName; +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import lombok.Value; + +/** + * A producer for SQS messages. + */ +@Value +@RequiredArgsConstructor(access = AccessLevel.PACKAGE) +public class SqsProducer implements ISenderReceiverCommunication { + /** + * the class name where the producer was found. + */ + @SerializedName(value="class_name") + String className; + + /** + * the method name were the producer was found. + */ + @SerializedName(value="method_name") + String methodName; + + /** + * the queue the messages are sent to. + */ + @SerializedName(value="queue_name") + String queueName; + + /** + * The project id of the referenced project. + */ + @SerializedName(value="destination_project_id") + String destinationProjectId; + + /** + * internal id of this node + */ + @SerializedName(value="id") + String id; + + @Override + public void visit(AbstractCommunicationModelVisitor visitor) { + visitor.visit(this); + } +} diff --git a/src/test/java/com/hlag/tools/commvis/analyzer/model/CommunicationModelTest.java b/src/test/java/com/hlag/tools/commvis/analyzer/model/CommunicationModelTest.java index 29b2269..cffeb53 100644 --- a/src/test/java/com/hlag/tools/commvis/analyzer/model/CommunicationModelTest.java +++ b/src/test/java/com/hlag/tools/commvis/analyzer/model/CommunicationModelTest.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.Test; import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import static org.assertj.core.api.Assertions.assertThat; @@ -13,9 +14,11 @@ void shouldHaveSerializedNameAnnotationOnFiled_toDecoupleTheFieldNameFromJson() Field[] declaredFields = CommunicationModel.class.getDeclaredFields(); for (Field f : declaredFields) { - SerializedName actualAnnotation = f.getAnnotation(SerializedName.class); + if (! Modifier.isStatic(f.getModifiers())) { + SerializedName actualAnnotation = f.getAnnotation(SerializedName.class); - assertThat(actualAnnotation).isNotNull(); + assertThat(actualAnnotation).withFailMessage(() -> String.format("Field %s has no @SerializedName annotation.", f.getName())).isNotNull(); + } } } } \ No newline at end of file diff --git a/src/test/java/com/hlag/tools/commvis/analyzer/model/EndpointFactoryTest.java b/src/test/java/com/hlag/tools/commvis/analyzer/model/EndpointFactoryTest.java index e8d3bd1..5de09a3 100644 --- a/src/test/java/com/hlag/tools/commvis/analyzer/model/EndpointFactoryTest.java +++ b/src/test/java/com/hlag/tools/commvis/analyzer/model/EndpointFactoryTest.java @@ -68,4 +68,14 @@ void shouldSetAllFields_whenCreateSqsReceiver() { Assertions.assertThat(actualSqsConsumer.getId()).isEqualTo(FIXED_ID); } + @Test + void shouldSetAllFields_whenCreateSqsProducer() { + SqsProducer actualSqsProducer = factory.createSqsProducer("className", "methodName", "queueName", "destinationProjectId"); + + Assertions.assertThat(actualSqsProducer.getClassName()).isEqualTo("className"); + Assertions.assertThat(actualSqsProducer.getMethodName()).isEqualTo("methodName"); + Assertions.assertThat(actualSqsProducer.getQueueName()).isEqualTo("queueName"); + Assertions.assertThat(actualSqsProducer.getDestinationProjectId()).isEqualTo("destinationProjectId"); + Assertions.assertThat(actualSqsProducer.getId()).isEqualTo(FIXED_ID); + } } \ No newline at end of file diff --git a/src/test/java/com/hlag/tools/commvis/analyzer/model/HttpConsumerTest.java b/src/test/java/com/hlag/tools/commvis/analyzer/model/HttpConsumerTest.java index f655215..5b391b2 100644 --- a/src/test/java/com/hlag/tools/commvis/analyzer/model/HttpConsumerTest.java +++ b/src/test/java/com/hlag/tools/commvis/analyzer/model/HttpConsumerTest.java @@ -23,12 +23,12 @@ void init() { @Test void shouldHaveSerializedNameAnnotationOnFiled_toDecoupleTheFieldNameFromJson() { - Field[] declaredFields = CommunicationModel.class.getDeclaredFields(); + Field[] declaredFields = HttpConsumer.class.getDeclaredFields(); for (Field f : declaredFields) { SerializedName actualAnnotation = f.getAnnotation(SerializedName.class); - assertThat(actualAnnotation).isNotNull(); + assertThat(actualAnnotation).withFailMessage(() -> String.format("Field %s has no @SerializedName annotation.", f.getName())).isNotNull(); } } diff --git a/src/test/java/com/hlag/tools/commvis/analyzer/model/HttpProducerTest.java b/src/test/java/com/hlag/tools/commvis/analyzer/model/HttpProducerTest.java index 4bc3bf7..d8a2cb4 100644 --- a/src/test/java/com/hlag/tools/commvis/analyzer/model/HttpProducerTest.java +++ b/src/test/java/com/hlag/tools/commvis/analyzer/model/HttpProducerTest.java @@ -10,12 +10,12 @@ class HttpProducerTest { @Test void shouldHaveSerializedNameAnnotationOnFiled_toDecoupleTheFieldNameFromJson() { - Field[] declaredFields = CommunicationModel.class.getDeclaredFields(); + Field[] declaredFields = HttpProducer.class.getDeclaredFields(); for (Field f : declaredFields) { SerializedName actualAnnotation = f.getAnnotation(SerializedName.class); - assertThat(actualAnnotation).isNotNull(); + assertThat(actualAnnotation).withFailMessage(() -> String.format("Field %s has no @SerializedName annotation.", f.getName())).isNotNull(); } } } \ No newline at end of file diff --git a/src/test/java/com/hlag/tools/commvis/analyzer/model/JmsReceiverTest.java b/src/test/java/com/hlag/tools/commvis/analyzer/model/JmsReceiverTest.java index 0a5e37d..e8bcdf1 100644 --- a/src/test/java/com/hlag/tools/commvis/analyzer/model/JmsReceiverTest.java +++ b/src/test/java/com/hlag/tools/commvis/analyzer/model/JmsReceiverTest.java @@ -10,12 +10,12 @@ class JmsReceiverTest { @Test void shouldHaveSerializedNameAnnotationOnFiled_toDecoupleTheFieldNameFromJson() { - Field[] declaredFields = CommunicationModel.class.getDeclaredFields(); + Field[] declaredFields = JmsReceiver.class.getDeclaredFields(); for (Field f : declaredFields) { SerializedName actualAnnotation = f.getAnnotation(SerializedName.class); - assertThat(actualAnnotation).isNotNull(); + assertThat(actualAnnotation).withFailMessage(() -> String.format("Field %s has no @SerializedName annotation.", f.getName())).isNotNull(); } } } \ No newline at end of file diff --git a/src/test/java/com/hlag/tools/commvis/analyzer/model/SqsConsumerTest.java b/src/test/java/com/hlag/tools/commvis/analyzer/model/SqsConsumerTest.java index 58a248e..97ee844 100644 --- a/src/test/java/com/hlag/tools/commvis/analyzer/model/SqsConsumerTest.java +++ b/src/test/java/com/hlag/tools/commvis/analyzer/model/SqsConsumerTest.java @@ -15,7 +15,7 @@ void shouldHaveSerializedNameAnnotationOnFiled_toDecoupleTheFieldNameFromJson() for (Field f : declaredFields) { SerializedName actualAnnotation = f.getAnnotation(SerializedName.class); - assertThat(actualAnnotation).isNotNull(); + assertThat(actualAnnotation).withFailMessage(() -> String.format("Field %s has no @SerializedName annotation.", f.getName())).isNotNull(); } } } \ No newline at end of file diff --git a/src/test/java/com/hlag/tools/commvis/analyzer/model/SqsProducerTest.java b/src/test/java/com/hlag/tools/commvis/analyzer/model/SqsProducerTest.java new file mode 100644 index 0000000..6d2a9f2 --- /dev/null +++ b/src/test/java/com/hlag/tools/commvis/analyzer/model/SqsProducerTest.java @@ -0,0 +1,21 @@ +package com.hlag.tools.commvis.analyzer.model; + +import com.google.gson.annotations.SerializedName; +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Field; + +import static org.assertj.core.api.Assertions.assertThat; + +class SqsProducerTest { + @Test + void shouldHaveSerializedNameAnnotationOnFiled_toDecoupleTheFieldNameFromJson() { + Field[] declaredFields = SqsProducer.class.getDeclaredFields(); + + for (Field f : declaredFields) { + SerializedName actualAnnotation = f.getAnnotation(SerializedName.class); + + assertThat(actualAnnotation).withFailMessage(() -> String.format("Field %s has no @SerializedName annotation.", f.getName())).isNotNull(); + } + } +} \ No newline at end of file