A Java client for the FullContact API
Java
Latest commit ad057f6 Oct 24, 2017 @MattSainz MattSainz Merge pull request #59 from fullcontact/ind-update
Add company industry support

README.md

FullContact4j

A Java client for the FullContact API. Supports Java 7+.

For FullContact4j 2.0 and later, we've designed the client from the bottom up with tons of cool new stuff.

See the changelog here.

Coming from version 1? Read this wiki page for a rundown of the big changes, then continue here.

Add to your project

FullContact uses Bintray as a repository.

Maven

<repositories>
  <repository>
    <id>fullcontact</id>
    <url>http://dl.bintray.com/content/fullcontact/fullcontact-oss</url>
  </repository>
</repositories>

<dependencies>
  <dependency>
    <groupId>com.fullcontact</groupId>
    <artifactId>fullcontact4j</artifactId>
    <version>(version here)</version>
  </dependency>
</dependencies>

Gradle

repositories {
    maven {
        url "http://dl.bintray.com/content/fullcontact/fullcontact-oss"
    }
}

dependencies {
    compile group: "com.fullcontact", name: "fullcontact4j", version: "(version here)"
}

Dependencies

OkHttp, which FullContact uses as an HTTP client.

Retrofit, for interacting with the FullContact API.

Jackson, a JSON library, for conversion of API responses.

Working with FullContact4j

FullContact4j 2.0 is designed from the ground up to be as painless to use as possible. FullContact clients are customizable and require just one line of code to set up; requests take only one line to create and one to execute. FullContact4j abstracts away all the headaches associated with HTTP communication with the API, ranging from managing possible response scenarios to keeping your requests below your account's rate limit (queries per second). Make a request object, execute it, and get a response object back.

Quick Overview

Firstly, read the API documentation! FullContact4j provides an object layer to FullContact API communication, but understanding webhooks, response flows, request parameters, and common snags is still important.

Once you’re on board with the API behavior, using FullContact4j is easy. Look up social and demographic data for an email address in just 3 lines of code:

FullContact fullContact = FullContact.withApiKey("your-api-key").build();
PersonRequest personRequest = fullContact.buildPersonRequest().email("bart@fullcontact.com").build();
PersonResponse personResponse = fullContact.sendRequest(personRequest);

