Guide: Using a validator via SOAP

Track

Test bed use

This guide walks you through the steps of using a validator from a client implemented in Java. The validator is accessed through its SOAP API, using the GITB validation service API, the common SOAP-based interface implemented by all validators.

The GITB validation service API allows validators to be integrated with other systems, but also makes it possible to use them as building blocks in conformance test cases.

Note

Non-Java validator clients: SOAP is platform agnostic so you can use a validator regardless of your development platform. The test bed however publishes a Java library with pre-built type classes that can be directly used in Java code (or by another JVM language).

What you will achieve

At the end of this guide you will have created a simple Java application that uses a validator through its SOAP API. This application may be used as-is or as a working example on how to integrate a validator in an existing Java application. As part of this guide you will:

  1. Create a new Java project using Apache Maven to import required basic libraries.

  2. Author the code needed to call a validator and process its validation report.

  3. Use an existing public validator to make a first validation.

What you will need

  • About 30 minutes.

  • The Java Development Kit (JDK), minimum version 11.

  • Apache Maven, minimum version 3.

  • Your preferred IDE or text editor.

  • A basic level of experience developing in Java.

  • Access to the internet.

How to complete this guide

This guide will lead you step-by-step through the process of creating a Java application that uses a validator. As an example we will be validating JSON and using the test bed’s generic JSON validator, a service that can validate arbitrary JSON content against a user-provided JSON schema. As a specific JSON example we will be considering the fictional purchase order case we saw in the JSON validation guide. For the validator’s inputs we will be referring to the JSON validator’s SOAP API documentation.

Although this tutorial focuses on JSON validation, the approach to follow for other types of validators is the same. The difference would only be in the inputs that are provided to each validator (see the relevant documentation for XML, CSV and RDF validator SOAP APIs).

Steps

Carry out the following steps to complete this guide.

Step 1: Create the project

Using your editor create an empty Java project using Maven. The project name, artifactId and groupId can be anything you please but for this tutorial we consider the following values:

  • Name: soap-sample

  • Group ID: org.example

  • Artifact ID: soap-sample

IDEs typically have simple wizards that guide you through a project’s creation process but in the end the resulting folder structure, matching the standard Maven project structure, will be as follows:

soap-sample
 |
 +-- pom.xml
 +-- src
      |
      +-- main
           |
           +-- java
           +-- resources
      +-- test
           |
           +-- java
           +-- resources

The only file that will contain some content at this point is your pom.xml file with the information you provided.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>soap-sample</artifactId>
    <version>1.0-SNAPSHOT</version>
</project>

Step 2: Define the dependencies

Edit your pom.xml file to include the following dependencies:

<dependencies>
    <dependency>
        <groupId>eu.europa.ec.itb</groupId>
        <artifactId>gitb-types</artifactId>
        <version>1.11.1</version>
    </dependency>
    <dependency>
        <groupId>com.sun.xml.ws</groupId>
        <artifactId>jaxws-rt</artifactId>
        <version>2.3.3</version>
    </dependency>
</dependencies>

The gitb-types library is provided by the test bed to include the specifications (XSDs and WSDLs) linked to the GITB service APIs. These define the web service definitions as well as their input and output XML types. This library also contains prebuilt Java classes and service stubs that can be used directly to simplify calling a service, as well as the serialisation and deserialisation of data. The specific version number matches the latest global test bed release; backwards compatibility for the GITB types is always ensured so using an old version, or a version different to the one used internally by the validator, will have no side-effects.

The jaxws-rt library provides the runtime classes needed to carry out SOAP web service operations. This is needed considering that the service stubs from gitb-types are interfaces and utility classes which lack a full web service runtime.

Both these dependencies are shared through the Maven Central Repository, meaning that any Maven installation with internet access will be able to automatically resolve them.

Note

When integrating into a full application the jaxws-rt dependency may likely be skipped given that your overall framework (e.g. Spring) will already provide web service support.

Step 3: Call the validator

Having defined our dependencies we now have everything we need to create our service client. To keep things simple we will define a single class that will also be our application’s entry point. Running this will call our validator and then exit.

Under the src/main/java folder define a new class Application in package org.example. In this class we will define our main entry point and a method that will call the validator.

package org.example;

public class Application {

    // Our entry point method.
    public static void main(String[] args) throws MalformedURLException {
        new Application().doValidation();
    }

    // The method that will call our validator (currently empty).
    private void doValidation() {
    }
}

We will now proceed to complete the doValidation method. In terms of the implementation we will keep things simple. Specifically:

  • As input we will use an online JSON sample passed as a URI.

  • In terms of output processing we will print on the console the validation findings and their details.

  • We will skip error handling and simply throw exceptions.

import com.gitb.core.AnyContent;
import com.gitb.core.ValueEmbeddingEnumeration;
import com.gitb.tr.BAR;
import com.gitb.vs.ValidateRequest;
import com.gitb.vs.ValidationResponse;
import com.gitb.vs.ValidationService_Service;

