Introduction

AFD Engine API makes using address management and bank validation in Java easy, minimising your work to get an integration up and running quickly, while also providing full flexibility to customise it to your requirements. Regardless of how you are using it our Java package makes integration with your application simple.

Setup

To use AFD Engine API you first need to install an AFD product (Windows only) or have access to an Evolution server (Java as a client is then completely platform independent). 

To use AFD Engine API in your Java project simply add the afd.api package (afdapi.jar) to your project. This can be downloaded here.

Eclipse

Right click your Project, select Build Path -> Configure Build Path. Under the Libaries Tab, click Add External JARs and browse to the afdapi.jar file.

NetBeans

Go to project properties (right click on the project). Click on the Libraries Tab and in turn the Compile Tab.

Click the “Add JAR/Folder” button and browse for the library file.

If using a locally installed product on Windows, the native libraries (javaAFDAPI32.dll and javaAFDAPI64.dll) will also need to reside in your Java library path (includes your Windows PATH environment variable so can be placed in any listed location).

Integrating into any Java Application

Creating an Instance of the Engine Class

To create an instance of the Engine class, add the following line to your code:

				
					Engine engine = new Engine(EngineType.ADDRESS);
				
			

(You can also use EngineType.BANK or EngineType.EMAIL if wanting to carry out Bank or Email Validation). If you wish to mix Address, Bank and/or Email validation simply create multiple instances of the Engine class.

Unless you use fully qualified references, you will also need to add the following line to the top of your java file:

				
					import afd.api.*;
				
			