(Don't have an API key? You can pick one up for free right here.)

withApiKey returns a FullContact client builder. You can specify timeouts, your own OkHttpClient, a user agent, and much more.

Behind the scenes, FullContact4j has done a lot for you:

  • authenticated with FullContact
  • accounted for rate limiting (for person API requests), sending the request if you are below your rate limit (or waiting to send your request until the time is right if you have exceeded your account limit).
  • checked for errors and parsed useful messages/data
  • turned the response JSON into a perfectly normal Java object.

If you prefer asynchronous calls, that requires only one change:

fullContact.sendRequest(personRequest, new FCCallback() {
  public void success(PersonResponse response) {
    System.out.println("got a response back!");
  }

  public void failure(FullContactException exception) {
    System.out.println("got an error :( ");
  }
});

You can see a simple demo of this client in action in the Hello World app example!

Making Requests

First, let’s get our request builder.

fullContact.buildPersonRequest()

All API requests can be made by calling their corresponding build____Request() method. Then, add relevant parameters and build:

fullContact.buildPersonRequest().email(“bart@fullcontact.com”).build();

It’s generally good practice to specify webhooks in your request, in case of a 202 response from Person API or a Card Reader upload for instance. That’s all configurable as well:

fullContact.buildPersonRequest()
  .webhookUrl(“http://www.example-site.com/api/finishedlookup”)
  .webhookBody(true)
  .email(“bart@fullcontact.com”)
  .build();

If the webhook URL is specified, all Person API responses will by default return a 202 response code (see webhooks documentation for more detail). If you need to test webhooks before implementing them in your own technology, you can always use something like requestb.in.

If you clearly mis-configured your request (adding two search parameters to Person API, or not giving a name to the name deducer API, etc), build() will throw an IllegalArgumentException with a message about what you did wrong:

java.lang.IllegalArgumentException: Request must specify exactly one: email or username
  at com.fullcontact.api.libs.fullcontact4j.http.name.NameDeduceRequest$Builder.validate(NameDeduceRequest.java:51)
  …

Now let’s send our request. Since FullContact4j uses a thread pool to execute requests, multiple consumers should be fine to make thread-safe requests from the same client instance. This can be done synchronously or asynchronously.

Synchronously is a little easier:

PersonRequest request = fullContact.buildPersonRequest().email(“bart@fullcontact.com”).build();
PersonResponse response = fullContact.sendRequest(request);

Every request has a corresponding response that it will return when sendRequest is called. This object contains all response data back from FullContact.

Asynchronous requests are similar. sendRequest() just takes one more parameter -- a FCCallback. It has a generic type parameter of the response type (PersonRequest corresponds to PersonResponse, LocationNormalizationRequest to LocationNormalizationResponse, etc). success() is called when a useful response is returned from the APIs:

fullContact.sendRequest(locationEnrichmentRequest, new FCCallback() {
  public void success(LocationEnrichmentResponse response) {
    System.out.println("got a response back!");
  }

  public void failure(FullContactException exception) {
    System.out.println("got an error :( ");
  }
});

You can turn webhook responses into these response objects using fromJson:

public void onCardReaderWebhook(String body) {
  CardReaderFullResponse response = CardReaderFullResponse.fromJson(body);
  System.out.println("Just got a card reader transcribed for " + response.getContact().getName().toString());
}

public void onPersonWebhook(String body) {
  PersonResponse response = WebhookResponse.fromJson(body, PersonResponse.class);
  System.out.println("Just got social profile info for " + response.getContactInfo().getName().toString());
}

As long as a response returns 200 or 202, FullContact4j will turn it into a java object representation holding all the information the regular JSON response would. If it's not in the JSON, it'll be an empty field.

PersonResponse response = client.sendRequest(personRequest);
if(response.getStatus() == 200) { //202 (searching) is possible here, we'll get an empty response!
  for(SocialProfile profile : response.getSocialProfiles()) {
    System.out.println("Check out my " + profile.getTypeId() + " profile: " + profile.getUrl());
  }
}

LocationEnrichmentResponse location = client.sendRequest(locationRequest);
System.out.println("I found a new place in " + location.getContinent() + " with a population of " + location.getPopulation());

When you're done with the client, be sure to call shutDown() on it to clean up any unused state in the client.

Error Handling

If an error is encountered (these correspond to yellow/red non-2xx response codes on the API flow diagrams), a FullContactException is created with useful information about the error, including errorCode and a message from the FullContact APIs about the nature of the error. For synchronous requests, this will cause sendRequest() to throw FullContactException. In asynchronous requests, FCCallback.failure(FullContactException exception) is called instead.

Supported APIs

FullContact4j supports all Person, Company, Email, Name, Location, Card Reader, and Account Statistics endpoints. These can all be accessed from their respective build_____Request() methods in the FullContact client. Some will need required parameters (like CardReaderRequest’s requirement for a front image InputStream) and automatically create a builder with those required parameters set.

Advanced

In the background, FullContact4j is making requests using an OkHttpClient. You can supply your own OkHttpClient.

OkHttpClient client = new OkHttpClient();
client.setReadTimeout(3000, TimeUnit.MILLISECONDS);
FullContact fcClient = FullContact.withApiKey("your-api-key").httpClient(client).build();

The user agent and request executor thread count are also configurable. For person API requests, the client will rate limit the amount of requests sent based on the rate limit for your plan. It will hold a request queue and execute at the maximum every 1/ratelimit seconds with some leeway if you haven’t sent requests in a certain period of time. FullContact4j guarantees no Person API rate limiting exceptions only as long a single client instance is the only user of an API key. However, if multiple instances of the client are being used simultaneously, FullContact4J cannot track your usage with high enough accuracy to guarantee that you will never get a rate limit exception (403). These may still occaisionally occur, and should be accounted for in your code. This rate limiter does NOT account for overages or quota limits. Make sure to check your account stats periodically to avoid overages.

I'm on Java 6!

The last Java 6-compatible FullContact4j release was version 3.3.3.