private void doValidation() throws MalformedURLException {
    // Create the request object.
    ValidateRequest request = new ValidateRequest();
    // Create the input for the content to validate and add it to the request.
    AnyContent contentToValidateInput = new AnyContent();
    contentToValidateInput.setName("contentToValidate");
    contentToValidateInput.setValue("https://www.itb.ec.europa.eu/files/json/sample.json");
    // Set the embedding method to "URI" to use the value for a remote lookup.
    contentToValidateInput.setEmbeddingMethod(ValueEmbeddingEnumeration.URI);
    request.getInput().add(contentToValidateInput);

    // Create the service client. This points to the WSDL of the online service.
    ValidationService_Service client = new ValidationService_Service(new URL("https://www.itb.ec.europa.eu/json/soap/any/validation?wsdl"));

    // Call the validator and get back the response.
    ValidationResponse response = client.getValidationServicePort().validate(request);
    // Print the report's number of findings per level.
    System.out.printf("Errors %s, warnings %s, messages %s%n",
            response.getReport().getCounters().getNrOfErrors(),
            response.getReport().getCounters().getNrOfWarnings(),
            response.getReport().getCounters().getNrOfAssertions()
    );
    // Print each finding's level and description.
    response.getReport().getReports().getInfoOrWarningOrError().forEach((reportItem) -> {
        System.out.printf("Level [%s], Description [%s]%n",
            reportItem.getName().getLocalPart(),
            ((BAR)reportItem.getValue()).getDescription()
        );
    });
}

Note that when providing the input, we defined an AnyContent instance that we named contentToValidate. The GITB validation service API defines the same operations for all validators as well as the input and output structures. In terms of input, you will always need to provide one or more AnyContent instances that will represent either simple values (as we have here) or containers, notably lists or maps. Such lists and maps can include any number of child AnyContent instances which are themselves simple values or further containers. The names, structures (in case of containers), purpose and values of the different expected inputs are part of a validator’s SOAP API documentation (see here for JSON validators).

Note

Validator input information: A validator’s expected inputs are also documented by the validator itself through its getModuleDefinition operation. More details on this are available in the GITB validation services documentation.

An input’s value is always provided as a string but this can be interpreted in different ways. This is where an input’s setEmbeddingMethod method comes in allowing you to specify how the value should be used. This can be:

  • ValueEmbeddingEnumeration.STRING, meaning that the value should be used as-is.

  • ValueEmbeddingEnumeration.URI, meaning that the value is a reference to a remote resource.

  • ValueEmbeddingEnumeration.BASE_64, meaning that the value is BASE64 encoded binary content.

In our example we want to validate a remote resource so we set the embedding method to be a URI. If we wanted to provide the JSON content directly we would adapt this as follows:

AnyContent contentToValidateInput = new AnyContent();
contentToValidateInput.setName("contentToValidate");
contentToValidateInput.setValue("{ ... }"); // This is the JSON content
contentToValidateInput.setEmbeddingMethod(ValueEmbeddingEnumeration.STRING);

We can now proceed to try out the validator by running the Application class’s main method. Doing so you will see a SOAP fault returned from the validator that mentions the following message:

Validation type [any] expects user-provided artifacts.

This error is specific to the generic JSON validator we are using for our test. The reason we got this is because we asked the validator to check our provided content when in fact the validator does not have any predefined validation artefacts to do the check with. In most cases this is something you wouldn’t come across as validators typically have preconfigured validation types, each with its set of validation rules. In our case however we need to provide these.

Let’s return to our implementation and pass a JSON schema to use for the validation. For this purpose we will use an online schema that defines rules for large purchase orders that we will pass using an input named externalSchemas (as defined in the validator’s documentation). This input is actually a list given that we could pass the validator multiple schemas to validate against. The elements of this list are expected to each be named schema and define the schema content to use. Let’s see how this translates to code:

private void doValidation() {
    ...
    // Define the JSON schema we will use.
    AnyContent schemaContent = new AnyContent();
    schemaContent.setName("schema");
    schemaContent.setValue("https://www.itb.ec.europa.eu/files/json/PurchaseOrder-large.schema.json");
    // Set this also as a URI given that its a remote reference.
    schemaContent.setEmbeddingMethod(ValueEmbeddingEnumeration.URI);
    // Create the schema container named "externalSchemas".
    AnyContent schemasInput = new AnyContent();
    schemasInput.setName("externalSchemas");
    // Add the schema to the list of schemas.
    schemasInput.getItem().add(schemaContent);
    // Add the list of schemas to the request
    request.getInput().add(schemasInput);
    ...
}

Running the validator after this change we will now get the expected output:

Errors 1, warnings 0, messages 0
Level [error], Description [[/items] The array must have at least 10 element(s), but actual number is 2.]

In this example we only made very basic processing of the validator’s output but you would typically want to use this further. The output is a TAR instance (Test Assertion Report) from which you can access the following noteworthy information:

  • The result, indicating the overall success, error or warning result.

  • The counters, as we saw in our example, giving us the total number of findings per violation level.

  • The context, a AnyContent instance as a map that contains custom data returned by the validator.

  • The report items, as we saw, with each item corresponding to one finding. Each such item is a JAXB wrapper over a BAR instance value, from which we can access information such as the item’s description, performed test, assertion identifier etc.

Note

Report item levels: The Java deserialisation of the report items currently requires you to determine their level using the element’s qualified name (error, warning, or info).

From this point on you should be able to extend this initial version with further features or adapt the code for use with other validators.

Note

Source code: The source code used for this example is available on GitHub.

Summary

Congratulations! You just implemented a simple Java client to call a validator using its SOAP API. In doing so you saw which dependencies you should use and worked with the validator’s inputs (simple and containers) and output (report).

See also

In this guide you saw how you can use a GITB-compliant validation service via its SOAP API. For details on how such a validator can be created you can refer to the following documentation:

Note that XML, JSON, RDF and CSV validators are in essence the same as custom-built ones but leverage a common basis provided by the test bed that allows you to define a new validator via simple configuration. From an API perspective all validators are nonetheless the same (defining of course different inputs per case).

Apart from using validators as standalone services and integrating with them as described in this guide, the validators’ SOAP API allows their use in GITB TDL test cases. These are test scenarios that can be loaded in the complete test bed platform to drive conformance testing, in which validators are used as building blocks to test exchanged content. For more information on such test cases you can refer to the following documentation: