Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 10 Next »

An example Webhook consumer service set up using Java and Spring Boot, which will be used for validation of object properties using catalogs. Such webhooks can be used, when a certain String-property can only be a value, that is contained within a specified catalog. In this case this webhook service will provide one 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 are derived from Spring Boot. Thus, a JDK version 1.8 or later and Maven 3.2 or later are required.

Also a running instance of a Catalog-Service is required, as well as the existence of the catalog within the system, that will be checked against.

The object property, which should be validated, must also exist in the system scheme.

Setting up the Webhook Service

To implement processing of incoming metadata using our 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 the RequestMapping annotation of the controller class and the PostMapping annotation of the endpoint method will need to find its way into the system hook configuration of our yuuvis® Momentum system. We will also define a method for working with the incoming metadata, which we will call from within our endpoint method.

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 Incomming Metadata

This is the core of the service. Create the class propertyValidationService and annotate it as @Service. This indicates that it holds the business logic and will communicate with the repository layer.

First we will set the object property name, which we want to validate. After that the name of the wanted catalog must be specified.

Set PropertyId and Name of the Catalog
final String propertyId = "[Name of property]";
final String catalogueName = "[Name of catalog]";

Then we will implement our metadata handling method validateObject. Here we will iterate through the imported or updated object and search for the requested property. When the property is found, it and the authorization token will be send to the private validation method validateProperty.

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.

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 is a private method within our service. It ensures that the given property String 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 successful response it logs the success of the result and finishes the import or update of the object.

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 (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 class.

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 configuration (SpEL) and save it to the configuration server. Here 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 the predicate for the webhook's initialisation. In this example we want our webhook to be activated when an object is being imported or updated and has the property "Name" assigned.

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 catalogs. Find the complete code project described in this tutorial in this GitHub Repository.

  • No labels