If using an evolution server rather than a locally installed product set the Authentication property to an instance of the Authentication class for your server, e.g.:

				
					engine.setAuthentication(new Authentication("http://myserver:81", "333333", "password));
				
			

This gives your server, serial number, and password.

If using a locally installed product on Windows and you wish to specify the location for the native library, call setLibraryPath to do so, e.g.:

				
					engine.setLibraryPath("C:\\mylibrarypath\\");
				
			

Task Reference for Engine Class

Address Lookup (Postcode and Fast-Find)

To find an address record from the postcode or any fragment of the address use the find method on an instance of the Engine class with the lookup string you wish to use and one of the following operations:

  • Operation.FASTFIND_LOOKUP – Looks up the supplied string which can be a postcode or any fragment of the address.
  • Operation.POSTCODE_LOOKUP – Looks up a supplied postcode
  • Operation.POSTCODE_PROPERTY_LOOKUP – Looks up up a supplied postcode which optionally may also include a property, e.g. “279, B11 1AA”

This will return:

  • > 0 The number of results found
  • < 0 No results have been found (-2) or an error has occurred (use getLastErrorText to obtain a human readable message for the error).

You can then iterate through the engine.Records collection to process each result in your application. This collection has the method getField(string) which you can use to return any of the fields for the result.

For example:

				
					// Create instance of the Engine class
    Engine engine = new Engine(EngineType.ADDRESS);
    // Set authentication options for evolution if required
    // engine.setAuthentication(new Authentication("http://myserver:81",
    // "333333", "password", "engineAPI"));
    // Lookup the records
    int results = engine.find("b11 1aa", Operation.FASTFIND_LOOKUP);
    // Check for error
    if (results < 0) {
        System.out.println(engine.getLastErrorText());
        return;
    }
    // Iterate through results
    for (Record record : engine.Records) {
        // Obtain the fields you require – some examples:
        String list = record.getField("List");
        String organisation = record.getField("Organisation");
        String property = record.getField("Property");
        String street = record.getField("Street");
        String locality = record.getField("Locality");
        String town = record.getField("Town");
        String postcode = record.getField("Postcode");
        // display a string for the result
        // - replace with a function to process the result in your application?
        System.out.println(list);
    }
				
			

The number of results returned for FastFind operations will be limited by the MaxRecords Property of the Engine class instance. When using installed data it may also be limited by the Timeout Property. For evolution the server’s pre-configured MaxSearchTime may be a limiting factor.

To carry out a search for an Address:

  • Call clear to Clear any current address fields.
  • Use the setField method to set the value of each field you wish to search
  • Call find with Operation.Search (the Lookup parameter will be ignored)

The find function will return:

  • > 0 The number of results found
  • < 0 No results have been found (-2) or an error has occurred (use LastErrorText to obtain a human readable message for the error).

You can then iterate through the engine.Records collection to process each result in your application. This collection has the method getField(string) which you can use to return any of the fields for the result.

For example:

				
					// Create instance of the Engine class
    Engine engine = new Engine(EngineType.ADDRESS);
    // Set authentication options for evolution if required
    //engine.setAuthentication(new Authentication("http://myserver:81",
    // "333333", "password", "EngineAPI"));
    // Set the fields to Search
    engine.clear();
    engine.setField("street", "Commercial Street");
    engine.setField("town", "Birmingham");
    // Lookup the records
    int results = engine.find(null, Operation.SEARCH);
    // Check for error
    if (results < 0) {
        System.out.println(engine.getLastErrorText());
        return;
    }
    // Iterate through results
    for (Record record : engine.Records) {
        // Obtain the fields you require – some examples:
        String list = record.getField("List");
        String organisation = record.getField("Organisation");
        String property = record.getField("Property");
        String street = record.getField("Street");
        String locality = record.getField("Locality");
        String town = record.getField("Town");
        String postcode = record.getField("Postcode");
        // display a string for the result
        // - replace with a function to process the result in your application?
        System.out.println(list);
    }
				
			

The number of results returned for Search operations will be limited by the MaxRecords Property of the Engine class instance. When using installed data it may also be limited by the Timeout Property. For evolution the server’s pre-configured MaxSearchTime may be a limiting factor.

Bank records can be looked up or searched for in exactly the same way as Address records (see section 3.2.1 and Section 3.2.2). The difference being that the Engine class must be instantiated with a parameter of EngineType.BANK rather than EngineType.ADDRESS.

The applicable operations are:

  • Operation.FASTFIND_LOOKUP –Looks up the supplied string which can be a sortcode, bank/branch name, location, STD Code or BIC.
  • Operation.SEARCH – Search for results matching the search fields specified using the SetField method.

An example of a Bank Lookup:

				
					// Create instance of the Engine class
    Engine engine = new Engine(EngineType.BANK);
    // Set authentication options for evolution if required
    //engine.setAuthentication(new Authentication("http://myserver:81", "333333",
    "password", "EngineAPI"));
    // Lookup the records
    int results = engine.find("560036", Operation.FASTFIND_LOOKUP);
    // Check for error
    if (results < 0) {
     System.out.println(engine.getLastErrorText());
     return;
    }
    // Iterate through results
    for (Record record : engine.Records) {
        // Obtain the fields you require – some examples:
        String list = record.getField("List");
        String sortcode = record.getField("SortCode");
        String ownerBankFullName = record.getField("OwnerBankFullName");
        String branchTitle = record.getField("FullBranchTitle");
        String location = record.getField("Location");
        String directDebits = record.getField("BACSDirectDebits");
        // display a string for the result
        // - replace with a function to process the result in your application?
        System.out.println(list);
    }
				
			

Bank Account Validation

To validate an account number use the setField method to set the value of the sort code and account number (alternatively the IBAN can be used)

You may also wish to set the clearing system if you want to restrict validation to the UK (BACS), or Irish (IPSO) systems only.

Call find with Operation.VALIDATE_ACCOUNT (the Lookup parameter will be ignored)

Following successful validation a single record will be returned. It is recommended you use the sortcode and account number returned rather than that you supplied as non-standard length account numbers will be transcribed for you.

An example of a Bank Account Validation:

				
					// Create instance of the Engine class
    Engine engine = new Engine(EngineType.BANK);
    // Set authentication options for evolution if required
    //engine.setAuthentication(new Authentication("http://myserver:81", "333333",
    "password", "EngineAPI"));
    // Set the Account Details to validate
    engine.clear();
    engine.setField("SortCode", "774814");
    engine.setField("AccountNumber", "24782346");
    // RollNumber can also be set if applicable, IBAN can also be validated instead
    // Validate the Account Details
    int results = engine.find(null, Operation.ACCOUNT_VALIDATE);
    // Check for error, e.g. invalid account number
    if (results < 0) {
        System.out.println(engine.getLastErrorText());
        return;
    }
    // Success will return a single result
    String sortcode = engine.getField("SortCode");
    String accountNumber = engine.getField("AccountNumber");
    String iban = engine.getField("IBAN");
    String rollNumber = engine.getField("RollNumber");
    String typeOfAccount = engine.getField("TypeOfAccount");
    String clearingSystem = engine.getField("ClearingSystem");
    System.out.println("Account Number is Valid");
				
			

