Integration Example:
Multi-Threaded Java Wrapper For IdM GlobalServices
Ensure you have an account setup. You will need the Username, Password and WSDL location.
Please note: Wherever <LatestWSDLVersion> is shown in Example Code below, please replace this with GlobalServices21a.wsdl.
If you are unsure of any of the details you can contact the helpdesk for more information.
IdMClientWrapper facilities
The module globalservices-capture-trace-verify-wrapper-lib exposes a main class IdMClientWrapper. This class has three public static methods which can be used to submit requests to IdMGlobalServices.
- performCaptureRequest()
- performTraceRequest()
- performVerifyRequest()
All these methods have a similar signature - they only differ in the ProfileRequest type of the last argument.
Note: the Verify functionality is not currently used by any of the Matchcode360 or Connexus web services.
Capture:
public static ProfileResponse performCaptureRequest(
final String username,
final String password,
final String endpoint,
int timeoutMS,
final ProfileRequestCapture request)
throws
TimeoutException,
Exception;
Trace:
public static ProfileResponse performTraceRequest(
final String username,
final String password,
final String endpoint,
int timeoutMS,
final ProfileRequestTrace request)
throws
TimeoutException,
Exception;
Verify:
Note: the Verify functionality is not currently used by any of the Matchcode360 or Connexus web services. Use the Capture method for email and telephone validation, for example.
public static ProfileResponse performVerifyRequest(
final String username,
final String password,
final String endpoint,
int timeoutMS,
final ProfileRequestVerify request)
throws
TimeoutException,
Exception;
Method Parameters
The parameters for these calls are as follows:
Parameter | Type | Description |
---|---|---|
username | String | The full username for the IdM account (e.g. username@domain) |
password | String | The plain-text password for the IdM account (e.g. pAssW0rd) |
endpoint | String | The URL for IdM Global Services (normally https://idmp.gb.co.uk/idm-globalservices-ws/<LatestWSDLVersion>) |
timeoutMS | int | Timeout in millisecond that the application should allow while waiting for an available client (e.g. 1000) |
request | ProfileRequestCapture or ProfileRequestTrace or ProfileRequestVerify |
The ProfileRequest of the appropriate type containing the request details. |
All the methods return a ProfileResponse instance.
Wrapper configuration
The IdMClientWrapper has a further static method which may be used to set the size of the pool of connections; the default pool size is 100. Any change to the pool size should be made in the application setup, and before any connections are used.
public static void setMaxConnections(int maxConnections);
Making a Capture Request
The following illustrates how the performCaptureRequest() method may be used for capture requests.
Create the main request object
The request details are held within an instance of ProfileRequestCapture, defined in the IdMGlobalServices WSDL. As a mimimum, the following three elements of the ProfileRequestCapture instance should be populated:
Element | Type | Description | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
customerReference | String | A reference that can be used to track the particular request (e.g. MyOrgRequest 23) | ||||||||||||||
profileGuid | String | Profile to execute detailing which data sets to use. See the individual services documentation for details. Some examples are given below:
|
||||||||||||||
requestData | ProfileRequestCaptureData | The details of the request |
Create the request data object
The request details are held within an instance of ProfileRequestCaptureData, defined in the IdMGlobalServices WSDL. The options element should be populated, together with one of the following, depending on the chosen profile:
Element | Type | Description |
---|---|---|
address | IdmDataSearchAddress | The address information (e.g. postcode, building number) for an address lookup profile |
telephone | List<IdmDataCaptureTelephone> | A list containing one or more mobile or landline telephone numbers for a telephone validation profile |
List<String> | A list containing one or more email addresses for an email validation profile | |
bank | List<IdMDataCaptureBank> | A list containing one or more bank details for an bank validation profile |
The general approach to setting up the request is:
- Create an instance of IdmRequestOptions and populate as required.
- Create an instance of IdmDataSearchAddress, or List of telephone, email or bank details and populate as required.
- Create an instance of ProfileRequestCaptureData, and set the options and the address, telephone, email or bank element.
- Create an instance of ProfileRequestCapture, and set the customerReference, profileGuid and requestData elements.
Making the request call
Once the profile request has been set up, the request is submitted to IdM Global Services by calling the appropriate static method of IdMClientWrapper, with the user credentials, endpoint, timeout and request object. The calling application should be prepared to handle any TimeoutException or general Exception which may be thrown and, as good practice, check in case the returned ProfileResponse object is null before attempting to parse it.
Parsing the response
The ProfileResponse structure contains the results for an operation performed against a profile.
Type: ProfileResponse
Field Name | Type | Description |
---|---|---|
Field Name | Type | Description |
profileHeader | ProfileHeader | Contains the Profile information for the results of the query |
profileResponses | ProfileResponseDetails | Response data to the query |
The ProfileResponseDetails structure contains the results for an operation performed against a product/data service in the Profile. It is possible to call multiple products in a single profile; in this case there will be multiple ProfileResponseDetails structures, one for each product.
Type: ProfileResponseDetails
Field Name | Type | Description |
---|---|---|
transactionGuid | String | Unique transaction identifier for the component e.g. Address Lookup component |
componentName | String | Name of the component |
componentStatus | Enum | SUCCESS, FAILURE, INSUFFICIENTCRITERIA, NA |
componentAction | String | Component Action |
responseType | Enum | CAPTURE |
invoice | DataLicenceInvoice | List of charges for the query |
captureResponse | CaptureResponse | Data from a component returning data e.g. Address lookup data |
validateResponse | ValidateResponse | Data from a component returning validation responses e.g. Telephone Validation service |
The CaptureResponse structure contains response records for a particular component/product. The data is held in a standard format across all products. The data structure is a flexible set of arrays designed to represent the data in a way that reflects the records in context of the search. The arrangement of the data will depend on the product in question. For more information on the layout of the response data please refer to the corresponding product documentation.
Type: CaptureResponse
Field Name | Type | Description |
---|---|---|
resultStatus | Enum | NA, INSUFFICIENTCRITERIA, NONE, SINGLE, MULTIPLE, PICKLIST, VERIFY |
recordsReturned | Int | Number individual of records returned e.g. number of addresses |
moreData | Boolean | More data on the server |
totalRecordCount | Int | Total records from the query |
totalPages | Int | Pagination - Total pages |
responseCount | Int | Number of groups of responses returned |
response | CaptureResponseData | Response data |
The ValidateResponse structure contains response records for a particular component/product. The data is held in a standard format across all products. For more information on the layout of the response data please refer to the corresponding product documentation.
Type: ValidateResponse
Field Name | Type | Description |
---|---|---|
resultStatus | Enum | NA, INSUFFICIENTCRITERIA, NONE, SINGLE, MULTIPLE, PICKLIST, VERIFY |
recordsReturned | Int | Number individual of records returned e.g. number of addresses |
responseCount | Int | Number of group of response returned |
response | ValidateResponseData | Response data |
Typical Options
Typical options may be set up with the code below.
protected IdmRequestOptions createIdmRequestOptions() {
IdmRequestOptions idmRequestOptions = new IdmRequestOptions();
idmRequestOptions.setOffset(0);
idmRequestOptions.setMaxReturn(10);
idmRequestOptions.setAddressEnvelopeFormat("A4P");
idmRequestOptions.setAddressSearchLevel(EnumAddressLevel.PREMISE);
idmRequestOptions.setAddressSearchType(EnumAddressSearchType.REGISTER);
idmRequestOptions.setCasing(EnumCasing.MIXED);
return idmRequestOptions;
}
UK Address Postcode Lookup
The whole process for performing a simple UK postcode-address lookup is illustrated below. The postcode to be looked up is provided in the String variable postcode.
// the URL of IdM GlobalServices v15b
final String ENDPOINT_URL = <br> "https://idmp.gb.co.uk/idm-globalservices-ws/<LatestWSDLVersion>";
// profile GUID for uk address lookups
final String ADDRESS_PROFILE_GUID = "6C49BC44-C104-41b2-BB62-2AE45A09DD54";
// maximum time to wait for a connection to become available from the pool
final int TIMEOUT_MS = 10000;
// create the request
// first, we need a ProfileRequestCapture object to hold all the information
ProfileRequestCapture profileRequestCapture = new ProfileRequestCapture();
// within the ProfileRequestCapture, data is held in a ProfileRequestCaptureData object
ProfileRequestCaptureData profileRequestCaptureData = new ProfileRequestCaptureData();
// setup some basic options
IdmRequestOptions idmRequestOptions = createIdmRequestOptions();
// put those options into the capture data
profileRequestCaptureData.setOptions(idmRequestOptions);
// for an address lookup, we need a search address object
IdmDataSearchAddress idmDataSearchAddress = new IdmDataSearchAddress();
// in this case, we just have the postcode
idmDataSearchAddress.setPostCode(postcode);
// put the address into the capture data
profileRequestCaptureData.setAddress(idmDataSearchAddress);
// now put the capture data into the overall request
profileRequestCapture.setRequestData(profileRequestCaptureData);
// set the configuration Id of the configuration we are licensed for (usually 1)
profileRequestCapture.setConfigurationId(1);
// set a descriptive reference
profileRequestCapture.setCustomerReference("GBG Sample Code");
// IMPORTANT: set the profile we are going to use - in this case for UK address web service
profileRequestCapture.setProfileGuid(ADDRESS_PROFILE_GUID);
// Now make the call using a static method on the IdMClientWrapper
// This is a capture request.
//
// We pass in the authentication credentials, the actual GlobalServices WSDL URL,
// a timeout limit in millisecond,
// and the request itself.
//
// We expect back a ProfileResponse object.
try {
System.out.println("Postcode address lookup running ...");
ProfileResponse profileResponse = IdMClientWrapper
.performCaptureRequest(
username,
password,
ENDPOINT_URL,
TIMEOUT_MS,
profileRequestCapture);
System.out.println("... postcode address lookup has returned.");
// disassemble the response to see what happened
System.out.println("Results from the postcode address lookup:");
profileResponseDisassembler.disassemble(profileResponse);
} catch (Exception e) {
// in case something went wrong
e.printStackTrace();
}
System.out.println("Postcode address lookup complete.");
Telephone Validation
The whole process for performing a simple telephone validation is illustrated below. There is a mobile telephone number in the String variable mobile, and a landline telephone number in the String variable landline.
// the URL of IdM GlobalServices v15b
final String ENDPOINT_URL = "https://idmp.gb.co.uk/idm-globalservices-ws/<LatestWSDLVersion>";
// profile GUID for global telephone validation
final String TELEPHONE_PROFILE_GUID = "454F13CA-8C71-40D6-9FEF-A88D821C99E4";
// maximum time to wait for a connection to become available from the pool
final int TIMEOUT_MS = 10000;
// create the request
// first, we need a ProfileRequestCapture object to hold all the information
ProfileRequestCapture profileRequestCapture = new ProfileRequestCapture();
// within the ProfileRequestCapture, data is held in a ProfileRequestCaptureData object
ProfileRequestCaptureData profileRequestCaptureData = new ProfileRequestCaptureData();
// setup some basic options
IdmRequestOptions idmRequestOptions = createIdmRequestOptions();
// put those options into the capture data
profileRequestCaptureData.setOptions(idmRequestOptions);
// for an global telephone validation lookup, we need a list of telephone objects
List<IdmDataCaptureTelephone> listOfTelephone = new ArrayList<IdmDataCaptureTelephone>();
// add the mobile
if ((null != mobile) && !mobile.isEmpty()) {
IdmDataCaptureTelephone phone = new IdmDataCaptureTelephone();
phone.setNumber(mobile);
phone.setType(EnumTelephone.MOBILE);
listOfTelephone.add(phone);
}
// add the landline
if ((null != landline) && !landline.isEmpty()) {
IdmDataCaptureTelephone phone = new IdmDataCaptureTelephone();
phone.setNumber(landline);
phone.setType(EnumTelephone.LANDLINE);
listOfTelephone.add(phone);
}
// put the list of telephones into the capture data
profileRequestCaptureData.getTelephone().addAll(listOfTelephone);
// now put the capture data into the overall request
profileRequestCapture.setRequestData(profileRequestCaptureData);
// set the configuration Id of the configuration we are licensed for (usually 1)
profileRequestCapture.setConfigurationId(1);
// set a descriptive reference
profileRequestCapture.setCustomerReference("GBG Sample Code");
// IMPORTANT: set the profile we are going to use - in this case for global telephone validation web service
profileRequestCapture.setProfileGuid(TELEPHONE_PROFILE_GUID);
// Now make the call using a static method on the IdMClientWrapper
// This is a capture request.
//
// We pass in the authentication credentials, the actual GlobalServices WSDL URL,
// a timeout limit in millisecond,
// and the request itself.
//
// We expect back a ProfileResponse object.
try {
System.out.println("Global telephone lookup running ...");
ProfileResponse profileResponse = IdMClientWrapper
.performCaptureRequest(
username,
password,
ENDPOINT_URL,
TIMEOUT_MS,
profileRequestCapture);
System.out.println("... global telephone lookup has returned.");
// disassemble the response to see what happened
System.out.println("Results from the global telephone lookup:");
profileResponseDisassembler.disassemble(profileResponse);
} catch (Exception e) {
// in case something went wrong
e.printStackTrace();
}
System.out.println("Global telephone lookup complete.");
Multi-Threaded UK Address Postcode Lookup
This section illustrates how multiple requests may be processed in parallel. The example uses a helper class ExampleSimpleThreadPool, and the code to run the example is as follows:
// create a simple thread pool for this exercise
ExampleSimpleThreadPool exampleSimpleThreadPool = new ExampleSimpleThreadPool(
username,
password,
ENDPOINT_URL,
poolSize,
numThreads);
// run the thread pool
System.out.println("Postcode address lookup multi-threaded running ...");
exampleSimpleThreadPool.runPool();
System.out.println("... postcode address lookup multi-threaded has returned.");
ExampleSimpleThreadPool class
The simple thread pool uses the standard Java java.util.concurrent.ExecutorService to run the address lookup threads in parallel. The class has one main method, runPool().
//
//Public method to start running the threads, and wait for them all to finish
//
public void runPool() {
// create a standard java ExecutorService for running the threads
ExecutorService executor = Executors.newFixedThreadPool(poolSize);
//create the individual threads, and add each one to the executor service
for (int threadIndex = 0; threadIndex < numThreads; threadIndex++) {
// create individual instances of the credentials
IdMCredentials credentials = IdMCredentials.createCredentials(username, password);
// pick a postcode from the list
int postcodeIndex = threadIndex % (POSTCODES.length);
String postcode = POSTCODES[postcodeIndex];
// create the worker thread
Runnable worker = new ExampleWorkerThread(
this.endpoint,
credentials,
postcode,
threadIndex);
// ask the executor service to run it
executor.execute(worker);
}
// close down the executor service (when it has finished) - we don't need it any more
executor.shutdown();
// ensure that it has finished before the java garbage disposal gets rid of it
while (!executor.isTerminated()) {
}
// done
System.out.println("Finished all threads");
}
The example selectes different postcodes from a list.
// list of postcodes to pick from
private static final String[] POSTCODES = {
"SW1A 1AA", "EH6 6SB", "NG11 7EP", "TW9 1PX", "EC2A 2GU", "G2 4JR", "L3 4AE", "IP5 3RE"};
The address lookup is performed within the run() method of the ExampleWorkerThread class.
ExampleWorkerThread class
The ExampleWorkerThread class implements the standard Java Runnable interface. The main code is as follows:
public class ExampleWorkerThread implements Runnable {
...
@Override
//
// Implementation method for the Runnable interface - this is called by the ExecutorService
//
public void run() {
System.out.println(Thread.currentThread().getName()+" START. Index="+Integer.toString(this.threadIndex)+", Postcode = "+this.postcode);
// process the request
try {
this.processRequest(this.threadIndex);
}
catch(Exception e) {
System.err.println("Exception caught in thread "+Integer.toString(this.threadIndex)+"=> "+e.getMessage());
}
// back from processing
System.out.println(Thread.currentThread().getName()+" END. Index="+Integer.toString(this.threadIndex));
}
//
// This method actually performs the address lookup
// @param threadIndex index of this thread
//
protected void processRequest(final int threadIndex) {
// create the request
// first, we need a ProfileRequestCapture object to hold all the information
ProfileRequestCapture profileRequestCapture = new ProfileRequestCapture();
// within the ProfileRequestCapture, data is held in a ProfileRequestCaptureData object
ProfileRequestCaptureData profileRequestCaptureData = new ProfileRequestCaptureData();
// setup some basic options
IdmRequestOptions idmRequestOptions = ExampleApplication.createIdmRequestOptions();
// put those options into the capture data
profileRequestCaptureData.setOptions(idmRequestOptions);
// for an address lookup, we need a search address object
IdmDataSearchAddress idmDataSearchAddress = new IdmDataSearchAddress();
// in this case, we just have the postcode
idmDataSearchAddress.setPostCode(postcode);
// put the address into the capture data
profileRequestCaptureData.setAddress(idmDataSearchAddress);
// now put the capture data into the overall request
profileRequestCapture.setRequestData(profileRequestCaptureData);
// set the configuration Id of the configuration we are licensed for (usually 1)
profileRequestCapture.setConfigurationId(1);
// set a descriptive reference
profileRequestCapture.setCustomerReference("Multithreaded sample: thread index="+Integer.toString(threadIndex));
// IMPORTANT: set the profile we are going to use - in this case for UK address web service
profileRequestCapture.setProfileGuid(ExampleApplication.ADDRESS_PROFILE_GUID);
// Now make the call using a static method on the IdMClientWrapper
// This is a capture request.
//
// We pass in the authentication credentials, the actual GlobalServices WSDL URL,
// a timeout limit in millisecond,
// and the request itself.
//
// We expect back a ProfileResponse object.
try {
System.out.println("Postcode address lookup running for thread index="+Integer.toString(threadIndex)+" ...");
ProfileResponse profileResponse = IdMClientWrapper
.performCaptureRequest(
this.idmCredentials.getUsername(),
this.idmCredentials.getPassword(),
this.endpoint,
TIMEOUT_MS,
profileRequestCapture);
System.out.println("... postcode address lookup has returned for thread index="+Integer.toString(threadIndex)+".");
// disassemble the response to see what happened,
System.out.println("Results from the postcode address lookup for thread index="+Integer.toString(threadIndex)+":");
this.profileResponseDisassembler.disassemble(profileResponse);
} catch (Exception e) {
e.printStackTrace();
}
}
}