Skip to content

Commit 79b2cf8

Browse files
committed
Merge branch 'master' into xray-gettingstarted
2 parents 1f84d67 + c64ae88 commit 79b2cf8

File tree

7 files changed

+82
-4
lines changed

7 files changed

+82
-4
lines changed

.ebextensions/env.config

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
Parameters:
2+
EmailAddress:
3+
Type: String
4+
5+
16
option_settings:
7+
aws:elasticbeanstalk:customoption:
8+
NotificationEmail: [email protected]
29
aws:elasticbeanstalk:application:environment:
310
AWS_REGION: '`{"Ref" : "AWS::Region"}`'
11+
NOTIFICATION_TOPIC: '`{"Ref" : "NotificationTopic"}`'
12+
NOTIFICATION_EMAIL: '`{"Ref" : "EmailAddress"}`'

.ebextensions/sns-topic.config

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Resources:
2+
NotificationTopic:
3+
Type: AWS::SNS::Topic
4+
Properties:
5+
Subscription:
6+
- Endpoint: {"Ref" : "EmailAddress"}
7+
Protocol: email

README.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,22 @@ Create a Java 8 SE environment in Elastic Beanstalk to host the application.
2222
3. When your environment is ready, the console redirects you to the environment Dashboard.
2323
4. Click the URL at the top of the page to open the site.
2424

25-
## Give the application permission to use DynamoDB
26-
When the Scorekeep API runs in AWS Elastic Beanstalk, it uses the permissions of its EC2 instance to call AWS. Elastic Beanstalk provides a default instance profile that you can extend to grant the application the permissions it needs to read from and write to resource tables in DynamoDB.
25+
## Give the application permission to use DynamoDB and SNS
26+
When the Scorekeep API runs in AWS Elastic Beanstalk, it uses the permissions of its EC2 instance to call AWS. Elastic Beanstalk provides a default instance profile that you can extend to grant the application the permissions it needs to read from and write to resource tables in DynamoDB, and send notifications with SNS.
2727

28-
*To add DynamoDB permissions to the instances in your Elastic Beanstalk environment*
28+
*To add DynamoDB and SNS permissions to the instances in your Elastic Beanstalk environment*
2929