Card Number Validation

To validate a debit or credit card number use the setField method to set the value of the card number and optionally expiry date. (The expiry date is checked that it is in range for the current date if provided).

Call find with Operation.VALIDATE_CARD (the Lookup parameter will be ignored).

Following successful validation a single record will be returned.

An example of Card Number Validation:

				
					// Create instance of the Engine class
    Engine engine = new Engine(EngineType.BANK);
    // Set authentication options for evolution if required
    //engine.setAuthentication(new Authentication("http://myserver:81", "333333",
    "password", "EngineAPI"));
    // Set the field to validate
    engine.Clear();
    engine.SetField("cardnumber", "4694782385016585");
    engine.SetField("expirydate", "10/17"); // This field is optional
    // Validate the Card Details
    int results = engine.find(null, operation.CARD_VALIDATE);
    // Check for error, e.g. invalid account number
    if (results < 0) {
        System.out.println(engine.getLastErrorText());
        return;
    }
    // Success will return a single result
    String cardType = engine.getField("CardType");
    System.out.println("Valid: " + cardType);
				
			

Email Validation

To validate an email address from an instance of the engine class instantiated with EngineType.EMAIL simply call the find method with the email address to validate and Operation.EMAIL_VALIDATE.

An example of Email Address Validation:

				
					// Create instance of the Engine class
    Engine engine = new Engine(EngineType.EMAIL);
    // Set authentication options for evolution if required
    //engine.setAuthentication(new Authentication("http://myserver:81",
    "333333", "password", "EngineAPI"));
    // Validate the Email Address
    int results = engine.find("support@afd.co.uk", Operation.EMAIL_VALIDATE);
    // Check for error, e.g. invalid Email Address
    if (results < 0) {
     System.out.println(engine.getLastErrorText());
     return;
    }
    // Email Address is Valid
    System.out.println("Email Address is Valid");
				
			

Statelessly Retrieving Previous Records

If you have returned results following an address or bank lookup or search and require to fetch one of those results again you can do this with a Retrieve operation. An example when you might wish to do this if is returning a list of results to the user, wanting to minimise data passed and then need to retrieve the full record when a user selects an individual record.

To do this you need to store the key (use getField(“Key”) to obtain this) when processing the original record. Please note that this Key is unique in a particular dataset so can be used statelessly or across multiple servers as long as the same version of the data is still in use. It is not unique across future versions of the data and therefore should not be stored in a database as a unique reference.

To retrieve a record call find with the key for the record specified in the lookup field and an Operation of Operation.RETRIEVE.

A single result will be returned which you can then process.

This will return:

  • 1 The single result was found
  • < 0 No results have been found (-2) or an error has occurred (use LastErrorText to obtain a human readable message for the error).

For example:

				
					// Create instance of the Engine class
    Engine engine = new Engine(EngineType.RETRIEVE);
    // Set authentication options for evolution if required
    //engine.setAuthentication(new Authentication("http://myserver:81",
    "333333", "password", "EngineAPI"));
    // Lookup the records
    int results = engine.find("B11 1AA1001", Operation.RETRIEVE);
    // Check for error
    if (results < 0) {
        System.out.println(engine.getLastErrorText());
        return;
    }
    // Obtain the fields you require – some examples:
    String organisation = engine.getField("Organisation");
    String property = engine.getField("Property");
    String street = engine.getField("Street");
    String locality = engine.getField("Locality");
    String town = engine.getField("Town");
    String postcode = engine.getField("Postcode");
				
			

Calling off results individually

For ease of use the find method used in the previous sections returns all results at once until a pre-determined timeout or maximum record count is reached (if applicable). When used with an evolution server there is little point to doing anything else as results have to result from the same web request.

