An Atom Publishing Protocol Client

See Your first AtomPub Server for a server example.

Minimal required Maven dependency

    <dependency>
      <groupId>org.apache.abdera</groupId>
      <artifactId>abdera-client</artifactId>
      <version>1.1.1</version>  
    </dependency>

Creating the AbderaClient instance

Create the AbderaClient
Abdera abdera = new Abdera();
AbderaClient client = new AbderaClient(abdera);

Retrieving resources (GET)

Retrieving resources using the AbderaClient is straightforward:

Retrieving resources
Abdera abdera = new Abdera();
AbderaClient client = new AbderaClient(abdera);
ClientResponse resp = client.get("http://localhost:8080/abdera-server-example/employee");
if (resp.getType() == ResponseType.SUCCESS) {
  Document<Feed> doc = resp.getDocument();
} else {
  // there was an error
}

If the resource is not an XML document, the ClientResponse object can provide an InputStream

  InputStream in = resp.getInputStream();
  resp.getContentType();

The ClientResponse object provides access to all of the response headers such as ETag and Last-Modified.

System.out.println(resp.getEntityTag());
System.out.println(resp.getLastModified());
System.out.println(resp.getContentLocation());
System.out.println(resp.getSlug());

For headers that can contain encoded non-ASCII characters (like the Atompub Slug header), the ClientResponse will automatically decode the header. For instance, given the header "Slug: I%C3%B1t%C3%ABrn%C3%A2ti%C3%B4n%C3%A0liz%C3%A6ti%C3%B8n", resp.getSlug() returns the value "Iñtërnâtiônàlizætiøn".

Creating resources (POST)

AbderaClient client = new AbderaClient(abdera);

Entry entry = abdera.newEntry();		
entry.setId(...);
entry.setTitle(...);
entry.setUpdated(...);
entry.setContent(...);
//...

ClientResponse resp = client.post("http://localhost:8080/abdera-server-example/employee",entry);

if (resp.getType() == ResponseType.SUCCESS) {
  // success
} else {
  // there was an error
}

Posting non-Abdera resources is also possible,

InputStream in = ...
InputStreamRequestEntity entity = new InputStreamRequestEntity(in, "image/png");

ClientResponse resp = client.post("http://www.example.org/collection",entity);

if (resp.getType() == ResponseType.SUCCESS) {
  // success
} else {
  // there was an error
}

Updating resources (PUT)

AbderaClient client = new AbderaClient(abdera);

Entry entry = abdera.newEntry();
// ...

ClientResponse resp = client.put("http://www.example.org/collection",entry);

if (resp.getType() == ResponseType.SUCCESS) {
  // success
} else {
  // there was an error
}

Posting non-Abdera resources is also possible,

InputStream in = ...
InputStreamRequestEntity entity = new InputStreamRequestEntity(in, "image/png");

ClientResponse resp = client.put("http://www.example.org/collection",entity);

if (resp.getType() == ResponseType.SUCCESS) {
  // success
} else {
  // there was an error
}

Deleting resources

AbderaClient client = new AbderaClient(abdera);

ClientResponse resp = client.delete("http://www.example.org/collection");

if (resp.getType() == ResponseType.SUCCESS) {
  // success
} else {
  // there was an error
}

Using Custom HTTP Methods

Custom HTTP methods can be used by calling the client.execute method

Abdera abdera = Abdera.getInstance();
AbderaClient client = new AbderaClient(abdera);

RequestEntity entity = ...
client.execute("PATCH", "http://example.org/foo", entity, null);

if (resp.getType() == ResponseType.SUCCESS) {
  // success
} else {
  // there was an error
}

Customizing Request Options

The RequestOptions class is used to customize the options for a client request. The RequestOptions class provides access to all HTTP Request Headers

RequestOptions options = client.getDefaultRequestOptions();
options.setIfMatch(new EntityTag("foo"));
options.setNoCache(true);

ClientResponse resp = client.get("http://example.org/foo", options);

if (resp.getType() == ResponseType.SUCCESS) {
  // success
} else {
  // there was an error
}

