Return-Path: X-Original-To: apmail-abdera-dev-archive@www.apache.org Delivered-To: apmail-abdera-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id A9C9C9E57 for ; Fri, 30 Dec 2011 23:24:39 +0000 (UTC) Received: (qmail 6387 invoked by uid 500); 30 Dec 2011 23:24:39 -0000 Delivered-To: apmail-abdera-dev-archive@abdera.apache.org Received: (qmail 6256 invoked by uid 500); 30 Dec 2011 23:24:38 -0000 Mailing-List: contact dev-help@abdera.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@abdera.apache.org Delivered-To: mailing list dev@abdera.apache.org Received: (qmail 6242 invoked by uid 500); 30 Dec 2011 23:24:38 -0000 Delivered-To: apmail-incubator-abdera-dev@incubator.apache.org Received: (qmail 6234 invoked by uid 99); 30 Dec 2011 23:24:37 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 30 Dec 2011 23:24:37 +0000 X-ASF-Spam-Status: No, hits=-0.7 required=5.0 tests=RCVD_IN_DNSWL_LOW,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of jasnell@gmail.com designates 209.85.215.175 as permitted sender) Received: from [209.85.215.175] (HELO mail-ey0-f175.google.com) (209.85.215.175) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 30 Dec 2011 23:24:31 +0000 Received: by eaal1 with SMTP id l1so12785567eaa.6 for ; Fri, 30 Dec 2011 15:24:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type; bh=v8C4rvZ0ReXO+pn2vA8v0tJq9M7c+gS8ooEgxnFLNPg=; b=uLCJcx1AMw3r4wHmQOmpA/xa0fkkad6JVmpKf6C7Jk3i4fCklnmZbL2Y1dVKeIUh1v tOTMxLMyKvdwLPowSR8nYZDIkoChfRoJFpkijuQijuWtnp73tw93R/t+DUJC/UDAN5/i p7Za7vg2WDkh3t+jKdvm+WcPLRhkmUpHpM9Mk= MIME-Version: 1.0 Received: by 10.204.145.86 with SMTP id c22mr9342993bkv.61.1325287449029; Fri, 30 Dec 2011 15:24:09 -0800 (PST) Received: by 10.204.139.134 with HTTP; Fri, 30 Dec 2011 15:24:09 -0800 (PST) Date: Fri, 30 Dec 2011 15:24:09 -0800 Message-ID: Subject: Non-blocking operations in Abdera2... From: James Snell To: Abdera Dev , Abdera User Content-Type: text/plain; charset=ISO-8859-1 I've been going through an updating the documentation for Abdera2 to highlight the various new features. As part of that effort, I've been playing around with a few of the new capabilities. One of the particularly interesting ones is that the integration with the Guava Libraries Function and Concurrency utilities allows applications built with Abdera2 to leverage a variety of non-blocking mechanisms. For instance, it's now possible to encrypt, decrypt, digitally sign and verify signatures on Atom documents without blocking the current thread of execution. Here's a quick example... First, we need to prepare the encryption provider (we use Bouncy Castle by default) KeyHelper.prepareDefaultJceProvider(); Now the cipher key... String jceAlgorithmName = "AES"; KeyGenerator keyGenerator = KeyGenerator.getInstance(jceAlgorithmName); keyGenerator.init(128); SecretKey key = keyGenerator.generateKey(); Create the entry to be encrypted... Abdera abdera = Abdera.getInstance(); Entry entry = abdera.newEntry(); entry.setId("http://example.org/foo/entry"); entry.setUpdatedNow(); entry.setTitle("This is an entry"); entry.setContentAsXhtml("This is markup"); entry.addAuthor("James"); entry.addLink("http://www.example.org"); Here's where it starts to get fun... The security api has been revamped and simplified in Abdera2... Security absec = new Security(abdera); The EncryptionOptions class is now immutable and threadsafe using the new common factory pattern... EncryptionOptions options = absec.getEncryption().getDefaultEncryptionOptions() .dataEncryptionKey(key).get(); Abdera2 uses the Guava Library to provide a Function object that wraps the encryption logic, we can then in turn wrap that function with a "Future Function", an Abdera2 concept that allows a Guava Function to be be executed within a separate thread. All we need to do is pass in an ExecutorService instance... ExecutorService exec = MoreExecutors2.getExitingExecutor(); Function,Future>> ff = MoreFunctions.futureFunction( absec.encryptor(options), exec); Now we can call our non-blocking encryption function... Future> future = ff.apply(entry.getDocument()); The Future returned by the function is an instance of the Guava ListenableFuture interface, allowing us to attach a listener that will wait for the completion of the encryption operation without blocking the current thread... com.google.common.util.concurrent.Futures.addCallback( (ListenableFuture>) future, new FutureCallback>() { public void onSuccess(Document result) { try { System.out.println("The results:"); result.writeTo(System.out); } catch (Throwable t) { t.printStackTrace(); } } public void onFailure(Throwable t) { t.printStackTrace(); } },exec); And that's it... non-blocking encryption of an Atom document. There are ways that I can compose that together with the digital signature capability to perform signing and encrypting in a single non-blocking operation. This is good stuff :-)