javaatom-feedibm-connectionsatompubapache-abdera

How to use Abdera atom client to send content and attachment


We are using Abdera to interact with the IBM Connections API, but our problem is mostly related to Abdera itself.

I think there is a bug in Abdera that does not allow you send an Entry that contains content and attachments in a single request. As a workaround you would probably be able to send two separate requests to create first with content and update afterwards with attachment. Sadly the Connections API required you to have all data in a single request or your old data is not preserved.

The following code shows an Abdera Entry that is created:

ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream("google-trends.tiff");

final Abdera abdera = new Abdera();
Entry entry = abdera.getFactory().newEntry();
entry.setTitle("THIS IS THE TITLE");
entry.setContentAsHtml("<p>CONTENT AS HTML</p>");
entry.setPublished(new Date());

Category category = abdera.getFactory().newCategory();
category.setLabel("Entry");
category.setScheme("http://www.ibm.com/xmlns/prod/sn/type");
category.setTerm("entry");
entry.addCategory(category);

RequestEntity request =
    new MultipartRelatedRequestEntity(entry, is, "image/jpg",
        "asdfasdfasdf");

When the MultipartRelatedRequestEntity is created a NullPointer is thrown:

java.lang.NullPointerException
    at
org.apache.abdera.protocol.client.util.MultipartRelatedRequestEntity.writeInput(MultipartRelatedRequestEntity.java:74)

This happens because it is expecting a content "src" element, but after digging into the source code of Abdera it seems like this is not a required element according to the specification. This looks like a bug in the Abdera code, no?

/**
 * <p>
 * RFC4287: atom:content MAY have a "src" attribute, whose value MUST be an IRI reference. If the "src" attribute is
 * present, atom:content MUST be empty. Atom Processors MAY use the IRI to retrieve the content and MAY choose to
 * ignore remote content or to present it in a different manner than local content.
 * </p>
 * <p>
 * If the "src" attribute is present, the "type" attribute SHOULD be provided and MUST be a MIME media type, rather
 * than "text", "html", or "xhtml".
 * </p>
 * 
 * @param src The IRI to use as the src attribute value for the content
 * @throws IRISyntaxException if the src value is malformed
 */

I have put a reference application connection to IBM Greenhouse Connections to show this, but have also included two unit tests in which the nullpointer can be tested without needing Connections. This can be found on GitHub


Solution

  • It is possible to get it working with Abdera, for future reference here is an example to post an entry that contains text content and also one (or more) attachmment(s). You need to use Part of the underlying HttpClient framework:

      final Entry entry = this.createActivityEntry();
      final RequestOptions options = this.client.getDefaultRequestOptions();
      options.setHeader("Content-Type", "multipart/related;type=\"application/atom+xml\"");
    
      StringPart entryPart = new StringPart("entry", entry.toString());
      entryPart.setContentType("application/atom+xml");
    
      FilePart filePart = new FilePart("file", new File(resource.getFile()));           
    
      RequestEntity request = new MultipartRequestEntity(new Part[] { entryPart, filePart}, this.client.getHttpClientParams());
      ClientResponse response = client.post(this.url + this.activityId, request, options);
    

    This allowed us to create an IBM Connections Activity Entry with content and attachments in one request, since this is needed by the API.