Skip to content

Enable specification of domain id for event generation #223

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 2.1.11
- REST API parameter `domainId` added.

## 2.1.10
- Mockito framework upgraded to 5.3.1

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.ericsson.eiffel.remrem.generate.constants.RemremGenerateServiceConstants;
import com.ericsson.eiffel.remrem.generate.exception.REMGenerateException;
import com.ericsson.eiffel.remrem.protocol.MsgService;
import com.ericsson.eiffel.remrem.semantics.schemas.EiffelConstants;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
Expand Down Expand Up @@ -77,6 +78,11 @@ public class RemremGenerateController {
@Value("${lenientValidationEnabledToUsers:false}")
private boolean lenientValidationEnabledToUsers;

public static final String PARAM_GENERATE_EIFFEL_DOMAIN_ID = "generate.eiffel.domainId";
@Value("${" + PARAM_GENERATE_EIFFEL_DOMAIN_ID + ":#{null}}")
private String defaultDomainId;
private boolean defaultDomainIdStripped = false;

public void setLenientValidationEnabledToUsers(boolean lenientValidationEnabledToUsers) {
this.lenientValidationEnabledToUsers = lenientValidationEnabledToUsers;
}
Expand All @@ -87,6 +93,115 @@ public void setRestTemplate(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}

// TODO Should be moved to semantics library
public static final String EiffelConstants_SOURCE = "source";
public static final String EiffelConstants_ID = "id";
public static final String EiffelConstants_DOMAIN_ID = "domainId";

private static final String DOMAIN_ID_FULL_PATH = EiffelConstants.META + "." +
EiffelConstants_SOURCE + "." + EiffelConstants_DOMAIN_ID;

private String getDefaultDomainId() {
if (defaultDomainId != null && !defaultDomainIdStripped) {
String strippedDefaultDomainId = defaultDomainId.strip();
defaultDomainIdStripped = true;
if (strippedDefaultDomainId.isBlank()) {
defaultDomainId = null;
log.error("Value of configuration parameter '" + PARAM_GENERATE_EIFFEL_DOMAIN_ID +
"' is blank ('" + strippedDefaultDomainId + "'); ignoring...");
}
}

return defaultDomainId;
}

protected void addDomainId(JsonObject generated, String domainId) {
// Handle default domain ID.
JsonObject meta = generated.getAsJsonObject().getAsJsonObject(EiffelConstants.META);
if (meta == null) {
// Nothing to do.
log.warn("Generated event doesn't contain '" + EiffelConstants.META + "' section; strange...");
return;
}

JsonElement idElement = meta.get(EiffelConstants_ID);
String id = null;
if (idElement != null) {
id = idElement.getAsString();
}

JsonObject source = meta.getAsJsonObject(EiffelConstants_SOURCE);
if (source == null) {
// Nothing to do.
log.warn("[" + id + "] Generated event doesn't contain '" + EiffelConstants.META +
"." + EiffelConstants_SOURCE + "' section; strange...");
return;
}

// Is domainId present in generated event?
JsonElement existingDomainIdElement = source.get(EiffelConstants_DOMAIN_ID);
String existingDomainId = null;
String strippedExistingDomainId = null;
boolean existingDomainIdIsValid = false;
if (existingDomainIdElement != null) {
existingDomainId = existingDomainIdElement.getAsString();
strippedExistingDomainId = existingDomainId.strip();
existingDomainIdIsValid = !strippedExistingDomainId.isBlank();
}

String defaultDomainId = getDefaultDomainId();
String domainIdToSet = null;
String domainIdInfoMessage = null;
if (domainId != null) {
// Use domain ID passed as REST API param. This is the highest-priority
// value and is used whenever available.
String strippedDomainId = domainId.strip();
if (!strippedDomainId.isBlank()) {
domainIdToSet = strippedDomainId;
domainIdInfoMessage = "[" + id + "] Setting '" + DOMAIN_ID_FULL_PATH + "' to '" + domainIdToSet +
"', value of RESTAPI param '" + RESTAPI_PARAM_DOMAIN_ID + "'";
}
else {
log.warn("Value of REST API parameter '" + RESTAPI_PARAM_DOMAIN_ID + "' is blank; ignoring...");
}
}
else {
// Domain id not specified by REST API or its value is not valid.
// Try to use default value from configuration file.
if (defaultDomainId != null) {
// Default value is available.
if (existingDomainIdIsValid) {
// Value of domainId in generated event exists and is valid, keep it.
}
else {
domainIdToSet = defaultDomainId;

domainIdInfoMessage = "[" + id + "] Setting '" + DOMAIN_ID_FULL_PATH + "' to '" + domainIdToSet +
"', value of configuration param '" + PARAM_GENERATE_EIFFEL_DOMAIN_ID + "'";
}
}
}

if (domainIdToSet != null) {
if (existingDomainIdElement != null) {
if (domainIdToSet == defaultDomainId && !existingDomainIdIsValid) {
// Value of domainId of generated event is not valid and will be replaced
// by defaultDomainId.
log.warn("[" + id + "] Element '" + DOMAIN_ID_FULL_PATH + "' of event exists," +
"but is invalid ('" + existingDomainId + "') and will be replaced");
}

// Element domainId already exists, remove it first.
source.remove(EiffelConstants_DOMAIN_ID);
}

log.info(domainIdInfoMessage);
source.addProperty(EiffelConstants_DOMAIN_ID, domainIdToSet);
}
}

public static final String RESTAPI_PARAM_DOMAIN_ID = "domainId";

/**
* Returns event information as json element based on the message protocol,
* taking message type and json body as input.
Expand All @@ -113,6 +228,7 @@ public ResponseEntity<?> generate(
@ApiParam(value = RemremGenerateServiceConstants.LOOKUP_IN_EXTERNAL_ERS) @RequestParam(value = "lookupInExternalERs", required = false, defaultValue = "false") final Boolean lookupInExternalERs,
@ApiParam(value = RemremGenerateServiceConstants.LOOKUP_LIMIT) @RequestParam(value = "lookupLimit", required = false, defaultValue = "1") final int lookupLimit,
@ApiParam(value = RemremGenerateServiceConstants.LenientValidation) @RequestParam(value = "okToLeaveOutInvalidOptionalFields", required = false, defaultValue = "false") final Boolean okToLeaveOutInvalidOptionalFields,
@ApiParam(value = "Domain ID") @RequestParam(value = RESTAPI_PARAM_DOMAIN_ID, required = false, defaultValue = "") final String domainId,
@ApiParam(value = "JSON message", required = true) @RequestBody JsonObject bodyJson) {

try {
Expand All @@ -122,6 +238,8 @@ public ResponseEntity<?> generate(
if (msgService != null) {
response = msgService.generateMsg(msgType, bodyJson, isLenientEnabled(okToLeaveOutInvalidOptionalFields));
JsonElement parsedResponse = parser.parse(response);
addDomainId(parsedResponse.getAsJsonObject(), domainId);

if(lookupLimit <= 0) {
return new ResponseEntity<>("LookupLimit must be greater than or equals to 1", HttpStatus.BAD_REQUEST);
}
Expand Down
4 changes: 3 additions & 1 deletion service/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,6 @@ event-repository.enabled: false
event-repository.url: http://<host>:<port>/<context-path-if-available>

# lenientValidationEnabledToUsers true will perform the validation only on mandatory fields, non-mandatory validation failures add into Eiffel message as property remremGenerateFailures
lenientValidationEnabledToUsers: false
lenientValidationEnabledToUsers: false

generate.source.domainId: test-domain
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ public void testErlookupSuccesswithMultipleIds() throws Exception {
JsonParser parser = new JsonParser();
JsonObject json = parser.parse(new FileReader(file)).getAsJsonObject();

ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelconfidencelevel", false, false, true, 1, false, json);
ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelconfidencelevel", false, false, true, 1, false, null, json);
assertEquals(elem.getStatusCode(), HttpStatus.OK);
}

Expand All @@ -229,7 +229,7 @@ public void testErlookupMultipleFound() throws Exception {
JsonParser parser = new JsonParser();
JsonObject json = parser.parse(new FileReader(file)).getAsJsonObject();

ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelcompositiondefined", true, false, true, 1, false, json);
ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelcompositiondefined", true, false, true, 1, false, null, json);
assertEquals(elem.getStatusCode(), HttpStatus.EXPECTATION_FAILED);
}

Expand All @@ -239,7 +239,7 @@ public void testErlookupMultipleTraces() throws Exception {
JsonParser parser = new JsonParser();
JsonObject json = parser.parse(new FileReader(file)).getAsJsonObject();

ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelartifactpublished", false, true, true, 1, false, json);
ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelartifactpublished", false, true, true, 1, false, null, json);
assertEquals(elem.getStatusCode(), HttpStatus.BAD_REQUEST);
}

Expand All @@ -249,7 +249,7 @@ public void testErlookupSuccesswithOneId() throws Exception {
JsonParser parser = new JsonParser();
JsonObject json = parser.parse(new FileReader(file)).getAsJsonObject();

ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelCompositionDefined", true, true, true, 1, false, json);
ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelCompositionDefined", true, true, true, 1, false, null, json);
assertEquals(elem.getStatusCode(), HttpStatus.OK);
}

Expand All @@ -259,7 +259,7 @@ public void testErlookupNoneFound() throws Exception {
JsonParser parser = new JsonParser();
JsonObject json = parser.parse(new FileReader(file)).getAsJsonObject();

ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelCompositionDefinedEvent", true, true, true, 1, false, json);
ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelCompositionDefinedEvent", true, true, true, 1, false, null, json);
assertEquals(elem.getStatusCode(), HttpStatus.NOT_ACCEPTABLE);
}

Expand All @@ -269,7 +269,7 @@ public void testErlookupMultipleTrace() throws Exception {
JsonParser parser = new JsonParser();
JsonObject json = parser.parse(new FileReader(file)).getAsJsonObject();

ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelSCSubmitted", false, true, true, 1, false, json);
ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelSCSubmitted", false, true, true, 1, false, null, json);
assertEquals(elem.getStatusCode(), HttpStatus.BAD_REQUEST);
}

Expand All @@ -279,7 +279,7 @@ public void testErlookupOptions() throws Exception {
JsonParser parser = new JsonParser();
JsonObject json = parser.parse(new FileReader(file)).getAsJsonObject();

ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelEnvironmentDefined", false, false, true, 2, false, json);
ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelEnvironmentDefined", false, false, true, 2, false, null, json);
assertEquals(elem.getStatusCode(), HttpStatus.OK);
}

Expand All @@ -289,7 +289,7 @@ public void testErlookupOptionsWithEmptyResponse() throws Exception {
JsonParser parser = new JsonParser();
JsonObject json = parser.parse(new FileReader(file)).getAsJsonObject();

ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelEnvironmentDefinedEvent", true, true, true, 2, false, json);
ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelEnvironmentDefinedEvent", true, true, true, 2, false, null, json);
assertEquals(elem.getStatusCode(), HttpStatus.OK);
}

Expand All @@ -299,7 +299,7 @@ public void testErlookupOptionsWithMultipleFound() throws Exception {
JsonParser parser = new JsonParser();
JsonObject json = parser.parse(new FileReader(file)).getAsJsonObject();

ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelCompositionDefinedEventt", false, false, true, 2, false, json);
ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelCompositionDefinedEventt", false, false, true, 2, false, null, json);
assertEquals(elem.getStatusCode(), HttpStatus.EXPECTATION_FAILED);
}

Expand All @@ -309,7 +309,7 @@ public void testErlookupOptionsWithNoneFound() throws Exception {
JsonParser parser = new JsonParser();
JsonObject json = parser.parse(new FileReader(file)).getAsJsonObject();

ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelConfidenceLevelModified", false, false, true, 2, false, json);
ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelConfidenceLevelModified", false, false, true, 2, false, null, json);
assertEquals(elem.getStatusCode(), HttpStatus.NOT_ACCEPTABLE);
}

Expand All @@ -319,7 +319,7 @@ public void testErlookupFailedWithOptions() throws Exception {
JsonParser parser = new JsonParser();
JsonObject json = parser.parse(new FileReader(file)).getAsJsonObject();

ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelTestCaseStarted", false, false, true, 2, false, json);
ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelTestCaseStarted", false, false, true, 2, false, null, json);
assertEquals(elem.getStatusCode(), HttpStatus.UNPROCESSABLE_ENTITY);
}

Expand All @@ -329,7 +329,7 @@ public void testErLookUpLimitZero() throws Exception {
JsonParser parser = new JsonParser();
JsonObject json = parser.parse(new FileReader(file)).getAsJsonObject();

ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelTestCaseStarted", false, false, true, 0, false, json);
ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelTestCaseStarted", false, false, true, 0, false, null, json);
assertEquals(elem.getStatusCode(), HttpStatus.BAD_REQUEST);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,38 +111,38 @@ public void setUp() throws Exception {

@Test
public void testSemanticsSuccessEvent() throws Exception {
ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelactivityfinished", false, false, true, 1, false, body.getAsJsonObject());
ResponseEntity<?> elem = unit.generate("eiffelsemantics", "eiffelactivityfinished", false, false, true, 1, false, null, body.getAsJsonObject());
assertEquals(elem.getStatusCode(), HttpStatus.OK);
}

@Test
public void testSemanticsFailureEvent() throws Exception {
ResponseEntity<?> elem = unit.generate("eiffelsemantics", "EiffelActivityFinished", false, false, true, 1, false, body.getAsJsonObject());
ResponseEntity<?> elem = unit.generate("eiffelsemantics", "EiffelActivityFinished", false, false, true, 1, false, null, body.getAsJsonObject());
assertEquals(elem.getStatusCode(), HttpStatus.BAD_REQUEST);
}

@Test
public void testEiffel3SuccessEvent() throws Exception {
ResponseEntity<?> elem = unit.generate("eiffel3", "eiffelartifactnew", false, false, true, 1, false, body.getAsJsonObject());
ResponseEntity<?> elem = unit.generate("eiffel3", "eiffelartifactnew", false, false, true, 1, false, null, body.getAsJsonObject());
assertEquals(elem.getStatusCode(), HttpStatus.OK);
}

@Test
public void testEiffel3FailureEvent() throws Exception {
ResponseEntity<?> elem = unit.generate("eiffel3", "eiffelartifactnewevent", false, false, true, 1, false, body.getAsJsonObject());
ResponseEntity<?> elem = unit.generate("eiffel3", "eiffelartifactnewevent", false, false, true, 1, false, null, body.getAsJsonObject());
assertEquals(elem.getStatusCode(), HttpStatus.BAD_REQUEST);
}

@Test
public void testMessageServiceUnavailableEvent() throws Exception {
ResponseEntity<?> elem = unit.generate("other", "EiffelActivityFinishedEvent", false, false, true, 1, false, body.getAsJsonObject());
ResponseEntity<?> elem = unit.generate("other", "EiffelActivityFinishedEvent", false, false, true, 1, false, null, body.getAsJsonObject());
assertEquals(elem.getStatusCode(), HttpStatus.SERVICE_UNAVAILABLE);
}

@Test
public void testlenientValidation() throws Exception {
unit.setLenientValidationEnabledToUsers(true);
ResponseEntity<?> elem = unit.generate("eiffelsemantics", "EiffelArtifactCreatedEvent", false, false, true, 1, true, body.getAsJsonObject());
ResponseEntity<?> elem = unit.generate("eiffelsemantics", "EiffelArtifactCreatedEvent", false, false, true, 1, true, null, body.getAsJsonObject());
assertEquals(elem.getStatusCode(), HttpStatus.OK);
}

Expand Down
8 changes: 4 additions & 4 deletions service/src/test/resources/ActivityFinished.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
"msgParams": {
"meta": {
"type": "EiffelActivityFinishedEvent",
"version": "3.0.0",
"version": "4.0.0",
"tags": [
"tag1",
"tag2"
"tag2",
"tag3"
],
"source": {
"domainId": "domainID",
"host": "host",
"name": "name",
"uri": "http:\/\/java.sun.com\/j2se\/1.3\/"
"uri": "http:\/\/java.sun.com\/j3se\/1.3\/"
}
}
},
Expand Down
21 changes: 20 additions & 1 deletion wiki/markdown/usage/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ When using maven command, Spring properties can also be changed by editing servi

Eiffel REMReM Service **generate-service.war** file should be deployed in Tomcat Server. For doing this, generate-service.war file should deployed in directory: _tomcat/webapps_.

Configuration is done in Tomcat using a config.properties file:�_tomcat/conf/config.properties_.
Configuration is done in Tomcat using a config.properties file:�_tomcat/conf/config.properties_.

**NOTE:** in each example assuming the generate-service.war is deployed in tomcat as **generate**.

Expand Down Expand Up @@ -164,3 +164,22 @@ More about [Lenient Validation](../usage/lenientvalidation.md).
```
lenientValidationEnabledToUsers : <true | false>
```

### Configuration of Default Domain Identifier
Default domain identifier can be specified using property `generate.source.domainId`:
```
generate.source.domainId: <string>
```
The default domain ID is used by endpoint `/` and presents it as value of property
`msgParams.meta.source.domainId` unless the property is specified by submitted
template or REST API param `domainId` of request to endpoint `/`.

Note, that domain identifier can be submitted in several ways:
1. application property `generate.source.domainId`;
2. REST API request parameter `domainId`, see section [Usage](../service.md#usage);
3. property `msgParams.meta.source.domainId` sent as part of REST API parameter bodyJson.

and they are prioritized like follows:
* if case 3. is specified, cases 2. and 1. are ignored;
* if case 2. is submitted, case 1. is ignored;
* domain id given by case 1. is used when neither case 3. nor case 2. is applied.
Loading