3030
1. Open the Elastic Beanstalk instance profile in the IAM console: [aws-elasticbeanstalk-ec2-role](https://console.aws.amazon.com/iam/home#roles/aws-elasticbeanstalk-ec2-role)
3131
2. Click **Attach Policy**.
3232
3. Select [AmazonDynamoDBFullAccess](https://console.aws.amazon.com/iam/home#policies/arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess) and click **Attach Policy**.
33+
3. Select [AmazonSNSFullAccess](https://console.aws.amazon.com/iam/home#policies/arn:aws:iam::aws:policy/AmazonSNSFullAccess) and click **Attach Policy**.
3334

3435
## Deploy the application
3536
Deploy the source code for the project to your Elastic Beanstalk environment.
3637

3738
*To deploy the source code*
3839

39-
1. Download the source bundle: [eb-java-scorekeep-v1.zip](https://github.com/awslabs/eb-java-scorekeep/releases/download/v1.1/eb-java-scorekeep-v1.zip)
40+
1. Download the source bundle: [eb-java-scorekeep-v1.zip](https://github.com/awslabs/eb-java-scorekeep/releases/download/v1.3/eb-java-scorekeep-v1.zip)
4041
2. Open the [Elastic Beanstalk Management Console](console.aws.amazon.com/elasticbeanstalk/home).
4142
3. Click your environment's name to open the Dashboard.
4243
4. Click **Upload and Deploy**.
@@ -47,6 +48,17 @@ Deploy the source code for the project to your Elastic Beanstalk environment.
4748

4849
Click through the app to explore its functionality. Use the network console in your browser to see the HTTP requests that it sends to the API to read and write users, sessions, games, moves and game state to DynamoDB via the API.
4950

51+
## Configure Notifications
52+
The API uses Amazon SNS to send a notification email when a game ends. To enable notifications, configure your email address in an environment variable.
53+
54+
*To enable notifications*
55+
1. Open your environment's page in the [environment management console](https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/environments-console.html).
56+
2. Choose **Configuration**.
57+
3. Choose **Software Configuration**
58+
4. Under **Environment Properties**, set **NOTIFICATION_TOPIC** to your email address.
59+
5. Check your email for a subscription confirmation.
60+
6. Complete a game to trigger a notification.
61+
5062
# How it works
5163
The project includes two independent components, an HTML and JavaScript frontend in Angular 1.5 and a Java backend that uses Spring to provide a public API.
5264

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ dependencies {
3030
compile("org.springframework.boot:spring-boot-starter-web")
3131
testCompile("org.springframework.boot:spring-boot-starter-test")
3232
compile("com.amazonaws:aws-java-sdk-dynamodb")
33+
compile("com.amazonaws:aws-java-sdk-sns")
3334
compile("com.amazonaws:aws-xray-recorder-sdk-core")
3435
compile("com.amazonaws:aws-xray-recorder-sdk-aws-sdk")
3536
compile("com.amazonaws:aws-xray-recorder-sdk-aws-sdk-instrumentor")

src/main/java/scorekeep/MoveFactory.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ public Move newMove(String sessionId, String gameId, String userId, String moveT
5555
} catch ( ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { throw new RulesException(rulesName); }
5656
// save new game state
5757
State newState = new State(stateId, sessionId, gameId, newStateText, newTurn);
58+
// send notification on game end
59+
if ( newStateText.startsWith("A") || newStateText.startsWith("B")) {
60+
Utils.sendNotification("Scorekeep game completed", "Winner: " + userId);
61+
}
5862
// register state and move id to game
5963
gameController.setGameMove(sessionId, gameId, moveId);
6064
gameController.setGameState(sessionId, gameId, stateId);

src/main/java/scorekeep/Utils.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package scorekeep;
2+
3+
import com.amazonaws.regions.Regions;
4+
import com.amazonaws.services.sns.AmazonSNS;
5+
import com.amazonaws.services.sns.AmazonSNSClientBuilder;
6+
import com.amazonaws.services.sns.model.PublishRequest;
7+
import com.amazonaws.services.sns.model.PublishResult;
8+
import com.amazonaws.services.sns.model.SubscribeRequest;
9+
import org.slf4j.Logger;
10+
import org.slf4j.LoggerFactory;
11+
12+
public class Utils {
13+
private static final Logger logger = LoggerFactory.getLogger("scorekeep.Utils");
14+
private static AmazonSNS snsclient = AmazonSNSClientBuilder.standard()
15+
.withRegion(Regions.fromName(System.getenv("AWS_REGION")))
16+
.build();
17+
/*
18+
* Send a notification email.
19+
*/
20+
public static void sendNotification(String subject, String body) {
21+
String topicarn = System.getenv("NOTIFICATION_TOPIC");
22+
PublishRequest publishRequest = new PublishRequest(topicarn, body, subject);
23+
PublishResult publishResult = snsclient.publish(publishRequest);
24+
logger.info("Email sent: " + publishResult.getMessageId());
25+
}
26+
27+
/*
28+
* Create an SNS subscription.
29+
*/
30+
public static void createSubscription() {
31+
String topicarn = System.getenv("NOTIFICATION_TOPIC");
32+
String emailaddress = System.getenv("NOTIFICATION_EMAIL");
33+
SubscribeRequest subRequest = new SubscribeRequest(topicarn, "email", emailaddress);
34+
snsclient.subscribe(subRequest);
35+
}
36+
37+
}

src/main/java/scorekeep/WebConfig.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@
1313
import java.net.URL;
1414

1515

16+
import org.slf4j.Logger;
17+
import org.slf4j.LoggerFactory;
18+
1619
@Configuration
1720
public class WebConfig {
21+
private static final Logger logger = LoggerFactory.getLogger(WebConfig.class);
1822

1923
@Bean
2024
public Filter TracingFilter() {
@@ -33,5 +37,9 @@ public Filter SimpleCORSFilter() {
3337
builder.withSamplingStrategy(new LocalizedSamplingStrategy(ruleFile));
3438

3539
AWSXRay.setGlobalRecorder(builder.build());
40+
41+
if ( System.getenv("NOTIFICATION_EMAIL") != null ){
42+
Utils.createSubscription();
43+
}
3644
}
3745
}

0 commit comments

Comments
 (0)