However in some cases when using an installed product, you may wish to return results one-by-one as they are called off or provide your own mechanism for determining when to abort a search (for example based on the actual results that come back).

In such scenarios rather than calling find, you can call the findFirst and findNext methods. findFirst has identical parameters to find but rather than returning the results in the Records List, it instead returns one result at a time (findNext takes no parameters).

You do also need to be aware that findFirst and/or findNext will sometimes return a value of 0 indicating a record or sector break which is provided to give the opportunity to cancel long searches and at which point no new result will be returned.

An example of an Address Fast-Find, identical that given in section 4.2.1 but using findFirst and findNext is as follows:

				
					// Create instance of the Engine class
    Engine engine = new Engine(EngineType.Address);
    // Lookup the records
    int result = engine.findFirst("b11 1aa", Operation.FASTFIND_LOOKUP);
    // Check for Error, but note if 0 has been returned it is still possible no
    results will be found
    if (result < 0) {
        System.out.println(engine.getLastErrorText());
        return;
    }
    // Process and call off each result
    long results = 0;
    while (result >= 0) {
        if (result > 0) {
            // obtain some of the fields for the result to use in your application
            String list = engine.getField("List");
            String organisation = engine.getField("Organisation");
            String property = engine.getField("Property");
            String street = engine.getField("Street");
            String locality = engine.getField("Locality");
            String town = engine.getField("Town");
            String postcode = engine.getField("Postcode");
            // display a string for the result
            // - replace with a function to process the result in your application?
            System.out.println(list);
            results++;
            }
            else if (result == 0) {
            / sector or record break – take the chance to allow user to cancel?
            }
            // set your own condition(s) to abort the search
            if (results > 500) break;
            result = engine.findNext();
        }
    if (results > 0) {
     // success
    }
    else {
        System.out.println("No Results Found");
    }
				
			

Function Reference for Engine Class

The following functions are available in the Engine Class:

clear

				
					void clear()
				
			

This clears the fields, necessary prior to setting criteria for a search (not necessary for fast-finds and postcode lookups).

getField

				
					String GetField(String)
				
			

This property returns the value of the specified field name for the current record. When using find to return multiple results at once you should use the getField method of a Record in the Records List property instead to retrieve fields from any record returned.

find

				
					int find(String Lookup, Operation)
    int find(String Lookup, Operation, SkipOption)
				
			

Carries out an operation using the AFD API. For a lookup, card or email validation the Lookup parameter specifies the lookup string (for example a postcode, sortcode, card number or email address). The Operation specifies the operation to carry out.

The following Operations are supported:

Engine TypeOperationDescription
AddressFASTFIND_LOOKUPLooks up an address fragement specified by the Lookup parameter. This could be a postcode or fields from an address.
 POSTCODE_PROPERTY_LOOKUPLooks up an address from the specified postcode and optionally property (e.g. “277, B11 1AA”) specified by the Lookup parameter.
 POSTCODE_LOOKUPLooks up an address from the specified postcode.
 SEARCHSearches for an address specified by criteria set by calling setField for the appropriate fields prior to calling this function (lookup parameter is ignored and can be null)
 RETRIEVERetrieves a previously returned record. The required records key field should be specified as the lookup parameter.
BankFASTFIND_LOOKUPLooks up a sort code or searches for a bank from the fragment given as specified by the Lookup parameter.
 SEARCHSearches for a bank branch specified by critieria set by calling setField for the appropriate fields prior to calling this function (lookup parameter is ignored and can be null).
 RETRIEVERetrieves a previously returned record. The required records key field should be specified as the lookup parameter.
 ACCOUNT_VALIDATEValidates an account number. Use setField to set both the sortcode and account number or alternatively the IBAN prior to calling this function. The lookup parameter is ignored.
 CARD_VALIDATEValidates a card number. The lookup parameter should be set to the card number to validate.
 EMAIL_VALIDATEValidates an email address. The lookup parameter should be set to the email address to validate.

For address functions you can optionally set the SkipOptions to a member of the SkipOptions enumeration to skip records in large searches. These options are as follows:

