Skip to content
This repository has been archived by the owner on May 15, 2024. It is now read-only.

feat: add annotation for SQS producer #36

Merged
merged 2 commits into from Jun 9, 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
9 changes: 9 additions & 0 deletions README.md
Expand Up @@ -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
```
<dependency>
<groupId>com.hlag.tools.commvis</groupId>
<artifactId>api</artifactId>
<version>2.5.5</version>
<scope>provided</scope>
</dependency>
```
## 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!
Expand Down
@@ -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 "";
}
@@ -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();
}
Expand Up @@ -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);
}
Expand Up @@ -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
*/
Expand Down Expand Up @@ -58,11 +60,17 @@ public class CommunicationModel {
@SerializedName(value = "sqs_consumers")
private Collection<SqsConsumer> sqsConsumers = new HashSet<>();

/**
* All SQS producers.
*/
@SerializedName(value = "sqs_producers")
private Collection<SqsProducer> 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 <T extends ISenderReceiverCommunication> void addSenderReceiver(T endpoint) {
Expand All @@ -74,6 +82,8 @@ public <T extends ISenderReceiverCommunication> 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()));
}
Expand All @@ -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));
}
}
Expand Up @@ -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());
}
}
@@ -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);
}
}
Expand Up @@ -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;

Expand All @@ -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();
}
}
}
}
Expand Up @@ -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);
}
}
Expand Up @@ -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();
}
}

Expand Down
Expand Up @@ -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();
}
}
}
Expand Up @@ -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();
}
}
}
Expand Up @@ -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();
}
}
}
@@ -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();
}
}
}