Page Properties |
---|
|
Product Version |
|
---|
Report Note |
|
---|
Assignee |
|
---|
Resources & Remarks Modification History Name | Date | Product Version | Action |
---|
Nils / Mihail | 01 NOV 2021 | 2021 Winter | created, written, rDEV | Antje | 02 NOV 2021 | 2021 Winter | rDOC |
|
Excerpt |
---|
An example Webhook consumer service set up using Java and Spring Boot |
...
for the validation of object properties using catalogs |
...
Section |
---|
|
Column |
---|
Table of Contents Table of Contents |
---|
exclude | (Table of Contents|Read on|systemHookConfiguration.json|Webhooks|CATALOG Service) |
---|
|
|
|
Introduction
For some properties of your DMS objects managed by yuuvis® Momentum, you might want to allow only certain string values that are defined in a catalog. One possible way to implement such a custom validation is the usage of a webhook dms.request.objects.upsert.database-before that is calling the CATALOG Service. In this tutorial, you will be guided through the set up of such an example webhook consumer service. It verifies that the value of a certain string property is contained in a specified catalog. Thus, this webhook service will provide one an extra validation layer for object import and/or update.
Requirements
In this tutorial, we'll create a Spring Boot Service using Java, meaning the requirements for the proejct project are derived from Spring Boot. Thus, a JDK version 1.8 or later and Maven 3.2 or later are required.
Also Furthermore, a running instance of a Catalog-the CATALOG Service is required, as well as the existence of the catalog within the system, that will be checked againsta global catalog against which the example webhook checks the property values.
The object property , which should be validated, must also exist be defined in the system scheme global schema that is available in all tenants.
Setting up the Webhook Service
To implement the processing of incoming metadata using our example webhook service, we need to configure an endpoint within a controller class of our Webhook Service. In this instance ValidationWebhookRestController
. The URL we define between class with the corresponding validation endpoint. In the example code block below, we define the class ValidationWebhookRestController
with the method validateObjectProperty
. The URL defined in the RequestMapping
annotation of the controller class and the PostMapping
annotation of the endpoint method will need to find its way into be referenced in the system hook configuration of our yuuvis® Momentum system as shown later in this article. We will also define a method the method propertyValidationService.validateObject
for working with the incoming metadata, which we will call from is called within our endpoint method.
Code Block |
---|
language | java |
---|
title | Controller Class with Endpoint for Webhook Consumption |
---|
|
@RestController
@RequestMapping("/api/dms/request")
public class ValidationWebhookRestController
{
@Autowired
private PropertyValidationService propertyValidationService;
@PostMapping(value = "/upsert", produces = {"application/json"})
public Map<String, Object> validateObjectProperty (@RequestBody Map<String, Object> dmsApiObjectList,
@RequestHeader(value = "Authorization", required = true) String authorization) throws HookException {
this.propertyValidationService.validateObject(dmsApiObjectList, authorization);
return dmsApiObjectList;
}
} |
Creating the Validation Service for
...
Incoming Metadata
This is the core of the heart of our example webhook consumer service. Create the class propertyValidationService
and annotate it as @Service
. This indicates that it holds the business logic and will communicate with the repository layerREPOSITORY service.
First we will set Within the class, we firstly specify the object property name, which we want to validate. After that Secondly, we specify the name of the wanted catalog must be specifiedcatalog against which we want to validate.
Code Block |
---|
language | java |
---|
title | Set PropertyId and Name of the Catalog |
---|
|
final String propertyId = "[Name of property]";
final String catalogueName = "[Name of catalog]"; |
Then Now we will implement our method validateObject
for metadata handling method validateObject
. Here, we will iterate through the imported or updated object and search for the requested property . When by using a method from the utility class PropertyUtils
. If the property is found, it and the authorization token will be is send to the private validation method validateProperty
together with the authentication token.
Code Block |
---|
language | java |
---|
title | Method for handling incomming Metadata |
---|
|
public void validateObject(Map<String, Object> dmsApiObjectList, String authorization) throws HookException
{
String propertyValue = null;
//Get object properties and send for validation
List<Map<String, Object>> newObjectList = (List<Map<String, Object>>) dmsApiObjectList.get("objects");
for (Map<String, Object> newObject : newObjectList) {
propertyValue = (String) PropertyUtils.getPropertyValue(newObject, propertyId);
validateProperty(propertyValue, authorization);
}
} |
The way of getting the right property is by using the class PropertyUtils
.utility class PropertyUtils
providing the above referenced method getPropertyValues
we implement as follows:
Code Block |
---|
language | java |
---|
title | PropertyUtils class for iterating through a objects' Metadata |
---|
|
public static Object getPropertyValue(Map<String, Object> object, String propertyId)
{
@SuppressWarnings("unchecked")
Map<String, Object> properties = (Map<String, Object>)object.get("properties");
return getValue(properties, propertyId);
}
private static Object getValue(Map<String, Object> properties, String propertyId)
{
@SuppressWarnings("unchecked")
Map<String, Object> property = (Map<String, Object>)properties.get(propertyId);
if(property != null)
{
return property.get("value");
}
return null;
} |
The validateProperty
method shown in the next code block is a private method within our example service. It ensures that the string given property String as propertyValue
is not empty or null
and then proceeds to create and send a HEAD request for validating the property using the given catalog name. On a Each successful response it logs the success of the result and finishes is logged and the import or update of the object is finished. In case of a failed validation, the method throws a HookException
as defined below.
Code Block |
---|
language | java |
---|
title | Method for validating a Property |
---|
|
private void validateProperty (String propertyValue, String authorization) throws HookException {
//Validate property with catalogue entry
if (propertyValue != null) {
if (!propertyValue.isBlank()) {
String url = "http://catalog/api/catalogs/" + catalogueName + "/" + propertyValue;
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", authorization);
HttpEntity requestEntity = new HttpEntity<>(null, headers);
try {
ResponseEntity<Void> response =
this.restTemplate.exchange(url, HttpMethod.HEAD, requestEntity, Void.class);
if (HttpStatus.OK.equals(response.getStatusCode().is2xxSuccessful()) {
LOGGER.debug("Property [" + propertyValue + "] validation was successful");
} else {
throw new HookException("Catalogue [" + catalogueName + "] does not exist or property [" + propertyValue + "] does not match any catalogue entry.");
}
} catch (HttpStatusCodeException e) {
if (HttpStatus.NOT_FOUND.equals(e.getStatusCode())) {
throw new HookException("Catalogue [" + catalogueName + "] does not exist or property [" + propertyValue + "] does not match any catalogue entry.");
} else {
//Error handling
throw new HookException("Something went wrong.");
}
}
} else {
throw new HookException("The property [" + propertyId + "] is empty.");
}
} else {
LOGGER.debug("This object does not have the property: " + propertyId);
}
} |
On a failed response the service throws a HookException from a custom HookException classThe following code block shows the definition of the HookException
realized in the custom class HookException
.
Code Block |
---|
language | java |
---|
title | HookException |
---|
|
public class HookException extends Exception
{
private static final long serialVersionUID = 1L;
public HookException(String message)
{
super(message);
}
public HookException(String string, Throwable exception)
{
super(string,exception);
}
} |
Webhook System Configuration
In the systemHookConfiguration.json
file, add the folowing following configuration (SpEL) and save it to the configuration server. Here In this configuration, we will specify the type of our validation webhook dms.request.objects.database-before
and its URL http://validationWebhook/api/dms/request/upsert
. Also here we will set We also specify the predicate for triggering of the webhook's initialisation. In this example, we want our webhook to be activated when if an object is being imported or updated and that has the property "Name" assigned.
Code Block |
---|
title | Webhook Configuration |
---|
|
{
"enable": true,
"predicate": "spel:properties['Name']!=null && (properties['Name']['value'])!=null",
"type": "dms.request.objects.upsert.database-before",
"url": "http://validationWebhook/api/dms/request/upsert",
"useDiscovery": true
} |
Summary
In this tutorial we went through the steps of creating and configuring a webhook service for validating object properties using catalogsa catalog. Find the complete code project described in this tutorial in this GitHub Repository.
>> GitHub
Info |
---|
|
Read on
Section |
---|
Column |
---|
| Insert excerpt |
---|
| CATALOG Service |
---|
| CATALOG Service |
---|
nopanel | true |
---|
| Keep reading
|
Column |
---|
| Insert excerpt |
---|
| systemHookConfiguration.json |
---|
| systemHookConfiguration.json |
---|
nopanel | true |
---|
| Keep reading
|
Column |
---|
| Insert excerpt |
---|
| Webhooks |
---|
| Webhooks |
---|
nopanel | true |
---|
| Keep reading
|
|
|