Skip to content
This repository was archived by the owner on Jan 19, 2022. It is now read-only.

Commit f5c583e

Browse files
committed
Adding support for EventBridge
1 parent 33e1535 commit f5c583e

File tree

12 files changed

+788
-2
lines changed

12 files changed

+788
-2
lines changed

.idea/misc.xml

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

spring-cloud-aws-dependencies/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
<name>Spring Cloud AWS Dependencies</name>
3232
<description>Spring Cloud AWS Dependencies</description>
3333
<properties>
34-
<aws-java-sdk.version>1.11.415</aws-java-sdk.version>
34+
<aws-java-sdk.version>1.11.624</aws-java-sdk.version>
3535
<elasticache.version>1.1.1</elasticache.version>
3636
<jmemcached.version>1.0.0</jmemcached.version>
3737
<spring-cloud-context.version>1.3.2.RELEASE</spring-cloud-context.version>

spring-cloud-aws-messaging/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@
4242
<groupId>com.amazonaws</groupId>
4343
<artifactId>aws-java-sdk-sqs</artifactId>
4444
</dependency>
45+
<dependency>
46+
<groupId>com.amazonaws</groupId>
47+
<artifactId>aws-java-sdk-events</artifactId>
48+
</dependency>
4549
<dependency>
4650
<groupId>org.springframework</groupId>
4751
<artifactId>spring-messaging</artifactId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2013-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.aws.messaging.config.annotation;
18+
19+
import java.lang.annotation.ElementType;
20+
import java.lang.annotation.Retention;
21+
import java.lang.annotation.RetentionPolicy;
22+
import java.lang.annotation.Target;
23+
24+
import org.springframework.context.annotation.Import;
25+
26+
/**
27+
* @author Jakub Narloch
28+
* @since 2.3.0
29+
*/
30+
@Target(ElementType.TYPE)
31+
@Retention(RetentionPolicy.RUNTIME)
32+
@Import({ EventBridgeConfiguration.class })
33+
public @interface EnableEventBridge {
34+
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2013-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.aws.messaging.config.annotation;
18+
19+
import com.amazonaws.auth.AWSCredentialsProvider;
20+
import com.amazonaws.services.cloudwatchevents.AmazonCloudWatchEvents;
21+
import com.amazonaws.services.cloudwatchevents.AmazonCloudWatchEventsClient;
22+
23+
import org.springframework.beans.factory.annotation.Autowired;
24+
import org.springframework.cloud.aws.context.annotation.ConditionalOnMissingAmazonClient;
25+
import org.springframework.cloud.aws.core.config.AmazonWebserviceClientFactoryBean;
26+
import org.springframework.cloud.aws.core.region.RegionProvider;
27+
import org.springframework.context.annotation.Bean;
28+
import org.springframework.context.annotation.Configuration;
29+
30+
/**
31+
* @author Jakub Narloch
32+
* @since 2.3.0
33+
*/
34+
@Configuration(proxyBeanMethods = false)
35+
public class EventBridgeConfiguration {
36+
37+
@Autowired(required = false)
38+
private AWSCredentialsProvider awsCredentialsProvider;
39+
40+
@Autowired(required = false)
41+
private RegionProvider regionProvider;
42+
43+
@ConditionalOnMissingAmazonClient(AmazonCloudWatchEvents.class)
44+
@Bean
45+
public AmazonWebserviceClientFactoryBean<AmazonCloudWatchEventsClient> amazonEvents() {
46+
return new AmazonWebserviceClientFactoryBean<>(AmazonCloudWatchEventsClient.class,
47+
this.awsCredentialsProvider, this.regionProvider);
48+
}
49+
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright 2013-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.aws.messaging.core;
18+
19+
import java.util.Optional;
20+
21+
import com.amazonaws.services.cloudwatchevents.AmazonCloudWatchEvents;
22+
import com.amazonaws.services.cloudwatchevents.model.PutEventsRequest;
23+
import com.amazonaws.services.cloudwatchevents.model.PutEventsRequestEntry;
24+
25+
import org.springframework.messaging.Message;
26+
import org.springframework.messaging.support.AbstractMessageChannel;
27+
28+
/**
29+
* @author Jakub Narloch
30+
* @since 2.3.0
31+
*/
32+
public class EventBusMessageChannel extends AbstractMessageChannel {
33+
34+
/**
35+
* The 'source' message header.
36+
*/
37+
public static final String EVENT_SOURCE_HEADER = "EVENT_SOURCE_HEADER";
38+
39+
/**
40+
* The 'detail-type' message header.
41+
*/
42+
public static final String EVENT_DETAIL_TYPE_HEADER = "EVENT_DETAIL_TYPE_HEADER";
43+
44+
private final AmazonCloudWatchEvents amazonEvents;
45+
46+
private final String eventBus;
47+
48+
public EventBusMessageChannel(AmazonCloudWatchEvents amazonEvents, String eventBus) {
49+
this.amazonEvents = amazonEvents;
50+
this.eventBus = eventBus;
51+
}
52+
53+
@Override
54+
protected boolean sendInternal(Message<?> message, long timeout) {
55+
PutEventsRequestEntry entry = new PutEventsRequestEntry()
56+
.withEventBusName(eventBus).withSource(findEventSource(message))
57+
.withDetailType(findEventDetailType(message))
58+
.withDetail(message.getPayload().toString());
59+
amazonEvents.putEvents(new PutEventsRequest().withEntries(entry));
60+
return true;
61+
}
62+
63+
private static String findEventSource(Message<?> message) {
64+
return findHeaderValue(message, EVENT_SOURCE_HEADER);
65+
}
66+
67+
private static String findEventDetailType(Message<?> message) {
68+
return findHeaderValue(message, EVENT_DETAIL_TYPE_HEADER);
69+
}
70+
71+
private static String findHeaderValue(Message<?> message, String header) {
72+
return Optional.ofNullable(message.getHeaders().get(header)).map(Object::toString)
73+
.orElse(null);
74+
}
75+
76+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright 2013-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.aws.messaging.core;
18+
19+
import java.util.HashMap;
20+
import java.util.Map;
21+
22+
import com.amazonaws.services.cloudwatchevents.AmazonCloudWatchEvents;
23+
24+
import org.springframework.cloud.aws.core.env.ResourceIdResolver;
25+
import org.springframework.cloud.aws.messaging.core.support.AbstractMessageChannelMessagingSendingTemplate;
26+
import org.springframework.cloud.aws.messaging.support.destination.DynamicEventBusDestinationResolver;
27+
import org.springframework.messaging.converter.MessageConverter;
28+
import org.springframework.messaging.core.DestinationResolver;
29+
30+
/**
31+
* @author Jakub Narloch
32+
* @since 2.3.0
33+
*/
34+
public class EventsMessagingTemplate
35+
extends AbstractMessageChannelMessagingSendingTemplate<EventBusMessageChannel> {
36+
37+
private final AmazonCloudWatchEvents amazonEvents;
38+
39+
public EventsMessagingTemplate(AmazonCloudWatchEvents amazonEvents) {
40+
this(amazonEvents, (ResourceIdResolver) null, null);
41+
}
42+
43+
public EventsMessagingTemplate(AmazonCloudWatchEvents amazonEvents,
44+
ResourceIdResolver resourceIdResolver, MessageConverter messageConverter) {
45+
super(new DynamicEventBusDestinationResolver(amazonEvents, resourceIdResolver));
46+
this.amazonEvents = amazonEvents;
47+
initMessageConverter(messageConverter);
48+
}
49+
50+
public EventsMessagingTemplate(AmazonCloudWatchEvents amazonEvents,
51+
DestinationResolver<String> destinationResolver,
52+
MessageConverter messageConverter) {
53+
super(destinationResolver);
54+
this.amazonEvents = amazonEvents;
55+
initMessageConverter(messageConverter);
56+
}
57+
58+
@Override
59+
protected EventBusMessageChannel resolveMessageChannel(
60+
String physicalResourceIdentifier) {
61+
return new EventBusMessageChannel(this.amazonEvents, physicalResourceIdentifier);
62+
}
63+
64+
public void sendEvent(String source, String detailType, Object message) {
65+
Map<String, Object> headers = new HashMap<>();
66+
headers.put(EventBusMessageChannel.EVENT_SOURCE_HEADER, source);
67+
headers.put(EventBusMessageChannel.EVENT_DETAIL_TYPE_HEADER, detailType);
68+
this.convertAndSend(getRequiredDefaultDestination(), message, headers);
69+
}
70+
71+
public void sendEvent(String eventBus, String source, String detailType,
72+
Object message) {
73+
Map<String, Object> headers = new HashMap<>();
74+
headers.put(EventBusMessageChannel.EVENT_SOURCE_HEADER, source);
75+
headers.put(EventBusMessageChannel.EVENT_DETAIL_TYPE_HEADER, detailType);
76+
this.convertAndSend(eventBus, message, headers);
77+
}
78+
79+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright 2013-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.aws.messaging.support.destination;
18+
19+
import com.amazonaws.services.cloudwatchevents.AmazonCloudWatchEvents;
20+
import com.amazonaws.services.cloudwatchevents.model.CreateEventBusRequest;
21+
22+
import org.springframework.cloud.aws.core.env.ResourceIdResolver;
23+
import org.springframework.cloud.aws.core.naming.AmazonResourceName;
24+
import org.springframework.messaging.core.DestinationResolutionException;
25+
import org.springframework.messaging.core.DestinationResolver;
26+
27+
/**
28+
* @author Jakub Narloch
29+
* @since 2.3.0
30+
*/
31+
public class DynamicEventBusDestinationResolver implements DestinationResolver<String> {
32+
33+
private final AmazonCloudWatchEvents amazonEvents;
34+
35+
private final ResourceIdResolver resourceIdResolver;
36+
37+
private boolean autoCreate;
38+
39+
public DynamicEventBusDestinationResolver(AmazonCloudWatchEvents amazonEvents) {
40+
this(amazonEvents, null);
41+
}
42+
43+
public DynamicEventBusDestinationResolver(AmazonCloudWatchEvents amazonEvents,
44+
ResourceIdResolver resourceIdResolver) {
45+
this.amazonEvents = amazonEvents;
46+
this.resourceIdResolver = resourceIdResolver;
47+
}
48+
49+
public void setAutoCreate(boolean autoCreate) {
50+
this.autoCreate = autoCreate;
51+
}
52+
53+
@Override
54+
public String resolveDestination(String name) throws DestinationResolutionException {
55+
if (autoCreate) {
56+
amazonEvents.createEventBus(new CreateEventBusRequest().withName(name))
57+
.getEventBusArn();
58+
return name;
59+
}
60+
61+
String eventBusName = name;
62+
if (resourceIdResolver != null) {
63+
eventBusName = resourceIdResolver.resolveToPhysicalResourceId(name);
64+
}
65+
66+
if (eventBusName != null
67+
&& AmazonResourceName.isValidAmazonResourceName(eventBusName)) {
68+
return AmazonResourceName.fromString(eventBusName).getResourceName();
69+
}
70+
71+
return eventBusName;
72+
}
73+
74+
}

0 commit comments

Comments
 (0)