Skip to content

Commit

Permalink
Merge pull request #15 from lsd-consulting/14
Browse files Browse the repository at this point in the history
Add support for Spring Cloud Stream
  • Loading branch information
lukasz-gryzbon authored Oct 8, 2022
2 parents 06359e4 + 6ca632d commit 2617a7e
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 4 deletions.
2 changes: 2 additions & 0 deletions lsd-interceptors/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ sourceCompatibility = '11'

dependencies {
implementation 'org.springframework:spring-web:5.3.16.RELEASE'
implementation 'org.springframework:spring-messaging:5.3.23'
implementation 'org.springframework.integration:spring-integration-core:5.5.15'
implementation 'com.squareup.okhttp3:okhttp:3.8.1'

testCompileOnly 'org.springframework:spring-web:5.1.11.RELEASE'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.lsdconsulting.interceptors.messaging;

import com.lsd.LsdContext;
import com.lsd.diagram.ValidComponentName;
import lombok.RequiredArgsConstructor;
import lsd.format.PrettyPrinter;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.ChannelInterceptor;

import static io.lsdconsulting.interceptors.http.common.Headers.HeaderKeys.SOURCE_NAME;
import static io.lsdconsulting.interceptors.http.common.Headers.HeaderKeys.TARGET_NAME;

@RequiredArgsConstructor
public class EventConsumerInterceptor implements ChannelInterceptor {

private final LsdContext lsdContext;

@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
String payload = PrettyPrinter.prettyPrint(new String((byte[]) message.getPayload()));
String source = (String) message.getHeaders().get(SOURCE_NAME.key());
String target = (String) message.getHeaders().get(TARGET_NAME.key());

lsdContext.capture("Consume event from " + ValidComponentName.of(source) + " to " + ValidComponentName.of(target), payload);

return message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.lsdconsulting.interceptors.messaging;

import com.lsd.LsdContext;
import com.lsd.diagram.ValidComponentName;
import lombok.RequiredArgsConstructor;
import lsd.format.PrettyPrinter;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.ChannelInterceptor;

import static io.lsdconsulting.interceptors.http.common.Headers.HeaderKeys.SOURCE_NAME;
import static io.lsdconsulting.interceptors.http.common.Headers.HeaderKeys.TARGET_NAME;

@RequiredArgsConstructor
public class EventPublisherInterceptor implements ChannelInterceptor {

private final LsdContext lsdContext;

@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
String payload = PrettyPrinter.prettyPrint(new String((byte[]) message.getPayload()));
String source = (String) message.getHeaders().get(SOURCE_NAME.key());
String target = (String) message.getHeaders().get(TARGET_NAME.key());

lsdContext.capture("Publish event from " + ValidComponentName.of(source) + " to " + ValidComponentName.of(target), payload);

return message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package io.lsdconsulting.interceptors.messaging.autoconfigure;

import com.lsd.LsdContext;
import io.lsdconsulting.interceptors.messaging.EventConsumerInterceptor;
import io.lsdconsulting.interceptors.messaging.EventPublisherInterceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.integration.config.GlobalChannelInterceptor;
import org.springframework.messaging.support.ChannelInterceptor;

/**
* <p>
* If a {@link LsdContext} and ChannelInterceptor classes is available it will automatically autoconfig a {@link LsdMessagingConfiguration}
* </p>
*/
@Configuration
@PropertySource(ignoreResourceNotFound = true, value = "classpath:lsd.properties")
@ConditionalOnClass(value = {LsdContext.class, ChannelInterceptor.class})
@ConditionalOnProperty(name = "lsd.interceptors.autoconfig.enabled", havingValue = "true", matchIfMissing = true)
public class LsdMessagingConfiguration {

private final LsdContext lsdContext = LsdContext.getInstance();

@Bean
@GlobalChannelInterceptor(patterns = "*-in-*", order = 100)
public EventConsumerInterceptor eventConsumerInterceptor() {
return new EventConsumerInterceptor(lsdContext);
}

@Bean
@GlobalChannelInterceptor(patterns = "*-out-*", order = 101)
public EventPublisherInterceptor eventPublisherInterceptor() {
return new EventPublisherInterceptor(lsdContext);
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package io.lsdconsulting.interceptors.aop;

import io.lsdconsulting.interceptors.aop.AopInterceptorDelegate;
import io.lsdconsulting.interceptors.aop.SpringDataRepositoryInterceptor;
import org.junit.jupiter.api.Test;

import static org.mockito.Mockito.mock;

class SpringDataRepositoryInterceptorTest {

private AopInterceptorDelegate delegate = mock(AopInterceptorDelegate.class);
private SpringDataRepositoryInterceptor interceptor = new SpringDataRepositoryInterceptor(delegate);
private final AopInterceptorDelegate delegate = mock(AopInterceptorDelegate.class);
private final SpringDataRepositoryInterceptor interceptor = new SpringDataRepositoryInterceptor(delegate);

@Test
void trapExceptionsToPreventBreakingBuilds() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package io.lsdconsulting.interceptors.messaging;

import com.lsd.LsdContext;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;

import java.util.Map;

import static io.lsdconsulting.interceptors.http.common.Headers.HeaderKeys.SOURCE_NAME;
import static io.lsdconsulting.interceptors.http.common.Headers.HeaderKeys.TARGET_NAME;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

class EventConsumerInterceptorTest {
private final ArgumentCaptor<String> patternCaptor = ArgumentCaptor.forClass(String.class);
private final ArgumentCaptor<String> payloadCaptor = ArgumentCaptor.forClass(String.class);

private final LsdContext lsdContext = mock(LsdContext.class);
private final Message<byte[]> message = mock(Message.class);

private final EventConsumerInterceptor underTest = new EventConsumerInterceptor(lsdContext);

@Test
void logInteraction() {
given(message.getPayload()).willReturn("{\"key\":\"value\"}".getBytes(UTF_8));
given(message.getHeaders()).willReturn(new MessageHeaders(Map.of(SOURCE_NAME.key(), "Source", TARGET_NAME.key(), "Target")));

underTest.preSend(message, null);

verify(lsdContext).capture(patternCaptor.capture(), payloadCaptor.capture());
assertThat(patternCaptor.getValue()).isEqualTo("Consume event from Source to Target");
assertThat(payloadCaptor.getValue()).isEqualTo(
"{\n" +
" \"key\": \"value\"\n" +
"}"
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package io.lsdconsulting.interceptors.messaging;

import com.lsd.LsdContext;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;

import java.util.Map;

import static io.lsdconsulting.interceptors.http.common.Headers.HeaderKeys.SOURCE_NAME;
import static io.lsdconsulting.interceptors.http.common.Headers.HeaderKeys.TARGET_NAME;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

class EventPublisherInterceptorTest {
private final ArgumentCaptor<String> patternCaptor = ArgumentCaptor.forClass(String.class);
private final ArgumentCaptor<String> payloadCaptor = ArgumentCaptor.forClass(String.class);

private final LsdContext lsdContext = mock(LsdContext.class);
private final Message<byte[]> message = mock(Message.class);

private final EventPublisherInterceptor underTest = new EventPublisherInterceptor(lsdContext);

@Test
void logInteraction() {
given(message.getPayload()).willReturn("{\"key\":\"value\"}".getBytes(UTF_8));
given(message.getHeaders()).willReturn(new MessageHeaders(Map.of(SOURCE_NAME.key(), "Source", TARGET_NAME.key(), "Target")));

underTest.preSend(message, null);

verify(lsdContext).capture(patternCaptor.capture(), payloadCaptor.capture());
assertThat(patternCaptor.getValue()).isEqualTo("Publish event from Source to Target");
assertThat(payloadCaptor.getValue()).isEqualTo(
"{\n" +
" \"key\": \"value\"\n" +
"}"
);
}
}

0 comments on commit 2617a7e

Please sign in to comment.