Skip to content

Commit 1df5d1f

Browse files
committed
temp: work in progress
1 parent 5630a7a commit 1df5d1f

File tree

95 files changed

+771
-438
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+771
-438
lines changed

annotations/build.gradle.kts

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
description = "Contains a way to attach message listeners via annotations"
3+
4+
dependencies {
5+
api(project(":java-dynamic-sqs-listener-core"))
6+
implementation(project(":common-utils"))
7+
implementation(project(":annotation-utils"))
8+
compileOnly(project(":documentation-annotations"))
9+
10+
testImplementation(project(":elasticmq-sqs-client"))
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package com.jashmore.sqs.annotations.container;
2+
3+
import static java.util.concurrent.TimeUnit.SECONDS;
4+
import static org.assertj.core.api.Assertions.assertThat;
5+
6+
import com.fasterxml.jackson.databind.ObjectMapper;
7+
import com.jashmore.sqs.QueueProperties;
8+
import com.jashmore.sqs.annotations.container.example.CustomAnnotation;
9+
import com.jashmore.sqs.annotations.container.example.CustomAnnotationMessageListenerContainerFactory;
10+
import com.jashmore.sqs.argument.payload.PayloadArgumentResolver;
11+
import com.jashmore.sqs.argument.payload.mapper.JacksonPayloadMapper;
12+
import com.jashmore.sqs.client.DefaultPlaceholderQueueResolver;
13+
import com.jashmore.sqs.client.DefaultSqsAsyncClientProvider;
14+
import com.jashmore.sqs.container.MessageListenerContainer;
15+
import com.jashmore.sqs.elasticmq.ElasticMqSqsAsyncClient;
16+
import com.jashmore.sqs.placeholder.StaticPlaceholderResolver;
17+
import com.jashmore.sqs.processor.DecoratingMessageProcessorFactory;
18+
import lombok.Builder;
19+
import lombok.Value;
20+
import org.junit.jupiter.api.AfterAll;
21+
import org.junit.jupiter.api.AfterEach;
22+
import org.junit.jupiter.api.BeforeEach;
23+
import org.junit.jupiter.api.Test;
24+
import software.amazon.awssdk.services.sqs.model.CreateQueueResponse;
25+
import software.amazon.awssdk.services.sqs.model.SendMessageRequest;
26+
27+
import java.util.List;
28+
import java.util.concurrent.CountDownLatch;
29+
import java.util.concurrent.ExecutionException;
30+
import java.util.concurrent.TimeoutException;
31+
32+
class AbstractBaseAnnotationMessageListenerContainerFactoryTest {
33+
private static final ObjectMapper MAPPER = new ObjectMapper();
34+
35+
private static final ElasticMqSqsAsyncClient elasticMQSqsAsyncClient = new ElasticMqSqsAsyncClient();
36+
37+
private QueueProperties queueProperties;
38+
39+
private CountDownLatch countDownLatch;
40+
41+
@BeforeEach
42+
void setUp() throws InterruptedException, ExecutionException, TimeoutException {
43+
countDownLatch = new CountDownLatch(1);
44+
queueProperties =
45+
elasticMQSqsAsyncClient
46+
.createQueue(builder -> builder.queueName("queueName"))
47+
.thenApply(CreateQueueResponse::queueUrl)
48+
.thenApply(url -> QueueProperties.builder().queueUrl(url).build())
49+
.get(5, SECONDS);
50+
}
51+
52+
@AfterEach
53+
void tearDownTest() throws Exception {
54+
elasticMQSqsAsyncClient.deleteQueue(builder -> builder.queueUrl(queueProperties.getQueueUrl())).get(5, SECONDS);
55+
}
56+
57+
@AfterAll
58+
static void tearDown() {
59+
elasticMQSqsAsyncClient.close();
60+
}
61+
62+
@Value
63+
@Builder
64+
@SuppressWarnings("WeakerAccess")
65+
public static class MyPojo {
66+
String name;
67+
}
68+
69+
@CustomAnnotation(queue = "queueName", identifier = "id")
70+
public void message(final MyPojo myPojo) {
71+
System.out.println("Hello!");
72+
countDownLatch.countDown();
73+
}
74+
75+
@Test
76+
void test() throws Exception {
77+
final CustomAnnotationMessageListenerContainerFactory factory =
78+
new CustomAnnotationMessageListenerContainerFactory(
79+
new DefaultSqsAsyncClientProvider(elasticMQSqsAsyncClient),
80+
new DefaultPlaceholderQueueResolver(new StaticPlaceholderResolver()),
81+
new DecoratingMessageProcessorFactory(List.of(), List.of()),
82+
methodParameter -> new PayloadArgumentResolver(new JacksonPayloadMapper(new ObjectMapper()))
83+
);
84+
85+
final MessageListenerContainer container = factory.buildContainer(
86+
new AbstractBaseAnnotationMessageListenerContainerFactoryTest(),
87+
AbstractBaseAnnotationMessageListenerContainerFactoryTest.class.getMethod("message", MyPojo.class)
88+
);
89+
container.start();
90+
91+
final MyPojo myPojo = MyPojo.builder()
92+
.name("test")
93+
.build();
94+
95+
final SendMessageRequest sendMessageRequest = SendMessageRequest.builder()
96+
.queueUrl(queueProperties.getQueueUrl())
97+
.messageBody(MAPPER.writeValueAsString(myPojo))
98+
.build();
99+
100+
elasticMQSqsAsyncClient.sendMessage(sendMessageRequest);
101+
102+
assertThat(countDownLatch.await(5, SECONDS)).isTrue();
103+
}
104+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.jashmore.sqs.annotations.container.example;
2+
3+
import static java.lang.annotation.ElementType.METHOD;
4+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
5+
6+
import java.lang.annotation.Retention;
7+
import java.lang.annotation.Target;
8+
9+
@Retention(RUNTIME)
10+
@Target(METHOD)
11+
public @interface CustomAnnotation {
12+
String queue() default "";
13+
String identifier() default "";
14+
String sqsClient() default "";
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.jashmore.sqs.annotations.container.example;
2+
3+
import com.jashmore.sqs.QueueProperties;
4+
import com.jashmore.sqs.annotations.container.AbstractBaseAnnotationMessageListenerContainerFactory;
5+
import com.jashmore.sqs.annotations.container.AnnotationParser;
6+
import com.jashmore.sqs.argument.ArgumentResolverService;
7+
import com.jashmore.sqs.broker.concurrent.ConcurrentMessageBroker;
8+
import com.jashmore.sqs.broker.concurrent.StaticConcurrentMessageBrokerProperties;
9+
import com.jashmore.sqs.client.QueueResolver;
10+
import com.jashmore.sqs.client.SqsAsyncClientProvider;
11+
import com.jashmore.sqs.container.CoreMessageListenerContainer;
12+
import com.jashmore.sqs.container.MessageListenerContainer;
13+
import com.jashmore.sqs.processor.DecoratingMessageProcessorFactory;
14+
import com.jashmore.sqs.processor.MessageProcessor;
15+
import com.jashmore.sqs.resolver.batching.BatchingMessageResolver;
16+
import com.jashmore.sqs.retriever.batching.BatchingMessageRetriever;
17+
import com.jashmore.sqs.retriever.batching.StaticBatchingMessageRetrieverProperties;
18+
import software.amazon.awssdk.services.sqs.SqsAsyncClient;
19+
20+
import java.util.function.Supplier;
21+
22+
public class CustomAnnotationMessageListenerContainerFactory extends
23+
AbstractBaseAnnotationMessageListenerContainerFactory<CustomAnnotation, Object> {
24+
25+
// We don't have any extra properties so just use an object
26+
public static class CustomAnnotationParser implements AnnotationParser<CustomAnnotation, Object> {
27+
@Override
28+
public Object parse(final CustomAnnotation annotation) {
29+
return new Object();
30+
}
31+
}
32+
33+
public CustomAnnotationMessageListenerContainerFactory(final SqsAsyncClientProvider sqsAsyncClientProvider,
34+
final QueueResolver queueResolver,
35+
final DecoratingMessageProcessorFactory decoratingMessageProcessorFactory,
36+
final ArgumentResolverService argumentResolverService) {
37+
super(sqsAsyncClientProvider, queueResolver, new CustomAnnotationMessageListenerContainerFactory.CustomAnnotationParser(), decoratingMessageProcessorFactory, argumentResolverService);
38+
}
39+
40+
@Override
41+
protected MessageListenerContainer buildContainer(final String identifier,
42+
final SqsAsyncClient sqsAsyncClient,
43+
final QueueProperties queueProperties,
44+
final Object containerProperties,
45+
final Supplier<MessageProcessor> messageProcessSupplier) {
46+
return new CoreMessageListenerContainer(
47+
identifier,
48+
() -> new ConcurrentMessageBroker(StaticConcurrentMessageBrokerProperties.builder().concurrencyLevel(1).build()),
49+
() -> new BatchingMessageRetriever(queueProperties, sqsAsyncClient, StaticBatchingMessageRetrieverProperties.builder().batchSize(1).build()),
50+
messageProcessSupplier,
51+
() -> new BatchingMessageResolver(queueProperties, sqsAsyncClient)
52+
);
53+
}
54+
55+
@Override
56+
protected Class<CustomAnnotation> getAnnotationClass() {
57+
return CustomAnnotation.class;
58+
}
59+
60+
@Override
61+
protected String getIdentifier(final CustomAnnotation annotation) {
62+
return annotation.identifier();
63+
}
64+
65+
@Override
66+
protected String getQueueNameOrUrl(final CustomAnnotation annotation) {
67+
return annotation.queue();
68+
}
69+
70+
@Override
71+
protected String getSqsClientIdentifier(final CustomAnnotation annotation) {
72+
return annotation.sqsClient();
73+
}
74+
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
package com.jashmore.sqs.spring.container;
1+
package com.jashmore.sqs.annotations.container;
22

33
import com.jashmore.sqs.container.MessageListenerContainer;
4+
import com.jashmore.sqs.container.MessageListenerContainerFactory;
45
import com.jashmore.sqs.util.annotation.AnnotationUtils;
56
import java.lang.annotation.Annotation;
67
import java.lang.reflect.Method;
+12-10
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
1-
package com.jashmore.sqs.spring.container;
1+
package com.jashmore.sqs.annotations.container;
22

33
import com.jashmore.documentation.annotations.Nullable;
44
import com.jashmore.sqs.QueueProperties;
55
import com.jashmore.sqs.argument.ArgumentResolverService;
66
import com.jashmore.sqs.container.MessageListenerContainer;
7+
import com.jashmore.sqs.container.MessageListenerContainerInitialisationException;
78
import com.jashmore.sqs.processor.CoreMessageProcessor;
9+
import com.jashmore.sqs.processor.DecoratingMessageProcessorFactory;
810
import com.jashmore.sqs.processor.MessageProcessor;
9-
import com.jashmore.sqs.spring.client.SqsAsyncClientProvider;
10-
import com.jashmore.sqs.spring.processor.DecoratingMessageProcessorFactory;
11-
import com.jashmore.sqs.spring.queue.QueueResolver;
12-
import com.jashmore.sqs.spring.util.IdentifierUtils;
11+
import com.jashmore.sqs.client.SqsAsyncClientProvider;
12+
import com.jashmore.sqs.client.QueueResolver;
1313
import java.lang.annotation.Annotation;
1414
import java.lang.reflect.Method;
1515
import java.util.function.Supplier;
16-
import org.springframework.util.StringUtils;
16+
17+
import com.jashmore.sqs.util.identifier.IdentifierUtils;
18+
import com.jashmore.sqs.util.string.StringUtils;
1719
import software.amazon.awssdk.services.sqs.SqsAsyncClient;
1820

1921
/**
@@ -23,19 +25,19 @@
2325
* @param <A> the Spring annotation that is used to define the container's properties
2426
* @param <P> the properties object that configures the {@link MessageListenerContainer}
2527
*/
26-
public abstract class AbstractCoreMessageListenerContainerFactory<A extends Annotation, P>
28+
public abstract class AbstractBaseAnnotationMessageListenerContainerFactory<A extends Annotation, P>
2729
extends AbstractAnnotationMessageListenerContainerFactory<A> {
2830

2931
private final SqsAsyncClientProvider sqsAsyncClientProvider;
3032
private final QueueResolver queueResolver;
31-
private final CoreAnnotationParser<A, P> annotationParser;
33+
private final AnnotationParser<A, P> annotationParser;
3234
private final DecoratingMessageProcessorFactory decoratingMessageProcessorFactory;
3335
private final ArgumentResolverService argumentResolverService;
3436

35-
protected AbstractCoreMessageListenerContainerFactory(
37+
protected AbstractBaseAnnotationMessageListenerContainerFactory(
3638
final SqsAsyncClientProvider sqsAsyncClientProvider,
3739
final QueueResolver queueResolver,
38-
final CoreAnnotationParser<A, P> annotationParser,
40+
final AnnotationParser<A, P> annotationParser,
3941
final DecoratingMessageProcessorFactory decoratingMessageProcessorFactory,
4042
final ArgumentResolverService argumentResolverService
4143
) {

spring/spring-core/src/main/java/com/jashmore/sqs/spring/container/CoreAnnotationParser.java renamed to annotations/src/main/java/com/jashmore/sqs/annotations/container/AnnotationParser.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
package com.jashmore.sqs.spring.container;
1+
package com.jashmore.sqs.annotations.container;
22

33
import java.lang.annotation.Annotation;
44

55
/**
66
* Parser used for converting an annotation into the properties needed for one of the core {@link com.jashmore.sqs.container.MessageListenerContainer}s.
77
*/
8-
public interface CoreAnnotationParser<A extends Annotation, P> {
8+
public interface AnnotationParser<A extends Annotation, P> {
99
/**
1010
* Parse the supplied annotation into the properties to build a {@link com.jashmore.sqs.container.MessageListenerContainer}.
1111
*
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
package com.jashmore.sqs.spring.decorator.visibilityextender;
1+
package com.jashmore.sqs.annotations.decorator.visibilityextender;
22

33
import static java.lang.annotation.ElementType.METHOD;
44
import static java.lang.annotation.RetentionPolicy.RUNTIME;
55

66
import com.jashmore.sqs.decorator.AutoVisibilityExtenderMessageProcessingDecorator;
77
import com.jashmore.sqs.decorator.AutoVisibilityExtenderMessageProcessingDecoratorProperties;
8+
89
import java.lang.annotation.Retention;
910
import java.lang.annotation.Target;
1011

Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1-
package com.jashmore.sqs.spring.decorator.visibilityextender;
1+
package com.jashmore.sqs.annotations.decorator.visibilityextender;
22

33
import com.jashmore.documentation.annotations.VisibleForTesting;
44
import com.jashmore.sqs.QueueProperties;
5+
import com.jashmore.sqs.placeholder.PlaceholderResolver;
56
import com.jashmore.sqs.decorator.AutoVisibilityExtenderMessageProcessingDecorator;
67
import com.jashmore.sqs.decorator.AutoVisibilityExtenderMessageProcessingDecoratorProperties;
7-
import com.jashmore.sqs.spring.decorator.MessageProcessingDecoratorFactory;
8-
import com.jashmore.sqs.spring.decorator.MessageProcessingDecoratorFactoryException;
8+
import com.jashmore.sqs.decorator.MessageProcessingDecoratorFactory;
9+
import com.jashmore.sqs.decorator.MessageProcessingDecoratorFactoryException;
910
import com.jashmore.sqs.util.annotation.AnnotationUtils;
1011
import java.lang.reflect.Method;
1112
import java.time.Duration;
1213
import java.util.Optional;
1314
import java.util.concurrent.CompletableFuture;
1415
import java.util.function.Supplier;
15-
import org.springframework.core.env.Environment;
16-
import org.springframework.util.StringUtils;
16+
17+
import com.jashmore.sqs.util.string.StringUtils;
1718
import software.amazon.awssdk.services.sqs.SqsAsyncClient;
1819

1920
/**
@@ -23,10 +24,10 @@
2324
public class AutoVisibilityExtenderMessageProcessingDecoratorFactory
2425
implements MessageProcessingDecoratorFactory<AutoVisibilityExtenderMessageProcessingDecorator> {
2526

26-
private final Environment environment;
27+
private final PlaceholderResolver placeholderResolver;
2728

28-
public AutoVisibilityExtenderMessageProcessingDecoratorFactory(final Environment environment) {
29-
this.environment = environment;
29+
public AutoVisibilityExtenderMessageProcessingDecoratorFactory(final PlaceholderResolver placeholderResolver) {
30+
this.placeholderResolver = placeholderResolver;
3031
}
3132

3233
@Override
@@ -108,7 +109,7 @@ private Duration getDurationFromSeconds(
108109
) {
109110
final String stringPropertyValue = stringProperty.get();
110111
if (StringUtils.hasText(stringPropertyValue)) {
111-
return Duration.ofSeconds(Integer.parseInt(environment.resolvePlaceholders(stringPropertyValue)));
112+
return Duration.ofSeconds(Integer.parseInt(placeholderResolver.resolvePlaceholders(stringPropertyValue)));
112113
}
113114

114115
final Integer integerValue = integerSupplier.get();

0 commit comments

Comments
 (0)