Guide: Using a validator via SOAP
Track |
---|
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:
Create a new Java project using Apache Maven to import required basic libraries.
Author the code needed to call a validator and process its validation report.
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
├── src
│ ├── main
│ │ ├── java
│ │ └── resources
│ └── test
│ ├── java
│ └── resources
└── pom.xml
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.20.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:
The XML validation guide, for XML validators using XML Schema and Schematron.
The RDF validation guide, for RDF validators using SHACL shapes.
The JSON validation guide, for JSON validators using JSON Schema.
The CSV validation guide, for CSV validators using Table Schema.
The GITB validation services documentation, for a fully custom validator.
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:
Guide: Creating a test suite explaining how a simple test case can be defined.
Guide: Defining your test configuration showing how a test case can be loaded in the test bed.
Guide: Executing a test case showing how test cases can be executed.
The GITB Test Description Language (TDL) reference, the XML language used to author test cases. Regarding validator usage you can specifically check the verify step that is responsible for validator calls.