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
Abdera abdera = new Abdera(); AbderaClient client = new AbderaClient(abdera);
Retrieving resources (GET)
Retrieving resources using the AbderaClient is straightforward:
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.
1 Comment
Aaron Evans
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)