Skip OptionDescription
NoneDefault – Returns all matching records (unless a timeout or maximum number of records is reached).
ADDRESSOnly returns the first matching record per address (or household). Only has any effect with Names & Numbers.
POSTCODEOnly returns the first matching record for each postcode.
SECTORReturns the first matching record per Sector (this is the portion of the postcode prior to the space and the first digit afterwards, e.g. “B11 1”).
OUTCODEReturns the first matching record per Outcode (this is the portion of the postcode prior to the space, e.g. “B11”);
TOWNReturns the first matching record per Royal Mail Post Town.
AREAReturns the first matching record per Postcode Area (this is the letters at the start of the postcode, e.g. “B” or “AB”).

This function returns the number of matching records returned, or a value < 0 if an error has occurred. Use getLastErrorText() to obtain a human readable version of an error.

findFirst

				
					int findFirst(String Lookup, Operation Operation)
    int findFirst(String, Operation, SkipOption)
				
			

This method is identical in parameters to find. The difference being that it will obtain the first result only (or sometimes a record or sector break in a long search). You can then call findNext() to obtain subsequent records.

In general it is recommended you use find to obtain results as this simplifies calling off results and in-built support for the MaxRecords and, for installed data, Timeout properties to restrict long searches to help prevent your application becoming unresponsive. However in cases were you are using locally installed data and wish to have full control over this process this method gives you that flexibility.

Some examples where you might use this would be if you wish to return results to the user as they are called off rather than at the end of a long search, or you wish to be able to determine when to abort a search based on the results themselves or user intervention then this method gives you that flexibility.

The return codes are the same as for find with the addition of 0 which indicates a record or sector break, when returned no result has been returned (You will need to call findNext to continue the search). This allows the opportunity to cancel long searches after a predetermined timeout etc. if required.

findNext

				
					int findNext()
				
			

This method is used following a call to findFirst to repeatedly call off subsequent records. It will return 1 on success, 0 on a record or sector break (indicating no new result has been returned but giving the opportunity to cancel or provide user responsiveness) or -6 to indicate the end of a search.

getLastErrorText

				
					String getLastErrorText()
				
			

This returns human readable text for the last error to occur (will return an empty string if the last operation was successful). While you may wish to display your own error text for some errors it is recommended that you fall-back to using this for any error code you have not handled yourself.

setField

				
					bool setField(String, String)
				
			

Sets the value of the specified field for searching (returns false if field doesn’t exist).

Getter/Setter Property Reference for Engine Class

AddressFields

				
					int getAddressFields()
    setAddressFields(int)
				
			

Set the number of address fields to use when returning free address fields with GetField (e.g. address1, address2, etc.). The default is 6, setting this to the same number as the fields you have causes Engine to squeeze fields in as required.

Authentication

				
					Authentication getAuthentication()
    setAuthentication(Authentication)
				
			

For Evolution use this property specifies the authentication options to use and should be set to an instance of the Authentication class prior to any operations being carried out (see Section 4 for further details).

IncludeOrganisation

				
					boolean getIncludeOrganisation()
    setIncludeOrganisation(boolean)
				
			

Boolean value indicating if the Organisation is included in free address field (i.e. if you obtain address1, address2, etc.)

LastErrorText

				
					String getLastErrorText()
				
			

This returns human readable text for the last error to occur (will return an empty string if the last operation was successful). While you may wish to display your own error text for some errors it is recommended that you fall-back to using this for any error code you have not handled yourself.

LastResult

				
					int getLastResult()
				
			

Returns the result code for the last operation. Will be < 0 if an error occurred or > 0 if successful.

LibraryPath

				
					setLibraryPath(String)
				
			

Sets the path containing the native libraries (applicable for locally installed Windows engine only).

MaxRecords

				
					int getMaxRecords()
    setMaxRecords(int)
				
			

Sets the Maximum number of records to return from any lookup or search (default 500).

Records

Following an option calling find this is a collection of the results (Record objects). Each Record in the collection has a getField method used to obtain individual fields for that result.

Timeout

				
					int getTimeout()
    setTimeout(int)
				
			

