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

Commit

Permalink
feat: add annotation for SQS producer (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
kayman-mk committed Jun 9, 2022
1 parent e5a60ea commit 39c42a3
Show file tree
Hide file tree
Showing 14 changed files with 161 additions and 12 deletions.
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();
}
}
}

0 comments on commit 39c42a3

Please sign in to comment.