The RequestOptions can be modified for any type of request.

Using SSL

To use Abdera to access SSL-protected endpoints, you need to register a trust manager. Abdera ships with a default non-op Trust Manager implementation that is designed to make it possible to use SSL services without providing any level of trust verification.

Abdera abdera = new Abdera();
AbderaClient client = new AbderaClient(abdera);
    
// Default trust manager provider registered for port 443
AbderaClient.registerTrustManager();
    
client.get("https://localhost:9080/foo");

By default, the Trust Manager will be registered on the default SSL port 443. If you want to register SSL support on a different port, you need to pass the port in when calling registerTrustManager

  AbderaClient.registerTrustManager(9443);

Alternatively, you can implement your own Trust Manager

Abdera abdera = new Abdera();
AbderaClient client = new AbderaClient(abdera);
    
AbderaClient.registerTrustManager(
  new X509TrustManager() {
    public void checkClientTrusted(
      X509Certificate[] certs, 
      String arg1) 
        throws CertificateException {
      // ignore this one for now
    }

    public void checkServerTrusted(
      X509Certificate[] certs, 
      String arg1) 
        throws CertificateException {
      // logic to determine if the cert is acceptable
      // throw a CertificateException if it's not
    }

    public X509Certificate[] getAcceptedIssuers() {
      List<X509Certificate> certs = new ArrayList<X509Certificate>();
      // prepare list of accepted issuer certs
      return certs.toArray(new X509Certificate[certs.size()]);
    }
        
  }
);
    
client.get("https://localhost:9080/foo");

Abdera also makes it possible to use SSL-based Client Certificate Authentication

Abdera abdera = new Abdera();
AbderaClient client = new AbderaClient(abdera);
    
KeyStore keystore = null;
ClientAuthSSLProtocolSocketFactory factory = 
  new ClientAuthSSLProtocolSocketFactory(
    keystore,"keystorepassword");
    
AbderaClient.registerFactory(factory, 443);

// DO NOT register a trust manager after this point
    
client.get("https://localhost:9080/foo");

Authentication

Abdera can use HTTP Authentication mechanisms when requesting entries

Abdera abdera = Abdera.getInstance();
AbderaClient client = new AbderaClient(abdera);

client.addCredentials(
  "http://example.org", 
  "realm", 
  "basic", 
  new UsernamePasswordCredentials(
    "username",
    "password"));

This will tell the AbderaClient to use the specified credentials whenever prompted to perform basic authentication on the url "http://example.org".

It is possible to use a custom Authentication mechanism by setting the Authorization header explicitly using the RequestOptions

RequestOptions options = client.getDefaultRequestOptions();
options.setAuthorization("MyAuthMechanism Foo Bar");

Cookies

While Abdera does not currently expose an API for working with HTTP cookies, the underlying HTTP client implementation supports and will use cookies within a single session. Cookies will not be stored permanently.

Caching

The Abdera Client includes a built-in HTTP Client Cache supporting the HTTP Cache-Control mechanism. The default cache implementation is an in-memory LRU cache that will not persist cached resources permanently. All of the standard cache-control mechanisms are supported with the notable exception that Vary response headers are not yet supported. When calling AbderaClient.get multiple times on a cached resource, if the cached copy is not stale, it will be returned.

The client cache can be disabled using the RequestOptions object,

RequestOptions options = client.getDefaultRequestOptions();
options.setUseLocalCache(false);

It is also possible to use HTTP cache-invalidation mechanisms such as no-cache and max-age

RequestOptions options = client.getDefaultRequestOptions();
options.setNoCache(true);
options.setMaxAge(10);

Implementing a Custom Cache Implementation

Alternative Client cache implementations can be provided by implementing the Cache and CacheFactory interfaces. These are registered using the file META-INF/services/org.apache.abdera.protocol.client.cache.CacheFactory.

  • No labels

1 Comment

  1. I'm pretty sure that client cache factories are found in the file:

    META-INF/services/org.apache.abdera.protocol.cache.CacheFactory

    (no 'client' in the name)