Sets the maximum time in seconds to spend searching for records (Default is 30 seconds). This helps prevent very long searches making an application unresponsive or a very vague search taking too long when it could instead be refined. This is applicable to installed products only. For evolution the server will be preconfigured with a MaxSearchTime which has the same effect.

UpperCaseTown

				
					setUpperCaseTown(boolean)
    Boolean getUpperCaseTown()
				
			

Indicates that the Town will always be returned in upper case (default and preferred by Royal Mail for address labels)

Record Class and Property

The Record class cannot be instantiated on its own. A List of Record objects is returned by the Records Property of the Engine class following an operation calling find.

The class has a single method getField. This property returns the value of the specified field name for the record.

Collections

EngineType

This collection is used on instantiating the Engine class to specify the type of Engine used. The values are ADDRESS for Address Management (e.g. Address Fastfind, Search, etc.), BANK for BankFinder (e.g. Account or Card Validation) or EMAIL for Email Validation.

You cannot mix types in one instance of the engine class, but you can have multiple instances of the class of different types called in the same function in your code.

Operation

This collection is used to specify the operation carried out. Section 3.3.3 provides a table with the valid Operations for each EngineType.

Return Codes

The possible return codes, available as the return code from findFirst or the lastResult property, are as follows:

Success Codes

These are the possible codes returned:

ValueDescription
0The search/lookup has not completed but may take some time and so is returning to give the user the option to cancel a long search.
1The function was successful and a matching record has been returned.
2This applies only to Bankfinder account number validation and indicates that the function was successful and the account number should be taken as valid. However, as account numbers on this sortcode cannot be validated you may wish to double check it is correct.

Error Codes

These specify the possible errors returned from any API function:

ValueDescription
-1The field specification string specified is invalid. This shouldn’t be returned under normal circumstances.
-2No records matching your lookup or search criteria were found.
-3The record number provided (e.g. when re-retrieving an item from a list box) is invalid.
-4An error occurred attempting to open the AFD data files. Check they are correctly installed.
-5An error occurred reading the data. Likely to be due to corrupt data so software may need to be re-installed.
-6End of Search (when the last result has already been called off – indicates there are no more results to return).
-7Indicates there is an error with the product registration. Normally due to it having expired. Run the Welcome program to re-register the software.
-8Occurs if you attempt to search for a Name and Organisation at the same time. Also occurs with Postcode Plus if the UDPRN field is searched for at the same time as any other field.
-99Indicates that the user clicked the cancel button if the DLL internal list box was used.
-12The sort code specified for an account number validation does not exist.
-13The sortcode specified for an account number validation is invalid.
-14The account number specified for an account number validation is invalid.
-21The sort code and account number given are for a building society account which also requires a roll number for account credits. No roll number has been supplied or is incorrect for this building society.
-22The International Bank Account Number provided is in an invalid format
-23The IBAN provided contains a country that is not recognised as valid
-24Both an IBAN and Account Number was provided and these details do not match.
-15The expiry date specified for a card validation is invalid.
-16The card has expired
-18The card number specified for a card validation is invalid.
-19The card number specified is a Visa card which can be used in an ATM only.
-20While the card number appears to be a valid one, the card is not of any of the known types and is therefore unlikely to be acceptable for payment.

Evolution Server Details

The Authentication Object is used to specify authentication details to use engine with an evolution server. If you do not assign one to the Authentication property of the Engine class then a default instance is created which uses local installed product.

We strongly recommend that the details passed to create an instance of the Authentication object are stored as modifiable configuration parameters in your application, so that details can be changed in the future without needing to alter code.

There are four initialisers for the Authentication object

Authentication()

This creates a version to work with installed data only. You will require a copy of an AFD product installed on each machine your software runs on. This is the fastest and most efficient method and is particularly ideal for offline use.

Authentication(Serial, Password)

This creates a version to work with AFD’s server. You pass it your serial number and password.

Authentication(Server, Serial, Password)

This creates a version to work with your own server. The Server parameter should be a string including the protocol, server and (if not 80) the port so as to give wide compatibility. For example http​://server:81

mailLink mailLink

We are here to help

We serve thousands of organisations and a network of hundreds of partners across multiple industry sectors, enabling them to have full confidence in their contact data.