Skip to content

Commit 879eb3c

Browse files
authored
Implement Subscription Handler (#8)
* [DURACI-6697]-Implement Subscription Handler * fix use of embeded mongo db * fix mongodbhandler for test * Implemented Review comments
1 parent 32aad51 commit 879eb3c

File tree

10 files changed

+823
-34
lines changed

10 files changed

+823
-34
lines changed

pom.xml

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<version>1.5.2.RELEASE</version>
1212
</parent>
1313

14-
<properties>
14+
<properties>
1515
<java.version>1.8</java.version>
1616
<plugin-version>0.8.6</plugin-version>
1717
<output-relative-path>src/main/java</output-relative-path>
@@ -57,6 +57,11 @@
5757
<artifactId>spring-boot-starter-amqp</artifactId>
5858
</dependency>
5959

60+
<dependency>
61+
<groupId>org.springframework.boot</groupId>
62+
<artifactId>spring-boot-starter-mail</artifactId>
63+
</dependency>
64+
6065
<dependency>
6166
<groupId>org.springframework.boot</groupId>
6267
<artifactId>spring-boot-starter-test</artifactId>
@@ -101,13 +106,8 @@
101106
<artifactId>commons-io</artifactId>
102107
<version>1.3.2</version>
103108
</dependency>
104-
<!--
105-
<dependency>
106-
<groupId>org.slf4j</groupId>
107-
<artifactId>slf4j-log4j12</artifactId>
108-
<version>1.7.25</version>
109-
</dependency>
110-
-->
109+
<!-- <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId>
110+
<version>1.7.25</version> </dependency> -->
111111

112112
<!-- https://mvnrepository.com/artifact/org.json/json -->
113113
<dependency>
@@ -146,19 +146,19 @@
146146
<version>2.6.1</version>
147147
<scope>compile</scope>
148148
</dependency>
149-
<dependency>
150-
<groupId>org.apache.qpid</groupId>
151-
<artifactId>qpid-broker</artifactId>
152-
<version>6.1.3</version>
153-
<scope>test</scope>
154-
</dependency>
149+
<dependency>
150+
<groupId>org.apache.qpid</groupId>
151+
<artifactId>qpid-broker</artifactId>
152+
<version>6.1.3</version>
153+
<scope>test</scope>
154+
</dependency>
155155

156-
<dependency>
157-
<groupId>de.flapdoodle.embed</groupId>
158-
<artifactId>de.flapdoodle.embed.mongo</artifactId>
159-
<version>2.0.0</version>
160-
<scope>test</scope>
161-
</dependency>
156+
<dependency>
157+
<groupId>de.flapdoodle.embed</groupId>
158+
<artifactId>de.flapdoodle.embed.mongo</artifactId>
159+
<version>2.0.0</version>
160+
<scope>test</scope>
161+
</dependency>
162162

163163
</dependencies>
164164
<build>
@@ -168,7 +168,7 @@
168168
<artifactId>spring-boot-maven-plugin</artifactId>
169169
</plugin>
170170

171-
<!-- PhoenixNAP RAML Code Generator plugin used to generate sources
171+
<!-- PhoenixNAP RAML Code Generator plugin used to generate sources
172172
from raml -->
173173
<plugin>
174174
<groupId>com.phoenixnap.oss</groupId>
@@ -232,18 +232,18 @@
232232
</plugin>
233233

234234
<plugin>
235-
<groupId>org.apache.maven.plugins</groupId>
236-
<artifactId>maven-surefire-plugin</artifactId>
237-
<version>2.20</version>
238-
<configuration>
239-
<excludes>
240-
<exclude>${someModule.test.excludes}</exclude>
241-
</excludes>
242-
<includes>
243-
<include>${someModule.test.includes}</include>
244-
</includes>
245-
</configuration>
246-
</plugin>
235+
<groupId>org.apache.maven.plugins</groupId>
236+
<artifactId>maven-surefire-plugin</artifactId>
237+
<version>2.20</version>
238+
<configuration>
239+
<excludes>
240+
<exclude>${someModule.test.excludes}</exclude>
241+
</excludes>
242+
<includes>
243+
<include>${someModule.test.includes}</include>
244+
</includes>
245+
</configuration>
246+
</plugin>
247247

248248
</plugins>
249249
</build>
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
Copyright 2017 Ericsson AB.
3+
For a full list of individual contributors, please see the commit history.
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+
http://www.apache.org/licenses/LICENSE-2.0
8+
Unless required by applicable law or agreed to in writing, software
9+
distributed under the License is distributed on an "AS IS" BASIS,
10+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
See the License for the specific language governing permissions and
12+
limitations under the License.
13+
*/
14+
package com.ericsson.ei.subscriptionhandler;
15+
16+
import java.text.DateFormat;
17+
import java.text.SimpleDateFormat;
18+
import java.util.Date;
19+
20+
import javax.annotation.PostConstruct;
21+
22+
import org.slf4j.Logger;
23+
import org.slf4j.LoggerFactory;
24+
import org.springframework.beans.factory.annotation.Autowired;
25+
import org.springframework.beans.factory.annotation.Value;
26+
import org.springframework.http.HttpStatus;
27+
import org.springframework.stereotype.Component;
28+
29+
import com.ericsson.ei.mongodbhandler.MongoDBHandler;
30+
import com.fasterxml.jackson.databind.JsonNode;
31+
import com.mongodb.BasicDBObject;
32+
import com.mongodb.util.JSON;
33+
34+
/**
35+
* This class represents the REST POST notification mechanism and the alternate
36+
* way to save the aggregatedObject details in the database when the
37+
* notification fails.
38+
*
39+
* @author xjibbal
40+
*
41+
*/
42+
43+
@Component
44+
public class InformSubscription {
45+
46+
@Value("${notification.failAttempt}")
47+
private int failAttempt;
48+
49+
@Value("${missedNotificationCollectionName}")
50+
private String missedNotificationCollectionName;
51+
52+
@Value("${missedNotificationDataBaseName}")
53+
private String missedNotificationDataBaseName;
54+
55+
@Value("${notification.ttl.value}")
56+
private int ttlValue;
57+
58+
@Autowired
59+
SpringRestTemplate restTemplate;
60+
61+
@Autowired
62+
MongoDBHandler mongoDBHandler;
63+
64+
@Autowired
65+
SendMail sendMail;
66+
67+
static Logger log = (Logger) LoggerFactory.getLogger(InformSubscription.class);
68+
69+
/**
70+
* This method extracts the mode of notification through which the
71+
* subscriber should be notified, from the subscription Object. And if the
72+
* notification fails, then it saved in the database.
73+
*
74+
* @param aggregatedObject
75+
* @param subscriptionJson
76+
*/
77+
public void informSubscriber(String aggregatedObject, JsonNode subscriptionJson) {
78+
String subscriptionName = subscriptionJson.get("subscriptionName").toString().replaceAll("^\"|\"$", "");
79+
log.info("SubscriptionName : " + subscriptionName);
80+
String notificationType = subscriptionJson.get("notificationType").toString().replaceAll("^\"|\"$", "");
81+
log.info("NotificationType : " + notificationType);
82+
String notificationMeta = subscriptionJson.get("notificationMeta").toString().replaceAll("^\"|\"$", "");
83+
log.info("NotificationMeta : " + notificationMeta);
84+
if (notificationType.trim().equals("REST_POST")) {
85+
log.info("Notification through REST_POST");
86+
int result = restTemplate.postData(aggregatedObject, notificationMeta);
87+
if (result == HttpStatus.OK.value()) {
88+
log.info("The result is : " + result);
89+
} else {
90+
for (int i = 0; i < failAttempt; i++) {
91+
result = restTemplate.postData(aggregatedObject, notificationMeta);
92+
log.info("After trying for " + (i + 1) + " times, the result is : " + result);
93+
if (result == HttpStatus.OK.value())
94+
break;
95+
}
96+
if (result != HttpStatus.OK.value()) {
97+
String input = prepareMissedNotification(aggregatedObject, subscriptionName, notificationMeta);
98+
log.info("Input missed Notification document : " + input);
99+
mongoDBHandler.createTTLIndex(missedNotificationDataBaseName, missedNotificationCollectionName,
100+
"Time", ttlValue);
101+
boolean output = mongoDBHandler.insertDocument(missedNotificationDataBaseName,
102+
missedNotificationCollectionName, input);
103+
log.info("The output of insertion of missed Notification : " + output);
104+
if (output == false) {
105+
log.info("failed to insert the notification into database");
106+
} else
107+
log.info("Notification saved in the database");
108+
}
109+
if (notificationType.equals("EMAIL")) {
110+
log.info("Notification through EMAIL");
111+
sendMail.sendMail(notificationMeta, aggregatedObject);
112+
113+
}
114+
}
115+
}
116+
}
117+
118+
/**
119+
* This method saves the missed Notification into a single document along
120+
* with Subscription name, notification meta and time period.
121+
*
122+
* @param aggregatedObject
123+
* @param subscriptionName
124+
* @param notificationType
125+
*
126+
* @return String
127+
*/
128+
public String prepareMissedNotification(String aggregatedObject, String subscriptionName, String notificationMeta) {
129+
String time = null;
130+
Date date = null;
131+
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
132+
date = new Date();
133+
time = dateFormat.format(date);
134+
try {
135+
date = dateFormat.parse(time);
136+
} catch (Exception e) {
137+
log.info(e.getMessage(), e);
138+
}
139+
BasicDBObject document = new BasicDBObject();
140+
document.put("subscriptionName", subscriptionName);
141+
document.put("notificationMeta", notificationMeta);
142+
document.put("Time", date);
143+
document.put("AggregatedObject", JSON.parse(aggregatedObject));
144+
return document.toString();
145+
}
146+
147+
/**
148+
* This method is responsible to display the configurable application
149+
* properties and to create TTL index on the missed Notification collection.
150+
*/
151+
@PostConstruct
152+
public void init() {
153+
log.debug("missedNotificationCollectionName : " + missedNotificationCollectionName);
154+
log.debug("missedNotificationDataBaseName : " + missedNotificationDataBaseName);
155+
log.debug("notification.failAttempt : " + failAttempt);
156+
log.debug("Missed Notification TTL value : " + ttlValue);
157+
}
158+
159+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
Copyright 2017 Ericsson AB.
3+
For a full list of individual contributors, please see the commit history.
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+
http://www.apache.org/licenses/LICENSE-2.0
8+
Unless required by applicable law or agreed to in writing, software
9+
distributed under the License is distributed on an "AS IS" BASIS,
10+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
See the License for the specific language governing permissions and
12+
limitations under the License.
13+
*/
14+
package com.ericsson.ei.subscriptionhandler;
15+
16+
import java.util.Iterator;
17+
18+
import org.slf4j.Logger;
19+
import org.slf4j.LoggerFactory;
20+
import org.springframework.beans.factory.annotation.Autowired;
21+
import org.springframework.stereotype.Component;
22+
23+
import com.ericsson.ei.jmespath.JmesPathInterface;
24+
import com.fasterxml.jackson.databind.JsonNode;
25+
import com.fasterxml.jackson.databind.ObjectMapper;
26+
import com.fasterxml.jackson.databind.node.ArrayNode;
27+
28+
/**
29+
* This class represents the mechanism to fetch the rule conditions from the
30+
* Subscription Object and match it with the aggregatedObject to check if it is
31+
* true.
32+
*
33+
* @author xjibbal
34+
*
35+
*/
36+
37+
@Component
38+
public class RunSubscription {
39+
40+
@Autowired
41+
private JmesPathInterface jmespath;
42+
43+
static Logger log = (Logger) LoggerFactory.getLogger(RunSubscription.class);
44+
45+
/**
46+
* This method matches every condition specified in the subscription Object
47+
* and if all conditions are matched then only the aggregatedObject is
48+
* eligible for notification via e-mail or REST POST.
49+
*
50+
* @param aggregatedObject
51+
* @param requirement
52+
* @param subscriptionJson
53+
* @return boolean
54+
*/
55+
public boolean runSubscriptionOnObject(String aggregatedObject, ArrayNode fulfilledRequirements,
56+
JsonNode subscriptionJson) {
57+
Iterator<JsonNode> requirementIterator = fulfilledRequirements.elements();
58+
boolean conditionFulfilled = false;
59+
while (requirementIterator.hasNext()) {
60+
JsonNode requirement = requirementIterator.next();
61+
log.info("The fulfilled requirement which will condition checked is : " + requirement.toString());
62+
ArrayNode conditions = (ArrayNode) requirement.get("conditions");
63+
log.info("Conditions of the subscription : " + conditions.toString());
64+
Iterator<JsonNode> conditionIterator = conditions.elements();
65+
// boolean conditionFulfilled = false;
66+
while (conditionIterator.hasNext()) {
67+
String rule = conditionIterator.next().get("jmespath").toString().replaceAll("^\"|\"$", "");
68+
String new_Rule = rule.replace("'", "\"");
69+
log.info("Rule : " + rule);
70+
log.info("New Rule after replacing single quote : " + new_Rule);
71+
JsonNode result = jmespath.runRuleOnEvent(rule, aggregatedObject);
72+
log.info("Result : " + result.toString());
73+
if (result.toString() != null) {
74+
conditionFulfilled = true;
75+
}
76+
}
77+
}
78+
log.info("The final value of conditionFulfilled is : " + conditionFulfilled);
79+
return conditionFulfilled;
80+
81+
}
82+
83+
/**
84+
* This method check if the subscription requirement type and the
85+
* aggregatedObject type are same.
86+
*
87+
* @param requirementIterator
88+
* @param aggregatedObject
89+
* @return JsonNode
90+
*/
91+
public ArrayNode checkRequirementType(Iterator<JsonNode> requirementIterator, String aggregatedObject) {
92+
ArrayNode fulfilledRequirements = new ObjectMapper().createArrayNode();
93+
;
94+
JsonNode requirement = null;
95+
JsonNode aggregatedJson = null;
96+
boolean condition = false;
97+
try {
98+
aggregatedJson = new ObjectMapper().readTree(aggregatedObject);
99+
log.info("AggregatedJson : " + aggregatedJson.toString());
100+
} catch (Exception e) {
101+
log.error(e.getMessage(), e);
102+
}
103+
String aggregatedType = aggregatedJson.get("type").toString();
104+
log.info("AggregatedType : " + aggregatedType.toString());
105+
while (requirementIterator.hasNext()) {
106+
requirement = requirementIterator.next();
107+
log.info("Requirements : " + requirement.toString());
108+
String requirementType = requirement.get("type").toString();
109+
log.info("Type of Subscription : " + requirementType);
110+
if (aggregatedType.equals(requirementType)) {
111+
log.info("Both the requirement types are equal");
112+
condition = true;
113+
log.info("The fulfilled requirement is : " + requirement.toString());
114+
fulfilledRequirements.add(requirement);
115+
} else
116+
log.info("Both requirement types are not equal");
117+
}
118+
if (condition == true)
119+
return fulfilledRequirements;
120+
else
121+
return null;
122+
}
123+
124+
}

0 commit comments

Comments
 (0)