Merge pull request #1515 from jclouds/async-is-an-option-1.6.x

Async is an option 1.6.x
diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackRestClientModule.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackRestClientModule.java
index 3ec22b8..ee7cc7e 100644
--- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackRestClientModule.java
+++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackRestClientModule.java
@@ -18,7 +18,7 @@
  */
 package org.jclouds.cloudstack.config;
 
-import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
+import static org.jclouds.rest.config.BinderUtils.bindSyncToAsyncHttpApi;
 
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
@@ -207,9 +207,9 @@
       });
       bind(CredentialType.class).toProvider(CredentialTypeFromPropertyOrDefault.class);
       // session client is used directly for filters and retry handlers, so let's bind it explicitly
-      bindHttpApi(binder(), SessionClient.class, SessionAsyncClient.class);
-      bindHttpApi(binder(), CloudStackDomainClient.class, CloudStackDomainAsyncClient.class);
-      bindHttpApi(binder(), CloudStackGlobalClient.class, CloudStackGlobalAsyncClient.class);
+      bindSyncToAsyncHttpApi(binder(), SessionClient.class, SessionAsyncClient.class);
+      bindSyncToAsyncHttpApi(binder(), CloudStackDomainClient.class, CloudStackDomainAsyncClient.class);
+      bindSyncToAsyncHttpApi(binder(), CloudStackGlobalClient.class, CloudStackGlobalAsyncClient.class);
       bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(InvalidateSessionAndRetryOn401AndLogoutOnClose.class);
       
       super.configure();
diff --git a/apis/filesystem/src/main/java/org/jclouds/filesystem/config/FilesystemBlobStoreContextModule.java b/apis/filesystem/src/main/java/org/jclouds/filesystem/config/FilesystemBlobStoreContextModule.java
index d87d5b2..096b9b6 100644
--- a/apis/filesystem/src/main/java/org/jclouds/filesystem/config/FilesystemBlobStoreContextModule.java
+++ b/apis/filesystem/src/main/java/org/jclouds/filesystem/config/FilesystemBlobStoreContextModule.java
@@ -18,7 +18,7 @@
  */
 package org.jclouds.filesystem.config;
 
-import static org.jclouds.rest.config.BinderUtils.bindBlockingApi;
+import static org.jclouds.rest.config.BinderUtils.bindSyncToAsyncApi;
 
 import org.jclouds.blobstore.AsyncBlobStore;
 import org.jclouds.blobstore.BlobRequestSigner;
@@ -50,7 +50,7 @@
    protected void configure() {
       bind(AsyncBlobStore.class).to(LocalAsyncBlobStore.class).asEagerSingleton();
       // forward all requests from TransientBlobStore to TransientAsyncBlobStore.  needs above binding as cannot proxy a class
-      bindBlockingApi(binder(), LocalBlobStore.class, AsyncBlobStore.class);
+      bindSyncToAsyncApi(binder(), LocalBlobStore.class, AsyncBlobStore.class);
       bind(BlobStore.class).to(LocalBlobStore.class);
 
       install(new BlobStoreObjectModule());
diff --git a/apis/openstack-cinder/src/main/java/org/jclouds/openstack/cinder/v1/CinderApiMetadata.java b/apis/openstack-cinder/src/main/java/org/jclouds/openstack/cinder/v1/CinderApiMetadata.java
index 581eaf6..3720103 100644
--- a/apis/openstack-cinder/src/main/java/org/jclouds/openstack/cinder/v1/CinderApiMetadata.java
+++ b/apis/openstack-cinder/src/main/java/org/jclouds/openstack/cinder/v1/CinderApiMetadata.java
@@ -30,6 +30,7 @@
 import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule;
+import org.jclouds.openstack.keystone.v2_0.config.MappedAuthenticationApiModule;
 import org.jclouds.openstack.v2_0.ServiceType;
 import org.jclouds.rest.internal.BaseRestApiMetadata;
 
@@ -88,6 +89,7 @@
          .defaultEndpoint("http://localhost:5000/v2.0/")
          .defaultProperties(CinderApiMetadata.defaultProperties())
          .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                                     .add(MappedAuthenticationApiModule.class)
                                      .add(KeystoneAuthenticationModule.class)
                                      .add(ZoneModule.class)
                                      .add(CinderParserModule.class)
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationApi.java
index d62bc67..8fc7aa3 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationApi.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationApi.java
@@ -18,47 +18,88 @@
  */
 package org.jclouds.openstack.keystone.v2_0;
 
+import java.io.Closeable;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.keystone.v2_0.binders.BindAuthToJsonPayload;
 import org.jclouds.openstack.keystone.v2_0.domain.Access;
 import org.jclouds.openstack.keystone.v2_0.domain.ApiAccessKeyCredentials;
 import org.jclouds.openstack.keystone.v2_0.domain.PasswordCredentials;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.SelectJson;
+
+import com.google.inject.name.Named;
 
 /**
  * Provides synchronous access to the KeyStone Service API.
  * <p/>
  * 
- * @see AuthenticationAsyncApi
- * @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/Service_API_Api_Operations.html"
+ * @see <a href=
+ *      "http://docs.openstack.org/api/openstack-identity-service/2.0/content/Service_API_Api_Operations.html"
  *      />
  * @author Adrian Cole
  */
-public interface AuthenticationApi {
+public interface AuthenticationApi extends Closeable {
 
    /**
     * Authenticate to generate a token.
     * 
     * @return access with token
     */
-   Access authenticateWithTenantNameAndCredentials(@Nullable String tenantId, PasswordCredentials passwordCredentials);
+   @Named("authenticate")
+   @POST
+   @SelectJson("access")
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/tokens")
+   @MapBinder(BindAuthToJsonPayload.class)
+   Access authenticateWithTenantNameAndCredentials(@Nullable @PayloadParam("tenantName") String tenantName,
+         PasswordCredentials passwordCredentials);
 
    /**
     * Authenticate to generate a token.
     * 
     * @return access with token
     */
-   Access authenticateWithTenantIdAndCredentials(@Nullable String tenantId, PasswordCredentials passwordCredentials);
+   @Named("authenticate")
+   @POST
+   @SelectJson("access")
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/tokens")
+   @MapBinder(BindAuthToJsonPayload.class)
+   Access authenticateWithTenantIdAndCredentials(@Nullable @PayloadParam("tenantId") String tenantId,
+         PasswordCredentials passwordCredentials);
 
    /**
     * Authenticate to generate a token.
     * 
     * @return access with token
     */
-   Access authenticateWithTenantNameAndCredentials(@Nullable String tenantId, ApiAccessKeyCredentials passwordCredentials);
-   
+   @Named("authenticate")
+   @POST
+   @SelectJson("access")
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/tokens")
+   @MapBinder(BindAuthToJsonPayload.class)
+   Access authenticateWithTenantNameAndCredentials(@Nullable @PayloadParam("tenantName") String tenantName,
+         ApiAccessKeyCredentials apiAccessKeyCredentials);
+
    /**
     * Authenticate to generate a token.
     * 
     * @return access with token
     */
-   Access authenticateWithTenantIdAndCredentials(@Nullable String tenantId, ApiAccessKeyCredentials passwordCredentials);
+   @Named("authenticate")
+   @POST
+   @SelectJson("access")
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/tokens")
+   @MapBinder(BindAuthToJsonPayload.class)
+   Access authenticateWithTenantIdAndCredentials(@Nullable @PayloadParam("tenantId") String tenantId,
+         ApiAccessKeyCredentials apiAccessKeyCredentials);
 }
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncApi.java
index 02dd7c5..6113aed 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncApi.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncApi.java
@@ -18,6 +18,8 @@
  */
 package org.jclouds.openstack.keystone.v2_0;
 
+import java.io.Closeable;
+
 import javax.ws.rs.Consumes;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
@@ -42,8 +44,11 @@
  * @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/Service_API_Api_Operations.html"
  *      />
  * @author Adrian Cole
+ * @deprecated will be removed in jclouds 1.7, as async interfaces are no longer
+ *             supported. please use {@link AuthenticationApi}
  */
-public interface AuthenticationAsyncApi {
+@Deprecated
+public interface AuthenticationAsyncApi extends Closeable {
 
    /**
     * @see AuthenticationApi#authenticateWithTenantNameAndCredentials(String,PasswordCredentials)
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java
index 003be87..7ddbdab 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java
@@ -29,6 +29,7 @@
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneParserModule;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneRestClientModule;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneRestClientModule.KeystoneAdminURLModule;
+import org.jclouds.openstack.keystone.v2_0.config.MappedAuthenticationApiModule;
 import org.jclouds.openstack.v2_0.ServiceType;
 import org.jclouds.rest.internal.BaseRestApiMetadata;
 
@@ -90,6 +91,7 @@
          .defaultEndpoint("http://localhost:5000/v${jclouds.api-version}/")
          .defaultProperties(KeystoneApiMetadata.defaultProperties())
          .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                                     .add(MappedAuthenticationApiModule.class)
                                      .add(KeystoneAuthenticationModule.class)
                                      .add(KeystoneAdminURLModule.class)
                                      .add(KeystoneParserModule.class)
diff --git a/core/src/main/java/org/jclouds/rest/ConfiguresRestContext.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/AuthenticationApiModule.java
similarity index 62%
copy from core/src/main/java/org/jclouds/rest/ConfiguresRestContext.java
copy to apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/AuthenticationApiModule.java
index 021bc4c..7142460 100644
--- a/core/src/main/java/org/jclouds/rest/ConfiguresRestContext.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/AuthenticationApiModule.java
@@ -16,22 +16,24 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.jclouds.rest;
+package org.jclouds.openstack.keystone.v2_0.config;
 
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
+import org.jclouds.openstack.keystone.v2_0.AuthenticationApi;
+
+import com.google.inject.AbstractModule;
 
 /**
- * designates the module configures a Client to a cloud.
  * 
  * @author Adrian Cole
- * 
  */
-@Retention(RUNTIME)
-@Target(TYPE)
-public @interface ConfiguresRestContext {
+public class AuthenticationApiModule extends AbstractModule  {
+
+   @Override
+   protected void configure() {
+      // AuthenticationApi is used directly for filters and retry handlers, so let's bind it explicitly
+      bindHttpApi(binder(), AuthenticationApi.class);
+   }
 
 }
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java
index c1e2012..0b2099d 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java
@@ -19,7 +19,6 @@
 package org.jclouds.openstack.keystone.v2_0.config;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
 import static org.jclouds.util.Suppliers2.getLastValueInMap;
 
 import java.net.URI;
@@ -47,8 +46,6 @@
 import org.jclouds.location.suppliers.derived.ZoneIdsFromZoneIdToURIKeySet;
 import org.jclouds.location.suppliers.implicit.FirstRegion;
 import org.jclouds.location.suppliers.implicit.FirstZone;
-import org.jclouds.openstack.keystone.v2_0.AuthenticationApi;
-import org.jclouds.openstack.keystone.v2_0.AuthenticationAsyncApi;
 import org.jclouds.openstack.keystone.v2_0.domain.Access;
 import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
 import org.jclouds.openstack.keystone.v2_0.functions.AuthenticateApiAccessKeyCredentials;
@@ -60,7 +57,6 @@
 import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToURIFromAccessForTypeAndVersion;
 import org.jclouds.openstack.keystone.v2_0.suppliers.ZoneIdToURIFromAccessForTypeAndVersion;
 import org.jclouds.rest.annotations.ApiVersion;
-import org.jclouds.rest.config.RestClientModule;
 
 import com.google.common.base.Function;
 import com.google.common.base.Supplier;
@@ -89,7 +85,7 @@
     * {@link javax.inject.Qualifier}</li>
     * <li>add the above annotation to any {@link AsyncApi} classes by placing it on the type. ex.
     * {@code @Endpoint(CloudDNS.class)}</li>
-    * <li>add the following to your {@link RestClientModule}</li>
+    * <li>add the following to your {@link org.jclouds.rest.config.RestClientModule}</li>
     * 
     * <pre>
     * bind(new TypeLiteral&lt;Supplier&lt;URI&gt;&gt;() {
@@ -184,12 +180,6 @@
    @Override
    protected void configure() {
       bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class);
-      bindAuthenticationApi();
-   }
-
-   protected void bindAuthenticationApi() {
-      // AuthenticationApi is used directly for filters and retry handlers, so let's bind it explicitly
-      bindHttpApi(binder(), AuthenticationApi.class, AuthenticationAsyncApi.class);
    }
 
    /**
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/MappedAuthenticationApiModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/MappedAuthenticationApiModule.java
new file mode 100644
index 0000000..0a49f15
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/MappedAuthenticationApiModule.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.openstack.keystone.v2_0.config;
+
+import static org.jclouds.rest.config.BinderUtils.bindSyncToAsyncHttpApi;
+
+import org.jclouds.openstack.keystone.v2_0.AuthenticationApi;
+import org.jclouds.openstack.keystone.v2_0.AuthenticationAsyncApi;
+
+import com.google.inject.AbstractModule;
+
+/**
+ * 
+ * @author Adrian Cole
+ * @deprecated will be removed in jclouds 1.7, as async interfaces are no longer
+ *             supported. please use {@link AuthenticationApiModule}
+ */
+@Deprecated
+public class MappedAuthenticationApiModule extends AbstractModule  {
+
+   @Override
+   protected void configure() {
+      // AuthenticationApi is used directly for filters and retry handlers, so let's bind it explicitly
+      bindSyncToAsyncHttpApi(binder(), AuthenticationApi.class, AuthenticationAsyncApi.class);
+   }
+
+}
diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/config/ProviderModuleExpectTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/config/ProviderModuleExpectTest.java
index 21705c9..7cbc64d 100644
--- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/config/ProviderModuleExpectTest.java
+++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/config/ProviderModuleExpectTest.java
@@ -1,9 +1,28 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.jclouds.openstack.keystone.v2_0.config;
 
-import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.ElementType.METHOD;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
 import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
+import static org.jclouds.util.Suppliers2.getLastValueInMap;
 import static org.testng.Assert.assertTrue;
 
 import java.io.Closeable;
@@ -13,6 +32,7 @@
 import java.util.Properties;
 
 import javax.inject.Qualifier;
+import javax.inject.Singleton;
 import javax.ws.rs.HEAD;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
@@ -23,21 +43,23 @@
 import org.jclouds.http.HttpResponse;
 import org.jclouds.json.config.GsonModule.DateAdapter;
 import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
+import org.jclouds.location.suppliers.RegionIdToURISupplier;
 import org.jclouds.openstack.keystone.v2_0.KeystoneApi;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ProviderModule;
+import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.RegionModule;
 import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneRestApiExpectTest;
-import org.jclouds.rest.ConfiguresRestClient;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.annotations.ApiVersion;
 import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.config.RestClientModule;
+import org.jclouds.rest.config.HttpApiModule;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
 import org.jclouds.rest.internal.BaseRestApiExpectTest;
-import org.jclouds.rest.internal.BaseRestApiMetadata;
 import org.testng.annotations.Test;
 
 import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableSet;
-import com.google.common.util.concurrent.ListenableFuture;
 import com.google.inject.Module;
-import com.google.inject.TypeLiteral;
+import com.google.inject.Provides;
 
 /**
  * Tests configuration via {@link ProviderModule}
@@ -48,31 +70,34 @@
 public class ProviderModuleExpectTest extends BaseRestApiExpectTest<ProviderModuleExpectTest.DNSApi> {
 
    @Retention(RUNTIME)
-   @Target(TYPE)
+   @Target(METHOD)
    @Qualifier
    static @interface DNS {
    }
 
-   @ConfiguresRestClient
-   public static class DNSRestClientModule extends RestClientModule<DNSApi, DNSAsyncApi> {
+   @ConfiguresHttpApi
+   public static class DNSHttpApiModule extends HttpApiModule<DNSApi> {
+
       @Override
       public void configure() {
-         bind(new TypeLiteral<Supplier<URI>>() {}).annotatedWith(DNS.class).to(new TypeLiteral<Supplier<URI>>() {});
          bind(DateAdapter.class).to(Iso8601DateAdapter.class);
          super.configure();
       }
-   }
 
-   static interface DNSApi extends Closeable {
-      boolean zoneExists(@PathParam("zoneName") String zoneName);
+      @Provides
+      @Singleton
+      @DNS
+      protected Supplier<URI> provideCDNUrl(RegionIdToURISupplier.Factory factory, @ApiVersion String apiVersion) {
+         return getLastValueInMap(factory.createForApiTypeAndVersion("dns", apiVersion));
+      }
    }
 
    @org.jclouds.rest.annotations.Endpoint(DNS.class)
-   static interface DNSAsyncApi extends Closeable {
+   static interface DNSApi extends Closeable {
       @HEAD
       @Path("/zones/{zoneName}")
       @Fallback(FalseOnNotFoundOr404.class)
-      public ListenableFuture<Boolean> zoneExists(@PathParam("zoneName") String zoneName);
+      boolean zoneExists(@PathParam("zoneName") String zoneName);
    }
 
    public void testDNSEndpointApplied() {
@@ -86,7 +111,7 @@
       assertTrue(api.zoneExists("foo.com"));
    }
 
-   private static class DNSApiMetadata extends BaseRestApiMetadata {
+   private static class DNSApiMetadata extends BaseHttpApiMetadata<DNSApi> {
 
       @Override
       public Builder toBuilder() {
@@ -102,31 +127,29 @@
       }
 
       public static Properties defaultProperties() {
-         Properties properties = BaseRestApiMetadata.defaultProperties();
+         Properties properties = BaseHttpApiMetadata.defaultProperties();
          properties.setProperty(SERVICE_TYPE, "dns");
          properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
          return properties;
       }
 
-      public static class Builder extends BaseRestApiMetadata.Builder<Builder> {
+      public static class Builder extends BaseHttpApiMetadata.Builder<DNSApi, Builder> {
 
          protected Builder() {
-            super(DNSApi.class, DNSAsyncApi.class);
             id("dns")
-                  .name("DNS API")
-                  .identityName("${tenantName}:${userName} or ${userName}, if your keystone supports a default tenant")
-                  .credentialName("${password}")
-                  .endpointName("Keystone base url ending in /v2.0/")
-                  .documentation(URI.create("http://dns"))
-                  .version("1.0")
-                  .defaultEndpoint("http://localhost:5000/v2.0/")
-                  .defaultProperties(DNSApiMetadata.defaultProperties())
-                  .defaultModules(
-                        ImmutableSet.<Class<? extends Module>> builder()
-                           .add(KeystoneAuthenticationModule.class)
-                           .add(ProviderModule.class)
-                           .add(DNSRestClientModule.class)
-                           .build());
+            .name("DNS API")
+            .identityName("${tenantName}:${userName} or ${userName}, if your keystone supports a default tenant")
+            .credentialName("${password}")
+            .endpointName("Keystone base url ending in /v2.0/")
+            .documentation(URI.create("http://dns"))
+            .version("1.0")
+            .defaultEndpoint("http://localhost:5000/v2.0/")
+            .defaultProperties(DNSApiMetadata.defaultProperties())
+            .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                                        .add(AuthenticationApiModule.class)
+                                        .add(KeystoneAuthenticationModule.class)
+                                        .add(RegionModule.class)
+                                        .add(DNSHttpApiModule.class).build());
          }
 
          @Override
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/NovaApiMetadata.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/NovaApiMetadata.java
index f5a8a92..d112814 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/NovaApiMetadata.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/NovaApiMetadata.java
@@ -33,6 +33,7 @@
 import org.jclouds.compute.ComputeServiceContext;
 import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
+import org.jclouds.openstack.keystone.v2_0.config.MappedAuthenticationApiModule;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule;
 import org.jclouds.openstack.nova.v2_0.compute.config.NovaComputeServiceContextModule;
 import org.jclouds.openstack.nova.v2_0.config.NovaParserModule;
@@ -106,6 +107,7 @@
          .defaultProperties(NovaApiMetadata.defaultProperties())
          .view(typeToken(ComputeServiceContext.class))
          .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                                     .add(MappedAuthenticationApiModule.class)
                                      .add(KeystoneAuthenticationModule.class)
                                      .add(ZoneModule.class)
                                      .add(NovaParserModule.class)
diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/CloudIdentityApiMetadata.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/CloudIdentityApiMetadata.java
index edf8f4d..a7372c7 100644
--- a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/CloudIdentityApiMetadata.java
+++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/CloudIdentityApiMetadata.java
@@ -1,4 +1,3 @@
-package org.jclouds.rackspace.cloudidentity.v2_0;
 /**
  * Licensed to jclouds, Inc. (jclouds) under one or more
  * contributor license agreements.  See the NOTICE file
@@ -17,6 +16,8 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.jclouds.rackspace.cloudidentity.v2_0;
+
 
 
 import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
@@ -33,6 +34,7 @@
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneRestClientModule.KeystoneAdminURLModule;
 import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule;
 import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.SyncToAsyncCloudIdentityAuthenticationApiModule;
 
 import com.google.common.collect.ImmutableSet;
 import com.google.common.reflect.TypeToken;
@@ -87,6 +89,7 @@
          .context(CONTEXT_TOKEN)
          .documentation(URI.create("http://docs.rackspace.com/auth/api/v2.0/auth-api-devguide/"))
          .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                                     .add(SyncToAsyncCloudIdentityAuthenticationApiModule.class)
                                      .add(CloudIdentityAuthenticationModule.class)
                                      .add(KeystoneAdminURLModule.class)
                                      .add(KeystoneParserModule.class)
diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/CloudIdentityAuthenticationApi.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/CloudIdentityAuthenticationApi.java
index ed3d03e..a86bdda 100644
--- a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/CloudIdentityAuthenticationApi.java
+++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/CloudIdentityAuthenticationApi.java
@@ -18,17 +18,27 @@
  */
 package org.jclouds.rackspace.cloudidentity.v2_0;
 
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.openstack.keystone.v2_0.AuthenticationApi;
+import org.jclouds.openstack.keystone.v2_0.binders.BindAuthToJsonPayload;
 import org.jclouds.openstack.keystone.v2_0.domain.Access;
 import org.jclouds.rackspace.cloudidentity.v2_0.domain.ApiKeyCredentials;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.SelectJson;
 
 /**
  * Provides synchronous access to the KeyStone Service API.
  * <p/>
  * 
- * @see AuthenticationAsyncApi
- * @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/Service_API_Api_Operations.html"
+ * @see <a href=
+ *      "http://docs.openstack.org/api/openstack-identity-service/2.0/content/Service_API_Api_Operations.html"
  *      />
  * @author Adrian Cole
  */
@@ -39,13 +49,27 @@
     * 
     * @return access with token
     */
-   Access authenticateWithTenantNameAndCredentials(@Nullable String tenantId, ApiKeyCredentials apiKeyCredentials);
+   @Named("authenticate")
+   @POST
+   @SelectJson("access")
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/tokens")
+   @MapBinder(BindAuthToJsonPayload.class)
+   Access authenticateWithTenantNameAndCredentials(@Nullable @PayloadParam("tenantName") String tenantName,
+         ApiKeyCredentials apiKeyCredentials);
 
    /**
     * Authenticate to generate a token.
     * 
     * @return access with token
     */
-   Access authenticateWithTenantIdAndCredentials(@Nullable String tenantId, ApiKeyCredentials apiKeyCredentials);
+   @Named("authenticate")
+   @POST
+   @SelectJson("access")
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/tokens")
+   @MapBinder(BindAuthToJsonPayload.class)
+   Access authenticateWithTenantIdAndCredentials(@Nullable @PayloadParam("tenantId") String tenantId,
+         ApiKeyCredentials apiKeyCredentials);
 
 }
diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/CloudIdentityAuthenticationAsyncApi.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/CloudIdentityAuthenticationAsyncApi.java
index c4c03a3..acb2dbb 100644
--- a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/CloudIdentityAuthenticationAsyncApi.java
+++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/CloudIdentityAuthenticationAsyncApi.java
@@ -43,7 +43,10 @@
  * @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/Service_API_Api_Operations.html"
  *      />
  * @author Adrian Cole
+ * @deprecated will be removed in jclouds 1.7, as async interfaces are no longer
+ *             supported. please use {@link CloudIdentityAuthenticationAsyncApi}
  */
+@Deprecated
 public interface CloudIdentityAuthenticationAsyncApi extends AuthenticationAsyncApi {
 
    /**
diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/config/CloudIdentityAuthenticationApiModule.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/config/CloudIdentityAuthenticationApiModule.java
new file mode 100644
index 0000000..7f60d3d
--- /dev/null
+++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/config/CloudIdentityAuthenticationApiModule.java
@@ -0,0 +1,45 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.cloudidentity.v2_0.config;
+
+import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
+
+import org.jclouds.openstack.keystone.v2_0.AuthenticationApi;
+import org.jclouds.rackspace.cloudidentity.v2_0.CloudIdentityAuthenticationApi;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+public class CloudIdentityAuthenticationApiModule extends AbstractModule  {
+
+   @Override
+   protected void configure() {
+      // AuthenticationApi is used directly for filters and retry handlers, so let's bind it explicitly
+      bindHttpApi(binder(), CloudIdentityAuthenticationApi.class);
+   }
+
+   @Provides
+   private AuthenticationApi provideAuthenticationApi(CloudIdentityAuthenticationApi in){ 
+      return in;
+   }
+}
diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/config/CloudIdentityAuthenticationModule.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/config/CloudIdentityAuthenticationModule.java
index d56fff2..2b5f7a2 100644
--- a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/config/CloudIdentityAuthenticationModule.java
+++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/config/CloudIdentityAuthenticationModule.java
@@ -18,26 +18,19 @@
  */
 package org.jclouds.rackspace.cloudidentity.v2_0.config;
 
-import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
-
 import java.util.Map;
 
 import org.jclouds.domain.Credentials;
-import org.jclouds.openstack.keystone.v2_0.AuthenticationAsyncApi;
-import org.jclouds.openstack.keystone.v2_0.AuthenticationApi;
 import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
 import org.jclouds.openstack.keystone.v2_0.domain.Access;
 import org.jclouds.openstack.keystone.v2_0.functions.AuthenticatePasswordCredentials;
-import org.jclouds.rackspace.cloudidentity.v2_0.CloudIdentityAuthenticationAsyncApi;
-import org.jclouds.rackspace.cloudidentity.v2_0.CloudIdentityAuthenticationApi;
 import org.jclouds.rackspace.cloudidentity.v2_0.functions.AuthenticateApiKeyCredentials;
 
 import com.google.common.base.Function;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSet.Builder;
 import com.google.inject.Injector;
-import com.google.inject.Scopes;
 
 /**
  * 
@@ -46,15 +39,6 @@
 public class CloudIdentityAuthenticationModule extends KeystoneAuthenticationModule {
 
    @Override
-   protected void bindAuthenticationApi() {
-      // AuthenticationApi is used directly for filters and retry handlers, so let's bind it explicitly
-      bindHttpApi(binder(), CloudIdentityAuthenticationApi.class,
-            CloudIdentityAuthenticationAsyncApi.class);
-      bind(AuthenticationApi.class).to(CloudIdentityAuthenticationApi.class).in(Scopes.SINGLETON);
-      bind(AuthenticationAsyncApi.class).to(CloudIdentityAuthenticationAsyncApi.class).in(Scopes.SINGLETON);
-   }
-
-   @Override
    protected Map<String, Function<Credentials, Access>> authenticationMethods(Injector i) {
       Builder<Function<Credentials, Access>> fns = ImmutableSet.<Function<Credentials, Access>> builder();
       fns.add(i.getInstance(AuthenticatePasswordCredentials.class));
diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/config/SyncToAsyncCloudIdentityAuthenticationApiModule.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/config/SyncToAsyncCloudIdentityAuthenticationApiModule.java
new file mode 100644
index 0000000..07782db
--- /dev/null
+++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v2_0/config/SyncToAsyncCloudIdentityAuthenticationApiModule.java
@@ -0,0 +1,58 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.cloudidentity.v2_0.config;
+
+import static org.jclouds.rest.config.BinderUtils.bindSyncToAsyncHttpApi;
+
+import org.jclouds.openstack.keystone.v2_0.AuthenticationApi;
+import org.jclouds.openstack.keystone.v2_0.AuthenticationAsyncApi;
+import org.jclouds.rackspace.cloudidentity.v2_0.CloudIdentityAuthenticationApi;
+import org.jclouds.rackspace.cloudidentity.v2_0.CloudIdentityAuthenticationAsyncApi;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+
+/**
+ * 
+ * @author Adrian Cole
+ * @deprecated will be removed in jclouds 1.7, as async interfaces are no longer
+ *             supported. please use
+ *             {@link CloudIdentityAuthenticationApiModule}
+ */
+@Deprecated
+public class SyncToAsyncCloudIdentityAuthenticationApiModule extends AbstractModule {
+
+   @Override
+   protected void configure() {
+      // AuthenticationApi is used directly for filters and retry handlers, so
+      // let's bind it explicitly
+      bindSyncToAsyncHttpApi(binder(), CloudIdentityAuthenticationApi.class, CloudIdentityAuthenticationAsyncApi.class);
+   }
+
+   @Provides
+   private AuthenticationApi provideAuthenticationApi(CloudIdentityAuthenticationApi in) {
+      return in;
+   }
+
+   @Provides
+   private AuthenticationAsyncApi provideAuthenticationAsyncApi(CloudIdentityAuthenticationAsyncApi in) {
+      return in;
+   }
+
+}
diff --git a/apis/rackspace-cloudloadbalancers/pom.xml b/apis/rackspace-cloudloadbalancers/pom.xml
index 366de20..1cfc325 100644
--- a/apis/rackspace-cloudloadbalancers/pom.xml
+++ b/apis/rackspace-cloudloadbalancers/pom.xml
@@ -37,8 +37,8 @@
     <test.rackspace-cloudloadbalancers.endpoint>https://identity.api.rackspacecloud.com/v2.0/</test.rackspace-cloudloadbalancers.endpoint>
     <test.rackspace-cloudloadbalancers.api-version>1</test.rackspace-cloudloadbalancers.api-version>
     <test.rackspace-cloudloadbalancers.build-version />
-    <test.rackspace-cloudloadbalancers.identity>${test.rackspace.identity}</test.rackspace-cloudloadbalancers.identity>
-    <test.rackspace-cloudloadbalancers.credential>${test.rackspace.credential}</test.rackspace-cloudloadbalancers.credential>
+    <test.rackspace-cloudloadbalancers.identity>${test.rackspace-us.identity}</test.rackspace-cloudloadbalancers.identity>
+    <test.rackspace-cloudloadbalancers.credential>${test.rackspace-us.credential}</test.rackspace-cloudloadbalancers.credential>
 
     <jclouds.osgi.export>org.jclouds.rackspace.cloudloadbalancers*;version="${project.version}"</jclouds.osgi.export>
     <jclouds.osgi.import>org.jclouds*;version="${project.version}",*</jclouds.osgi.import>
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/CloudLoadBalancersApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/CloudLoadBalancersApi.java
index edd433d..634ba49 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/CloudLoadBalancersApi.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/CloudLoadBalancersApi.java
@@ -43,11 +43,10 @@
 import com.google.inject.Provides;
 
 /**
- * Provides synchronous access to Rackspace Cloud Load Balancers.
+ * Provides access to Rackspace Cloud Load Balancers.
  * <p/>
  * 
- * @see CloudLoadBalancersAsyncApi 
- * @author Adrian Cole
+ * @author Everett Toews
  */
 public interface CloudLoadBalancersApi extends Closeable {
    /**
@@ -58,14 +57,14 @@
    Set<String> getConfiguredZones();
 
    /**
-    * Provides synchronous access to Load Balancer features.
+    * Provides access to Load Balancer features.
     */
    @Delegate
    LoadBalancerApi getLoadBalancerApiForZone(
          @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
    
    /**
-    * Provides synchronous access to Node features.
+    * Provides access to Node features.
     */
    @Delegate
    @Path("/loadbalancers/{lbId}")
@@ -73,7 +72,7 @@
          @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
 
    /**
-    * Provides synchronous access to Access Rule features.
+    * Provides access to Access Rule features.
     */
    @Delegate
    @Path("/loadbalancers/{lbId}")
@@ -81,7 +80,7 @@
          @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
 
    /**
-    * Provides synchronous access to Virtual IP features.
+    * Provides access to Virtual IP features.
     */
    @Delegate
    @Path("/loadbalancers/{lbId}")
@@ -89,7 +88,7 @@
          @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
 
    /**
-    * Provides synchronous access to Connection features.
+    * Provides access to Connection features.
     */
    @Delegate
    @Path("/loadbalancers/{lbId}")
@@ -97,7 +96,7 @@
          @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
 
    /**
-    * Provides synchronous access to Health Monitor features.
+    * Provides access to Health Monitor features.
     */
    @Delegate
    @Path("/loadbalancers/{lbId}")
@@ -105,7 +104,7 @@
          @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
 
    /**
-    * Provides synchronous access to Session Persistence features.
+    * Provides access to Session Persistence features.
     */
    @Delegate
    @Path("/loadbalancers/{lbId}")
@@ -113,7 +112,7 @@
          @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
 
    /**
-    * Provides synchronous access to Content Caching features.
+    * Provides access to Content Caching features.
     */
    @Delegate
    @Path("/loadbalancers/{lbId}")
@@ -121,7 +120,7 @@
          @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
 
    /**
-    * Provides synchronous access to SSL Termination features.
+    * Provides access to SSL Termination features.
     */
    @Delegate
    @Path("/loadbalancers/{lbId}")
@@ -129,7 +128,7 @@
          @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
 
    /**
-    * Provides synchronous access to Error Page features.
+    * Provides access to Error Page features.
     */
    @Delegate
    @Path("/loadbalancers/{lbId}")
@@ -137,7 +136,7 @@
          @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
 
    /**
-    * Provides synchronous access to Report features.
+    * Provides access to Report features.
     */
    @Delegate
    ReportApi getReportApiForZone(
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/CloudLoadBalancersApiMetadata.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/CloudLoadBalancersApiMetadata.java
index 64a3363..f5740f8 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/CloudLoadBalancersApiMetadata.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/CloudLoadBalancersApiMetadata.java
@@ -28,30 +28,21 @@
 import org.jclouds.loadbalancer.LoadBalancerServiceContext;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule;
 import org.jclouds.rackspace.cloudidentity.v2_0.ServiceType;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationApiModule;
 import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule;
 import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes;
-import org.jclouds.rackspace.cloudloadbalancers.v1.config.CloudLoadBalancersRestClientModule;
+import org.jclouds.rackspace.cloudloadbalancers.v1.config.CloudLoadBalancersHttpApiModule;
 import org.jclouds.rackspace.cloudloadbalancers.v1.loadbalancer.config.CloudLoadBalancersLoadBalancerContextModule;
-import org.jclouds.rest.internal.BaseRestApiMetadata;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
 
 import com.google.common.collect.ImmutableSet;
-import com.google.common.reflect.TypeToken;
 import com.google.inject.Module;
 /**
  * Implementation of {@link ApiMetadata} for CloudLoadBalancers 1.0 API
  * 
  * @author Adrian Cole
  */
-public class CloudLoadBalancersApiMetadata extends BaseRestApiMetadata {
-
-   /**
-    * @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(CloudLoadBalancersApi.class)} as
-    *             {@link CloudLoadBalancersAsyncApi} interface will be removed in jclouds 1.7.
-    */
-   @Deprecated
-   public static final TypeToken<org.jclouds.rest.RestContext<CloudLoadBalancersApi, CloudLoadBalancersAsyncApi>> CONTEXT_TOKEN = new TypeToken<org.jclouds.rest.RestContext<CloudLoadBalancersApi, CloudLoadBalancersAsyncApi>>() {
-      private static final long serialVersionUID = 1L;
-   };
+public class CloudLoadBalancersApiMetadata extends BaseHttpApiMetadata<CloudLoadBalancersApi> {
 
    @Override
    public Builder toBuilder() {
@@ -67,17 +58,15 @@
    }
 
    public static Properties defaultProperties() {
-      Properties properties = BaseRestApiMetadata.defaultProperties();
+      Properties properties = BaseHttpApiMetadata.defaultProperties();
       properties.setProperty(SERVICE_TYPE, ServiceType.LOAD_BALANCERS);
       properties.setProperty(CREDENTIAL_TYPE, CloudIdentityCredentialTypes.API_KEY_CREDENTIALS);
       return properties;
    }
 
-   public static class Builder extends BaseRestApiMetadata.Builder<Builder> {
+   public static class Builder extends BaseHttpApiMetadata.Builder<CloudLoadBalancersApi, Builder> {
 
-      @SuppressWarnings("deprecation")
       protected Builder() {
-         super(CloudLoadBalancersApi.class, CloudLoadBalancersAsyncApi.class);
          id("rackspace-cloudloadbalancers")
                .name("Rackspace Cloud Load Balancers API")
                .identityName("Username")
@@ -87,12 +76,12 @@
                .defaultEndpoint("https://identity.api.rackspacecloud.com/v2.0/")
                .defaultProperties(CloudLoadBalancersApiMetadata.defaultProperties())
                .view(typeToken(LoadBalancerServiceContext.class))
-               .defaultModules(
-                     ImmutableSet.<Class<? extends Module>> of(
-                           CloudIdentityAuthenticationModule.class,
-                           ZoneModule.class,
-                           CloudLoadBalancersRestClientModule.class,
-                           CloudLoadBalancersLoadBalancerContextModule.class));
+               .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                            .add(CloudIdentityAuthenticationApiModule.class)
+                            .add(CloudIdentityAuthenticationModule.class)
+                            .add(ZoneModule.class)
+                            .add(CloudLoadBalancersHttpApiModule.class)
+                            .add(CloudLoadBalancersLoadBalancerContextModule.class).build());
       }
 
       @Override
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/CloudLoadBalancersAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/CloudLoadBalancersAsyncApi.java
deleted file mode 100644
index dca10a6..0000000
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/CloudLoadBalancersAsyncApi.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.rackspace.cloudloadbalancers.v1;
-
-import java.io.Closeable;
-import java.util.Set;
-
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.Zone;
-import org.jclouds.location.functions.ZoneToEndpoint;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.AccessRuleAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.ConnectionAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.ContentCachingAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.ErrorPageAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.HealthMonitorAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.LoadBalancerAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.NodeAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.ReportAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.SSLTerminationAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.SessionPersistenceAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.VirtualIPAsyncApi;
-import org.jclouds.rest.annotations.Delegate;
-import org.jclouds.rest.annotations.EndpointParam;
-
-import com.google.inject.Provides;
-
-/**
- * Provides asynchronous access to Rackspace Cloud Load Balancers.
- * <p/>
- * 
- * @see CloudLoadBalancersApi
- * @author Adrian Cole
- * @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(CloudLoadBalancersApi.class)} as
- *             {@link CloudLoadBalancersAsyncApi} interface will be removed in jclouds 1.7.
- */
-@Deprecated
-public interface CloudLoadBalancersAsyncApi extends Closeable {
-   /**
-    * @return the Zone codes configured
-    */
-   @Provides
-   @Zone
-   Set<String> getConfiguredZones();
-
-   /**
-    * Provides asynchronous access to LoadBalancer features.
-    */
-   @Delegate
-   LoadBalancerAsyncApi getLoadBalancerApiForZone(
-         @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
-   
-   /**
-    * Provides asynchronous access to Node features.
-    */
-   @Delegate
-   @Path("/loadbalancers/{lbId}")
-   NodeAsyncApi getNodeApiForZoneAndLoadBalancer(
-         @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
-
-   /**
-    * Provides asynchronous access to Access Rule features.
-    */
-   @Delegate
-   @Path("/loadbalancers/{lbId}")
-   AccessRuleAsyncApi getAccessRuleApiForZoneAndLoadBalancer(
-         @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
-
-   /**
-    * Provides asynchronous access to Virtual IP features.
-    */
-   @Delegate
-   @Path("/loadbalancers/{lbId}")
-   VirtualIPAsyncApi getVirtualIPApiForZoneAndLoadBalancer(
-         @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
-
-   /**
-    * Provides asynchronous access to Connection features.
-    */
-   @Delegate
-   @Path("/loadbalancers/{lbId}")
-   ConnectionAsyncApi getConnectionApiForZoneAndLoadBalancer(
-         @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
-
-   /**
-    * Provides asynchronous access to Health Monitor features.
-    */
-   @Delegate
-   @Path("/loadbalancers/{lbId}")
-   HealthMonitorAsyncApi getHealthMonitorApiForZoneAndLoadBalancer(
-         @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
-
-   /**
-    * Provides asynchronous access to Session Persistence features.
-    */
-   @Delegate
-   @Path("/loadbalancers/{lbId}")
-   SessionPersistenceAsyncApi getSessionPersistenceApiForZoneAndLoadBalancer(
-         @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
-
-   /**
-    * Provides asynchronous access to Content Caching features.
-    */
-   @Delegate
-   @Path("/loadbalancers/{lbId}")
-   ContentCachingAsyncApi getContentCachingApiForZoneAndLoadBalancer(
-         @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
-
-   /**
-    * Provides asynchronous access to SSL Termination features.
-    */
-   @Delegate
-   @Path("/loadbalancers/{lbId}")
-   SSLTerminationAsyncApi getSSLTerminationApiForZoneAndLoadBalancer(
-         @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
-
-   /**
-    * Provides asynchronous access to Error Page features.
-    */
-   @Delegate
-   @Path("/loadbalancers/{lbId}")
-   ErrorPageAsyncApi getErrorPageApiForZoneAndLoadBalancer(
-         @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone, @PathParam("lbId") int lbId);
-
-   /**
-    * Provides asynchronous access to Report features.
-    */
-   @Delegate
-   ReportAsyncApi getReportApiForZone(
-         @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
-}
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/config/CloudLoadBalancersHttpApiModule.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/config/CloudLoadBalancersHttpApiModule.java
new file mode 100644
index 0000000..3c1629c
--- /dev/null
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/config/CloudLoadBalancersHttpApiModule.java
@@ -0,0 +1,59 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rackspace.cloudloadbalancers.v1.config;
+
+import org.jclouds.http.HttpErrorHandler;
+import org.jclouds.http.annotation.ClientError;
+import org.jclouds.http.annotation.Redirection;
+import org.jclouds.http.annotation.ServerError;
+import org.jclouds.json.config.GsonModule.DateAdapter;
+import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
+import org.jclouds.rackspace.cloudloadbalancers.v1.CloudLoadBalancersApi;
+import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ConvertLB;
+import org.jclouds.rackspace.cloudloadbalancers.v1.handlers.ParseCloudLoadBalancersErrorFromHttpResponse;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.config.HttpApiModule;
+
+import com.google.inject.assistedinject.FactoryModuleBuilder;
+
+/**
+ * Configures the Rackspace Cloud Load Balancers connection.
+ * 
+ * @author Adrian Cole
+ */
+@ConfiguresHttpApi
+public class CloudLoadBalancersHttpApiModule extends HttpApiModule<CloudLoadBalancersApi> {
+
+   @Override
+   protected void configure() {
+      bind(DateAdapter.class).to(Iso8601DateAdapter.class);
+      install(new FactoryModuleBuilder().build(ConvertLB.Factory.class));
+      super.configure();
+   }
+
+   @Override
+   protected void bindErrorHandlers() {
+      bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(
+            ParseCloudLoadBalancersErrorFromHttpResponse.class);
+      bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(
+            ParseCloudLoadBalancersErrorFromHttpResponse.class);
+      bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(
+            ParseCloudLoadBalancersErrorFromHttpResponse.class);
+   }
+}
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/config/CloudLoadBalancersRestClientModule.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/config/CloudLoadBalancersRestClientModule.java
deleted file mode 100644
index 921ba16..0000000
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/config/CloudLoadBalancersRestClientModule.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.rackspace.cloudloadbalancers.v1.config;
-
-import java.util.Map;
-
-import org.jclouds.http.HttpErrorHandler;
-import org.jclouds.http.annotation.ClientError;
-import org.jclouds.http.annotation.Redirection;
-import org.jclouds.http.annotation.ServerError;
-import org.jclouds.json.config.GsonModule.DateAdapter;
-import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
-import org.jclouds.rackspace.cloudloadbalancers.v1.CloudLoadBalancersApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.CloudLoadBalancersAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.AccessRuleApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.AccessRuleAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.ConnectionApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.ConnectionAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.ContentCachingApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.ContentCachingAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.ErrorPageApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.ErrorPageAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.HealthMonitorApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.HealthMonitorAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.LoadBalancerApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.LoadBalancerAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.NodeApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.NodeAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.ReportApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.ReportAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.SSLTerminationApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.SSLTerminationAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.SessionPersistenceApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.SessionPersistenceAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.VirtualIPApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.features.VirtualIPAsyncApi;
-import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ConvertLB;
-import org.jclouds.rackspace.cloudloadbalancers.v1.handlers.ParseCloudLoadBalancersErrorFromHttpResponse;
-import org.jclouds.rest.ConfiguresRestClient;
-import org.jclouds.rest.config.RestClientModule;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.inject.assistedinject.FactoryModuleBuilder;
-
-/**
- * Configures the Rackspace Cloud Load Balancers connection.
- * 
- * @author Adrian Cole
- */
-@ConfiguresRestClient
-public class CloudLoadBalancersRestClientModule extends
-         RestClientModule<CloudLoadBalancersApi, CloudLoadBalancersAsyncApi> {
-
-   public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()
-            .put(LoadBalancerApi.class, LoadBalancerAsyncApi.class)
-            .put(NodeApi.class, NodeAsyncApi.class)
-            .put(AccessRuleApi.class, AccessRuleAsyncApi.class)
-            .put(VirtualIPApi.class, VirtualIPAsyncApi.class)
-            .put(ConnectionApi.class, ConnectionAsyncApi.class)
-            .put(HealthMonitorApi.class, HealthMonitorAsyncApi.class)
-            .put(SessionPersistenceApi.class, SessionPersistenceAsyncApi.class)
-            .put(ContentCachingApi.class, ContentCachingAsyncApi.class)
-            .put(SSLTerminationApi.class, SSLTerminationAsyncApi.class)
-            .put(ErrorPageApi.class, ErrorPageAsyncApi.class)
-            .put(ReportApi.class, ReportAsyncApi.class)
-            .build();
-
-   public CloudLoadBalancersRestClientModule() {
-      super(DELEGATE_MAP);
-   }
-
-   @Override
-   protected void configure() {
-      bind(DateAdapter.class).to(Iso8601DateAdapter.class);
-      install(new FactoryModuleBuilder().build(ConvertLB.Factory.class));
-      super.configure();
-   }
-
-   @Override
-   protected void bindErrorHandlers() {
-      bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(
-               ParseCloudLoadBalancersErrorFromHttpResponse.class);
-      bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(
-               ParseCloudLoadBalancersErrorFromHttpResponse.class);
-      bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(
-               ParseCloudLoadBalancersErrorFromHttpResponse.class);
-   }
-}
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/AccessRuleApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/AccessRuleApi.java
index 4d32b23..c8db030 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/AccessRuleApi.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/AccessRuleApi.java
@@ -18,17 +18,35 @@
  */
 package org.jclouds.rackspace.cloudloadbalancers.v1.features;
 
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.AccessRule;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.AccessRuleWithId;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.WrapWith;
 
 /**
  * The access list management feature allows fine-grained network access controls to be applied to the load balancer's
  * virtual IP address.
  * <p/>
  * 
- * @see AccessRuleAsyncApi
  * @author Everett Toews
  */
+@RequestFilters(AuthenticateRequest.class)
 public interface AccessRuleApi {
    /**
     * Create new access rules or append to existing access rules.
@@ -38,11 +56,22 @@
     * AccessRules. A single address or subnet definition is considered unique and cannot be duplicated between rules
     * in an access list.
     */
-   void create(Iterable<AccessRule> accessRules);
+   @Named("accessrule:create")
+   @POST
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(VoidOnNotFoundOr404.class)
+   @Path("/accesslist")
+   void create(@WrapWith("accessList") Iterable<AccessRule> accessRules);
 
    /**
     * List the AccessRules.
     */
+   @Named("accessrule:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   @SelectJson("accessList")
+   @Path("/accesslist")
    Iterable<AccessRuleWithId> list();
    
    /**
@@ -50,19 +79,34 @@
     * 
     * @return true on a successful delete, false if the access rule was not found
     */
-   boolean delete(int id);
+   @Named("accessrule:delete")
+   @DELETE
+   @Fallback(FalseOnNotFoundOr404.class)
+   @Path("/accesslist/{id}")
+   @Consumes("*/*")
+   boolean delete(@PathParam("id") int id);
    
    /**
     * Batch delete the access rules given the specified ids.
     * 
     * @return true on a successful delete, false if the access rule was not found
     */
-   boolean delete(Iterable<Integer> ids);
+   @Named("accessrule:delete")
+   @DELETE
+   @Fallback(FalseOnNotFoundOr404.class)
+   @Path("/accesslist")
+   @Consumes("*/*")
+   boolean delete(@QueryParam("id") Iterable<Integer> ids);
    
    /**
     * Delete the entire access list.
     * 
     * @return true on a successful delete, false if the access rule was not found
     */
+   @Named("accessrule:delete")
+   @DELETE
+   @Fallback(FalseOnNotFoundOr404.class)
+   @Path("/accesslist")
+   @Consumes("*/*")
    boolean deleteAll();
 }
\ No newline at end of file
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/AccessRuleAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/AccessRuleAsyncApi.java
deleted file mode 100644
index 6a4c872..0000000
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/AccessRuleAsyncApi.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.rackspace.cloudloadbalancers.v1.features;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
-import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.AccessRule;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.AccessRuleWithId;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SelectJson;
-import org.jclouds.rest.annotations.WrapWith;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides asynchronous access to Rackspace Cloud Load Balancers via their REST API.
- * <p/>
- * 
- * @see AccessRuleApi
- * @author Everett Toews
- */
-@RequestFilters(AuthenticateRequest.class)
-public interface AccessRuleAsyncApi {
-
-   /**
-    * @see AccessRuleApi#create(Iterable)
-    */
-   @Named("accessrule:create")
-   @POST
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(VoidOnNotFoundOr404.class)
-   @Path("/accesslist")
-   ListenableFuture<Void> create(@WrapWith("accessList") Iterable<AccessRule> accessRules);
-
-   /**
-    * @see AccessRuleApi#list()
-    */
-   @Named("accessrule:list")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
-   @SelectJson("accessList")
-   @Path("/accesslist")
-   ListenableFuture<Iterable<AccessRuleWithId>> list();
-
-   /**
-    * @see AccessRuleApi#delete(int)
-    */
-   @Named("accessrule:delete")
-   @DELETE
-   @Fallback(FalseOnNotFoundOr404.class)
-   @Path("/accesslist/{id}")
-   @Consumes("*/*")
-   ListenableFuture<Boolean> delete(@PathParam("id") int id);
-
-   /**
-    * @see AccessRuleApi#delete(Iterable)
-    */
-   @Named("accessrule:delete")
-   @DELETE
-   @Fallback(FalseOnNotFoundOr404.class)
-   @Path("/accesslist")
-   @Consumes("*/*")
-   ListenableFuture<Boolean> delete(@QueryParam("id") Iterable<Integer> ids);
-
-   /**
-    * @see AccessRuleApi#deleteAll()
-    */
-   @Named("accessrule:delete")
-   @DELETE
-   @Fallback(FalseOnNotFoundOr404.class)
-   @Path("/accesslist")
-   @Consumes("*/*")
-   ListenableFuture<Boolean> deleteAll();
-}
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ConnectionApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ConnectionApi.java
index 1aa6560..cca0298 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ConnectionApi.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ConnectionApi.java
@@ -18,25 +18,58 @@
  */
 package org.jclouds.rackspace.cloudloadbalancers.v1.features;
 
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.FalseOnNotFoundOr422;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.ConnectionThrottle;
+import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseNestedBoolean;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.WrapWith;
 
 /**
  * Connection management features.
  * <p/>
  * 
- * @see ConnectionAsyncApi
  * @author Everett Toews
  */
+@RequestFilters(AuthenticateRequest.class)
 public interface ConnectionApi {
    /**
     * The connection throttling feature imposes limits on the number of connections per IP address to help mitigate 
     * malicious or abusive traffic to your applications.
     */
-   void createOrUpdateConnectionThrottle(ConnectionThrottle connectionThrottle);
+   @Named("connectionthrottle:create")
+   @PUT
+   @Consumes(MediaType.APPLICATION_JSON) 
+   @Fallback(VoidOnNotFoundOr404.class)
+   @Path("/connectionthrottle")
+   void createOrUpdateConnectionThrottle(
+         @WrapWith("connectionThrottle") ConnectionThrottle connectionThrottle);
 
    /**
     * Get connection throttle.
     */
+   @Named("connectionthrottle:get")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @SelectJson("connectionThrottle")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Path("/connectionthrottle")
    ConnectionThrottle getConnectionThrottle();
    
    /**
@@ -44,20 +77,45 @@
     * 
     * @return true on a successful delete, false if the connection throttle was not found.
     */
+   @Named("connectionthrottle:delete")
+   @DELETE
+   @Fallback(FalseOnNotFoundOr422.class)
+   @Path("/connectionthrottle")
+   @Consumes("*/*")
    boolean deleteConnectionThrottle();
    
    /**
     * Determine if the load balancer is logging connections.
     */
+   @Named("connectionlogging:state")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseNestedBoolean.class)
+   @Fallback(FalseOnNotFoundOr404.class)
+   @Path("/connectionlogging")
    boolean isConnectionLogging();
    
    /**
     * Enable logging connections.
     */
+   @Named("connectionlogging:state")
+   @PUT
+   @Produces(MediaType.APPLICATION_JSON)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(VoidOnNotFoundOr404.class)
+   @Payload("{\"connectionLogging\":{\"enabled\":true}}")
+   @Path("/connectionlogging")
    void enableConnectionLogging();
    
    /**
     * Disable logging connections.
     */
+   @Named("connectionlogging:state")
+   @PUT
+   @Produces(MediaType.APPLICATION_JSON)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(VoidOnNotFoundOr404.class)
+   @Payload("{\"connectionLogging\":{\"enabled\":false}}")
+   @Path("/connectionlogging")
    void disableConnectionLogging();
 }
\ No newline at end of file
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ConnectionAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ConnectionAsyncApi.java
deleted file mode 100644
index e50fd71..0000000
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ConnectionAsyncApi.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.rackspace.cloudloadbalancers.v1.features;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
-import org.jclouds.Fallbacks.FalseOnNotFoundOr422;
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.ConnectionThrottle;
-import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseNestedBoolean;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.Payload;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.ResponseParser;
-import org.jclouds.rest.annotations.SelectJson;
-import org.jclouds.rest.annotations.WrapWith;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides asynchronous access to Rackspace Cloud Load Balancers via their REST API.
- * <p/>
- * 
- * @see ConnectionApi
- * @author Everett Toews
- */
-@RequestFilters(AuthenticateRequest.class)
-public interface ConnectionAsyncApi {
-
-   /**
-    * @see ConnectionApi#createOrUpdateConnectionThrottle(ConnectionThrottle)
-    */
-   @Named("connectionthrottle:create")
-   @PUT
-   @Consumes(MediaType.APPLICATION_JSON) 
-   @Fallback(VoidOnNotFoundOr404.class)
-   @Path("/connectionthrottle")
-   ListenableFuture<Void> createOrUpdateConnectionThrottle(
-         @WrapWith("connectionThrottle") ConnectionThrottle connectionThrottle);
-
-   /**
-    * @see ConnectionApi#getConnectionThrottle()
-    */
-   @Named("connectionthrottle:get")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @SelectJson("connectionThrottle")
-   @Fallback(NullOnNotFoundOr404.class)
-   @Path("/connectionthrottle")
-   ListenableFuture<ConnectionThrottle> getConnectionThrottle();
-
-   /**
-    * @see ConnectionApi#deleteConnectionThrottle()
-    */
-   @Named("connectionthrottle:delete")
-   @DELETE
-   @Fallback(FalseOnNotFoundOr422.class)
-   @Path("/connectionthrottle")
-   @Consumes("*/*")
-   ListenableFuture<Boolean> deleteConnectionThrottle();
-
-   /**
-    * @see ConnectionApi#isConnectionLogging()
-    */
-   @Named("connectionlogging:state")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @ResponseParser(ParseNestedBoolean.class)
-   @Fallback(FalseOnNotFoundOr404.class)
-   @Path("/connectionlogging")
-   ListenableFuture<Boolean> isConnectionLogging();
-
-   /**
-    * @see ConnectionApi#enableConnectionLogging()
-    */
-   @Named("connectionlogging:state")
-   @PUT
-   @Produces(MediaType.APPLICATION_JSON)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(VoidOnNotFoundOr404.class)
-   @Payload("{\"connectionLogging\":{\"enabled\":true}}")
-   @Path("/connectionlogging")
-   ListenableFuture<Void> enableConnectionLogging();
-
-   /**
-    * @see ConnectionApi#disableConnectionLogging()
-    */
-   @Named("connectionlogging:state")
-   @PUT
-   @Produces(MediaType.APPLICATION_JSON)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(VoidOnNotFoundOr404.class)
-   @Payload("{\"connectionLogging\":{\"enabled\":false}}")
-   @Path("/connectionlogging")
-   ListenableFuture<Void> disableConnectionLogging();
-}
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ContentCachingApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ContentCachingApi.java
index 0f28ed3..63f315e 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ContentCachingApi.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ContentCachingApi.java
@@ -18,6 +18,23 @@
  */
 package org.jclouds.rackspace.cloudloadbalancers.v1.features;
 
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
+import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseNestedBoolean;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+
 /**
  * When content caching is enabled, recently-accessed files are stored on the load balancer for easy retrieval by web 
  * clients. Content caching improves the performance of high traffic web sites by temporarily storing data that was 
@@ -26,22 +43,42 @@
  * web server.
  * <p/>
  * 
- * @see ContentCachingAsyncApi
  * @author Everett Toews
  */
+@RequestFilters(AuthenticateRequest.class)
 public interface ContentCachingApi {
    /**
     * Determine if the load balancer is content caching.
     */
+   @Named("contentcaching:state")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseNestedBoolean.class)
+   @Fallback(FalseOnNotFoundOr404.class)
+   @Path("/contentcaching")
    boolean isContentCaching();
    
    /**
     * Enable content caching.
     */
+   @Named("contentcaching:state")
+   @PUT
+   @Produces(MediaType.APPLICATION_JSON)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(VoidOnNotFoundOr404.class)
+   @Payload("{\"contentCaching\":{\"enabled\":true}}")
+   @Path("/contentcaching")
    void enable();
    
    /**
     * Disable content caching.
     */
+   @Named("contentcaching:state")
+   @PUT
+   @Produces(MediaType.APPLICATION_JSON)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(VoidOnNotFoundOr404.class)
+   @Payload("{\"contentCaching\":{\"enabled\":false}}")
+   @Path("/contentcaching")
    void disable();
 }
\ No newline at end of file
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ContentCachingAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ContentCachingAsyncApi.java
deleted file mode 100644
index 47ad77c..0000000
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ContentCachingAsyncApi.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.rackspace.cloudloadbalancers.v1.features;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
-import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseNestedBoolean;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.Payload;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.ResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides asynchronous access to Rackspace Cloud Load Balancers via their REST API.
- * <p/>
- * 
- * @see ContentCachingApi
- * @author Everett Toews
- */
-@RequestFilters(AuthenticateRequest.class)
-public interface ContentCachingAsyncApi {
-
-   /**
-    * @see ContentCachingApi#isContentCaching()
-    */
-   @Named("contentcaching:state")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @ResponseParser(ParseNestedBoolean.class)
-   @Fallback(FalseOnNotFoundOr404.class)
-   @Path("/contentcaching")
-   ListenableFuture<Boolean> isContentCaching();
-
-   /**
-    * @see ContentCachingApi#enable()
-    */
-   @Named("contentcaching:state")
-   @PUT
-   @Produces(MediaType.APPLICATION_JSON)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(VoidOnNotFoundOr404.class)
-   @Payload("{\"contentCaching\":{\"enabled\":true}}")
-   @Path("/contentcaching")
-   ListenableFuture<Void> enable();
-
-   /**
-    * @see ContentCachingApi#disableConnectionLogging()
-    */
-   @Named("contentcaching:state")
-   @PUT
-   @Produces(MediaType.APPLICATION_JSON)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(VoidOnNotFoundOr404.class)
-   @Payload("{\"contentCaching\":{\"enabled\":false}}")
-   @Path("/contentcaching")
-   ListenableFuture<Void> disable();
-}
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ErrorPageApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ErrorPageApi.java
index dbb9df1..a55129e 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ErrorPageApi.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ErrorPageApi.java
@@ -18,6 +18,25 @@
  */
 package org.jclouds.rackspace.cloudloadbalancers.v1.features;
 
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
+import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseNestedString;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+
 /**
  * An error page is the html file that is shown to an end user who is attempting to access a load balancer node that 
  * is offline/unavailable. During provisioning, every load balancer is configured with a default error page that gets 
@@ -25,23 +44,41 @@
  * balancer with an HTTP-based protocol. Page updates will override existing content.
  * <p/>
  * 
- * @see ErrorPageAsyncApi
  * @author Everett Toews
  */
+@RequestFilters(AuthenticateRequest.class)
 public interface ErrorPageApi {
    /**
     * Specify the HTML content for the custom error page. Must be 65536 characters or less.
     */
-   void create(String content);
+   @Named("errorpage:create")
+   @PUT
+   @Consumes(MediaType.WILDCARD)
+   @Produces(MediaType.APPLICATION_JSON)
+   @Fallback(VoidOnNotFoundOr404.class)
+   @Payload("%7B\"errorpage\":%7B\"content\":\"{content}\"%7D%7D")
+   @Path("/errorpage")
+   void create(@PayloadParam("content") String content);
    
    /**
     * Get the error page HTML content.
     */
+   @Named("errorpage:get")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseNestedString.class)
+   @Fallback(VoidOnNotFoundOr404.class)
+   @Path("/errorpage")
    String get();
    
    /**
     * If a custom error page is deleted, or the load balancer is changed to a non-HTTP protocol, the default error 
     * page will be restored.
     */
+   @Named("errorpage:delete")
+   @DELETE
+   @Consumes(MediaType.WILDCARD)
+   @Fallback(FalseOnNotFoundOr404.class)
+   @Path("/errorpage")
    boolean delete();
 }
\ No newline at end of file
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ErrorPageAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ErrorPageAsyncApi.java
deleted file mode 100644
index 2d94d7a..0000000
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ErrorPageAsyncApi.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.rackspace.cloudloadbalancers.v1.features;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
-import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseNestedString;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.Payload;
-import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.ResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides asynchronous access to Rackspace Cloud Load Balancers via their REST API.
- * <p/>
- * 
- * @see ErrorPageApi
- * @author Everett Toews
- */
-@RequestFilters(AuthenticateRequest.class)
-public interface ErrorPageAsyncApi {
-
-   /**
-    * @see ErrorPageApi#create(String)
-    */
-   @Named("errorpage:create")
-   @PUT
-   @Consumes(MediaType.WILDCARD)
-   @Produces(MediaType.APPLICATION_JSON)
-   @Fallback(VoidOnNotFoundOr404.class)
-   @Payload("%7B\"errorpage\":%7B\"content\":\"{content}\"%7D%7D")
-   @Path("/errorpage")
-   ListenableFuture<Void> create(@PayloadParam("content") String content);
-
-   /**
-    * @see ErrorPageApi#get()
-    */
-   @Named("errorpage:get")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @ResponseParser(ParseNestedString.class)
-   @Fallback(VoidOnNotFoundOr404.class)
-   @Path("/errorpage")
-   ListenableFuture<String> get();
-
-   /**
-    * @see ErrorPageApi#delete()
-    */
-   @Named("errorpage:delete")
-   @DELETE
-   @Consumes(MediaType.WILDCARD)
-   @Fallback(FalseOnNotFoundOr404.class)
-   @Path("/errorpage")
-   ListenableFuture<Boolean> delete();
-}
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/HealthMonitorApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/HealthMonitorApi.java
index 72f6ff5..d3b581d 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/HealthMonitorApi.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/HealthMonitorApi.java
@@ -18,7 +18,23 @@
  */
 package org.jclouds.rackspace.cloudloadbalancers.v1.features;
 
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.FalseOnNotFoundOr422;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.HealthMonitor;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.WrapWith;
 
 /**
  * The load balancing service includes a health monitoring operation which periodically checks your back-end nodes to 
@@ -31,18 +47,29 @@
  * failover for effectively routing traffic in case the primary node fails. This is an additional feature that will 
  * ensure you remain up in case your primary node fails.
  * <p/>
- * @see HealthMonitorAsyncApi
  * @author Everett Toews
  */
+@RequestFilters(AuthenticateRequest.class)
 public interface HealthMonitorApi {
    /**
     * Create or update a health monitor.
     */
-   void createOrUpdate(HealthMonitor healthMonitor);
+   @Named("healthmonitor:create")
+   @PUT
+   @Consumes(MediaType.APPLICATION_JSON) 
+   @Fallback(VoidOnNotFoundOr404.class)
+   @Path("/healthmonitor")
+   void createOrUpdate(@WrapWith("healthMonitor") HealthMonitor healthMonitor);
 
    /**
     * Get health monitor.
     */
+   @Named("healthmonitor:get")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @SelectJson("healthMonitor")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Path("/healthmonitor")
    HealthMonitor get();
    
    /**
@@ -50,5 +77,10 @@
     * 
     * @return true on a successful delete, false if the health monitor was not found
     */
+   @Named("healthmonitor:delete")
+   @DELETE
+   @Fallback(FalseOnNotFoundOr422.class)
+   @Path("/healthmonitor")
+   @Consumes("*/*")
    boolean delete();
 }
\ No newline at end of file
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/HealthMonitorAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/HealthMonitorAsyncApi.java
deleted file mode 100644
index f99cb58..0000000
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/HealthMonitorAsyncApi.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.rackspace.cloudloadbalancers.v1.features;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.Fallbacks.FalseOnNotFoundOr422;
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.HealthMonitor;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SelectJson;
-import org.jclouds.rest.annotations.WrapWith;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides asynchronous access to Rackspace Cloud Load Balancers via their REST API.
- * <p/>
- * 
- * @see HealthMonitorApi
- * @author Everett Toews
- */
-@RequestFilters(AuthenticateRequest.class)
-public interface HealthMonitorAsyncApi {
-
-   /**
-    * @see HealthMonitorApi#createOrUpdate(HealthMonitor)
-    */
-   @Named("healthmonitor:create")
-   @PUT
-   @Consumes(MediaType.APPLICATION_JSON) 
-   @Fallback(VoidOnNotFoundOr404.class)
-   @Path("/healthmonitor")
-   ListenableFuture<Void> createOrUpdate(@WrapWith("healthMonitor") HealthMonitor healthMonitor);
-
-   /**
-    * @see HealthMonitorApi#get()
-    */
-   @Named("healthmonitor:get")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @SelectJson("healthMonitor")
-   @Fallback(NullOnNotFoundOr404.class)
-   @Path("/healthmonitor")
-   ListenableFuture<HealthMonitor> get();
-
-   /**
-    * @see HealthMonitorApi#delete()
-    */
-   @Named("healthmonitor:delete")
-   @DELETE
-   @Fallback(FalseOnNotFoundOr422.class)
-   @Path("/healthmonitor")
-   @Consumes("*/*")
-   ListenableFuture<Boolean> delete();
-}
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/LoadBalancerApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/LoadBalancerApi.java
index cedc29e..5884ca6 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/LoadBalancerApi.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/LoadBalancerApi.java
@@ -20,21 +20,52 @@
 
 import java.util.Map;
 
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptyMapOnNotFoundOr404;
+import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.collect.PagedIterable;
+import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
 import org.jclouds.openstack.v2_0.options.PaginationOptions;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.LoadBalancer;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.UpdateLoadBalancer;
+import org.jclouds.rackspace.cloudloadbalancers.v1.binders.BindMetadataToJsonPayload;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.CreateLoadBalancer;
+import org.jclouds.rackspace.cloudloadbalancers.v1.domain.LoadBalancer;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.Metadata;
+import org.jclouds.rackspace.cloudloadbalancers.v1.domain.UpdateLoadBalancer;
+import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseLoadBalancer;
+import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseLoadBalancers;
+import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseMetadata;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.Transform;
+import org.jclouds.rest.annotations.WrapWith;
 
 /**
- * Provides synchronous access to CloudLoadBalancers LoadBalancer features.
+ * Provides access to CloudLoadBalancers LoadBalancer features.
  * <p/>
  * 
- * @see LoadBalancerAsyncApi
  * @author Everett Toews
  */
+@RequestFilters(AuthenticateRequest.class)
 public interface LoadBalancerApi {
    /**
     * Create a new load balancer with the configuration defined by the request.
@@ -43,7 +74,13 @@
     *         identifier, the caller can check on the progress of the operation by performing a
     *         {@link LoadBalancerApi#get}.
     */
-   LoadBalancer create(CreateLoadBalancer createLB);
+   @Named("lb:create")
+   @POST
+   @ResponseParser(ParseLoadBalancer.class)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Path("/loadbalancers")
+   LoadBalancer create(@WrapWith("loadBalancer") CreateLoadBalancer createLB);
 
    /**
     * Update the properties of a load balancer.
@@ -52,46 +89,97 @@
     *         identifier, the caller can check on the progress of the operation by performing a
     *         {@link LoadBalancerApi#get}.
     */
-   void update(int id, UpdateLoadBalancer updateLB);
+   @Named("lb:update")
+   @PUT
+   @ResponseParser(ParseLoadBalancer.class)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/loadbalancers/{id}")
+   void update(@PathParam("id") int id, @WrapWith("loadBalancer") UpdateLoadBalancer updateLB);
 
    /**
     * List the load balancers.
     */
+   @Named("lb:list")
+   @GET
+   @ResponseParser(ParseLoadBalancers.class)
+   @Transform(ParseLoadBalancers.ToPagedIterable.class)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/loadbalancers")
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
    PagedIterable<LoadBalancer> list();
    
    /**
     * List the load balancers with full control of pagination.
     */
+   @Named("lb:list")
+   @GET
+   @ResponseParser(ParseLoadBalancers.class)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
+   @Path("/loadbalancers")
    IterableWithMarker<LoadBalancer> list(PaginationOptions options);
 
    /**
     * Get a load balancer.
     */
-   LoadBalancer get(int id);
+   @Named("lb:get")
+   @GET
+   @ResponseParser(ParseLoadBalancer.class)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Path("/loadbalancers/{id}")
+   LoadBalancer get(@PathParam("id") int id);
 
    /**
     * Delete a load balancer.
     */
-   void delete(int id);
+   @Named("lb:delete")
+   @DELETE
+   @Fallback(VoidOnNotFoundOr404.class)
+   @Path("/loadbalancers/{id}")
+   @Consumes("*/*")
+   void delete(@PathParam("id") int id);
    
    /**
     * When a metadata item is added, it is assigned a unique identifier that can be used for mutating operations such
     * as changing the value attribute or removing it. Key and value must be 256 characters or less. 
     * All UTF-8 characters are valid.
     */
-   Metadata createMetadata(int id, Map<String, String> metadata);
+   @Named("lb:createmetadata")
+   @POST
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseMetadata.class)
+   @Fallback(EmptyMapOnNotFoundOr404.class)
+   @Path("/loadbalancers/{id}/metadata")
+   Metadata createMetadata(@PathParam("id") int id, 
+                           @BinderParam(BindMetadataToJsonPayload.class) Map<String, String> metadata);
     
    /**
     * List a load balancer's metadata.
     */
-   Metadata getMetadata(int id);
+   @Named("lb:getmetadata")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseMetadata.class)
+   @Fallback(EmptyMapOnNotFoundOr404.class)
+   @Path("/loadbalancers/{id}/metadata")
+   Metadata getMetadata(@PathParam("id") int id);
    
    /**
     * Update metadatum. Key and value must be 256 characters or less. All UTF-8 characters are valid.
     * 
     * @return true on a successful update, false if the metadatum was not found
     */
-   boolean updateMetadatum(int id, int metadatumId, String value);
+   @Named("lb:updatemetadatum")
+   @PUT
+   @Produces(MediaType.APPLICATION_JSON)
+   @Consumes("*/*")
+   @Fallback(FalseOnNotFoundOr404.class)
+   @Payload("%7B\"meta\":%7B\"value\":\"{value}\"%7D%7D")
+   @Path("/loadbalancers/{id}/metadata/{metadatumId}")
+   boolean updateMetadatum(@PathParam("id") int id, 
+                           @PathParam("metadatumId") int metadatumId, 
+                           @PayloadParam("value") String value);
 
    /**
     * Delete metadatum.
@@ -100,7 +188,13 @@
     * 
     * @return true on a successful removal, false if the metadatum was not found
     */
-   boolean deleteMetadatum(int id, int metadatumId);
+   @Named("lb:deletemetadatum")
+   @DELETE
+   @Fallback(FalseOnNotFoundOr404.class)
+   @Consumes("*/*")
+   @Path("/loadbalancers/{id}/metadata/{metadatumId}")
+   boolean deleteMetadatum(@PathParam("id") int id, @PathParam("metadatumId") int metadatumId);
+
    
    /**
     * Batch delete metadata given the specified ids.
@@ -111,5 +205,11 @@
     * 
     * @return true on a successful removal, false if the metadata was not found
     */
-   boolean deleteMetadata(int id, Iterable<Integer> metadataIds);
+   @Named("lb:deletemetadata")
+   @DELETE
+   @Fallback(FalseOnNotFoundOr404.class)
+   @Consumes("*/*")
+   @Path("/loadbalancers/{id}/metadata")
+   boolean deleteMetadata(@PathParam("id") int id, 
+                          @QueryParam("id") Iterable<Integer> metadataIds);
 }
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/LoadBalancerAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/LoadBalancerAsyncApi.java
deleted file mode 100644
index 1c40668..0000000
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/LoadBalancerAsyncApi.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.rackspace.cloudloadbalancers.v1.features;
-
-import java.util.Map;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.Fallbacks.EmptyMapOnNotFoundOr404;
-import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
-import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.collect.IterableWithMarker;
-import org.jclouds.collect.PagedIterable;
-import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
-import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
-import org.jclouds.openstack.v2_0.options.PaginationOptions;
-import org.jclouds.rackspace.cloudloadbalancers.v1.binders.BindMetadataToJsonPayload;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.LoadBalancer;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.UpdateLoadBalancer;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.CreateLoadBalancer;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.Metadata;
-import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseLoadBalancer;
-import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseLoadBalancers;
-import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseMetadata;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.Payload;
-import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.ResponseParser;
-import org.jclouds.rest.annotations.Transform;
-import org.jclouds.rest.annotations.WrapWith;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides asynchronous access to Rackspace Cloud Load Balancers via their REST API.
- * <p/>
- * 
- * @see LoadBalancerApi
- * @author Everett Toews
- */
-@RequestFilters(AuthenticateRequest.class)
-public interface LoadBalancerAsyncApi {
-
-   /**
-    * @see LoadBalancerApi#create(CreateLoadBalancer)
-    */
-   @Named("lb:create")
-   @POST
-   @ResponseParser(ParseLoadBalancer.class)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(NullOnNotFoundOr404.class)
-   @Path("/loadbalancers")
-   ListenableFuture<LoadBalancer> create(@WrapWith("loadBalancer") CreateLoadBalancer createLB);
-
-   /**
-    * @see LoadBalancerApi#update(int, UpdateLoadBalancer)
-    */
-   @Named("lb:update")
-   @PUT
-   @ResponseParser(ParseLoadBalancer.class)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/loadbalancers/{id}")
-   ListenableFuture<Void> update(@PathParam("id") int id, @WrapWith("loadBalancer") UpdateLoadBalancer updateLB);
-
-   /**
-    * @see LoadBalancerApi#list()
-    */
-   @Named("lb:list")
-   @GET
-   @ResponseParser(ParseLoadBalancers.class)
-   @Transform(ParseLoadBalancers.ToPagedIterable.class)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/loadbalancers")
-   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
-   ListenableFuture<PagedIterable<LoadBalancer>> list();
-
-   /** 
-    * @see LoadBalancerApi#list(PaginationOptions) 
-    */
-   @Named("lb:list")
-   @GET
-   @ResponseParser(ParseLoadBalancers.class)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
-   @Path("/loadbalancers")
-   ListenableFuture<IterableWithMarker<LoadBalancer>> list(PaginationOptions options);
-
-   /**
-    * @see LoadBalancerApi#get(int)
-    */
-   @Named("lb:get")
-   @GET
-   @ResponseParser(ParseLoadBalancer.class)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(NullOnNotFoundOr404.class)
-   @Path("/loadbalancers/{id}")
-   ListenableFuture<LoadBalancer> get(@PathParam("id") int id);
-
-   /**
-    * @see LoadBalancerApi#delete(int)
-    */
-   @Named("lb:delete")
-   @DELETE
-   @Fallback(VoidOnNotFoundOr404.class)
-   @Path("/loadbalancers/{id}")
-   @Consumes("*/*")
-   ListenableFuture<Void> delete(@PathParam("id") int id);
-
-   /**
-    * @see LoadBalancerApi#createMetadata(int, Iterable)
-    */
-   @Named("lb:createmetadata")
-   @POST
-   @Consumes(MediaType.APPLICATION_JSON)
-   @ResponseParser(ParseMetadata.class)
-   @Fallback(EmptyMapOnNotFoundOr404.class)
-   @Path("/loadbalancers/{id}/metadata")
-   ListenableFuture<Metadata> createMetadata(
-         @PathParam("id") int id, 
-         @BinderParam(BindMetadataToJsonPayload.class) Map<String, String> metadata);
-
-   /**
-    * @see LoadBalancerApi#getMetadata(int)
-    */
-   @Named("lb:getmetadata")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @ResponseParser(ParseMetadata.class)
-   @Fallback(EmptyMapOnNotFoundOr404.class)
-   @Path("/loadbalancers/{id}/metadata")
-   ListenableFuture<Metadata> getMetadata(@PathParam("id") int lb);
-
-   /**
-    * @see LoadBalancerApi#updateMetadatum(int, int, String)
-    */
-   @Named("lb:updatemetadatum")
-   @PUT
-   @Produces(MediaType.APPLICATION_JSON)
-   @Consumes("*/*")
-   @Fallback(FalseOnNotFoundOr404.class)
-   @Payload("%7B\"meta\":%7B\"value\":\"{value}\"%7D%7D")
-   @Path("/loadbalancers/{id}/metadata/{metadatumId}")
-   ListenableFuture<Boolean> updateMetadatum(@PathParam("id") int id, 
-                                             @PathParam("metadatumId") int metadatumId, 
-                                             @PayloadParam("value") String value);
-
-   /**
-    * @see LoadBalancerApi#deleteMetadatum(int, int)
-    */
-   @Named("lb:deletemetadatum")
-   @DELETE
-   @Fallback(FalseOnNotFoundOr404.class)
-   @Consumes("*/*")
-   @Path("/loadbalancers/{id}/metadata/{metadatumId}")
-   ListenableFuture<Boolean> deleteMetadatum(@PathParam("id") int id, @PathParam("metadatumId") int metadatumId);
-
-   /**
-    * @see LoadBalancerApi#deleteMetadata(int, Iterable)
-    */
-   @Named("lb:deletemetadata")
-   @DELETE
-   @Fallback(FalseOnNotFoundOr404.class)
-   @Consumes("*/*")
-   @Path("/loadbalancers/{id}/metadata")
-   ListenableFuture<Boolean> deleteMetadata(@PathParam("id") int id, 
-                                            @QueryParam("id") Iterable<Integer> metadataIds);
-}
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/NodeApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/NodeApi.java
index 325f377..0a445a9 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/NodeApi.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/NodeApi.java
@@ -21,75 +21,168 @@
 import java.util.Map;
 import java.util.Set;
 
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptyMapOnNotFoundOr404;
+import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.collect.PagedIterable;
+import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
 import org.jclouds.openstack.v2_0.options.PaginationOptions;
+import org.jclouds.rackspace.cloudloadbalancers.v1.binders.BindMetadataToJsonPayload;
+import org.jclouds.rackspace.cloudloadbalancers.v1.domain.AddNode;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.Metadata;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.Node;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.UpdateNode;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.AddNode;
+import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseMetadata;
+import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseNode;
+import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseNodes;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.Transform;
+import org.jclouds.rest.annotations.WrapWith;
 
 /**
- * Provides synchronous access to CloudLoadBalancers Node features.
+ * Provides access to CloudLoadBalancers Node features.
  * <p/>
  * 
- * @see NodeAsyncApi
  * @author Everett Toews
  */
+@RequestFilters(AuthenticateRequest.class)
 public interface NodeApi {
    /**
     * Add a new node with the configuration defined by the request.
     */
-	Set<Node> add(Iterable<AddNode> addNodes);
+   @Named("node:add")
+   @POST
+   @SelectJson("nodes")
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Path("/nodes")
+   Set<Node> add(@WrapWith("nodes") Iterable<AddNode> addNodes);
 
    /**
     * Update the attributes of a node.
     */
-   void update(int id, UpdateNode updateNode);
+   @Named("node:update")
+   @PUT
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/nodes/{id}")
+   void update(@PathParam("id") int id, @WrapWith("node") UpdateNode updateNode);
 
    /**
     * List the nodes.
     */
+   @Named("node:list")
+   @GET
+   @ResponseParser(ParseNodes.class)
+   @Transform(ParseNodes.ToPagedIterable.class)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Path("/nodes")
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
    PagedIterable<Node> list();
 
    /**
     * List the nodes with full control of pagination.
     */
+   @Named("node:list")
+   @GET
+   @ResponseParser(ParseNodes.class)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
+   @Path("/nodes")
    IterableWithMarker<Node> list(PaginationOptions options);
 
    /**
     * Get a node.
     */
-   Node get(int id);
+   @Named("node:get")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseNode.class)
+   @Path("/nodes/{id}")
+   @Fallback(NullOnNotFoundOr404.class)
+   Node get(@PathParam("id") int id);
 
    /**
     * Remove a node from the load balancer.
     */
-   void remove(int id);
+   @Named("node:remove")
+   @DELETE
+   @Path("/nodes/{id}")
+   @Fallback(VoidOnNotFoundOr404.class)
+   @Consumes("*/*")
+   void remove(@PathParam("id") int id);
    
    /**
     * Batch remove nodes from the load balancer.
     */
-   void remove(Iterable<Integer> ids);
+   @Named("node:remove")
+   @DELETE
+   @Path("/nodes")
+   @Fallback(VoidOnNotFoundOr404.class)
+   @Consumes("*/*")
+   void remove(@QueryParam("id") Iterable<Integer> ids);
    
    /**
     * When a metadata item is added, it is assigned a unique identifier that can be used for mutating operations such
     * as changing the value attribute or removing it. Key and value must be 256 characters or less. 
     * All UTF-8 characters are valid.
     */
-   Metadata createMetadata(int id, Map<String, String> metadata);
+   @Named("node:createmetadata")
+   @POST
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseMetadata.class)
+   @Fallback(EmptyMapOnNotFoundOr404.class)
+   @Path("/nodes/{id}/metadata")
+   Metadata createMetadata(@PathParam("id") int id, 
+                           @BinderParam(BindMetadataToJsonPayload.class) Map<String, String> metadata);
     
    /**
     * List a load balancer's metadata.
     */
-   Metadata getMetadata(int id);
-   
+   @Named("node:getmetadata")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseMetadata.class)
+   @Fallback(EmptyMapOnNotFoundOr404.class)
+   @Path("/nodes/{id}/metadata")
+   Metadata getMetadata(@PathParam("id") int lb);
+
    /**
     * Update metadatum. Key and value must be 256 characters or less. All UTF-8 characters are valid.
     * 
     * @return true on a successful update, false if the metadatum was not found
     */
-   boolean updateMetadatum(int id, int metadatumId, String value);
+   @Named("node:updatemetadatum")
+   @PUT
+   @Produces(MediaType.APPLICATION_JSON)
+   @Consumes("*/*")
+   @Fallback(FalseOnNotFoundOr404.class)
+   @Payload("%7B\"meta\":%7B\"value\":\"{value}\"%7D%7D")
+   @Path("/nodes/{id}/metadata/{metadatumId}")
+   boolean updateMetadatum(@PathParam("id") int id, 
+                           @PathParam("metadatumId") int metadatumId, 
+                           @PayloadParam("value") String value);
 
    /**
     * Delete metadatum.
@@ -98,7 +191,12 @@
     * 
     * @return true on a successful removal, false if the metadatum was not found
     */
-   boolean deleteMetadatum(int id, int metadatumId);
+   @Named("node:deletemetadatum")
+   @DELETE
+   @Fallback(FalseOnNotFoundOr404.class)
+   @Consumes("*/*")
+   @Path("/nodes/{id}/metadata/{metadatumId}")
+   boolean deleteMetadatum(@PathParam("id") int id, @PathParam("metadatumId") int metadatumId);
    
    /**
     * Batch delete metadata given the specified ids.
@@ -109,5 +207,11 @@
     * 
     * @return true on a successful removal, false if the metadata was not found
     */
-   boolean deleteMetadata(int id, Iterable<Integer> metadataIds);
+   @Named("node:deletemetadata")
+   @DELETE
+   @Fallback(FalseOnNotFoundOr404.class)
+   @Consumes("*/*")
+   @Path("/nodes/{id}/metadata")
+   boolean deleteMetadata(@PathParam("id") int id, 
+                          @QueryParam("id") Iterable<Integer> metadataIds);
 }
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/NodeAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/NodeAsyncApi.java
deleted file mode 100644
index fd542a9..0000000
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/NodeAsyncApi.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.rackspace.cloudloadbalancers.v1.features;
-
-import java.util.Map;
-import java.util.Set;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.Fallbacks.EmptyMapOnNotFoundOr404;
-import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
-import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.collect.IterableWithMarker;
-import org.jclouds.collect.PagedIterable;
-import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
-import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
-import org.jclouds.openstack.v2_0.options.PaginationOptions;
-import org.jclouds.rackspace.cloudloadbalancers.v1.binders.BindMetadataToJsonPayload;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.LoadBalancer;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.Metadata;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.Node;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.UpdateNode;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.AddNode;
-import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseMetadata;
-import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseNode;
-import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseNodes;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.Payload;
-import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.ResponseParser;
-import org.jclouds.rest.annotations.SelectJson;
-import org.jclouds.rest.annotations.Transform;
-import org.jclouds.rest.annotations.WrapWith;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides asynchronous access to Cloud Load Balancers Node features.
- * <p/>
- * 
- * @see NodeAsyncApi
- * @author Everett Toews
- */
-@RequestFilters(AuthenticateRequest.class)
-public interface NodeAsyncApi {
-
-   /**
-    * @see NodeApi#add(Set)
-    */
-   @Named("node:add")
-   @POST
-   @SelectJson("nodes")
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(NullOnNotFoundOr404.class)
-   @Path("/nodes")
-   ListenableFuture<Set<Node>> add(@WrapWith("nodes") Iterable<AddNode> addNodes);
-
-   /**
-    * @see NodeApi#update(int, UpdateNode)
-    */
-   @Named("node:update")
-   @PUT
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/nodes/{id}")
-   ListenableFuture<Void> update(@PathParam("id") int id, @WrapWith("node") UpdateNode updateNode);
-   
-   /**
-    * @see NodeApi#list()
-    */
-   @Named("node:list")
-   @GET
-   @ResponseParser(ParseNodes.class)
-   @Transform(ParseNodes.ToPagedIterable.class)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Path("/nodes")
-   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
-   ListenableFuture<PagedIterable<Node>> list();
-
-   /** 
-    * @see NodeApi#list(PaginationOptions) 
-    */
-   @Named("node:list")
-   @GET
-   @ResponseParser(ParseNodes.class)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
-   @Path("/nodes")
-   ListenableFuture<IterableWithMarker<LoadBalancer>> list(PaginationOptions options);
-   
-   /**
-    * @see NodeApi#get(int)
-    */
-   @Named("node:get")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @ResponseParser(ParseNode.class)
-   @Path("/nodes/{id}")
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Node> get(@PathParam("id") int id);
-   
-   /**
-    * @see NodeApi#remove(int)
-    */
-   @Named("node:remove")
-   @DELETE
-   @Path("/nodes/{id}")
-   @Fallback(VoidOnNotFoundOr404.class)
-   @Consumes("*/*")
-   ListenableFuture<Void> remove(@PathParam("id") int id);
-   
-   /**
-    * @see NodeApi#remove(Set)
-    */
-   @Named("node:remove")
-   @DELETE
-   @Path("/nodes")
-   @Fallback(VoidOnNotFoundOr404.class)
-   @Consumes("*/*")
-   ListenableFuture<Void> remove(@QueryParam("id") Iterable<Integer> ids);
-
-   /**
-    * @see NodeApi#createMetadata(int, Iterable)
-    */
-   @Named("node:createmetadata")
-   @POST
-   @Consumes(MediaType.APPLICATION_JSON)
-   @ResponseParser(ParseMetadata.class)
-   @Fallback(EmptyMapOnNotFoundOr404.class)
-   @Path("/nodes/{id}/metadata")
-   ListenableFuture<Metadata> createMetadata(
-         @PathParam("id") int id, 
-         @BinderParam(BindMetadataToJsonPayload.class) Map<String, String> metadata);
-
-   /**
-    * @see NodeApi#getMetadata(int)
-    */
-   @Named("node:getmetadata")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @ResponseParser(ParseMetadata.class)
-   @Fallback(EmptyMapOnNotFoundOr404.class)
-   @Path("/nodes/{id}/metadata")
-   ListenableFuture<Metadata> getMetadata(@PathParam("id") int lb);
-
-   /**
-    * @see NodeApi#updateMetadatum(int, int, String)
-    */
-   @Named("node:updatemetadatum")
-   @PUT
-   @Produces(MediaType.APPLICATION_JSON)
-   @Consumes("*/*")
-   @Fallback(FalseOnNotFoundOr404.class)
-   @Payload("%7B\"meta\":%7B\"value\":\"{value}\"%7D%7D")
-   @Path("/nodes/{id}/metadata/{metadatumId}")
-   ListenableFuture<Boolean> updateMetadatum(@PathParam("id") int id, 
-                                             @PathParam("metadatumId") int metadatumId, 
-                                             @PayloadParam("value") String value);
-
-   /**
-    * @see NodeApi#deleteMetadatum(int, int)
-    */
-   @Named("node:deletemetadatum")
-   @DELETE
-   @Fallback(FalseOnNotFoundOr404.class)
-   @Consumes("*/*")
-   @Path("/nodes/{id}/metadata/{metadatumId}")
-   ListenableFuture<Boolean> deleteMetadatum(@PathParam("id") int id, @PathParam("metadatumId") int metadatumId);
-
-   /**
-    * @see NodeApi#deleteMetadata(int, Iterable)
-    */
-   @Named("node:deletemetadata")
-   @DELETE
-   @Fallback(FalseOnNotFoundOr404.class)
-   @Consumes("*/*")
-   @Path("/nodes/{id}/metadata")
-   ListenableFuture<Boolean> deleteMetadata(@PathParam("id") int id, 
-                                            @QueryParam("id") Iterable<Integer> metadataIds);
-}
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ReportApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ReportApi.java
index fe1981c..0222ae7 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ReportApi.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ReportApi.java
@@ -20,63 +20,151 @@
 
 import java.util.Date;
 
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.collect.PagedIterable;
+import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
 import org.jclouds.openstack.v2_0.options.PaginationOptions;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.HistoricalUsage;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.LoadBalancer;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.LoadBalancerStats;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.LoadBalancerUsage;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.Protocol;
+import org.jclouds.rackspace.cloudloadbalancers.v1.functions.DateParser;
+import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseAlgorithms;
+import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseLoadBalancerUsages;
+import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseLoadBalancers;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.ParamParser;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.Transform;
 
 /**
  * Reporting for load balancers.
  * <p/>
- * @see ReportAsyncApi
  * @author Everett Toews
  */
+@RequestFilters(AuthenticateRequest.class)
 public interface ReportApi {
    /**
     * List billable load balancers for the given date range.
     */
-   PagedIterable<LoadBalancer> listBillableLoadBalancers(Date startTime, Date endTime);
+   @Named("report:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseLoadBalancers.class)
+   @Transform(ParseLoadBalancers.ToPagedIterable.class)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Path("/loadbalancers/billable")
+   PagedIterable<LoadBalancer> listBillableLoadBalancers(
+         @ParamParser(DateParser.class) @QueryParam("startTime") Date startTime, 
+         @ParamParser(DateParser.class) @QueryParam("endTime") Date endTime);
    
+   @Named("report:list")
+   @GET
+   @ResponseParser(ParseLoadBalancers.class)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
+   @Path("/loadbalancers/billable")
    IterableWithMarker<LoadBalancer> listBillableLoadBalancers(PaginationOptions options);
 
    /**
     * View all transfer activity, average number of connections, and number of virtual IPs associated with the load
     * balancing service. Historical usage data is available for up to 90 days of service activity.
     */
-   HistoricalUsage getHistoricalUsage(Date startTime, Date endTime);
+   @Named("report:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Path("/loadbalancers/usage")
+   HistoricalUsage getHistoricalUsage(
+         @ParamParser(DateParser.class) @QueryParam("startTime") Date startTime, 
+         @ParamParser(DateParser.class) @QueryParam("endTime") Date endTime);
    
    /**
     * Historical usage data is available for up to 90 days of service activity.
     */
-   PagedIterable<LoadBalancerUsage> listLoadBalancerUsage(int loadBalancerId, Date startTime, Date endTime);
-   
+   @Named("report:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseLoadBalancerUsages.class)
+   @Transform(ParseLoadBalancerUsages.ToPagedIterable.class)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Path("/loadbalancers/{id}/usage")
+   PagedIterable<LoadBalancerUsage> listLoadBalancerUsage(@PathParam("id") int loadBalancerId,
+         @ParamParser(DateParser.class) @QueryParam("startTime") Date startTime, 
+         @ParamParser(DateParser.class) @QueryParam("endTime") Date endTime);
+
+   @Named("report:list")
+   @GET
+   @ResponseParser(ParseLoadBalancerUsages.class)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
+   @Path("/loadbalancers/{id}/usage")
    IterableWithMarker<LoadBalancerUsage> listLoadBalancerUsage(PaginationOptions options);
    
    /**
     * Current usage represents all usage recorded within the preceding 24 hours.
     */
-   PagedIterable<LoadBalancerUsage> listCurrentLoadBalancerUsage(int loadBalancerId);
-   
+   @Named("report:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseLoadBalancerUsages.class)
+   @Transform(ParseLoadBalancerUsages.ToPagedIterable.class)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Path("/loadbalancers/{id}/usage/current")
+   PagedIterable<LoadBalancerUsage> listCurrentLoadBalancerUsage(@PathParam("id") int loadBalancerId);
+
+   @Named("report:list")
+   @GET
+   @ResponseParser(ParseLoadBalancerUsages.class)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
+   @Path("/loadbalancers/{id}/usage/current")
    IterableWithMarker<LoadBalancerUsage> listCurrentLoadBalancerUsage(PaginationOptions options);
    
    /**
     * Current usage represents all usage recorded within the preceding 24 hours.
     */
-   LoadBalancerStats getLoadBalancerStats(int loadBalancerId);
+   @Named("report:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Path("/loadbalancers/{id}/stats")
+   LoadBalancerStats getLoadBalancerStats(@PathParam("id") int loadBalancerId);
    
    /**
     * All load balancers must define the protocol of the service which is being load balanced. The protocol selection 
     * should be based on the protocol of the back-end nodes. When configuring a load balancer, the default port for 
     * the given protocol will be selected from this list unless otherwise specified.
     */
+   @Named("report:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @SelectJson("protocols")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Path("/loadbalancers/protocols")
    Iterable<Protocol> listProtocols();
    
    /**
     * Get all of the possible algorthims usable by load balancers.
     */
+   @Named("report:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseAlgorithms.class)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Path("/loadbalancers/algorithms")
    Iterable<String> listAlgorithms();
 }
\ No newline at end of file
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ReportAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ReportAsyncApi.java
deleted file mode 100644
index b43662c..0000000
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/ReportAsyncApi.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.rackspace.cloudloadbalancers.v1.features;
-
-import java.util.Date;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.collect.IterableWithMarker;
-import org.jclouds.collect.PagedIterable;
-import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
-import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
-import org.jclouds.openstack.v2_0.options.PaginationOptions;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.HistoricalUsage;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.LoadBalancer;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.LoadBalancerStats;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.LoadBalancerUsage;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.Protocol;
-import org.jclouds.rackspace.cloudloadbalancers.v1.functions.DateParser;
-import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseAlgorithms;
-import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseLoadBalancerUsages;
-import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseLoadBalancers;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.ParamParser;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.ResponseParser;
-import org.jclouds.rest.annotations.SelectJson;
-import org.jclouds.rest.annotations.Transform;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides asynchronous access to Rackspace Cloud Load Balancers via their REST API.
- * <p/>
- * 
- * @see ReportApi
- * @author Everett Toews
- */
-@RequestFilters(AuthenticateRequest.class)
-public interface ReportAsyncApi {
-   /**
-    * @see ReportApi#listBillableLoadBalancers(Date, Date)
-    */
-   @Named("report:list")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @ResponseParser(ParseLoadBalancers.class)
-   @Transform(ParseLoadBalancers.ToPagedIterable.class)
-   @Fallback(NullOnNotFoundOr404.class)
-   @Path("/loadbalancers/billable")
-   ListenableFuture<PagedIterable<LoadBalancer>> listBillableLoadBalancers(
-         @ParamParser(DateParser.class) @QueryParam("startTime") Date startTime, 
-         @ParamParser(DateParser.class) @QueryParam("endTime") Date endTime);
-
-   /** 
-    * @see ReportApi#listBillableLoadBalancers(PaginationOptions) 
-    */
-   @Named("report:list")
-   @GET
-   @ResponseParser(ParseLoadBalancers.class)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
-   @Path("/loadbalancers/billable")
-   ListenableFuture<IterableWithMarker<LoadBalancer>> listBillableLoadBalancers(PaginationOptions options);
-
-   /**
-    * @see ReportApi#getHistoricalUsage(Date, Date)
-    */
-   @Named("report:list")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(NullOnNotFoundOr404.class)
-   @Path("/loadbalancers/usage")
-   ListenableFuture<HistoricalUsage> getHistoricalUsage(
-         @ParamParser(DateParser.class) @QueryParam("startTime") Date startTime, 
-         @ParamParser(DateParser.class) @QueryParam("endTime") Date endTime);
-
-   /**
-    * @see ReportApi#listLoadBalancerUsage(int, Date, Date)
-    */
-   @Named("report:list")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @ResponseParser(ParseLoadBalancerUsages.class)
-   @Transform(ParseLoadBalancerUsages.ToPagedIterable.class)
-   @Fallback(NullOnNotFoundOr404.class)
-   @Path("/loadbalancers/{id}/usage")
-   ListenableFuture<PagedIterable<LoadBalancerUsage>> listLoadBalancerUsage(
-         @PathParam("id") int loadBalancerId,
-         @ParamParser(DateParser.class) @QueryParam("startTime") Date startTime, 
-         @ParamParser(DateParser.class) @QueryParam("endTime") Date endTime);
-
-   /** 
-    * @see ReportApi#listLoadBalancerUsage(PaginationOptions)
-    */
-   @Named("report:list")
-   @GET
-   @ResponseParser(ParseLoadBalancerUsages.class)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
-   @Path("/loadbalancers/{id}/usage")
-   ListenableFuture<IterableWithMarker<LoadBalancerUsage>> listLoadBalancerUsage(PaginationOptions options);
-
-   /**
-    * @see ReportApi#listCurrentLoadBalancerUsage(int)
-    */
-   @Named("report:list")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @ResponseParser(ParseLoadBalancerUsages.class)
-   @Transform(ParseLoadBalancerUsages.ToPagedIterable.class)
-   @Fallback(NullOnNotFoundOr404.class)
-   @Path("/loadbalancers/{id}/usage/current")
-   ListenableFuture<PagedIterable<LoadBalancerUsage>> listCurrentLoadBalancerUsage(
-         @PathParam("id") int loadBalancerId);
-
-   /** 
-    * @see ReportApi#listCurrentLoadBalancerUsage(PaginationOptions)
-    */
-   @Named("report:list")
-   @GET
-   @ResponseParser(ParseLoadBalancerUsages.class)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
-   @Path("/loadbalancers/{id}/usage/current")
-   ListenableFuture<IterableWithMarker<LoadBalancerUsage>> listCurrentLoadBalancerUsage(PaginationOptions options);
-
-   /**
-    * @see ReportApi#getLoadBalancerStats(int)
-    */
-   @Named("report:list")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(NullOnNotFoundOr404.class)
-   @Path("/loadbalancers/{id}/stats")
-   ListenableFuture<LoadBalancerStats> getLoadBalancerStats(
-         @PathParam("id") int loadBalancerId);
-
-   /**
-    * @see ReportApi#listProtocols()
-    */
-   @Named("report:list")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @SelectJson("protocols")
-   @Fallback(NullOnNotFoundOr404.class)
-   @Path("/loadbalancers/protocols")
-   ListenableFuture<Iterable<Protocol>> listProtocols();
-
-   /**
-    * @see ReportApi#listAlgorithms()
-    */
-   @Named("report:list")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @ResponseParser(ParseAlgorithms.class)
-   @Fallback(NullOnNotFoundOr404.class)
-   @Path("/loadbalancers/algorithms")
-   ListenableFuture<Iterable<String>> listAlgorithms();
-}
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/SSLTerminationApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/SSLTerminationApi.java
index 54cdcb4..2d995e3 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/SSLTerminationApi.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/SSLTerminationApi.java
@@ -18,7 +18,23 @@
  */
 package org.jclouds.rackspace.cloudloadbalancers.v1.features;
 
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.FalseOnNotFoundOr422;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.SSLTermination;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.WrapWith;
 
 /**
  * The SSL Termination feature allows a load balancer user to terminate SSL traffic at the load balancer layer versus 
@@ -50,9 +66,9 @@
  * be secure.</li>
  * </ol>
  *
- * @see SSLTerminationAsyncApi
  * @author Everett Toews
  */
+@RequestFilters(AuthenticateRequest.class)
 public interface SSLTerminationApi {
    /**
     * Create or update SSL termination.
@@ -71,11 +87,22 @@
     * If a user wants to replace the existing SSL configuration, a new certificate, privatekey, and securePort 
     * combination must be provided instead of, or in addition to, the optional/editable attributes.
     */
-   void createOrUpdate(SSLTermination sslTermination);
+   @Named("ssltermination:create")
+   @PUT
+   @Consumes(MediaType.APPLICATION_JSON) 
+   @Fallback(VoidOnNotFoundOr404.class)
+   @Path("/ssltermination")
+   void createOrUpdate(@WrapWith("sslTermination") SSLTermination sslTermination);
 
    /**
     * Get SSL termination info.
     */
+   @Named("ssltermination:get")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @SelectJson("sslTermination")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Path("/ssltermination")
    SSLTermination get();
    
    /**
@@ -83,5 +110,10 @@
     * 
     * @return true on a successful delete, false if the SSL termination was not found
     */
+   @Named("ssltermination:delete")
+   @DELETE
+   @Fallback(FalseOnNotFoundOr422.class)
+   @Path("/ssltermination")
+   @Consumes("*/*")
    boolean delete();
 }
\ No newline at end of file
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/SSLTerminationAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/SSLTerminationAsyncApi.java
deleted file mode 100644
index fc8d678..0000000
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/SSLTerminationAsyncApi.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.rackspace.cloudloadbalancers.v1.features;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.Fallbacks.FalseOnNotFoundOr422;
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.SSLTermination;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SelectJson;
-import org.jclouds.rest.annotations.WrapWith;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides asynchronous access to Rackspace Cloud Load Balancers via their REST API.
- * <p/>
- * 
- * @see SSLTerminationApi
- * @author Everett Toews
- */
-@RequestFilters(AuthenticateRequest.class)
-public interface SSLTerminationAsyncApi {
-
-   /**
-    * @see SSLTerminationApi#createOrUpdate(SSLTermination)
-    */
-   @Named("ssltermination:create")
-   @PUT
-   @Consumes(MediaType.APPLICATION_JSON) 
-   @Fallback(VoidOnNotFoundOr404.class)
-   @Path("/ssltermination")
-   ListenableFuture<Void> createOrUpdate(@WrapWith("sslTermination") SSLTermination sslTermination);
-
-   /**
-    * @see SSLTerminationApi#get()
-    */
-   @Named("ssltermination:get")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @SelectJson("sslTermination")
-   @Fallback(NullOnNotFoundOr404.class)
-   @Path("/ssltermination")
-   ListenableFuture<SSLTermination> get();
-
-   /**
-    * @see SSLTerminationApi#delete()
-    */
-   @Named("ssltermination:delete")
-   @DELETE
-   @Fallback(FalseOnNotFoundOr422.class)
-   @Path("/ssltermination")
-   @Consumes("*/*")
-   ListenableFuture<Boolean> delete();
-}
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/SessionPersistenceApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/SessionPersistenceApi.java
index 1588c5a..7a013ec 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/SessionPersistenceApi.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/SessionPersistenceApi.java
@@ -18,7 +18,25 @@
  */
 package org.jclouds.rackspace.cloudloadbalancers.v1.features;
 
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.SessionPersistence;
+import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseSessionPersistence;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
 
 
 /**
@@ -26,15 +44,21 @@
  * directed to the same node. This is common with many web applications that do not inherently share application 
  * state between back-end servers. Two session persistence modes are available, HTTP Cookie and Source IP.
  *  
- * @see SessionPersistenceAsyncApi
  * @author Everett Toews
  */
+@RequestFilters(AuthenticateRequest.class)
 public interface SessionPersistenceApi {
    /**
     * Get the current session persistence.
     * 
     * @see SessionPersistence
     */
+   @Named("sessionpersistence:get")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseSessionPersistence.class)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Path("/sessionpersistence")
    SessionPersistence get();
    
    /**
@@ -42,12 +66,24 @@
     * 
     * @see SessionPersistence
     */
-   void create(SessionPersistence sessionPersistence);
+   @Named("sessionpersistence:create")
+   @PUT
+   @Produces(MediaType.APPLICATION_JSON)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(VoidOnNotFoundOr404.class)
+   @Payload("%7B\"sessionPersistence\":%7B\"persistenceType\":\"{sessionPersistence}\"%7D%7D")
+   @Path("/sessionpersistence")
+   void create(@PayloadParam("sessionPersistence") SessionPersistence sessionPersistence);
    
    /**
     * Delete session persistence.
     * 
     * @see SessionPersistence
     */
+   @Named("sessionpersistence:delete")
+   @DELETE
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(VoidOnNotFoundOr404.class)
+   @Path("/sessionpersistence")
    void delete();
 }
\ No newline at end of file
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/SessionPersistenceAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/SessionPersistenceAsyncApi.java
deleted file mode 100644
index 7ef1eb1..0000000
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/SessionPersistenceAsyncApi.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.rackspace.cloudloadbalancers.v1.features;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.SessionPersistence;
-import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseSessionPersistence;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.Payload;
-import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.ResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides asynchronous access to Rackspace Cloud Load Balancers via their REST API.
- * <p/>
- * 
- * @see SessionPersistenceApi
- * @author Everett Toews
- */
-@RequestFilters(AuthenticateRequest.class)
-public interface SessionPersistenceAsyncApi {
-
-   /**
-    * @see SessionPersistenceApi#get()
-    */
-   @Named("sessionpersistence:get")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @ResponseParser(ParseSessionPersistence.class)
-   @Fallback(NullOnNotFoundOr404.class)
-   @Path("/sessionpersistence")
-   ListenableFuture<SessionPersistence> get();
-
-   /**
-    * @see SessionPersistenceApi#create(SessionPersistence)
-    */
-   @Named("sessionpersistence:create")
-   @PUT
-   @Produces(MediaType.APPLICATION_JSON)
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(VoidOnNotFoundOr404.class)
-   @Payload("%7B\"sessionPersistence\":%7B\"persistenceType\":\"{sessionPersistence}\"%7D%7D")
-   @Path("/sessionpersistence")
-   ListenableFuture<Void> create(@PayloadParam("sessionPersistence") SessionPersistence sessionPersistence);
-
-   /**
-    * @see SessionPersistenceApi#delete()
-    */
-   @Named("sessionpersistence:delete")
-   @DELETE
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(VoidOnNotFoundOr404.class)
-   @Path("/sessionpersistence")
-   ListenableFuture<Void> delete();
-}
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/VirtualIPApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/VirtualIPApi.java
index e4d33fb..a1fcdb5 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/VirtualIPApi.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/VirtualIPApi.java
@@ -18,8 +18,27 @@
  */
 package org.jclouds.rackspace.cloudloadbalancers.v1.features;
 
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.VirtualIP;
 import org.jclouds.rackspace.cloudloadbalancers.v1.domain.VirtualIPWithId;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.binders.BindToJsonPayload;
 
 /**
  * A virtual IP makes a load balancer accessible by clients. The load balancing service supports either a public VIP,
@@ -27,18 +46,29 @@
  * resides.
  * <p/>
  * 
- * @see VirtualIPAsyncApi
  * @author Everett Toews
  */
+@RequestFilters(AuthenticateRequest.class)
 public interface VirtualIPApi {
    /**
     * Create a new virtual IP.
     */
-   VirtualIPWithId create(VirtualIP virtualIP);
+   @Named("virtualip:create")
+   @POST
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Path("/virtualips")
+   VirtualIPWithId create(@BinderParam(BindToJsonPayload.class) VirtualIP virtualIP);
 
    /**
     * List the virtual IPs.
     */
+   @Named("virtualip:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   @SelectJson("virtualIps")
+   @Path("/virtualips")
    Iterable<VirtualIPWithId> list();
    
    /**
@@ -48,7 +78,12 @@
     * 
     * @return true on a successful delete, false if the virtual IP was not found
     */
-   boolean delete(int id);
+   @Named("virtualip:delete")
+   @DELETE
+   @Fallback(FalseOnNotFoundOr404.class)
+   @Path("/virtualips/{id}")
+   @Consumes("*/*")
+   boolean delete(@PathParam("id") int id);
    
    /**
     * Batch delete virtual IPs given the specified ids.
@@ -61,5 +96,10 @@
     * 
     * @return true on a successful delete, false if the virtual IP was not found
     */
-   boolean delete(Iterable<Integer> ids);
+   @Named("virtualip:delete")
+   @DELETE
+   @Fallback(FalseOnNotFoundOr404.class)
+   @Path("/virtualips")
+   @Consumes("*/*")
+   boolean delete(@QueryParam("id") Iterable<Integer> ids);
 }
\ No newline at end of file
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/VirtualIPAsyncApi.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/VirtualIPAsyncApi.java
deleted file mode 100644
index 4653f2f..0000000
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/features/VirtualIPAsyncApi.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.rackspace.cloudloadbalancers.v1.features;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
-import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.VirtualIP;
-import org.jclouds.rackspace.cloudloadbalancers.v1.domain.VirtualIPWithId;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SelectJson;
-import org.jclouds.rest.binders.BindToJsonPayload;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides asynchronous access to Rackspace Cloud Load Balancers via their REST API.
- * <p/>
- * 
- * @see VirtualIPApi
- * @author Everett Toews
- */
-@RequestFilters(AuthenticateRequest.class)
-public interface VirtualIPAsyncApi {
-
-   /**
-    * @see VirtualIPApi#create(VirtualIP)
-    */
-   @Named("virtualip:create")
-   @POST
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(NullOnNotFoundOr404.class)
-   @Path("/virtualips")
-   ListenableFuture<VirtualIPWithId> create(@BinderParam(BindToJsonPayload.class) VirtualIP virtualIP);
-
-   /**
-    * @see VirtualIPApi#list()
-    */
-   @Named("virtualip:list")
-   @GET
-   @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
-   @SelectJson("virtualIps")
-   @Path("/virtualips")
-   ListenableFuture<Iterable<VirtualIPWithId>> list();
-
-   /**
-    * @see VirtualIPApi#delete(int)
-    */
-   @Named("virtualip:delete")
-   @DELETE
-   @Fallback(FalseOnNotFoundOr404.class)
-   @Path("/virtualips/{id}")
-   @Consumes("*/*")
-   ListenableFuture<Boolean> delete(@PathParam("id") int id);
-
-   /**
-    * @see VirtualIPApi#delete(Iterable)
-    */
-   @Named("virtualip:delete")
-   @DELETE
-   @Fallback(FalseOnNotFoundOr404.class)
-   @Path("/virtualips")
-   @Consumes("*/*")
-   ListenableFuture<Boolean> delete(@QueryParam("id") Iterable<Integer> ids);
-}
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseLoadBalancerUsages.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseLoadBalancerUsages.java
index e418b47..0279be0 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseLoadBalancerUsages.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseLoadBalancerUsages.java
@@ -27,7 +27,7 @@
 import javax.inject.Singleton;
 
 import org.jclouds.collect.IterableWithMarker;
-import org.jclouds.collect.internal.CallerArg0ToPagedIterable;
+import org.jclouds.collect.internal.Arg0ToPagedIterable;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
 import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
@@ -38,6 +38,7 @@
 import org.jclouds.rackspace.cloudloadbalancers.v1.functions.ParseLoadBalancerUsages.LoadBalancerUsages;
 
 import com.google.common.base.Function;
+import com.google.common.base.Optional;
 import com.google.inject.TypeLiteral;
 
 /**
@@ -61,7 +62,7 @@
       }
    }
 
-   public static class ToPagedIterable extends CallerArg0ToPagedIterable<LoadBalancerUsage, ToPagedIterable> {
+   public static class ToPagedIterable extends Arg0ToPagedIterable.FromCaller<LoadBalancerUsage, ToPagedIterable> {
 
       private final CloudLoadBalancersApi api;
 
@@ -71,7 +72,8 @@
       }
 
       @Override
-      protected Function<Object, IterableWithMarker<LoadBalancerUsage>> markerToNextForCallingArg0(final String zone) {
+      protected Function<Object, IterableWithMarker<LoadBalancerUsage>> markerToNextForArg0(Optional<Object> arg0) {
+         String zone = arg0.isPresent() ? arg0.get().toString() : null;
          final ReportApi reportApi = api.getReportApiForZone(zone);
          
          return new Function<Object, IterableWithMarker<LoadBalancerUsage>>() {
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseLoadBalancers.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseLoadBalancers.java
index 56ea07c..d5f2e2a 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseLoadBalancers.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseLoadBalancers.java
@@ -27,7 +27,7 @@
 
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.collect.IterableWithMarkers;
-import org.jclouds.collect.internal.CallerArg0ToPagedIterable;
+import org.jclouds.collect.internal.Arg0ToPagedIterable;
 import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
 import org.jclouds.http.functions.ParseJson;
@@ -40,6 +40,7 @@
 import org.jclouds.rest.InvocationContext;
 
 import com.google.common.base.Function;
+import com.google.common.base.Optional;
 import com.google.common.collect.Iterables;
 
 /**
@@ -92,7 +93,7 @@
 
    }
 
-   public static class ToPagedIterable extends CallerArg0ToPagedIterable<LoadBalancer, ToPagedIterable> {
+   public static class ToPagedIterable extends Arg0ToPagedIterable.FromCaller<LoadBalancer, ToPagedIterable> {
 
       private final CloudLoadBalancersApi api;
 
@@ -102,7 +103,8 @@
       }
 
       @Override
-      protected Function<Object, IterableWithMarker<LoadBalancer>> markerToNextForCallingArg0(final String zone) {
+      protected Function<Object, IterableWithMarker<LoadBalancer>> markerToNextForArg0(Optional<Object> arg0) {
+         String zone = arg0.isPresent() ? arg0.get().toString() : null;
          final LoadBalancerApi loadBalancerApi = api.getLoadBalancerApiForZone(zone);
          
          return new Function<Object, IterableWithMarker<LoadBalancer>>() {
diff --git a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseNodes.java b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseNodes.java
index e7745ce..14914d3 100644
--- a/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseNodes.java
+++ b/apis/rackspace-cloudloadbalancers/src/main/java/org/jclouds/rackspace/cloudloadbalancers/v1/functions/ParseNodes.java
@@ -27,7 +27,7 @@
 import javax.inject.Singleton;
 
 import org.jclouds.collect.IterableWithMarker;
-import org.jclouds.collect.internal.CallerArg0ToPagedIterable;
+import org.jclouds.collect.internal.Arg0ToPagedIterable;
 import org.jclouds.http.HttpRequest;
 import org.jclouds.http.functions.ParseJson;
 import org.jclouds.json.Json;
@@ -40,6 +40,7 @@
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
+import com.google.common.base.Optional;
 import com.google.inject.TypeLiteral;
 
 /**
@@ -64,7 +65,7 @@
       super(json, new TypeLiteral<Nodes>() { });
    }
 
-   public static class ToPagedIterable extends CallerArg0ToPagedIterable<Node, ToPagedIterable> {
+   public static class ToPagedIterable extends Arg0ToPagedIterable.FromCaller<Node, ToPagedIterable> {
 
       private final CloudLoadBalancersApi api;
       private int lbId;
@@ -86,7 +87,8 @@
       }
 
       @Override
-      protected Function<Object, IterableWithMarker<Node>> markerToNextForCallingArg0(final String zone) {
+      protected Function<Object, IterableWithMarker<Node>> markerToNextForArg0(Optional<Object> arg0) {
+         String zone = arg0.isPresent() ? arg0.get().toString() : null;
          final NodeApi nodeApi = api.getNodeApiForZoneAndLoadBalancer(zone, lbId);
          
          return new Function<Object, IterableWithMarker<Node>>() {
diff --git a/apis/route53/src/main/java/org/jclouds/route53/Route53Api.java b/apis/route53/src/main/java/org/jclouds/route53/Route53Api.java
index 4909226..43d11db 100644
--- a/apis/route53/src/main/java/org/jclouds/route53/Route53Api.java
+++ b/apis/route53/src/main/java/org/jclouds/route53/Route53Api.java
@@ -20,22 +20,35 @@
 
 import java.io.Closeable;
 
+import javax.inject.Named;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.rest.annotations.Delegate;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
 import org.jclouds.route53.domain.Change;
-import org.jclouds.route53.features.ResourceRecordSetApi;
 import org.jclouds.route53.features.HostedZoneApi;
+import org.jclouds.route53.features.ResourceRecordSetApi;
+import org.jclouds.route53.filters.RestAuthentication;
+import org.jclouds.route53.xml.ChangeHandler;
 
 /**
  * Provides access to Amazon Route53 via the Query API
  * <p/>
  * 
- * @see Route53AsyncApi
  * @see <a href="http://docs.amazonwebservices.com/Route53/latest/APIReference"
  *      />
  * @author Adrian Cole
  */
+@RequestFilters(RestAuthentication.class)
+@VirtualHost
+@Path("/{jclouds.api-version}")
 public interface Route53Api extends Closeable {
 
    /**
@@ -45,17 +58,24 @@
     *           The ID of the change batch request.
     * @return null, if not found
     */
-   Change getChange(String changeID);
+   @Named("GetChange")
+   @GET
+   @Path("/change/{changeId}")
+   @XMLResponseParser(ChangeHandler.class)
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Change getChange(@PathParam("changeId") String changeID);
 
    /**
-    * Provides synchronous access to Zone features.
+    * Provides access to Zone features.
     */
    @Delegate
    HostedZoneApi getHostedZoneApi();
    
    /**
-    * Provides synchronous access to record set features.
+    * Provides access to record set features.
     */
    @Delegate
+   @Path("/hostedzone/{zoneId}")
    ResourceRecordSetApi getResourceRecordSetApiForHostedZone(@PathParam("zoneId") String zoneId);
 }
diff --git a/apis/route53/src/main/java/org/jclouds/route53/Route53ApiMetadata.java b/apis/route53/src/main/java/org/jclouds/route53/Route53ApiMetadata.java
index f64443c..1785e22 100644
--- a/apis/route53/src/main/java/org/jclouds/route53/Route53ApiMetadata.java
+++ b/apis/route53/src/main/java/org/jclouds/route53/Route53ApiMetadata.java
@@ -25,35 +25,23 @@
 import java.util.Properties;
 
 import org.jclouds.apis.ApiMetadata;
-import org.jclouds.rest.internal.BaseRestApiMetadata;
-import org.jclouds.route53.config.Route53RestClientModule;
-
-import com.google.common.reflect.TypeToken;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
+import org.jclouds.route53.config.Route53HttpApiModule;
 
 /**
  * Implementation of {@link ApiMetadata} for Amazon's Route53 api.
  * 
  * @author Adrian Cole
  */
-public class Route53ApiMetadata extends BaseRestApiMetadata {
-
-   /**
-    * @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(Route53Api.class)} as
-    *             {@link Route53AsyncApi} interface will be removed in jclouds 1.7.
-    */
-   @Deprecated
-   public static final TypeToken<org.jclouds.rest.RestContext<? extends Route53Api, ? extends Route53AsyncApi>> CONTEXT_TOKEN = new TypeToken<org.jclouds.rest.RestContext<? extends Route53Api, ? extends Route53AsyncApi>>() {
-      private static final long serialVersionUID = 1L;
-   };
+public class Route53ApiMetadata extends BaseHttpApiMetadata<Route53Api> {
 
    @Override
    public Builder toBuilder() {
-      return new Builder(getApi(), getAsyncApi()).fromApiMetadata(this);
+      return new Builder().fromApiMetadata(this);
    }
 
-   @SuppressWarnings("deprecation")
    public Route53ApiMetadata() {
-      this(new Builder(Route53Api.class, Route53AsyncApi.class));
+      this(new Builder());
    }
 
    protected Route53ApiMetadata(Builder builder) {
@@ -61,16 +49,15 @@
    }
 
    public static Properties defaultProperties() {
-      Properties properties = BaseRestApiMetadata.defaultProperties();
+      Properties properties = BaseHttpApiMetadata.defaultProperties();
       properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
       properties.setProperty(PROPERTY_HEADER_TAG, "amz");
       return properties;
    }
 
-   public static class Builder extends BaseRestApiMetadata.Builder<Builder> {
+   public static class Builder extends BaseHttpApiMetadata.Builder<Route53Api, Builder> {
 
-      protected Builder(Class<?> api, Class<?> asyncApi) {
-         super(api, asyncApi);
+      protected Builder() {
          id("route53")
          .name("Amazon Route 53 Api")
          .identityName("Access Key ID")
@@ -79,7 +66,7 @@
          .documentation(URI.create("http://docs.aws.amazon.com/Route53/latest/APIReference/"))
          .defaultEndpoint("https://route53.amazonaws.com")
          .defaultProperties(Route53ApiMetadata.defaultProperties())
-         .defaultModule(Route53RestClientModule.class);
+         .defaultModule(Route53HttpApiModule.class);
       }
 
       @Override
diff --git a/apis/route53/src/main/java/org/jclouds/route53/Route53AsyncApi.java b/apis/route53/src/main/java/org/jclouds/route53/Route53AsyncApi.java
deleted file mode 100644
index fac0d40..0000000
--- a/apis/route53/src/main/java/org/jclouds/route53/Route53AsyncApi.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.route53;
-
-import java.io.Closeable;
-
-import javax.inject.Named;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.rest.annotations.Delegate;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-import org.jclouds.route53.domain.Change;
-import org.jclouds.route53.features.ResourceRecordSetAsyncApi;
-import org.jclouds.route53.features.HostedZoneAsyncApi;
-import org.jclouds.route53.filters.RestAuthentication;
-import org.jclouds.route53.xml.ChangeHandler;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to Amazon Route53 via the Query API
- * <p/>
- * 
- * @see <a href="http://docs.amazonwebservices.com/Route53/latest/APIReference"
- *      />
- * @author Adrian Cole
- * @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(Route53Api.class)} as
- *             {@link Route53AsyncApi} interface will be removed in jclouds 1.7.
- */
-@Deprecated
-@RequestFilters(RestAuthentication.class)
-@VirtualHost
-@Path("/{jclouds.api-version}")
-public interface Route53AsyncApi extends Closeable {
-
-   /**
-    * @see Route53Api#getChange()
-    */
-   @Named("GetChange")
-   @GET
-   @Path("/change/{changeId}")
-   @XMLResponseParser(ChangeHandler.class)
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Change> getChange(@PathParam("changeId") String changeID);
-
-   /**
-    * Provides asynchronous access to Zone features.
-    */
-   @Delegate
-   HostedZoneAsyncApi getHostedZoneApi();
-
-   /**
-    * Provides asynchronous access to record set features.
-    */
-   @Delegate
-   ResourceRecordSetAsyncApi getResourceRecordSetApiForHostedZone(@PathParam("zoneId") String zoneId);
-}
diff --git a/apis/route53/src/main/java/org/jclouds/route53/config/Route53RestClientModule.java b/apis/route53/src/main/java/org/jclouds/route53/config/Route53HttpApiModule.java
similarity index 67%
rename from apis/route53/src/main/java/org/jclouds/route53/config/Route53RestClientModule.java
rename to apis/route53/src/main/java/org/jclouds/route53/config/Route53HttpApiModule.java
index 613bf54..b7b930f 100644
--- a/apis/route53/src/main/java/org/jclouds/route53/config/Route53RestClientModule.java
+++ b/apis/route53/src/main/java/org/jclouds/route53/config/Route53HttpApiModule.java
@@ -18,32 +18,23 @@
  */
 package org.jclouds.route53.config;
 
-import static org.jclouds.reflect.Reflection2.typeToken;
-
 import java.util.Date;
-import java.util.Map;
 
 import javax.inject.Singleton;
 
-import org.jclouds.aws.config.AWSRestClientModule;
+import org.jclouds.aws.config.AWSHttpApiModule;
 import org.jclouds.date.DateService;
 import org.jclouds.date.TimeStamp;
 import org.jclouds.http.HttpErrorHandler;
 import org.jclouds.http.annotation.ClientError;
 import org.jclouds.http.annotation.Redirection;
 import org.jclouds.http.annotation.ServerError;
-import org.jclouds.rest.ConfiguresRestClient;
+import org.jclouds.rest.ConfiguresHttpApi;
 import org.jclouds.rest.RequestSigner;
 import org.jclouds.route53.Route53Api;
-import org.jclouds.route53.Route53AsyncApi;
-import org.jclouds.route53.features.ResourceRecordSetApi;
-import org.jclouds.route53.features.ResourceRecordSetAsyncApi;
-import org.jclouds.route53.features.HostedZoneApi;
-import org.jclouds.route53.features.HostedZoneAsyncApi;
 import org.jclouds.route53.filters.RestAuthentication;
 import org.jclouds.route53.handlers.Route53ErrorHandler;
 
-import com.google.common.collect.ImmutableMap;
 import com.google.inject.Provides;
 
 /**
@@ -51,14 +42,9 @@
  * 
  * @author Adrian Cole
  */
-@ConfiguresRestClient
-public class Route53RestClientModule extends AWSRestClientModule<Route53Api, Route53AsyncApi> {
-   public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()//
-         .put(HostedZoneApi.class, HostedZoneAsyncApi.class)
-         .put(ResourceRecordSetApi.class, ResourceRecordSetAsyncApi.class).build();
-
-   public Route53RestClientModule() {
-      super(typeToken(Route53Api.class), typeToken(Route53AsyncApi.class), DELEGATE_MAP);
+@ConfiguresHttpApi
+public class Route53HttpApiModule extends AWSHttpApiModule<Route53Api> {
+   public Route53HttpApiModule() {
    }
    
    @Provides
diff --git a/apis/route53/src/main/java/org/jclouds/route53/features/HostedZoneApi.java b/apis/route53/src/main/java/org/jclouds/route53/features/HostedZoneApi.java
index 36a0198..1cfc8ea 100644
--- a/apis/route53/src/main/java/org/jclouds/route53/features/HostedZoneApi.java
+++ b/apis/route53/src/main/java/org/jclouds/route53/features/HostedZoneApi.java
@@ -18,22 +18,48 @@
  */
 package org.jclouds.route53.features;
 
+import static javax.ws.rs.core.MediaType.APPLICATION_XML;
+
+import javax.inject.Named;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.collect.IterableWithMarker;
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.Transform;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
 import org.jclouds.route53.domain.Change;
 import org.jclouds.route53.domain.Change.Status;
 import org.jclouds.route53.domain.HostedZone;
 import org.jclouds.route53.domain.HostedZoneAndNameServers;
 import org.jclouds.route53.domain.NewHostedZone;
+import org.jclouds.route53.filters.RestAuthentication;
+import org.jclouds.route53.functions.HostedZonesToPagedIterable;
+import org.jclouds.route53.xml.ChangeHandler;
+import org.jclouds.route53.xml.CreateHostedZoneResponseHandler;
+import org.jclouds.route53.xml.GetHostedZoneResponseHandler;
+import org.jclouds.route53.xml.ListHostedZonesResponseHandler;
 
 /**
- * @see HostedZoneAsyncApi
  * @see <a href=
  *      "http://docs.aws.amazon.com/Route53/latest/APIReference/ActionsOnHostedZones.html"
  *      />
  * @author Adrian Cole
  */
+@RequestFilters(RestAuthentication.class)
+@VirtualHost
 public interface HostedZoneApi {
 
    /**
@@ -51,28 +77,55 @@
     *           retries. ex. {@code MyDNSMigration_01}
     * @return the new zone in progress, in {@link Status#PENDING}.
     */
-   NewHostedZone createWithReference(String name, String callerReference);
+   @Named("CreateHostedZone")
+   @POST
+   @Produces(APPLICATION_XML)
+   @Path("/hostedzone")
+   @Payload("<CreateHostedZoneRequest xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Name>{name}</Name><CallerReference>{callerReference}</CallerReference></CreateHostedZoneRequest>")
+   @XMLResponseParser(CreateHostedZoneResponseHandler.class)
+   NewHostedZone createWithReference(@PayloadParam("name") String name,
+         @PayloadParam("callerReference") String callerReference);
 
    /**
     * like {@link #createWithReference(String, String)}, except you can specify
     * a comment.
     */
-   NewHostedZone createWithReferenceAndComment(String name, String callerReference, String comment);
+   @Named("CreateHostedZone")
+   @POST
+   @Produces(APPLICATION_XML)
+   @Path("/hostedzone")
+   @Payload("<CreateHostedZoneRequest xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Name>{name}</Name><CallerReference>{callerReference}</CallerReference><HostedZoneConfig><Comment>{comment}</Comment></HostedZoneConfig></CreateHostedZoneRequest>")
+   @XMLResponseParser(CreateHostedZoneResponseHandler.class)
+   NewHostedZone createWithReferenceAndComment(@PayloadParam("name") String name,
+         @PayloadParam("callerReference") String callerReference, @PayloadParam("comment") String comment);
 
    /**
     * returns all zones in order.
     */
+   @Named("ListHostedZones")
+   @GET
+   @Path("/hostedzone")
+   @XMLResponseParser(ListHostedZonesResponseHandler.class)
+   @Transform(HostedZonesToPagedIterable.class)
    PagedIterable<HostedZone> list();
 
    /**
     * retrieves up to 100 zones in order.
     */
+   @Named("ListHostedZones")
+   @GET
+   @Path("/hostedzone")
+   @XMLResponseParser(ListHostedZonesResponseHandler.class)
    IterableWithMarker<HostedZone> listFirstPage();
 
    /**
     * retrieves up to 100 zones in order, starting at {@code nextMarker}
     */
-   IterableWithMarker<HostedZone> listAt(String nextMarker);
+   @Named("ListHostedZones")
+   @GET
+   @Path("/hostedzone")
+   @XMLResponseParser(ListHostedZonesResponseHandler.class)
+   IterableWithMarker<HostedZone> listAt(@QueryParam("marker") String nextMarker);
 
    /**
     * Retrieves information about the specified zone, including its nameserver
@@ -83,8 +136,13 @@
     *           {@code Z1PA6795UKMFR9}
     * @return null if not found
     */
+   @Named("GetHostedZone")
+   @GET
+   @Path("/hostedzone/{zoneId}")
+   @XMLResponseParser(GetHostedZoneResponseHandler.class)
+   @Fallback(NullOnNotFoundOr404.class)
    @Nullable
-   HostedZoneAndNameServers get(String id);
+   HostedZoneAndNameServers get(@PathParam("zoneId") String zoneId);
 
    /**
     * This action deletes a hosted zone.
@@ -93,6 +151,11 @@
     *           id of the zone to delete. ex {@code Z1PA6795UKMFR9}
     * @return null if not found or the change in progress
     */
+   @Named("DeleteHostedZone")
+   @DELETE
+   @Path("/hostedzone/{zoneId}")
+   @XMLResponseParser(ChangeHandler.class)
+   @Fallback(NullOnNotFoundOr404.class)
    @Nullable
-   Change delete(String id);
+   Change delete(@PathParam("zoneId") String zoneId);
 }
diff --git a/apis/route53/src/main/java/org/jclouds/route53/features/HostedZoneAsyncApi.java b/apis/route53/src/main/java/org/jclouds/route53/features/HostedZoneAsyncApi.java
deleted file mode 100644
index 490a79c..0000000
--- a/apis/route53/src/main/java/org/jclouds/route53/features/HostedZoneAsyncApi.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.route53.features;
-
-import static javax.ws.rs.core.MediaType.APPLICATION_XML;
-
-import javax.inject.Named;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.collect.IterableWithMarker;
-import org.jclouds.collect.PagedIterable;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.Payload;
-import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.Transform;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-import org.jclouds.route53.domain.Change;
-import org.jclouds.route53.domain.HostedZone;
-import org.jclouds.route53.domain.HostedZoneAndNameServers;
-import org.jclouds.route53.domain.NewHostedZone;
-import org.jclouds.route53.filters.RestAuthentication;
-import org.jclouds.route53.functions.HostedZonesToPagedIterable;
-import org.jclouds.route53.xml.ChangeHandler;
-import org.jclouds.route53.xml.CreateHostedZoneResponseHandler;
-import org.jclouds.route53.xml.GetHostedZoneResponseHandler;
-import org.jclouds.route53.xml.ListHostedZonesResponseHandler;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * @see HostedZoneApi
- * @see <a href=
- *      "http://docs.aws.amazon.com/Route53/latest/APIReference/ActionsOnHostedZones.html"
- *      />
- * @author Adrian Cole
- */
-@RequestFilters(RestAuthentication.class)
-@VirtualHost
-@Path("/{jclouds.api-version}")
-public interface HostedZoneAsyncApi {
-   /**
-    * @see HostedZoneApi#createWithReference
-    */
-   @Named("CreateHostedZone")
-   @POST
-   @Produces(APPLICATION_XML)
-   @Path("/hostedzone")
-   @Payload("<CreateHostedZoneRequest xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Name>{name}</Name><CallerReference>{callerReference}</CallerReference></CreateHostedZoneRequest>")
-   @XMLResponseParser(CreateHostedZoneResponseHandler.class)
-   ListenableFuture<NewHostedZone> createWithReference(@PayloadParam("name") String name,
-         @PayloadParam("callerReference") String callerReference);
-
-   /**
-    * @see HostedZoneApi#createWithReferenceAndComment
-    */
-   @Named("CreateHostedZone")
-   @POST
-   @Produces(APPLICATION_XML)
-   @Path("/hostedzone")
-   @Payload("<CreateHostedZoneRequest xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><Name>{name}</Name><CallerReference>{callerReference}</CallerReference><HostedZoneConfig><Comment>{comment}</Comment></HostedZoneConfig></CreateHostedZoneRequest>")
-   @XMLResponseParser(CreateHostedZoneResponseHandler.class)
-   ListenableFuture<NewHostedZone> createWithReferenceAndComment(@PayloadParam("name") String name,
-         @PayloadParam("callerReference") String callerReference, @PayloadParam("comment") String comment);
-
-   /**
-    * @see HostedZoneApi#list()
-    */
-   @Named("ListHostedZones")
-   @GET
-   @Path("/hostedzone")
-   @XMLResponseParser(ListHostedZonesResponseHandler.class)
-   @Transform(HostedZonesToPagedIterable.class)
-   ListenableFuture<PagedIterable<HostedZone>> list();
-
-   /**
-    * @see HostedZoneApi#listFirstPage
-    */
-   @Named("ListHostedZones")
-   @GET
-   @Path("/hostedzone")
-   @XMLResponseParser(ListHostedZonesResponseHandler.class)
-   ListenableFuture<IterableWithMarker<HostedZone>> listFirstPage();
-
-   /**
-    * @see HostedZoneApi#listAt(String)
-    */
-   @Named("ListHostedZones")
-   @GET
-   @Path("/hostedzone")
-   @XMLResponseParser(ListHostedZonesResponseHandler.class)
-   ListenableFuture<IterableWithMarker<HostedZone>> listAt(@QueryParam("marker") String nextMarker);
-
-   /**
-    * @see HostedZoneApi#get()
-    */
-   @Named("GetHostedZone")
-   @GET
-   @Path("/hostedzone/{zoneId}")
-   @XMLResponseParser(GetHostedZoneResponseHandler.class)
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<HostedZoneAndNameServers> get(@PathParam("zoneId") String zoneId);
-
-   /**
-    * @see HostedZoneApi#delete()
-    */
-   @Named("DeleteHostedZone")
-   @DELETE
-   @Path("/hostedzone/{zoneId}")
-   @XMLResponseParser(ChangeHandler.class)
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Change> delete(@PathParam("zoneId") String zoneId);
-}
diff --git a/apis/route53/src/main/java/org/jclouds/route53/features/ResourceRecordSetApi.java b/apis/route53/src/main/java/org/jclouds/route53/features/ResourceRecordSetApi.java
index 1eef42a..a3592e3 100644
--- a/apis/route53/src/main/java/org/jclouds/route53/features/ResourceRecordSetApi.java
+++ b/apis/route53/src/main/java/org/jclouds/route53/features/ResourceRecordSetApi.java
@@ -18,48 +18,98 @@
  */
 package org.jclouds.route53.features;
 
+import static javax.ws.rs.core.MediaType.APPLICATION_XML;
+
+import javax.inject.Named;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.ParamParser;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.Transform;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
+import org.jclouds.route53.binders.BindChangeBatch;
+import org.jclouds.route53.binders.BindNextRecord;
 import org.jclouds.route53.domain.Change;
 import org.jclouds.route53.domain.ChangeBatch;
 import org.jclouds.route53.domain.ResourceRecordSet;
 import org.jclouds.route53.domain.ResourceRecordSetIterable;
 import org.jclouds.route53.domain.ResourceRecordSetIterable.NextRecord;
+import org.jclouds.route53.filters.RestAuthentication;
+import org.jclouds.route53.functions.ResourceRecordSetIterableToPagedIterable;
+import org.jclouds.route53.functions.SerializeRRS;
+import org.jclouds.route53.xml.ChangeHandler;
+import org.jclouds.route53.xml.ListResourceRecordSetsResponseHandler;
 
 /**
- * @see ResourceRecordSetAsyncApi
  * @see <a href=
  *      "http://docs.aws.amazon.com/Route53/latest/APIReference/ActionsOnRRS.html"
  *      />
  * @author Adrian Cole
  */
+@RequestFilters(RestAuthentication.class)
+@VirtualHost
 public interface ResourceRecordSetApi {
 
    /**
     * schedules creation of the resource record set.
     */
-   Change create(ResourceRecordSet rrs);
+   @Named("ChangeResourceRecordSets")
+   @POST
+   @Produces(APPLICATION_XML)
+   @Path("/rrset")
+   @Payload("<ChangeResourceRecordSetsRequest xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><ChangeBatch><Changes><Change><Action>CREATE</Action>{rrs}</Change></Changes></ChangeBatch></ChangeResourceRecordSetsRequest>")
+   @XMLResponseParser(ChangeHandler.class)
+   Change create(@PayloadParam("rrs") @ParamParser(SerializeRRS.class) ResourceRecordSet rrs);
 
    /**
     * applies a batch of changes atomically.
     */
-   Change apply(ChangeBatch changes);
+   @Named("ChangeResourceRecordSets")
+   @POST
+   @Produces(APPLICATION_XML)
+   @Path("/rrset")
+   @XMLResponseParser(ChangeHandler.class)
+   Change apply(@BinderParam(BindChangeBatch.class) ChangeBatch changes);
 
    /**
     * returns all resource record sets in order.
     */
+   @Named("ListResourceRecordSets")
+   @GET
+   @Path("/rrset")
+   @XMLResponseParser(ListResourceRecordSetsResponseHandler.class)
+   @Transform(ResourceRecordSetIterableToPagedIterable.class)
    PagedIterable<ResourceRecordSet> list();
 
    /**
     * retrieves up to 100 resource record sets in order.
     */
+   @Named("ListResourceRecordSets")
+   @GET
+   @Path("/rrset")
+   @XMLResponseParser(ListResourceRecordSetsResponseHandler.class)
    ResourceRecordSetIterable listFirstPage();
 
    /**
     * retrieves up to 100 resource record sets in order, starting at
     * {@code nextRecord}
     */
-   ResourceRecordSetIterable listAt(NextRecord nextRecord);
+   @Named("ListResourceRecordSets")
+   @GET
+   @Path("/rrset")
+   @XMLResponseParser(ListResourceRecordSetsResponseHandler.class)
+   ResourceRecordSetIterable listAt(@BinderParam(BindNextRecord.class) NextRecord nextRecord);
 
    /**
     * This action deletes a resource record set.
@@ -68,6 +118,13 @@
     *           the resource record set to delete
     * @return null if not found or the change in progress
     */
+   @Named("ChangeResourceRecordSets")
+   @POST
+   @Produces(APPLICATION_XML)
+   @Path("/rrset")
+   @Payload("<ChangeResourceRecordSetsRequest xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><ChangeBatch><Changes><Change><Action>DELETE</Action>{rrs}</Change></Changes></ChangeBatch></ChangeResourceRecordSetsRequest>")
+   @XMLResponseParser(ChangeHandler.class)
+   @Fallback(NullOnNotFoundOr404.class)
    @Nullable
-   Change delete(ResourceRecordSet rrs);
+   Change delete(@PayloadParam("rrs") @ParamParser(SerializeRRS.class) ResourceRecordSet rrs);
 }
diff --git a/apis/route53/src/main/java/org/jclouds/route53/features/ResourceRecordSetAsyncApi.java b/apis/route53/src/main/java/org/jclouds/route53/features/ResourceRecordSetAsyncApi.java
deleted file mode 100644
index f008ae4..0000000
--- a/apis/route53/src/main/java/org/jclouds/route53/features/ResourceRecordSetAsyncApi.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.route53.features;
-
-import static javax.ws.rs.core.MediaType.APPLICATION_XML;
-
-import javax.inject.Named;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.collect.PagedIterable;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.ParamParser;
-import org.jclouds.rest.annotations.Payload;
-import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.Transform;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-import org.jclouds.route53.binders.BindChangeBatch;
-import org.jclouds.route53.binders.BindNextRecord;
-import org.jclouds.route53.domain.Change;
-import org.jclouds.route53.domain.ChangeBatch;
-import org.jclouds.route53.domain.ResourceRecordSet;
-import org.jclouds.route53.domain.ResourceRecordSetIterable;
-import org.jclouds.route53.domain.ResourceRecordSetIterable.NextRecord;
-import org.jclouds.route53.filters.RestAuthentication;
-import org.jclouds.route53.functions.ResourceRecordSetIterableToPagedIterable;
-import org.jclouds.route53.functions.SerializeRRS;
-import org.jclouds.route53.xml.ChangeHandler;
-import org.jclouds.route53.xml.ListResourceRecordSetsResponseHandler;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * @see ResourceRecordSetApi
- * @see <a href=
- *      "http://docs.aws.amazon.com/Route53/latest/APIReference/ActionsOnRRS.html"
- *      />
- * @author Adrian Cole
- */
-@RequestFilters(RestAuthentication.class)
-@VirtualHost
-@Path("/{jclouds.api-version}/hostedzone/{zoneId}")
-public interface ResourceRecordSetAsyncApi {
-   /**
-    * @see ResourceRecordSetApi#create
-    */
-   @Named("ChangeResourceRecordSets")
-   @POST
-   @Produces(APPLICATION_XML)
-   @Path("/rrset")
-   @Payload("<ChangeResourceRecordSetsRequest xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><ChangeBatch><Changes><Change><Action>CREATE</Action>{rrs}</Change></Changes></ChangeBatch></ChangeResourceRecordSetsRequest>")
-   @XMLResponseParser(ChangeHandler.class)
-   ListenableFuture<Change> create(@PayloadParam("rrs") @ParamParser(SerializeRRS.class) ResourceRecordSet rrs);
-   
-   /**
-    * @see ResourceRecordSetApi#apply
-    */
-   @Named("ChangeResourceRecordSets")
-   @POST
-   @Produces(APPLICATION_XML)
-   @Path("/rrset")
-   @XMLResponseParser(ChangeHandler.class)
-   ListenableFuture<Change> apply(@BinderParam(BindChangeBatch.class) ChangeBatch changes);
-
-   /**
-    * @see ResourceRecordSetApi#list()
-    */
-   @Named("ListResourceRecordSets")
-   @GET
-   @Path("/rrset")
-   @XMLResponseParser(ListResourceRecordSetsResponseHandler.class)
-   @Transform(ResourceRecordSetIterableToPagedIterable.class)
-   ListenableFuture<PagedIterable<ResourceRecordSet>> list();
-
-   /**
-    * @see ResourceRecordSetApi#listFirstPage
-    */
-   @Named("ListResourceRecordSets")
-   @GET
-   @Path("/rrset")
-   @XMLResponseParser(ListResourceRecordSetsResponseHandler.class)
-   ListenableFuture<ResourceRecordSetIterable> listFirstPage();
-
-   /**
-    * @see ResourceRecordSetApi#listAt(NextRecord)
-    */
-   @Named("ListResourceRecordSets")
-   @GET
-   @Path("/rrset")
-   @XMLResponseParser(ListResourceRecordSetsResponseHandler.class)
-   ListenableFuture<ResourceRecordSetIterable> listAt(@BinderParam(BindNextRecord.class) NextRecord nextRecord);
-
-   /**
-    * @see ResourceRecordSetApi#delete
-    */
-   @Named("ChangeResourceRecordSets")
-   @POST
-   @Produces(APPLICATION_XML)
-   @Path("/rrset")
-   @Payload("<ChangeResourceRecordSetsRequest xmlns=\"https://route53.amazonaws.com/doc/2012-02-29/\"><ChangeBatch><Changes><Change><Action>DELETE</Action>{rrs}</Change></Changes></ChangeBatch></ChangeResourceRecordSetsRequest>")
-   @XMLResponseParser(ChangeHandler.class)
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Change> delete(@PayloadParam("rrs") @ParamParser(SerializeRRS.class) ResourceRecordSet rrs);
-}
diff --git a/apis/route53/src/test/java/org/jclouds/route53/Route53ApiMetadataTest.java b/apis/route53/src/test/java/org/jclouds/route53/Route53ApiMetadataTest.java
index 76ef1b3..13094b5 100644
--- a/apis/route53/src/test/java/org/jclouds/route53/Route53ApiMetadataTest.java
+++ b/apis/route53/src/test/java/org/jclouds/route53/Route53ApiMetadataTest.java
@@ -19,7 +19,7 @@
 package org.jclouds.route53;
 
 import org.jclouds.View;
-import org.jclouds.rest.internal.BaseRestApiMetadataTest;
+import org.jclouds.rest.internal.BaseHttpApiMetadataTest;
 import org.testng.annotations.Test;
 
 import com.google.common.collect.ImmutableSet;
@@ -30,9 +30,9 @@
  * @author Adrian Cole
  */
 @Test(groups = "unit", testName = "Route53ApiMetadataTest")
-public class Route53ApiMetadataTest extends BaseRestApiMetadataTest {
+public class Route53ApiMetadataTest extends BaseHttpApiMetadataTest {
 
-   // no tenant abstraction, yet
+   // no dns abstraction, yet
    public Route53ApiMetadataTest() {
       super(new Route53ApiMetadata(), ImmutableSet.<TypeToken<? extends View>> of());
    }
diff --git a/apis/route53/src/test/java/org/jclouds/route53/internal/BaseRoute53ApiLiveTest.java b/apis/route53/src/test/java/org/jclouds/route53/internal/BaseRoute53ApiLiveTest.java
index d26a64a..d8684b4 100644
--- a/apis/route53/src/test/java/org/jclouds/route53/internal/BaseRoute53ApiLiveTest.java
+++ b/apis/route53/src/test/java/org/jclouds/route53/internal/BaseRoute53ApiLiveTest.java
@@ -49,7 +49,8 @@
       super.setup();
       inSync = retry(new Predicate<Change>() {
          public boolean apply(Change input) {
-            return api.getChange(input.getId()).getStatus() == INSYNC;
+            Change change = api.getChange(input.getId());
+            return change != null && change.getStatus() == INSYNC;
          }
       }, 600, 1, 5, SECONDS);
    }
diff --git a/apis/route53/src/test/java/org/jclouds/route53/internal/BaseRoute53ExpectTest.java b/apis/route53/src/test/java/org/jclouds/route53/internal/BaseRoute53ExpectTest.java
index 78f6f06..44886e7 100644
--- a/apis/route53/src/test/java/org/jclouds/route53/internal/BaseRoute53ExpectTest.java
+++ b/apis/route53/src/test/java/org/jclouds/route53/internal/BaseRoute53ExpectTest.java
@@ -22,9 +22,9 @@
 
 import org.jclouds.date.DateService;
 import org.jclouds.http.HttpResponse;
-import org.jclouds.rest.ConfiguresRestClient;
+import org.jclouds.rest.ConfiguresHttpApi;
 import org.jclouds.rest.internal.BaseRestApiExpectTest;
-import org.jclouds.route53.config.Route53RestClientModule;
+import org.jclouds.route53.config.Route53HttpApiModule;
 
 import com.google.inject.Module;
 /**
@@ -37,8 +37,8 @@
       provider = "route53";
    }
    
-   @ConfiguresRestClient
-   private static final class TestRoute53RestClientModule extends Route53RestClientModule {
+   @ConfiguresHttpApi
+   private static final class TestRoute53HttpApiModule extends Route53HttpApiModule {
 
       @Override
       protected String provideTimeStamp(final DateService dateService) {
@@ -51,6 +51,6 @@
 
    @Override
    protected Module createModule() {
-      return new TestRoute53RestClientModule();
+      return new TestRoute53HttpApiModule();
    }
 }
diff --git a/apis/sts/src/main/java/org/jclouds/aws/config/AWSHttpApiModule.java b/apis/sts/src/main/java/org/jclouds/aws/config/AWSHttpApiModule.java
new file mode 100644
index 0000000..0b0437f
--- /dev/null
+++ b/apis/sts/src/main/java/org/jclouds/aws/config/AWSHttpApiModule.java
@@ -0,0 +1,73 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.aws.config;
+
+
+import java.util.Set;
+
+import javax.inject.Singleton;
+
+import org.jclouds.aws.handlers.AWSClientErrorRetryHandler;
+import org.jclouds.aws.handlers.ParseAWSErrorFromXmlContent;
+import org.jclouds.http.HttpErrorHandler;
+import org.jclouds.http.HttpRetryHandler;
+import org.jclouds.http.annotation.ClientError;
+import org.jclouds.http.annotation.Redirection;
+import org.jclouds.http.annotation.ServerError;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.config.HttpApiModule;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Provides;
+
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+@ConfiguresHttpApi
+public abstract class AWSHttpApiModule<A> extends HttpApiModule<A> {
+   protected AWSHttpApiModule() {
+
+   }
+
+   protected AWSHttpApiModule(Class<A> api) {
+      super(api);
+   }
+
+   @Provides
+   @ClientError
+   @Singleton
+   protected Set<String> provideRetryableCodes(){
+      return ImmutableSet.of("RequestTimeout", "OperationAborted", "SignatureDoesNotMatch");
+   }
+   
+   @Override
+   protected void bindErrorHandlers() {
+      bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseAWSErrorFromXmlContent.class);
+      bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ParseAWSErrorFromXmlContent.class);
+      bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseAWSErrorFromXmlContent.class);
+   }
+
+   @Override
+   protected void bindRetryHandlers() {
+      bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(AWSClientErrorRetryHandler.class);
+   }
+
+}
diff --git a/apis/sts/src/main/java/org/jclouds/aws/config/AWSRestClientModule.java b/apis/sts/src/main/java/org/jclouds/aws/config/AWSRestClientModule.java
index f953f15..2638605 100644
--- a/apis/sts/src/main/java/org/jclouds/aws/config/AWSRestClientModule.java
+++ b/apis/sts/src/main/java/org/jclouds/aws/config/AWSRestClientModule.java
@@ -32,6 +32,7 @@
 import org.jclouds.http.annotation.Redirection;
 import org.jclouds.http.annotation.ServerError;
 import org.jclouds.rest.ConfiguresRestClient;
+import org.jclouds.rest.config.HttpApiModule;
 import org.jclouds.rest.config.RestClientModule;
 
 import com.google.common.collect.ImmutableSet;
@@ -42,7 +43,10 @@
 /**
  * 
  * @author Adrian Cole
+ * 
+ * @deprecated will be removed in jclouds 1.7; use {@link AWSHttpApiModule}
  */
+@Deprecated
 @ConfiguresRestClient
 public abstract class AWSRestClientModule<S, A> extends RestClientModule<S, A> {
 
diff --git a/apis/sts/src/main/java/org/jclouds/aws/config/FormSigningHttpApiModule.java b/apis/sts/src/main/java/org/jclouds/aws/config/FormSigningHttpApiModule.java
new file mode 100644
index 0000000..bb677cd
--- /dev/null
+++ b/apis/sts/src/main/java/org/jclouds/aws/config/FormSigningHttpApiModule.java
@@ -0,0 +1,61 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.aws.config;
+
+import java.util.Date;
+
+import javax.inject.Singleton;
+
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.date.DateService;
+import org.jclouds.date.TimeStamp;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.RequestSigner;
+
+import com.google.inject.Provides;
+
+/**
+ * Configures signature process and dependencies needed for AWS Query apis
+ * (which we sent as POST requests, hence the name Form).
+ * 
+ * @author Adrian Cole
+ */
+@ConfiguresHttpApi
+public abstract class FormSigningHttpApiModule<A> extends AWSHttpApiModule<A> {
+   protected FormSigningHttpApiModule() {
+
+   }
+
+   protected FormSigningHttpApiModule(Class<A> api) {
+      super(api);
+   }
+
+   @Provides
+   @TimeStamp
+   protected String provideTimeStamp(DateService dateService) {
+      return dateService.iso8601DateFormat(new Date(System.currentTimeMillis()));
+   }
+
+   @Provides
+   @Singleton
+   RequestSigner provideRequestSigner(FormSigner in) {
+      return in;
+   }
+
+}
diff --git a/apis/sts/src/main/java/org/jclouds/aws/xml/SessionCredentialsHandler.java b/apis/sts/src/main/java/org/jclouds/aws/xml/SessionCredentialsHandler.java
index c26f78a..7e010a4 100644
--- a/apis/sts/src/main/java/org/jclouds/aws/xml/SessionCredentialsHandler.java
+++ b/apis/sts/src/main/java/org/jclouds/aws/xml/SessionCredentialsHandler.java
@@ -18,12 +18,13 @@
  */
 package org.jclouds.aws.xml;
 
+import static org.jclouds.util.SaxUtils.currentOrNull;
+
 import javax.inject.Inject;
 
 import org.jclouds.aws.domain.SessionCredentials;
 import org.jclouds.date.DateService;
 import org.jclouds.http.functions.ParseSax;
-import org.jclouds.util.SaxUtils;
 
 /**
  * @see <a href=
@@ -55,13 +56,17 @@
    @Override
    public void endElement(String uri, String name, String qName) {
       if (qName.equals("AccessKeyId")) {
-         builder.accessKeyId(SaxUtils.currentOrNull(currentText));
+         builder.accessKeyId(currentOrNull(currentText));
       } else if (qName.equals("SecretAccessKey")) {
-         builder.secretAccessKey(SaxUtils.currentOrNull(currentText));
+         builder.secretAccessKey(currentOrNull(currentText));
       } else if (qName.equals("SessionToken")) {
-         builder.sessionToken(SaxUtils.currentOrNull(currentText));
+         builder.sessionToken(currentOrNull(currentText));
       } else if (qName.equals("Expiration")) {
-         builder.expiration(dateService.iso8601DateParse(SaxUtils.currentOrNull(currentText)));
+         try {
+            builder.expiration(dateService.iso8601SecondsDateParse(currentOrNull(currentText)));
+         } catch (IllegalArgumentException e) {
+            builder.expiration(dateService.iso8601DateParse(currentOrNull(currentText)));
+         }
       }
       currentText = new StringBuilder();
    }
diff --git a/apis/sts/src/main/java/org/jclouds/sts/STSApi.java b/apis/sts/src/main/java/org/jclouds/sts/STSApi.java
index 5211af1..5122912 100644
--- a/apis/sts/src/main/java/org/jclouds/sts/STSApi.java
+++ b/apis/sts/src/main/java/org/jclouds/sts/STSApi.java
@@ -20,32 +20,55 @@
 
 import java.io.Closeable;
 
+import javax.inject.Named;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
 import org.jclouds.aws.domain.SessionCredentials;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.aws.xml.SessionCredentialsHandler;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
 import org.jclouds.sts.domain.User;
 import org.jclouds.sts.domain.UserAndSessionCredentials;
 import org.jclouds.sts.options.AssumeRoleOptions;
 import org.jclouds.sts.options.FederatedUserOptions;
 import org.jclouds.sts.options.SessionCredentialsOptions;
+import org.jclouds.sts.xml.UserAndSessionCredentialsHandler;
 
 /**
  * Provides access to Amazon STS via the Query API
  * <p/>
  * 
- * @see STSAsyncApi
  * @see <a href="http://docs.amazonwebservices.com/STS/latest/APIReference" />
  * @author Adrian Cole
  */
+@RequestFilters(FormSigner.class)
+@VirtualHost
 public interface STSApi extends Closeable {
    /**
     * Returns a set of temporary credentials for an AWS account or IAM user,
     * with a default timeout
     */
+   @Named("GetSessionToken")
+   @POST
+   @Path("/")
+   @XMLResponseParser(SessionCredentialsHandler.class)
+   @FormParams(keys = "Action", values = "GetSessionToken")
    SessionCredentials createTemporaryCredentials();
 
    /**
     * like {@link #createTemporaryCredentials()}, except you can modify the
     * timeout and other parameters.
     */
+   @Named("GetSessionToken")
+   @POST
+   @Path("/")
+   @XMLResponseParser(SessionCredentialsHandler.class)
+   @FormParams(keys = "Action", values = "GetSessionToken")
    SessionCredentials createTemporaryCredentials(SessionCredentialsOptions options);
 
    /**
@@ -58,13 +81,25 @@
     *           The Amazon Resource Name (ARN) of the role that the caller is
     *           assuming.
     */
-   UserAndSessionCredentials assumeRole(String roleArn, String sessionName);
+   @Named("AssumeRole")
+   @POST
+   @Path("/")
+   @XMLResponseParser(UserAndSessionCredentialsHandler.class)
+   @FormParams(keys = "Action", values = "AssumeRole")
+   UserAndSessionCredentials assumeRole(@FormParam("RoleArn") String roleArn,
+         @FormParam("RoleSessionName") String sessionName);
    
    /**
     * like {@link #assumeRole(String, String)}, except you can modify the
     * timeout and other parameters.
     */
-   UserAndSessionCredentials assumeRole(String roleArn, String sessionName, AssumeRoleOptions options);
+   @Named("AssumeRole")
+   @POST
+   @Path("/")
+   @XMLResponseParser(UserAndSessionCredentialsHandler.class)
+   @FormParams(keys = "Action", values = "AssumeRole")
+   UserAndSessionCredentials assumeRole(@FormParam("RoleArn") String roleArn,
+         @FormParam("RoleSessionName") String sessionName, AssumeRoleOptions options);
    
    /**
     * Returns a set of temporary credentials for a federated user with the user
@@ -74,12 +109,21 @@
     *           The name of the federated user, included as part of
     *           {@link User#getId}.
     */
-   UserAndSessionCredentials createFederatedUser(String userName);
+   @Named("GetFederationToken")
+   @POST
+   @Path("/")
+   @XMLResponseParser(UserAndSessionCredentialsHandler.class)
+   @FormParams(keys = "Action", values = "GetFederationToken")
+   UserAndSessionCredentials createFederatedUser(@FormParam("Name") String userName);
    
    /**
     * like {@link #createFederatedUser(String)}, except you can modify the
     * timeout and other parameters.
     */
-   UserAndSessionCredentials createFederatedUser(String userName, FederatedUserOptions options);
-
+   @Named("GetFederationToken")
+   @POST
+   @Path("/")
+   @XMLResponseParser(UserAndSessionCredentialsHandler.class)
+   @FormParams(keys = "Action", values = "GetFederationToken")
+   UserAndSessionCredentials createFederatedUser(@FormParam("Name") String userName, FederatedUserOptions options);
 }
diff --git a/apis/sts/src/main/java/org/jclouds/sts/STSApiMetadata.java b/apis/sts/src/main/java/org/jclouds/sts/STSApiMetadata.java
index 9fc653a..e5e31f9 100644
--- a/apis/sts/src/main/java/org/jclouds/sts/STSApiMetadata.java
+++ b/apis/sts/src/main/java/org/jclouds/sts/STSApiMetadata.java
@@ -25,35 +25,23 @@
 import java.util.Properties;
 
 import org.jclouds.apis.ApiMetadata;
-import org.jclouds.rest.internal.BaseRestApiMetadata;
-import org.jclouds.sts.config.STSRestClientModule;
-
-import com.google.common.reflect.TypeToken;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
+import org.jclouds.sts.config.STSHttpApiModule;
 
 /**
  * Implementation of {@link ApiMetadata} for Amazon's STS api.
  * 
  * @author Adrian Cole
  */
-public class STSApiMetadata extends BaseRestApiMetadata {
-
-   /**
-    * @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(STSApi.class)} as
-    *             {@link STSAsyncApi} interface will be removed in jclouds 1.7.
-    */
-   @Deprecated
-   public static final TypeToken<org.jclouds.rest.RestContext<STSApi, STSAsyncApi>> CONTEXT_TOKEN = new TypeToken<org.jclouds.rest.RestContext<STSApi, STSAsyncApi>>() {
-      private static final long serialVersionUID = 1L;
-   };
+public class STSApiMetadata extends BaseHttpApiMetadata<STSApi> {
 
    @Override
    public Builder toBuilder() {
-      return new Builder(getApi(), getAsyncApi()).fromApiMetadata(this);
+      return new Builder().fromApiMetadata(this);
    }
 
-   @SuppressWarnings("deprecation")
    public STSApiMetadata() {
-      this(new Builder(STSApi.class, STSAsyncApi.class));
+      this(new Builder());
    }
 
    protected STSApiMetadata(Builder builder) {
@@ -61,16 +49,15 @@
    }
 
    public static Properties defaultProperties() {
-      Properties properties = BaseRestApiMetadata.defaultProperties();
+      Properties properties = BaseHttpApiMetadata.defaultProperties();
       properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
       properties.setProperty(PROPERTY_HEADER_TAG, "amz");
       return properties;
    }
 
-   public static class Builder extends BaseRestApiMetadata.Builder<Builder> {
+   public static class Builder extends BaseHttpApiMetadata.Builder<STSApi, Builder> {
 
-      protected Builder(Class<?> api, Class<?> asyncApi) {
-         super(api, asyncApi);
+      protected Builder() {
          id("sts")
          .name("Amazon STS Api")
          .identityName("Access Key ID")
@@ -79,7 +66,7 @@
          .documentation(URI.create("http://docs.amazonwebservices.com/STS/latest/APIReference/"))
          .defaultEndpoint("https://sts.amazonaws.com")
          .defaultProperties(STSApiMetadata.defaultProperties())
-         .defaultModule(STSRestClientModule.class);
+         .defaultModule(STSHttpApiModule.class);
       }
 
       @Override
diff --git a/apis/sts/src/main/java/org/jclouds/sts/STSAsyncApi.java b/apis/sts/src/main/java/org/jclouds/sts/STSAsyncApi.java
deleted file mode 100644
index fdeed75..0000000
--- a/apis/sts/src/main/java/org/jclouds/sts/STSAsyncApi.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.sts;
-
-import java.io.Closeable;
-
-import javax.inject.Named;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.aws.domain.SessionCredentials;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.aws.xml.SessionCredentialsHandler;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-import org.jclouds.sts.domain.UserAndSessionCredentials;
-import org.jclouds.sts.options.AssumeRoleOptions;
-import org.jclouds.sts.options.FederatedUserOptions;
-import org.jclouds.sts.options.SessionCredentialsOptions;
-import org.jclouds.sts.xml.UserAndSessionCredentialsHandler;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to Amazon STS via the Query API
- * <p/>
- * 
- * @see <a href="http://docs.amazonwebservices.com/STS/latest/APIReference" />
- * @author Adrian Cole
- * @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(STSApi.class)} as
- *             {@link STSAsyncApi} interface will be removed in jclouds 1.7.
- */
-@Deprecated
-@RequestFilters(FormSigner.class)
-@VirtualHost
-public interface STSAsyncApi extends Closeable {
-
-   /**
-    * @see STSApi#createTemporaryCredentials()
-    */
-   @Named("GetSessionToken")
-   @POST
-   @Path("/")
-   @XMLResponseParser(SessionCredentialsHandler.class)
-   @FormParams(keys = "Action", values = "GetSessionToken")
-   ListenableFuture<SessionCredentials> createTemporaryCredentials();
-
-   /**
-    * @see STSApi#createTemporaryCredentials(SessionCredentialsOptions)
-    */
-   @Named("GetSessionToken")
-   @POST
-   @Path("/")
-   @XMLResponseParser(SessionCredentialsHandler.class)
-   @FormParams(keys = "Action", values = "GetSessionToken")
-   ListenableFuture<SessionCredentials> createTemporaryCredentials(SessionCredentialsOptions options);
-
-   /**
-    * @see STSApi#assumeRole(String, String)
-    */
-   @Named("AssumeRole")
-   @POST
-   @Path("/")
-   @XMLResponseParser(UserAndSessionCredentialsHandler.class)
-   @FormParams(keys = "Action", values = "AssumeRole")
-   ListenableFuture<UserAndSessionCredentials> assumeRole(@FormParam("RoleArn") String roleArn,
-         @FormParam("RoleSessionName") String sessionName);
-
-   /**
-    * @see STSApi#assumeRole(String, String, AssumeRoleOptions)
-    */
-   @Named("AssumeRole")
-   @POST
-   @Path("/")
-   @XMLResponseParser(UserAndSessionCredentialsHandler.class)
-   @FormParams(keys = "Action", values = "AssumeRole")
-   ListenableFuture<UserAndSessionCredentials> assumeRole(@FormParam("RoleArn") String roleArn,
-         @FormParam("RoleSessionName") String sessionName, AssumeRoleOptions options);
-   
-   /**
-    * @see STSApi#createFederatedUser(String)
-    */
-   @Named("GetFederationToken")
-   @POST
-   @Path("/")
-   @XMLResponseParser(UserAndSessionCredentialsHandler.class)
-   @FormParams(keys = "Action", values = "GetFederationToken")
-   ListenableFuture<UserAndSessionCredentials> createFederatedUser(@FormParam("Name") String userName);
-
-   /**
-    * @see STSApi#createFederatedUser(FederatedUserOptions)
-    */
-   @Named("GetFederationToken")
-   @POST
-   @Path("/")
-   @XMLResponseParser(UserAndSessionCredentialsHandler.class)
-   @FormParams(keys = "Action", values = "GetFederationToken")
-   ListenableFuture<UserAndSessionCredentials> createFederatedUser(@FormParam("Name") String userName, FederatedUserOptions options);
-}
diff --git a/core/src/main/java/org/jclouds/rest/ConfiguresRestContext.java b/apis/sts/src/main/java/org/jclouds/sts/config/STSHttpApiModule.java
similarity index 69%
copy from core/src/main/java/org/jclouds/rest/ConfiguresRestContext.java
copy to apis/sts/src/main/java/org/jclouds/sts/config/STSHttpApiModule.java
index 021bc4c..7ec9db4 100644
--- a/core/src/main/java/org/jclouds/rest/ConfiguresRestContext.java
+++ b/apis/sts/src/main/java/org/jclouds/sts/config/STSHttpApiModule.java
@@ -16,22 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.jclouds.rest;
+package org.jclouds.sts.config;
 
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
+import org.jclouds.aws.config.FormSigningHttpApiModule;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.sts.STSApi;
 
 /**
- * designates the module configures a Client to a cloud.
+ * Configures the STS connection.
  * 
  * @author Adrian Cole
- * 
  */
-@Retention(RUNTIME)
-@Target(TYPE)
-public @interface ConfiguresRestContext {
+@ConfiguresHttpApi
+public class STSHttpApiModule extends FormSigningHttpApiModule<STSApi> {
 
 }
diff --git a/apis/sts/src/main/java/org/jclouds/sts/config/STSRestClientModule.java b/apis/sts/src/main/java/org/jclouds/sts/config/STSRestClientModule.java
deleted file mode 100644
index b912dbd..0000000
--- a/apis/sts/src/main/java/org/jclouds/sts/config/STSRestClientModule.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.sts.config;
-
-import static org.jclouds.reflect.Reflection2.typeToken;
-
-import org.jclouds.aws.config.FormSigningRestClientModule;
-import org.jclouds.rest.ConfiguresRestClient;
-import org.jclouds.sts.STSApi;
-import org.jclouds.sts.STSAsyncApi;
-
-/**
- * Configures the STS connection.
- * 
- * @author Adrian Cole
- */
-@ConfiguresRestClient
-public class STSRestClientModule extends FormSigningRestClientModule<STSApi, STSAsyncApi> {
-
-   public STSRestClientModule() {
-      super(typeToken(STSApi.class), typeToken(STSAsyncApi.class));
-   }
-
-}
diff --git a/apis/sts/src/test/java/org/jclouds/sts/STSApiMetadataTest.java b/apis/sts/src/test/java/org/jclouds/sts/STSApiMetadataTest.java
index 98c5431..cd9c5ff 100644
--- a/apis/sts/src/test/java/org/jclouds/sts/STSApiMetadataTest.java
+++ b/apis/sts/src/test/java/org/jclouds/sts/STSApiMetadataTest.java
@@ -19,7 +19,7 @@
 package org.jclouds.sts;
 
 import org.jclouds.View;
-import org.jclouds.rest.internal.BaseRestApiMetadataTest;
+import org.jclouds.rest.internal.BaseHttpApiMetadataTest;
 import org.testng.annotations.Test;
 
 import com.google.common.collect.ImmutableSet;
@@ -30,9 +30,9 @@
  * @author Adrian Cole
  */
 @Test(groups = "unit", testName = "STSApiMetadataTest")
-public class STSApiMetadataTest extends BaseRestApiMetadataTest {
+public class STSApiMetadataTest extends BaseHttpApiMetadataTest {
 
-   // no tenant abstraction, yet
+   // no token abstraction, yet
    public STSApiMetadataTest() {
       super(new STSApiMetadata(), ImmutableSet.<TypeToken<? extends View>> of());
    }
diff --git a/apis/sts/src/test/java/org/jclouds/sts/internal/BaseSTSExpectTest.java b/apis/sts/src/test/java/org/jclouds/sts/internal/BaseSTSExpectTest.java
index b400418..288d4cb 100644
--- a/apis/sts/src/test/java/org/jclouds/sts/internal/BaseSTSExpectTest.java
+++ b/apis/sts/src/test/java/org/jclouds/sts/internal/BaseSTSExpectTest.java
@@ -19,8 +19,8 @@
 package org.jclouds.sts.internal;
 
 import org.jclouds.date.DateService;
-import org.jclouds.sts.config.STSRestClientModule;
-import org.jclouds.rest.ConfiguresRestClient;
+import org.jclouds.sts.config.STSHttpApiModule;
+import org.jclouds.rest.ConfiguresHttpApi;
 import org.jclouds.rest.internal.BaseRestApiExpectTest;
 
 import com.google.inject.Module;
@@ -35,8 +35,8 @@
       provider = "sts";
    }
    
-   @ConfiguresRestClient
-   private static final class TestSTSRestClientModule extends STSRestClientModule {
+   @ConfiguresHttpApi
+   private static final class TestSTSHttpApiModule extends STSHttpApiModule {
 
       @Override
       protected String provideTimeStamp(final DateService dateService) {
@@ -46,6 +46,6 @@
 
    @Override
    protected Module createModule() {
-      return new TestSTSRestClientModule();
+      return new TestSTSHttpApiModule();
    }
 }
diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftKeystoneApiMetadata.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftKeystoneApiMetadata.java
index f547168..8c55657 100644
--- a/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftKeystoneApiMetadata.java
+++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/SwiftKeystoneApiMetadata.java
@@ -27,6 +27,7 @@
 import org.jclouds.apis.ApiMetadata;
 import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
+import org.jclouds.openstack.keystone.v2_0.config.MappedAuthenticationApiModule;
 import org.jclouds.openstack.services.ServiceType;
 import org.jclouds.openstack.swift.blobstore.config.SwiftBlobStoreContextModule;
 import org.jclouds.openstack.swift.blobstore.config.TemporaryUrlExtensionModule.SwiftKeystoneTemporaryUrlExtensionModule;
@@ -90,6 +91,7 @@
                .context(CONTEXT_TOKEN)
                .defaultProperties(SwiftKeystoneApiMetadata.defaultProperties())
                .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                                           .add(MappedAuthenticationApiModule.class)
                                            .add(KeystoneStorageEndpointModule.class)
                                            .add(KeystoneAuthenticationModule.RegionModule.class)
                                            .add(SwiftKeystoneRestClientModule.class)
diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/TemporaryUrlExtensionModule.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/TemporaryUrlExtensionModule.java
index bcc6882..1da670c 100644
--- a/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/TemporaryUrlExtensionModule.java
+++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/TemporaryUrlExtensionModule.java
@@ -18,7 +18,7 @@
  */
 package org.jclouds.openstack.swift.blobstore.config;
 
-import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
+import static org.jclouds.rest.config.BinderUtils.bindSyncToAsyncHttpApi;
 import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
 
 import java.util.concurrent.TimeUnit;
@@ -70,7 +70,7 @@
          TemporaryUrlExtensionModule<SwiftKeystoneAsyncClient> {
 
       protected void bindTemporaryUrlKeyApi() {
-         bindHttpApi(binder(), TemporaryUrlKeyApi.class, KeystoneTemporaryUrlKeyAsyncApi.class);
+         bindSyncToAsyncHttpApi(binder(), TemporaryUrlKeyApi.class, KeystoneTemporaryUrlKeyAsyncApi.class);
       }
 
       @Override
@@ -115,7 +115,7 @@
    protected abstract void bindRequestSigner();
 
    protected void bindTemporaryUrlKeyApi() {
-      bindHttpApi(binder(), TemporaryUrlKeyApi.class, TemporaryUrlKeyAsyncApi.class);
+      bindSyncToAsyncHttpApi(binder(), TemporaryUrlKeyApi.class, TemporaryUrlKeyAsyncApi.class);
    }
 
 }
diff --git a/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/SwiftKeystoneBlobSignerExpectTest.java b/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/SwiftKeystoneBlobSignerExpectTest.java
index 59ec1c5..328d5be 100644
--- a/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/SwiftKeystoneBlobSignerExpectTest.java
+++ b/apis/swift/src/test/java/org/jclouds/openstack/swift/blobstore/SwiftKeystoneBlobSignerExpectTest.java
@@ -29,6 +29,7 @@
 import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
+import org.jclouds.openstack.keystone.v2_0.config.MappedAuthenticationApiModule;
 import org.jclouds.openstack.swift.SwiftKeystoneApiMetadata;
 import org.jclouds.openstack.swift.blobstore.config.SwiftBlobStoreContextModule;
 import org.jclouds.openstack.swift.blobstore.config.TemporaryUrlExtensionModule.SwiftKeystoneTemporaryUrlExtensionModule;
@@ -139,6 +140,7 @@
    protected ApiMetadata createApiMetadata() {
       return new SwiftKeystoneApiMetadata().toBuilder()
                                    .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                                         .add(MappedAuthenticationApiModule.class)
                                          .add(KeystoneStorageEndpointModule.class)
                                          .add(KeystoneAuthenticationModule.RegionModule.class)
                                          .add(SwiftKeystoneRestClientModule.class)
diff --git a/apis/vcloud/src/main/java/org/jclouds/vcloud/config/VCloudRestClientModule.java b/apis/vcloud/src/main/java/org/jclouds/vcloud/config/VCloudRestClientModule.java
index 6026cab..8be7904 100644
--- a/apis/vcloud/src/main/java/org/jclouds/vcloud/config/VCloudRestClientModule.java
+++ b/apis/vcloud/src/main/java/org/jclouds/vcloud/config/VCloudRestClientModule.java
@@ -28,7 +28,7 @@
 import static com.google.common.collect.Maps.transformValues;
 import static com.google.common.collect.Maps.uniqueIndex;
 import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
-import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
+import static org.jclouds.rest.config.BinderUtils.bindSyncToAsyncHttpApi;
 import static org.jclouds.util.Predicates2.retry;
 import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_DEFAULT_FENCEMODE;
 import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED;
@@ -206,8 +206,8 @@
       bind(new TypeLiteral<Function<VAppTemplate, Envelope>>() {
       }).to(new TypeLiteral<ValidateVAppTemplateAndReturnEnvelopeOrThrowIllegalArgumentException>() {
       });
-      bindHttpApi(binder(), VCloudVersionsClient.class, VCloudVersionsAsyncClient.class);
-      bindHttpApi(binder(), VCloudLoginClient.class, VCloudLoginAsyncClient.class);
+      bindSyncToAsyncHttpApi(binder(), VCloudVersionsClient.class, VCloudVersionsAsyncClient.class);
+      bindSyncToAsyncHttpApi(binder(), VCloudLoginClient.class, VCloudLoginAsyncClient.class);
    }
 
    protected void bindCacheLoaders() {
diff --git a/blobstore/src/main/java/org/jclouds/blobstore/config/TransientBlobStoreContextModule.java b/blobstore/src/main/java/org/jclouds/blobstore/config/TransientBlobStoreContextModule.java
index e04e90c..004b00d 100644
--- a/blobstore/src/main/java/org/jclouds/blobstore/config/TransientBlobStoreContextModule.java
+++ b/blobstore/src/main/java/org/jclouds/blobstore/config/TransientBlobStoreContextModule.java
@@ -18,7 +18,7 @@
  */
 package org.jclouds.blobstore.config;
 
-import static org.jclouds.rest.config.BinderUtils.bindBlockingApi;
+import static org.jclouds.rest.config.BinderUtils.bindSyncToAsyncApi;
 
 import org.jclouds.blobstore.AsyncBlobStore;
 import org.jclouds.blobstore.BlobRequestSigner;
@@ -41,7 +41,7 @@
    protected void configure() {
       bind(AsyncBlobStore.class).to(LocalAsyncBlobStore.class).asEagerSingleton();
       // forward all requests from TransientBlobStore to TransientAsyncBlobStore.  needs above binding as cannot proxy a class
-      bindBlockingApi(binder(), LocalBlobStore.class, AsyncBlobStore.class);
+      bindSyncToAsyncApi(binder(), LocalBlobStore.class, AsyncBlobStore.class);
       install(new BlobStoreObjectModule());
       install(new BlobStoreMapModule());
       bind(BlobStore.class).to(LocalBlobStore.class);
diff --git a/common/openstack/src/main/java/org/jclouds/openstack/config/OpenStackAuthenticationModule.java b/common/openstack/src/main/java/org/jclouds/openstack/config/OpenStackAuthenticationModule.java
index 6fdacfd..c714695 100644
--- a/common/openstack/src/main/java/org/jclouds/openstack/config/OpenStackAuthenticationModule.java
+++ b/common/openstack/src/main/java/org/jclouds/openstack/config/OpenStackAuthenticationModule.java
@@ -19,7 +19,7 @@
 package org.jclouds.openstack.config;
 
 import static com.google.common.base.Suppliers.memoizeWithExpiration;
-import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
+import static org.jclouds.rest.config.BinderUtils.bindSyncToAsyncHttpApi;
 
 import java.util.Date;
 import java.util.concurrent.ExecutionException;
@@ -59,7 +59,7 @@
    @Override
    protected void configure() {
       // OpenStackAuthClient is used directly for filters and retry handlers, so let's bind it explicitly
-      bindHttpApi(binder(), OpenStackAuthClient.class, OpenStackAuthAsyncClient.class);
+      bindSyncToAsyncHttpApi(binder(), OpenStackAuthClient.class, OpenStackAuthAsyncClient.class);
       install(new FactoryModuleBuilder().build(URIFromAuthenticationResponseForService.Factory.class));
       bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class);
    }
diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/config/AuthenticationServiceModule.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/config/AuthenticationServiceModule.java
index a7fabd7..285513d 100644
--- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/config/AuthenticationServiceModule.java
+++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/config/AuthenticationServiceModule.java
@@ -18,7 +18,7 @@
  */
 package org.jclouds.openstack.keystone.v1_1.config;
 
-import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
+import static org.jclouds.rest.config.BinderUtils.bindSyncToAsyncHttpApi;
 import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
 
 import java.util.concurrent.ExecutionException;
@@ -60,7 +60,7 @@
    @Override
    protected void configure() {
       // ServiceClient is used directly for filters and retry handlers, so let's bind it explicitly
-      bindHttpApi(binder(), AuthenticationClient.class, AuthenticationAsyncClient.class);
+      bindSyncToAsyncHttpApi(binder(), AuthenticationClient.class, AuthenticationAsyncClient.class);
       install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
                RegionIdToURIFromAuthForServiceSupplier.class).build(RegionIdToURISupplier.Factory.class));
       install(new FactoryModuleBuilder().implement(ImplicitRegionIdSupplier.class, V1DefaultRegionIdSupplier.class)
diff --git a/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/config/TerremarkVCloudRestClientModule.java b/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/config/TerremarkVCloudRestClientModule.java
index 2042f71..8227459 100644
--- a/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/config/TerremarkVCloudRestClientModule.java
+++ b/common/trmk/src/main/java/org/jclouds/trmk/vcloud_0_8/config/TerremarkVCloudRestClientModule.java
@@ -26,7 +26,7 @@
 import static com.google.common.collect.Maps.transformValues;
 import static com.google.common.collect.Maps.uniqueIndex;
 import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
-import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
+import static org.jclouds.rest.config.BinderUtils.bindSyncToAsyncHttpApi;
 import static org.jclouds.trmk.vcloud_0_8.reference.VCloudConstants.PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED;
 import static org.jclouds.util.Predicates2.retry;
 
@@ -134,8 +134,8 @@
       bind(new TypeLiteral<Function<org.jclouds.trmk.vcloud_0_8.domain.Org, Iterable<? extends CatalogItem>>>() {
       }).to(new TypeLiteral<AllCatalogItemsInOrg>() {
       });
-      bindHttpApi(binder(), TerremarkVCloudVersionsClient.class, TerremarkVCloudVersionsAsyncClient.class);
-      bindHttpApi(binder(), TerremarkVCloudLoginClient.class, TerremarkVCloudLoginAsyncClient.class);
+      bindSyncToAsyncHttpApi(binder(), TerremarkVCloudVersionsClient.class, TerremarkVCloudVersionsAsyncClient.class);
+      bindSyncToAsyncHttpApi(binder(), TerremarkVCloudLoginClient.class, TerremarkVCloudLoginAsyncClient.class);
    }
 
    @Provides
diff --git a/compute/src/main/java/org/jclouds/compute/internal/UtilsImpl.java b/compute/src/main/java/org/jclouds/compute/internal/UtilsImpl.java
index 9e1f00b..1f6b966 100644
--- a/compute/src/main/java/org/jclouds/compute/internal/UtilsImpl.java
+++ b/compute/src/main/java/org/jclouds/compute/internal/UtilsImpl.java
@@ -31,7 +31,6 @@
 import org.jclouds.domain.Credentials;
 import org.jclouds.json.Json;
 import org.jclouds.logging.Logger.LoggerFactory;
-import org.jclouds.rest.HttpAsyncClient;
 import org.jclouds.rest.HttpClient;
 import org.jclouds.ssh.SshClient;
 import org.jclouds.ssh.SshClient.Factory;
@@ -54,11 +53,12 @@
    private final Function<NodeMetadata, SshClient> sshForNode;
 
    @Inject
-   UtilsImpl(Injector injector, Json json, XMLParser xml, HttpClient simpleClient, HttpAsyncClient simpleAsyncClient,
-            Crypto encryption, DateService date, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
-            @Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor, EventBus eventBus,
-            Map<String, Credentials> credentialStore, LoggerFactory loggerFactory,
-            Function<NodeMetadata, SshClient> sshForNode) {
+   UtilsImpl(Injector injector, Json json, XMLParser xml, HttpClient simpleClient,
+         org.jclouds.rest.HttpAsyncClient simpleAsyncClient, Crypto encryption, DateService date,
+         @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
+         @Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor, EventBus eventBus,
+         Map<String, Credentials> credentialStore, LoggerFactory loggerFactory,
+         Function<NodeMetadata, SshClient> sshForNode) {
       super(injector, json, xml, simpleClient, simpleAsyncClient, encryption, date, userExecutor, ioExecutor, eventBus,
             credentialStore, loggerFactory);
       this.sshForNode = sshForNode;
diff --git a/core/src/main/java/org/jclouds/ContextBuilder.java b/core/src/main/java/org/jclouds/ContextBuilder.java
index ccdf4eb..6bd2679 100644
--- a/core/src/main/java/org/jclouds/ContextBuilder.java
+++ b/core/src/main/java/org/jclouds/ContextBuilder.java
@@ -20,10 +20,12 @@
 
 import static com.google.common.base.Objects.toStringHelper;
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Predicates.and;
 import static com.google.common.base.Predicates.containsPattern;
 import static com.google.common.base.Predicates.instanceOf;
 import static com.google.common.base.Predicates.not;
 import static com.google.common.base.Predicates.notNull;
+import static com.google.common.base.Predicates.or;
 import static com.google.common.base.Throwables.propagate;
 import static com.google.common.collect.Iterables.addAll;
 import static com.google.common.collect.Iterables.any;
@@ -57,6 +59,7 @@
 import org.jclouds.concurrent.SingleThreaded;
 import org.jclouds.concurrent.config.ConfiguresExecutorService;
 import org.jclouds.concurrent.config.ExecutorServiceModule;
+import org.jclouds.config.BindApiContextWithWildcardExtendsExplicitAndRawType;
 import org.jclouds.config.BindNameToContext;
 import org.jclouds.config.BindPropertiesToExpandedValues;
 import org.jclouds.config.BindRestContextWithWildcardExtendsExplicitAndRawType;
@@ -75,9 +78,14 @@
 import org.jclouds.providers.config.BindProviderMetadataContextAndCredentials;
 import org.jclouds.providers.internal.UpdateProviderMetadataFromProperties;
 import org.jclouds.rest.ConfiguresCredentialStore;
+import org.jclouds.rest.ConfiguresHttpApi;
 import org.jclouds.rest.ConfiguresRestClient;
+import org.jclouds.rest.HttpApiMetadata;
 import org.jclouds.rest.RestApiMetadata;
+import org.jclouds.rest.RestContext;
 import org.jclouds.rest.config.CredentialStoreModule;
+import org.jclouds.rest.config.HttpApiModule;
+import org.jclouds.rest.config.SyncToAsyncHttpInvocationModule;
 import org.jclouds.rest.config.RestClientModule;
 import org.jclouds.rest.config.RestModule;
 
@@ -382,9 +390,9 @@
    public static Injector buildInjector(String name, ProviderMetadata providerMetadata, Supplier<Credentials> creds, List<Module> inputModules) {
       List<Module> modules = newArrayList();
       modules.addAll(inputModules);
-      boolean restModuleSpecifiedByUser = restClientModulePresent(inputModules);
-      Iterable<Module> defaultModules = ifSpecifiedByUserDontIncludeDefaultRestModule(
-               providerMetadata.getApiMetadata(), restModuleSpecifiedByUser);
+      boolean apiModuleSpecifiedByUser = apiModulePresent(inputModules);
+      Iterable<Module> defaultModules = ifSpecifiedByUserDontIncludeDefaultApiModule(
+               providerMetadata.getApiMetadata(), apiModuleSpecifiedByUser);
       addAll(modules, defaultModules);
       addClientModuleIfNotPresent(providerMetadata.getApiMetadata(), modules);
       addRestContextBinding(providerMetadata.getApiMetadata(), modules);
@@ -415,17 +423,24 @@
    }
 
    static void addRestContextBinding(ApiMetadata apiMetadata, List<Module> modules) {
-      if (apiMetadata instanceof RestApiMetadata) {
+      if (apiMetadata instanceof HttpApiMetadata) {
+         try {
+            modules
+                  .add(new BindApiContextWithWildcardExtendsExplicitAndRawType(HttpApiMetadata.class.cast(apiMetadata)));
+         } catch (IllegalArgumentException ignored) {
+
+         }
+      } else if (apiMetadata instanceof RestApiMetadata) {
          try {
             modules.add(new BindRestContextWithWildcardExtendsExplicitAndRawType(RestApiMetadata.class
-                     .cast(apiMetadata)));
-         } catch (IllegalArgumentException e) {
+                  .cast(apiMetadata)));
+         } catch (IllegalArgumentException ignored) {
 
          }
       }
    }
 
-   static Iterable<Module> ifSpecifiedByUserDontIncludeDefaultRestModule(ApiMetadata apiMetadata,
+   static Iterable<Module> ifSpecifiedByUserDontIncludeDefaultApiModule(ApiMetadata apiMetadata,
             boolean restModuleSpecifiedByUser) {
       Iterable<Module> defaultModules = transform(apiMetadata.getDefaultModules(),
                new Function<Class<? extends Module>, Module>() {
@@ -443,7 +458,7 @@
 
                });
       if (restModuleSpecifiedByUser)
-         defaultModules = filter(defaultModules, not(configuresRest));
+         defaultModules = filter(defaultModules, and(not(configuresApi), not(configuresRest)));
       return defaultModules;
    }
 
@@ -476,30 +491,40 @@
 
    @VisibleForTesting
    static void addClientModuleIfNotPresent(ApiMetadata apiMetadata, List<Module> modules) {
-      if (!restClientModulePresent(modules)) {
+      if (!apiModulePresent(modules)) {
          addClientModule(apiMetadata, modules);
       }
    }
+   private static boolean apiModulePresent(List<Module> modules) {
+      return any(modules, or(configuresApi, configuresRest));
+   }
 
-   static Predicate<Module> configuresRest = new Predicate<Module>() {
+   private static Predicate<Module> configuresApi = new Predicate<Module>() {
+      public boolean apply(Module input) {
+         return input.getClass().isAnnotationPresent(ConfiguresHttpApi.class);
+      }
+
+   };
+
+   private static Predicate<Module> configuresRest = new Predicate<Module>() {
       public boolean apply(Module input) {
          return input.getClass().isAnnotationPresent(ConfiguresRestClient.class);
       }
 
    };
 
-   static boolean restClientModulePresent(List<Module> modules) {
-      return any(modules, configuresRest);
-   }
-
    @SuppressWarnings({ "unchecked", "rawtypes" })
    static void addClientModule(ApiMetadata apiMetadata, List<Module> modules) {
       // TODO: move this up
-      if (apiMetadata instanceof RestApiMetadata) {
+      if (apiMetadata instanceof HttpApiMetadata) {
+         HttpApiMetadata api = HttpApiMetadata.class.cast(apiMetadata);
+         modules.add(new HttpApiModule(api.getApi()));
+      } else if (apiMetadata instanceof RestApiMetadata) {
          RestApiMetadata rest = RestApiMetadata.class.cast(apiMetadata);
          modules.add(new RestClientModule(typeToken(rest.getApi()), typeToken(rest.getAsyncApi())));
       } else {
          modules.add(new RestModule());
+         modules.add(new SyncToAsyncHttpInvocationModule());
       }
    }
 
diff --git a/core/src/main/java/org/jclouds/config/BindApiContextWithWildcardExtendsExplicitAndRawType.java b/core/src/main/java/org/jclouds/config/BindApiContextWithWildcardExtendsExplicitAndRawType.java
new file mode 100644
index 0000000..b4f641c
--- /dev/null
+++ b/core/src/main/java/org/jclouds/config/BindApiContextWithWildcardExtendsExplicitAndRawType.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.config;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.reflect.Reflection2.typeToken;
+
+import org.jclouds.rest.ApiContext;
+import org.jclouds.rest.HttpApiMetadata;
+import org.jclouds.rest.internal.ApiContextImpl;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
+
+import com.google.common.reflect.TypeToken;
+import com.google.inject.AbstractModule;
+import com.google.inject.TypeLiteral;
+import com.google.inject.util.Types;
+
+/**
+ * Allows you to lookup the {@link HttpApiMetadata#getContext()} as
+ * {@link ApiContext}, {@code ApiContext<Api>}, and {@code ApiContext<?>}.
+ * 
+ * @author Adrian Cole
+ */
+public class BindApiContextWithWildcardExtendsExplicitAndRawType extends AbstractModule {
+   private final HttpApiMetadata<?> httpApiMetadata;
+
+   public BindApiContextWithWildcardExtendsExplicitAndRawType(HttpApiMetadata<?> httpApiMetadata)
+         throws IllegalArgumentException {
+      this.httpApiMetadata = checkNotNull(httpApiMetadata, "httpApiMetadata");
+      checkArgument(httpApiMetadata.getContext().getRawType().equals(ApiContext.class),
+            "this does not work as %s raw type is not ApiContext", httpApiMetadata.getContext());
+   }
+
+   @SuppressWarnings("unchecked")
+   @Override
+   protected void configure() {
+      TypeToken<?> concreteType = BaseHttpApiMetadata.contextToken(typeToken(httpApiMetadata.getApi()));
+      // bind explicit type
+      bind(TypeLiteral.get(concreteType.getType())).to(
+            TypeLiteral.class.cast(TypeLiteral.get(Types.newParameterizedType(ApiContextImpl.class,
+                  httpApiMetadata.getApi()))));
+      // bind potentially wildcard type
+      if (!concreteType.equals(httpApiMetadata.getContext())) {
+         bind(TypeLiteral.get(httpApiMetadata.getContext().getType())).to(
+               TypeLiteral.class.cast(TypeLiteral.get(Types.newParameterizedType(ApiContextImpl.class,
+                     httpApiMetadata.getApi()))));
+      }
+      // bind w/o types
+      bind(TypeLiteral.get(ApiContext.class)).to(
+            TypeLiteral.class.cast(TypeLiteral.get(Types.newParameterizedType(ApiContextImpl.class,
+                  httpApiMetadata.getApi()))));
+   }
+}
diff --git a/core/src/main/java/org/jclouds/config/BindRestContextWithWildcardExtendsExplicitAndRawType.java b/core/src/main/java/org/jclouds/config/BindRestContextWithWildcardExtendsExplicitAndRawType.java
index d14c554..e47d718 100644
--- a/core/src/main/java/org/jclouds/config/BindRestContextWithWildcardExtendsExplicitAndRawType.java
+++ b/core/src/main/java/org/jclouds/config/BindRestContextWithWildcardExtendsExplicitAndRawType.java
@@ -35,7 +35,10 @@
  * Allows you to lookup the {@link RestApiMetadata#getContext()} as {@link RestContext}, {@code RestContext<Client, AsyncClient>}, and {@code
  *  
  * @author Adrian Cole
+ * @deprecated please use {@link BindApiContextWithWildcardExtendsExplicitAndRawType} as
+ *             async interface will be removed in jclouds 1.7.
  */
+@Deprecated
 public class BindRestContextWithWildcardExtendsExplicitAndRawType extends AbstractModule {
    private final RestApiMetadata restApiMetadata;
 
diff --git a/core/src/main/java/org/jclouds/providers/AnonymousProviderMetadata.java b/core/src/main/java/org/jclouds/providers/AnonymousProviderMetadata.java
index 5bbdeee..ccede4c 100644
--- a/core/src/main/java/org/jclouds/providers/AnonymousProviderMetadata.java
+++ b/core/src/main/java/org/jclouds/providers/AnonymousProviderMetadata.java
@@ -22,6 +22,7 @@
 
 import org.jclouds.apis.ApiMetadata;
 import org.jclouds.providers.internal.BaseProviderMetadata;
+import org.jclouds.rest.AnonymousHttpApiMetadata;
 import org.jclouds.rest.AnonymousRestApiMetadata;
 
 /**
@@ -31,11 +32,14 @@
  */
 public class AnonymousProviderMetadata extends BaseProviderMetadata {
 
+   public static <A> ProviderMetadata forApiOnEndpoint(Class<A> api, String endpoint) {
+      return forApiWithEndpoint(AnonymousHttpApiMetadata.forApi(api), endpoint);
+   }
+
    public static ProviderMetadata forClientMappedToAsyncClientOnEndpoint(Class<?> client, Class<?> asyncClient,
             String endpoint) {
       return forApiWithEndpoint(AnonymousRestApiMetadata.forClientMappedToAsyncClient(client, asyncClient), endpoint);
    }
-
    public static ProviderMetadata forApiWithEndpoint(ApiMetadata md, String endpoint) {
       checkNotNull(md, "api");
       checkNotNull(endpoint, "endpoint (%s)", md.getEndpointName());
diff --git a/core/src/main/java/org/jclouds/reflect/Types2.java b/core/src/main/java/org/jclouds/reflect/Types2.java
new file mode 100644
index 0000000..c900d3d
--- /dev/null
+++ b/core/src/main/java/org/jclouds/reflect/Types2.java
@@ -0,0 +1,45 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.reflect;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import java.lang.reflect.TypeVariable;
+
+import com.google.common.annotations.Beta;
+import com.google.common.reflect.TypeToken;
+
+/**
+ * @since 1.7
+ */
+@Beta
+public class Types2 {
+
+   /**
+    * Helpful when you are capturing the type inside a constructor.
+    * 
+    * @throws IllegalStateException
+    *            if the type is an instanceof {@link TypeVariable}
+    */
+   public static <T> TypeToken<T> checkBound(TypeToken<T> type) throws IllegalStateException {
+      checkState(!(type.getType() instanceof TypeVariable<?>),
+            "unbound type variable: %s, use ctor that explicitly assigns this", type);
+      return type;
+   }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/jclouds/rest/AnonymousHttpApiMetadata.java b/core/src/main/java/org/jclouds/rest/AnonymousHttpApiMetadata.java
new file mode 100644
index 0000000..b5335ca
--- /dev/null
+++ b/core/src/main/java/org/jclouds/rest/AnonymousHttpApiMetadata.java
@@ -0,0 +1,69 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rest;
+
+import java.net.URI;
+
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Useful in creating arbitrary http apis.
+ * 
+ * @author Adrian Cole
+ */
+@Beta
+public class AnonymousHttpApiMetadata<A> extends BaseHttpApiMetadata<A> {
+
+   public static <A> AnonymousHttpApiMetadata<A> forApi(Class<A> httpApi) {
+      return new Builder<A>(httpApi).build();
+   }
+
+   @Override
+   public Builder<A> toBuilder() {
+      return new Builder<A>(getApi()).fromApiMetadata(this);
+   }
+
+   private AnonymousHttpApiMetadata(Builder<A> builder) {
+      super(builder);
+   }
+
+   private static final class Builder<A> extends BaseHttpApiMetadata.Builder<A, Builder<A>> {
+
+      private Builder(Class<A> api) {
+         super(api);
+         id(api.getSimpleName())
+         .identityName("unused")
+         .defaultIdentity("foo")
+         .version("1")
+         .documentation(URI.create("http://jclouds.org/documentation"));
+      }
+
+      @Override
+      public AnonymousHttpApiMetadata<A> build() {
+         return new AnonymousHttpApiMetadata<A>(this);
+      }
+
+      @Override
+      protected Builder<A> self() {
+         return this;
+      }
+   }
+}
diff --git a/core/src/main/java/org/jclouds/rest/AnonymousRestApiMetadata.java b/core/src/main/java/org/jclouds/rest/AnonymousRestApiMetadata.java
index 8eecd36..b5d10b4 100644
--- a/core/src/main/java/org/jclouds/rest/AnonymousRestApiMetadata.java
+++ b/core/src/main/java/org/jclouds/rest/AnonymousRestApiMetadata.java
@@ -20,6 +20,7 @@
 
 import java.net.URI;
 
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
 import org.jclouds.rest.internal.BaseRestApiMetadata;
 
 import com.google.common.annotations.Beta;
@@ -28,6 +29,8 @@
  * Useful in creating arbitrary clients.
  * 
  * @author Adrian Cole
+ * @deprecated please use {@link AnonymousHttpApiMetadata} as
+ *             async interface will be removed in jclouds 1.7.
  */
 @Beta
 public class AnonymousRestApiMetadata extends BaseRestApiMetadata {
diff --git a/core/src/main/java/org/jclouds/rest/ConfiguresRestContext.java b/core/src/main/java/org/jclouds/rest/ApiContext.java
similarity index 60%
copy from core/src/main/java/org/jclouds/rest/ConfiguresRestContext.java
copy to core/src/main/java/org/jclouds/rest/ApiContext.java
index 021bc4c..8aac086 100644
--- a/core/src/main/java/org/jclouds/rest/ConfiguresRestContext.java
+++ b/core/src/main/java/org/jclouds/rest/ApiContext.java
@@ -18,20 +18,28 @@
  */
 package org.jclouds.rest;
 
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import org.jclouds.Context;
+import org.jclouds.rest.internal.ApiContextImpl;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
+import com.google.inject.ImplementedBy;
 
 /**
- * designates the module configures a Client to a cloud.
+ * Represents an authenticated context to the cloud.
+ * 
+ * <h2>Note</h2> Please issue {@link #close()} when you are finished with this context in order to
+ * release resources.
+ * 
  * 
  * @author Adrian Cole
- * 
  */
-@Retention(RUNTIME)
-@Target(TYPE)
-public @interface ConfiguresRestContext {
+@ImplementedBy(ApiContextImpl.class)
+public interface ApiContext<A> extends Context {
 
+
+   /**
+    * low-level api to the cloud. Threadsafe implementations will return a singleton.
+    * 
+    * @return a connection to the cloud where all methods block
+    */
+   A getApi();
 }
diff --git a/core/src/main/java/org/jclouds/rest/ConfiguresRestContext.java b/core/src/main/java/org/jclouds/rest/ConfiguresHttpApi.java
similarity index 89%
rename from core/src/main/java/org/jclouds/rest/ConfiguresRestContext.java
rename to core/src/main/java/org/jclouds/rest/ConfiguresHttpApi.java
index 021bc4c..1d39d79 100644
--- a/core/src/main/java/org/jclouds/rest/ConfiguresRestContext.java
+++ b/core/src/main/java/org/jclouds/rest/ConfiguresHttpApi.java
@@ -25,13 +25,13 @@
 import java.lang.annotation.Target;
 
 /**
- * designates the module configures a Client to a cloud.
+ * designates the module configures a top-level api which is annotated with http methods.
  * 
  * @author Adrian Cole
  * 
  */
 @Retention(RUNTIME)
 @Target(TYPE)
-public @interface ConfiguresRestContext {
+public @interface ConfiguresHttpApi {
 
 }
diff --git a/core/src/main/java/org/jclouds/rest/ConfiguresRestContext.java b/core/src/main/java/org/jclouds/rest/HttpApiMetadata.java
similarity index 63%
copy from core/src/main/java/org/jclouds/rest/ConfiguresRestContext.java
copy to core/src/main/java/org/jclouds/rest/HttpApiMetadata.java
index 021bc4c..69e31fa 100644
--- a/core/src/main/java/org/jclouds/rest/ConfiguresRestContext.java
+++ b/core/src/main/java/org/jclouds/rest/HttpApiMetadata.java
@@ -18,20 +18,30 @@
  */
 package org.jclouds.rest;
 
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import org.jclouds.apis.ApiMetadata;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
+import com.google.common.annotations.Beta;
 
 /**
- * designates the module configures a Client to a cloud.
  * 
  * @author Adrian Cole
- * 
+ * @since 1.6
+ * @see ConfiguresHttpApi
  */
-@Retention(RUNTIME)
-@Target(TYPE)
-public @interface ConfiguresRestContext {
+@Beta
+public interface HttpApiMetadata<A> extends ApiMetadata {
 
+   public static interface Builder<A, T extends Builder<A, T>> extends ApiMetadata.Builder<T> {
+
+      /**
+       * @see ApiMetadata#getApi()
+       */
+      T api(Class<A> api);
+   }
+
+   /**
+    * 
+    * @return the type of the java api which has http annotations on its methods.
+    */
+   Class<A> getApi();
 }
diff --git a/core/src/main/java/org/jclouds/rest/HttpAsyncClient.java b/core/src/main/java/org/jclouds/rest/HttpAsyncClient.java
index 49c3326..7cce631 100644
--- a/core/src/main/java/org/jclouds/rest/HttpAsyncClient.java
+++ b/core/src/main/java/org/jclouds/rest/HttpAsyncClient.java
@@ -43,7 +43,10 @@
  * Simple rest client
  * 
  * @author Adrian Cole
+ * @deprecated will be removed in jclouds 1.7, as async interfaces are no longer
+ *             supported.
  */
+@Deprecated
 public interface HttpAsyncClient {
    /**
     * @see HttpClient#post
diff --git a/core/src/main/java/org/jclouds/rest/HttpClient.java b/core/src/main/java/org/jclouds/rest/HttpClient.java
index ab9eca1..7e6a720a 100644
--- a/core/src/main/java/org/jclouds/rest/HttpClient.java
+++ b/core/src/main/java/org/jclouds/rest/HttpClient.java
@@ -21,9 +21,21 @@
 import java.io.InputStream;
 import java.net.URI;
 
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HEAD;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseETagHeader;
 import org.jclouds.io.Payload;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.ResponseParser;
 
 /**
  * Simple client
@@ -32,6 +44,34 @@
  */
 public interface HttpClient {
    /**
+    * @return eTag
+    */
+   @PUT
+   @ResponseParser(ParseETagHeader.class)
+   String put(@EndpointParam URI location, Payload payload);
+
+   /**
+    * @return eTag
+    */
+   @POST
+   @ResponseParser(ParseETagHeader.class)
+   String post(@EndpointParam URI location, Payload payload);
+
+   /**
+    * @see HttpClient#exists
+    */
+   @HEAD
+   @Fallback(FalseOnNotFoundOr404.class)
+   boolean exists(@EndpointParam URI location);
+
+   /**
+    * @return null if the resource didn't exist.
+    */
+   @GET
+   @Fallback(NullOnNotFoundOr404.class)
+   InputStream get(@EndpointParam URI location);
+
+   /**
     * 
     * @param request
     * @return response, but make sure you consume its content.
@@ -39,24 +79,10 @@
    HttpResponse invoke(HttpRequest request);
 
    /**
-    * @return eTag
-    */
-   String put(URI location, Payload payload);
-
-   /**
-    * @return eTag
-    */
-   String post(URI location, Payload payload);
-
-   boolean exists(URI location);
-
-   /**
-    * @return null if the resource didn't exist.
-    */
-   InputStream get(URI location);
-
-   /**
     * @return false if the resource didn't exist.
     */
-   boolean delete(URI location);
+   @DELETE
+   @Fallback(FalseOnNotFoundOr404.class)
+   boolean delete(@EndpointParam URI location);
+
 }
diff --git a/core/src/main/java/org/jclouds/rest/RestApiMetadata.java b/core/src/main/java/org/jclouds/rest/RestApiMetadata.java
index 7798cd1..7acb056 100644
--- a/core/src/main/java/org/jclouds/rest/RestApiMetadata.java
+++ b/core/src/main/java/org/jclouds/rest/RestApiMetadata.java
@@ -21,12 +21,17 @@
 import org.jclouds.apis.ApiMetadata;
 
 import com.google.common.annotations.Beta;
+import com.google.common.util.concurrent.ListenableFuture;
 
 /**
  * 
  * @author Adrian Cole
  * @since 1.5
+ * 
+ * @deprecated please use {@link HttpApiMetadata} as
+ *             async interface will be removed in jclouds 1.7.
  */
+@Deprecated
 @Beta
 public interface RestApiMetadata extends ApiMetadata {
 
diff --git a/core/src/main/java/org/jclouds/rest/Utils.java b/core/src/main/java/org/jclouds/rest/Utils.java
index c5bf450..44695ac 100644
--- a/core/src/main/java/org/jclouds/rest/Utils.java
+++ b/core/src/main/java/org/jclouds/rest/Utils.java
@@ -75,11 +75,22 @@
     */
    Json json();
 
+   /**
+    * 
+    * @deprecated will be removed in jclouds 1.7, as async interfaces are no
+    *             longer supported.
+    * @see #getHttpClient()
+    */
+   @Deprecated
    HttpAsyncClient getHttpAsyncClient();
 
    /**
-    * #see #getHttpAsyncClient
+    * 
+    * @deprecated will be removed in jclouds 1.7, as async interfaces are no
+    *             longer supported.
+    * @see #http()
     */
+   @Deprecated
    HttpAsyncClient asyncHttp();
 
    HttpClient getHttpClient();
diff --git a/core/src/main/java/org/jclouds/rest/config/AsyncHttpApiProvider.java b/core/src/main/java/org/jclouds/rest/config/AnnotatedHttpApiProvider.java
similarity index 74%
rename from core/src/main/java/org/jclouds/rest/config/AsyncHttpApiProvider.java
rename to core/src/main/java/org/jclouds/rest/config/AnnotatedHttpApiProvider.java
index 2765f27..40ec61c 100644
--- a/core/src/main/java/org/jclouds/rest/config/AsyncHttpApiProvider.java
+++ b/core/src/main/java/org/jclouds/rest/config/AnnotatedHttpApiProvider.java
@@ -28,27 +28,26 @@
 
 import com.google.common.base.Function;
 import com.google.inject.Provider;
-import com.google.inject.TypeLiteral;
 
 /**
  * 
  * @author Adrian Cole
  */
 @Singleton
-public class AsyncHttpApiProvider<A> implements Provider<A> {
-   private final Class<? super A> asyncApiType;
+public class AnnotatedHttpApiProvider<A> implements Provider<A> {
+   private final Class<A> annotatedApiType;
    private final DelegatesToInvocationFunction<A, Function<Invocation, Object>> httpInvoker;
 
    @Inject
-   private AsyncHttpApiProvider(DelegatesToInvocationFunction<A, Function<Invocation, Object>> httpInvoker,
-         TypeLiteral<A> asyncApiType) {
+   private AnnotatedHttpApiProvider(DelegatesToInvocationFunction<A, Function<Invocation, Object>> httpInvoker,
+         Class<A> annotatedApiType) {
       this.httpInvoker = httpInvoker;
-      this.asyncApiType = asyncApiType.getRawType();
+      this.annotatedApiType = annotatedApiType;
    }
 
    @SuppressWarnings("unchecked")
    @Override
    public A get() {
-      return (A) Proxy.newProxyInstance(asyncApiType.getClassLoader(), new Class<?>[] { asyncApiType }, httpInvoker);
+      return (A) Proxy.newProxyInstance(annotatedApiType.getClassLoader(), new Class<?>[] { annotatedApiType }, httpInvoker);
    }
 }
diff --git a/core/src/main/java/org/jclouds/rest/config/AsyncHttpApiProvider.java b/core/src/main/java/org/jclouds/rest/config/AnnotatedSyncToAsyncHttpApiProvider.java
similarity index 60%
copy from core/src/main/java/org/jclouds/rest/config/AsyncHttpApiProvider.java
copy to core/src/main/java/org/jclouds/rest/config/AnnotatedSyncToAsyncHttpApiProvider.java
index 2765f27..0dfb6f6 100644
--- a/core/src/main/java/org/jclouds/rest/config/AsyncHttpApiProvider.java
+++ b/core/src/main/java/org/jclouds/rest/config/AnnotatedSyncToAsyncHttpApiProvider.java
@@ -25,6 +25,7 @@
 
 import org.jclouds.reflect.Invocation;
 import org.jclouds.rest.internal.DelegatesToInvocationFunction;
+import org.jclouds.rest.internal.DelegatesToPotentiallySyncToAsyncInvocationFunction;
 
 import com.google.common.base.Function;
 import com.google.inject.Provider;
@@ -33,22 +34,27 @@
 /**
  * 
  * @author Adrian Cole
+ * @deprecated please use {@link DelegatesToInvocationFunction} as async
+ *             interface will be removed in jclouds 1.7.
  */
+@Deprecated
 @Singleton
-public class AsyncHttpApiProvider<A> implements Provider<A> {
-   private final Class<? super A> asyncApiType;
-   private final DelegatesToInvocationFunction<A, Function<Invocation, Object>> httpInvoker;
+public class AnnotatedSyncToAsyncHttpApiProvider<A> implements Provider<A> {
+   private final Class<? super A> annotatedApiType;
+   private final DelegatesToPotentiallySyncToAsyncInvocationFunction<A, Function<Invocation, Object>> httpInvoker;
 
    @Inject
-   private AsyncHttpApiProvider(DelegatesToInvocationFunction<A, Function<Invocation, Object>> httpInvoker,
-         TypeLiteral<A> asyncApiType) {
+   private AnnotatedSyncToAsyncHttpApiProvider(
+         DelegatesToPotentiallySyncToAsyncInvocationFunction<A, Function<Invocation, Object>> httpInvoker,
+         TypeLiteral<A> annotatedApiType) {
       this.httpInvoker = httpInvoker;
-      this.asyncApiType = asyncApiType.getRawType();
+      this.annotatedApiType = annotatedApiType.getRawType();
    }
 
    @SuppressWarnings("unchecked")
    @Override
    public A get() {
-      return (A) Proxy.newProxyInstance(asyncApiType.getClassLoader(), new Class<?>[] { asyncApiType }, httpInvoker);
+      return (A) Proxy.newProxyInstance(annotatedApiType.getClassLoader(), new Class<?>[] { annotatedApiType },
+            httpInvoker);
    }
 }
diff --git a/core/src/main/java/org/jclouds/rest/config/BinderUtils.java b/core/src/main/java/org/jclouds/rest/config/BinderUtils.java
index 4cf560c..7ef6f6d 100644
--- a/core/src/main/java/org/jclouds/rest/config/BinderUtils.java
+++ b/core/src/main/java/org/jclouds/rest/config/BinderUtils.java
@@ -31,7 +31,32 @@
 public class BinderUtils {
 
    /**
-    * adds an explicit binding for {@code async} by parsing its annotations. Then. adds an explicit binding for an
+    * adds an explicit binding for {@code async} by parsing its annotations.
+    * 
+    * @param <S>
+    *           sync interface that blocks
+    * @param <A>
+    *           api type with http annotations
+    * @param binder
+    *           guice binder
+    * @param api
+    *           type with http annotations
+    */
+   public static <S, A> void bindHttpApi(Binder binder, Class<A> api) {
+      bindClass(binder, api);
+      bindAnnotatedHttpApiProvider(binder, api);
+   }
+   
+   @SuppressWarnings({ "unchecked", "serial" })
+   private static <T> void bindAnnotatedHttpApiProvider(Binder binder, Class<T> annotated) {
+      TypeToken<AnnotatedHttpApiProvider<T>> token = new TypeToken<AnnotatedHttpApiProvider<T>>() {
+      }.where(new TypeParameter<T>() {
+      }, annotated);
+      binder.bind(annotated).toProvider(TypeLiteral.class.cast(TypeLiteral.get(token.getType())));
+   }
+
+   /**
+    * adds an explicit binding for {@code async} by parsing its annotations. Then, adds an explicit binding for an
     * interface which synchronously blocks on similar calls to an {@code async} type.
     * 
     * @param <S>
@@ -44,66 +69,89 @@
     *           type interface that blocks
     * @param async
     *           type type that returns {@link ListenableFuture}
+    * 
+    * @deprecated will be removed in jclouds 1.7, as async interfaces are no
+    *             longer supported.
     */
-   public static <S, A> void bindHttpApi(Binder binder, Class<S> sync, Class<A> async) {
+   @Deprecated
+   public static <S, A> void bindSyncToAsyncHttpApi(Binder binder, Class<S> sync, Class<A> async) {
       bindClass(binder, sync);
       bindClass(binder, async);
-      bindAsyncHttpApiProvider(binder, async);
+      bindAnnotatedSyncToAsyncHttpApiProvider(binder, async);
       bindHttpApiProvider(binder, sync, async);
    }
-   
-   @SuppressWarnings("unchecked")
-   private static <T> void bindAsyncHttpApiProvider(Binder binder, Class<T> async) {
-      TypeToken<AsyncHttpApiProvider<T>> token = new TypeToken<AsyncHttpApiProvider<T>>() {
-         private static final long serialVersionUID = 1L;
+
+   /**
+    * @deprecated will be removed in jclouds 1.7, as async interfaces are no
+    *             longer supported.
+    */
+   @Deprecated
+   @SuppressWarnings({ "unchecked", "serial" })
+   private static <T> void bindAnnotatedSyncToAsyncHttpApiProvider(Binder binder, Class<T> annotated) {
+      TypeToken<AnnotatedSyncToAsyncHttpApiProvider<T>> token = new TypeToken<AnnotatedSyncToAsyncHttpApiProvider<T>>() {
       }.where(new TypeParameter<T>() {
-      }, async);
-      binder.bind(async).toProvider(TypeLiteral.class.cast(TypeLiteral.get(token.getType())));
+      }, annotated);
+      binder.bind(annotated).toProvider(TypeLiteral.class.cast(TypeLiteral.get(token.getType())));
    }
-   
-   @SuppressWarnings("unchecked")
+
+   /**
+    * 
+    * @deprecated will be removed in jclouds 1.7, as async interfaces are no
+    *             longer supported.
+    */
+   @Deprecated
+   @SuppressWarnings({ "unchecked", "serial" })
    private static <S, A> void bindHttpApiProvider(Binder binder, Class<S> sync, Class<A> async) {
-      TypeToken<HttpApiProvider<S, A>> token = new TypeToken<HttpApiProvider<S, A>>() {
-         private static final long serialVersionUID = 1L;
+      TypeToken<SyncToAsyncHttpApiProvider<S, A>> token = new TypeToken<SyncToAsyncHttpApiProvider<S, A>>() {
       }.where(new TypeParameter<S>() {
       }, sync).where(new TypeParameter<A>() {
       }, async);
       binder.bind(sync).toProvider(TypeLiteral.class.cast(TypeLiteral.get(token.getType())));
    }
+   
    /**
-    * adds an explicit binding for an interface which synchronously blocks on similar calls to an {@code async} type.
+    * adds an explicit binding for an interface which synchronously blocks on
+    * similar calls to an {@code async} type.
     * 
     * @param <S>
     *           sync interface that blocks
     * @param <A>
-    *           async type where all methods have same args as {@code sync}, but returns {@link ListenableFuture}
+    *           async type where all methods have same args as {@code sync}, but
+    *           returns {@link ListenableFuture}
     * @param binder
     *           guice binder
     * @param sync
     *           type interface that blocks
     * @param async
     *           type type that returns {@link ListenableFuture}
+    * 
+    * @deprecated will be removed in jclouds 1.7, as async interfaces are no
+    *             longer supported.
     */
-   public static <S, A> void bindBlockingApi(Binder binder, Class<S> sync, Class<A> async) {
+   @Deprecated
+   public static <S, A> void bindSyncToAsyncApi(Binder binder, Class<S> sync, Class<A> async) {
       bindClass(binder, sync);
       bindClass(binder, async);
       bindCallGetOnFutures(binder, sync, async);
    }
 
-   @SuppressWarnings("unchecked")
+   /**
+    * @deprecated will be removed in jclouds 1.7, as async interfaces are no
+    *             longer supported.
+    */
+   @Deprecated
+   @SuppressWarnings({ "unchecked", "serial" })
    private static <S, A> void bindCallGetOnFutures(Binder binder, Class<S> sync, Class<A> async) {
       TypeToken<CallGetOnFuturesProvider<S, A>> token = new TypeToken<CallGetOnFuturesProvider<S, A>>() {
-         private static final long serialVersionUID = 1L;
       }.where(new TypeParameter<S>() {
       }, sync).where(new TypeParameter<A>() {
       }, async);
       binder.bind(sync).toProvider(TypeLiteral.class.cast(TypeLiteral.get(token.getType())));
    }
 
-   @SuppressWarnings("unchecked")
+   @SuppressWarnings({ "unchecked", "serial" })
    private static <K> void bindClass(Binder binder, Class<K> sync) {
       binder.bind(TypeLiteral.class.cast(TypeLiteral.get(new TypeToken<Class<K>>() {
-         private static final long serialVersionUID = 1L;
       }.where(new TypeParameter<K>() {
       }, sync).getType()))).toInstance(sync);
    }
diff --git a/core/src/main/java/org/jclouds/rest/config/CallGetOnFuturesProvider.java b/core/src/main/java/org/jclouds/rest/config/CallGetOnFuturesProvider.java
index 27fb53c..5a297e3 100644
--- a/core/src/main/java/org/jclouds/rest/config/CallGetOnFuturesProvider.java
+++ b/core/src/main/java/org/jclouds/rest/config/CallGetOnFuturesProvider.java
@@ -24,7 +24,7 @@
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import org.jclouds.rest.internal.DelegatesToInvocationFunction;
+import org.jclouds.rest.internal.DelegatesToPotentiallySyncToAsyncInvocationFunction;
 import org.jclouds.rest.internal.InvokeAndCallGetOnFutures;
 
 import com.google.common.cache.Cache;
@@ -33,20 +33,22 @@
 
 /**
  * @author Adrian Cole
+ * @deprecated will be removed in jclouds 1.7, as async interfaces are no longer supported.
  */
+@Deprecated
 @Singleton
 public class CallGetOnFuturesProvider<S, A> implements Provider<S> {
 
    private final Class<? super S> apiType;
-   private final DelegatesToInvocationFunction<S, InvokeAndCallGetOnFutures<A>> syncInvoker;
+   private final DelegatesToPotentiallySyncToAsyncInvocationFunction<S, InvokeAndCallGetOnFutures<A>> syncInvoker;
 
    @Inject
    private CallGetOnFuturesProvider(Cache<Invokable<?, ?>, Invokable<?, ?>> invokables,
-         DelegatesToInvocationFunction<S, InvokeAndCallGetOnFutures<A>> syncInvoker, Class<S> apiType,
+         DelegatesToPotentiallySyncToAsyncInvocationFunction<S, InvokeAndCallGetOnFutures<A>> syncInvoker, Class<S> apiType,
          Class<A> asyncApiType) {
       this.syncInvoker = syncInvoker;
       this.apiType = apiType;
-      RestModule.putInvokables(apiType, asyncApiType, invokables);
+      SyncToAsyncHttpInvocationModule.putInvokables(apiType, asyncApiType, invokables);
    }
 
    @SuppressWarnings("unchecked")
diff --git a/core/src/main/java/org/jclouds/rest/config/HttpApiModule.java b/core/src/main/java/org/jclouds/rest/config/HttpApiModule.java
new file mode 100644
index 0000000..5c0e70b
--- /dev/null
+++ b/core/src/main/java/org/jclouds/rest/config/HttpApiModule.java
@@ -0,0 +1,102 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rest.config;
+
+import static org.jclouds.reflect.Types2.checkBound;
+import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
+
+import org.jclouds.reflect.Invocation;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.HttpAsyncClient;
+import org.jclouds.rest.HttpClient;
+import org.jclouds.rest.internal.InvokeHttpMethod;
+
+import com.google.common.base.Function;
+import com.google.common.reflect.TypeToken;
+import com.google.inject.TypeLiteral;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+@ConfiguresHttpApi
+public class HttpApiModule<A> extends RestModule {
+   protected final Class<A> api;
+
+   /**
+    * Note that this ctor requires that you instantiate w/resolved generic
+    * params. For example, via a subclass of a bound type, or natural
+    * instantiation w/resolved type params.
+    */
+   @SuppressWarnings("unchecked")
+   protected HttpApiModule() {
+      this.api = Class.class.cast(checkBound(new TypeToken<A>(getClass()) {
+         private static final long serialVersionUID = 1L;
+      }).getRawType());
+   }
+
+   public HttpApiModule(Class<A> api) {
+     this.api = api;
+   }
+
+   @Override
+   protected void configure() {
+      super.configure();
+      bind(new TypeLiteral<Function<Invocation, Object>>() {
+      }).to(InvokeHttpMethod.class);
+      bindHttpApi(binder(), api);
+      bindHttpApi(binder(), HttpClient.class);
+      // TODO: remove when references are gone
+      bindHttpApi(binder(), HttpAsyncClient.class);
+      bindErrorHandlers();
+      bindRetryHandlers();
+   }
+
+   /**
+    * overrides this to change the default retry handlers for the http engine
+    * 
+    * ex.
+    * 
+    * <pre>
+    * bind(HttpRetryHandler.class).annotatedWith(Redirection.class).to(AWSRedirectionRetryHandler.class);
+    * bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(AWSClientErrorRetryHandler.class);
+    * </pre>
+    * 
+    */
+   protected void bindRetryHandlers() {
+   }
+
+   /**
+    * overrides this to change the default error handlers for the http engine
+    * 
+    * ex.
+    * 
+    * <pre>
+    * bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseAWSErrorFromXmlContent.class);
+    * bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ParseAWSErrorFromXmlContent.class);
+    * bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseAWSErrorFromXmlContent.class);
+    * </pre>
+    * 
+    * 
+    */
+   protected void bindErrorHandlers() {
+
+   }
+
+}
diff --git a/core/src/main/java/org/jclouds/rest/config/RestClientModule.java b/core/src/main/java/org/jclouds/rest/config/RestClientModule.java
index dfa63c1..271547d 100644
--- a/core/src/main/java/org/jclouds/rest/config/RestClientModule.java
+++ b/core/src/main/java/org/jclouds/rest/config/RestClientModule.java
@@ -18,10 +18,9 @@
  */
 package org.jclouds.rest.config;
 
-import static com.google.common.base.Preconditions.checkState;
-import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
+import static org.jclouds.reflect.Types2.checkBound;
+import static org.jclouds.rest.config.BinderUtils.bindSyncToAsyncHttpApi;
 
-import java.lang.reflect.TypeVariable;
 import java.util.Map;
 
 import org.jclouds.rest.ConfiguresRestClient;
@@ -32,18 +31,23 @@
 /**
  * 
  * @author Adrian Cole
+ * 
+ * @deprecated will be removed in jclouds 1.7; use {@link HttpApiModule}
  */
+@Deprecated
 @ConfiguresRestClient
 public class RestClientModule<S, A> extends RestModule {
    protected final TypeToken<S> syncClientType;
    protected final TypeToken<A> asyncClientType;
 
+   private final SyncToAsyncHttpInvocationModule invocationModule;
+
    /**
     * Note that this ctor requires that you instantiate w/resolved generic params. For example, via
     * a subclass of a bound type, or natural instantiation w/resolved type params.
     */
    protected RestClientModule(Map<Class<?>, Class<?>> sync2Async) {
-      super(sync2Async);
+      this.invocationModule = new SyncToAsyncHttpInvocationModule(sync2Async);
       this.syncClientType = checkBound(new TypeToken<S>(getClass()) {
          private static final long serialVersionUID = 1L;
       });
@@ -51,15 +55,6 @@
          private static final long serialVersionUID = 1L;
       });
    }
-   
-   /**
-    * @throws IllegalStateException if the type is an instanceof {@link TypeVariable}
-    */
-   private static <T> TypeToken<T> checkBound(TypeToken<T> type) throws IllegalStateException {
-      checkState(!(type.getType() instanceof TypeVariable<?>),
-               "unbound type variable: %s, use ctor that explicitly assigns this", type);
-      return type;
-   }
 
    /**
     * @see #RestClientModule(Map)
@@ -79,7 +74,7 @@
     * only necessary when type params are not resolvable at runtime.
     */
    public RestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType, Map<Class<?>, Class<?>> sync2Async) {
-      super(sync2Async);
+      this.invocationModule = new SyncToAsyncHttpInvocationModule(sync2Async);
       this.syncClientType = checkBound(syncClientType);
       this.asyncClientType = checkBound(asyncClientType);
    }
@@ -87,7 +82,8 @@
    @Override
    protected void configure() {
       super.configure();
-      bindHttpApi(binder(), syncClientType.getRawType(), asyncClientType.getRawType());
+      install(invocationModule);
+      bindSyncToAsyncHttpApi(binder(), syncClientType.getRawType(), asyncClientType.getRawType());
       bindErrorHandlers();
       bindRetryHandlers();
    }
diff --git a/core/src/main/java/org/jclouds/rest/config/RestModule.java b/core/src/main/java/org/jclouds/rest/config/RestModule.java
index db7f67b..fb16e17 100644
--- a/core/src/main/java/org/jclouds/rest/config/RestModule.java
+++ b/core/src/main/java/org/jclouds/rest/config/RestModule.java
@@ -18,23 +18,13 @@
  */
 package org.jclouds.rest.config;
 
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Iterables.toArray;
-import static com.google.common.collect.Iterables.transform;
 import static com.google.common.util.concurrent.Atomics.newReference;
-import static org.jclouds.reflect.Reflection2.method;
-import static org.jclouds.reflect.Reflection2.methods;
-import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
 
-import java.io.Closeable;
 import java.net.Proxy;
 import java.net.URI;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
 
-import javax.inject.Singleton;
-
 import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
 import org.jclouds.functions.IdentityFunction;
 import org.jclouds.http.HttpRequest;
@@ -46,24 +36,14 @@
 import org.jclouds.proxy.ProxyForURI;
 import org.jclouds.reflect.Invocation;
 import org.jclouds.rest.AuthorizationException;
-import org.jclouds.rest.HttpAsyncClient;
-import org.jclouds.rest.HttpClient;
 import org.jclouds.rest.binders.BindToJsonPayloadWrappedWith;
-import org.jclouds.rest.internal.InvokeHttpMethod;
 import org.jclouds.rest.internal.RestAnnotationProcessor;
 import org.jclouds.rest.internal.TransformerForRequest;
 
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.base.Supplier;
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.reflect.Invokable;
-import com.google.common.reflect.Parameter;
 import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
 import com.google.inject.TypeLiteral;
 import com.google.inject.assistedinject.FactoryModuleBuilder;
 
@@ -72,109 +52,25 @@
    public static final TypeLiteral<Supplier<URI>> URI_SUPPLIER_TYPE = new TypeLiteral<Supplier<URI>>() {
    };
 
-   protected final Map<Class<?>, Class<?>> sync2Async;
    protected final AtomicReference<AuthorizationException> authException = newReference();
 
-   public RestModule() {
-      this(ImmutableMap.<Class<?>, Class<?>> of());
-   }
-
-   public RestModule(Map<Class<?>, Class<?>> sync2Async) {
-      this.sync2Async = sync2Async;
-   }
-
-   /**
-    * seeds well-known invokables.
-    */
-   @Provides
-   @Singleton
-   protected Cache<Invokable<?, ?>, Invokable<?, ?>> seedKnownSync2AsyncInvokables() {
-      return seedKnownSync2AsyncInvokables(sync2Async);
-   }
-
-   /**
-    * function view of above
-    */
-   @Provides
-   @Singleton
-   protected Function<Invocation, Invocation> sync2async(final Cache<Invokable<?, ?>, Invokable<?, ?>> cache) {
-      return new Function<Invocation, Invocation>() {
-         public Invocation apply(Invocation in) {
-            return Invocation.create(
-                  checkNotNull(cache.getIfPresent(in.getInvokable()), "invokable %s not in %s", in.getInvokable(),
-                        cache), in.getArgs());
-         }
-      };
-   }
-
-   @VisibleForTesting
-   static Cache<Invokable<?, ?>, Invokable<?, ?>> seedKnownSync2AsyncInvokables(Map<Class<?>, Class<?>> sync2Async) {
-      Cache<Invokable<?, ?>, Invokable<?, ?>> sync2AsyncBuilder = CacheBuilder.newBuilder().build();
-      putInvokables(HttpClient.class, HttpAsyncClient.class, sync2AsyncBuilder);
-      for (Map.Entry<Class<?>, Class<?>> entry : sync2Async.entrySet()) {
-         putInvokables(entry.getKey(), entry.getValue(), sync2AsyncBuilder);
-      }
-      return sync2AsyncBuilder;
-   }
-
-   // accessible for ClientProvider
-   public static void putInvokables(Class<?> sync, Class<?> async, Cache<Invokable<?, ?>, Invokable<?, ?>> cache) {
-      for (Invokable<?, ?> invoked : methods(sync)) {
-         Invokable<?, ?> delegatedMethod = method(async, invoked.getName(), getParameterTypes(invoked));
-         checkArgument(
-               delegatedMethod.getExceptionTypes().equals(invoked.getExceptionTypes()) || isCloseable(delegatedMethod),
-               "invoked %s has different typed exceptions than target %s", invoked, delegatedMethod);
-         cache.put(invoked, delegatedMethod);
-      }
-   }
-
-   /**
-    * In JDK7 Closeable.close is declared in AutoCloseable, which throws
-    * Exception vs IOException, so we have to be more lenient about exception
-    * type declarations.
-    * 
-    * <h4>note</h4>
-    * 
-    * This will be refactored out when we delete Async code in jclouds 1.7.
-    */
-   private static boolean isCloseable(Invokable<?, ?> delegatedMethod) {
-      return "close".equals(delegatedMethod.getName())
-            && Closeable.class.isAssignableFrom(delegatedMethod.getDeclaringClass());
-   }
-
-   /**
-    * for portability with {@link Class#getMethod(String, Class...)}
-    */
-   private static Class<?>[] getParameterTypes(Invokable<?, ?> in) {
-      return toArray(transform(checkNotNull(in, "invokable").getParameters(), new Function<Parameter, Class<?>>() {
-         public Class<?> apply(Parameter input) {
-            return input.getType().getRawType();
-         }
-      }), Class.class);
-   }
-
    protected void installLocations() {
       install(new LocationModule());
    }
 
    @Override
    protected void configure() {
-      bind(new TypeLiteral<Map<Class<?>, Class<?>>>() {
-      }).toInstance(sync2Async);
       install(new SaxParserModule());
       install(new GsonModule());
       install(new SetCaller.Module());
       install(new FactoryModuleBuilder().build(BindToJsonPayloadWrappedWith.Factory.class));
       bind(new TypeLiteral<Function<HttpRequest, Function<HttpResponse, ?>>>() {
       }).to(TransformerForRequest.class);
-      bind(new TypeLiteral<Function<Invocation, Object>>() {
-      }).to(InvokeHttpMethod.class);
       bind(new TypeLiteral<org.jclouds.Fallback<Object>>() {
       }).to(MapHttp4xxCodesToExceptions.class);
       bind(new TypeLiteral<Function<Invocation, HttpRequest>>() {
       }).to(RestAnnotationProcessor.class);
       bind(IdentityFunction.class).toInstance(IdentityFunction.INSTANCE);
-      bindHttpApi(binder(), HttpClient.class, HttpAsyncClient.class);
       // this will help short circuit scenarios that can otherwise lock out users
       bind(new TypeLiteral<AtomicReference<AuthorizationException>>() {
       }).toInstance(authException);
diff --git a/core/src/main/java/org/jclouds/rest/config/HttpApiProvider.java b/core/src/main/java/org/jclouds/rest/config/SyncToAsyncHttpApiProvider.java
similarity index 68%
rename from core/src/main/java/org/jclouds/rest/config/HttpApiProvider.java
rename to core/src/main/java/org/jclouds/rest/config/SyncToAsyncHttpApiProvider.java
index 4df9f77..57b80aa 100644
--- a/core/src/main/java/org/jclouds/rest/config/HttpApiProvider.java
+++ b/core/src/main/java/org/jclouds/rest/config/SyncToAsyncHttpApiProvider.java
@@ -25,7 +25,7 @@
 import javax.inject.Singleton;
 
 import org.jclouds.reflect.Invocation;
-import org.jclouds.rest.internal.DelegatesToInvocationFunction;
+import org.jclouds.rest.internal.DelegatesToPotentiallySyncToAsyncInvocationFunction;
 
 import com.google.common.base.Function;
 import com.google.common.cache.Cache;
@@ -35,18 +35,20 @@
 /**
  * 
  * @author Adrian Cole
+ * @deprecated will be removed in jclouds 1.7; use {@link AnnotatedHttpApiProvider}
  */
+@Deprecated
 @Singleton
-public class HttpApiProvider<S, A> implements Provider<S> {
+public class SyncToAsyncHttpApiProvider<S, A> implements Provider<S> {
    private final Class<? super S> apiType;
-   private final DelegatesToInvocationFunction<S, Function<Invocation, Object>> httpInvoker;
+   private final DelegatesToPotentiallySyncToAsyncInvocationFunction<S, Function<Invocation, Object>> httpInvoker;
 
    @Inject
-   private HttpApiProvider(Cache<Invokable<?, ?>, Invokable<?, ?>> invokables,
-         DelegatesToInvocationFunction<S, Function<Invocation, Object>> httpInvoker, Class<S> apiType, Class<A> asyncApiType) {
+   private SyncToAsyncHttpApiProvider(Cache<Invokable<?, ?>, Invokable<?, ?>> invokables,
+         DelegatesToPotentiallySyncToAsyncInvocationFunction<S, Function<Invocation, Object>> httpInvoker, Class<S> apiType, Class<A> asyncApiType) {
       this.httpInvoker = httpInvoker;
       this.apiType = apiType;
-      RestModule.putInvokables(apiType, asyncApiType, invokables);
+      SyncToAsyncHttpInvocationModule.putInvokables(apiType, asyncApiType, invokables);
    }
 
    @SuppressWarnings("unchecked")
diff --git a/core/src/main/java/org/jclouds/rest/config/SyncToAsyncHttpInvocationModule.java b/core/src/main/java/org/jclouds/rest/config/SyncToAsyncHttpInvocationModule.java
new file mode 100644
index 0000000..81f85191
--- /dev/null
+++ b/core/src/main/java/org/jclouds/rest/config/SyncToAsyncHttpInvocationModule.java
@@ -0,0 +1,150 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rest.config;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.toArray;
+import static com.google.common.collect.Iterables.transform;
+import static org.jclouds.reflect.Reflection2.method;
+import static org.jclouds.reflect.Reflection2.methods;
+
+import java.io.Closeable;
+import java.util.Map;
+
+import javax.inject.Singleton;
+
+import org.jclouds.reflect.Invocation;
+import org.jclouds.rest.HttpAsyncClient;
+import org.jclouds.rest.HttpClient;
+import org.jclouds.rest.internal.DelegatesToInvocationFunction;
+import org.jclouds.rest.internal.DelegatesToPotentiallySyncToAsyncInvocationFunction;
+import org.jclouds.rest.internal.InvokeAndCallGetOnFutures;
+import org.jclouds.rest.internal.InvokeSyncToAsyncHttpMethod;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.reflect.Invokable;
+import com.google.common.reflect.Parameter;
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+import com.google.inject.TypeLiteral;
+
+/**
+ * supports sync-async mapping
+ * 
+ * @deprecated will be removed in jclouds 1.7; use {@link HttpApiModule}
+ */
+@Deprecated
+public class SyncToAsyncHttpInvocationModule extends AbstractModule {
+   protected final Map<Class<?>, Class<?>> sync2Async;
+
+   public SyncToAsyncHttpInvocationModule() {
+      this(ImmutableMap.<Class<?>, Class<?>> of());
+   }
+
+   public SyncToAsyncHttpInvocationModule(Map<Class<?>, Class<?>> sync2Async) {
+      this.sync2Async = sync2Async;
+   }
+
+   @Override
+   protected void configure() {
+      bind(new TypeLiteral<Map<Class<?>, Class<?>>>() {
+      }).toInstance(sync2Async);
+      bind(new TypeLiteral<Function<Invocation, Object>>() {
+      }).to(InvokeSyncToAsyncHttpMethod.class);
+      BinderUtils.bindSyncToAsyncHttpApi(binder(), HttpClient.class, HttpAsyncClient.class);
+   }
+
+   /**
+    * seeds well-known invokables.
+    */
+   @Provides
+   @Singleton
+   protected Cache<Invokable<?, ?>, Invokable<?, ?>> seedKnownSync2AsyncInvokables() {
+      return seedKnownSync2AsyncInvokables(sync2Async);
+   }
+
+   /**
+    * function view of above
+    * 
+    * @see InvokeAndCallGetOnFutures
+    * @see InvokeSyncToAsyncHttpMethod
+    */
+   @Provides
+   @Singleton
+   protected Function<Invocation, Invocation> sync2async(final Cache<Invokable<?, ?>, Invokable<?, ?>> cache) {
+      return new Function<Invocation, Invocation>() {
+         public Invocation apply(Invocation in) {
+            return Invocation.create(
+                  checkNotNull(cache.getIfPresent(in.getInvokable()), "invokable %s not in %s", in.getInvokable(),
+                        cache), in.getArgs());
+         }
+      };
+   }
+
+   @VisibleForTesting
+   static Cache<Invokable<?, ?>, Invokable<?, ?>> seedKnownSync2AsyncInvokables(Map<Class<?>, Class<?>> sync2Async) {
+      Cache<Invokable<?, ?>, Invokable<?, ?>> sync2AsyncBuilder = CacheBuilder.newBuilder().build();
+      putInvokables(HttpClient.class, HttpAsyncClient.class, sync2AsyncBuilder);
+      for (Map.Entry<Class<?>, Class<?>> entry : sync2Async.entrySet()) {
+         putInvokables(entry.getKey(), entry.getValue(), sync2AsyncBuilder);
+      }
+      return sync2AsyncBuilder;
+   }
+
+   // accessible for ClientProvider
+   public static void putInvokables(Class<?> sync, Class<?> async, Cache<Invokable<?, ?>, Invokable<?, ?>> cache) {
+      for (Invokable<?, ?> invoked : methods(sync)) {
+         Invokable<?, ?> delegatedMethod = method(async, invoked.getName(), getParameterTypes(invoked));
+         checkArgument(delegatedMethod.getExceptionTypes().equals(invoked.getExceptionTypes())
+               || isCloseable(delegatedMethod), "invoked %s has different typed exceptions than target %s", invoked,
+               delegatedMethod);
+         cache.put(invoked, delegatedMethod);
+      }
+   }
+
+   /**
+    * In JDK7 Closeable.close is declared in AutoCloseable, which throws
+    * Exception vs IOException, so we have to be more lenient about exception
+    * type declarations.
+    * 
+    * <h4>note</h4>
+    * 
+    * This will be refactored out when we delete Async code in jclouds 1.7.
+    */
+   private static boolean isCloseable(Invokable<?, ?> delegatedMethod) {
+      return "close".equals(delegatedMethod.getName())
+            && Closeable.class.isAssignableFrom(delegatedMethod.getDeclaringClass());
+   }
+
+   /**
+    * for portability with {@link Class#getMethod(String, Class...)}
+    */
+   private static Class<?>[] getParameterTypes(Invokable<?, ?> in) {
+      return toArray(transform(checkNotNull(in, "invokable").getParameters(), new Function<Parameter, Class<?>>() {
+         public Class<?> apply(Parameter input) {
+            return input.getType().getRawType();
+         }
+      }), Class.class);
+   }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/jclouds/rest/internal/ApiContextImpl.java b/core/src/main/java/org/jclouds/rest/internal/ApiContextImpl.java
new file mode 100644
index 0000000..1296f43
--- /dev/null
+++ b/core/src/main/java/org/jclouds/rest/internal/ApiContextImpl.java
@@ -0,0 +1,60 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rest.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Inject;
+
+import org.jclouds.annotations.Name;
+import org.jclouds.domain.Credentials;
+import org.jclouds.internal.ContextImpl;
+import org.jclouds.lifecycle.Closer;
+import org.jclouds.location.Provider;
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.rest.ApiContext;
+import org.jclouds.rest.Utils;
+
+import com.google.common.base.Supplier;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Singleton;
+import com.google.inject.TypeLiteral;
+
+/**
+ * @author Adrian Cole
+*/
+@Singleton
+public class ApiContextImpl<A> extends ContextImpl implements ApiContext<A> {
+
+   private final A api;
+
+   @Inject
+   protected ApiContextImpl(@Name String name, ProviderMetadata providerMetadata,
+         @Provider Supplier<Credentials> creds, Utils utils, Closer closer, Injector injector, TypeLiteral<A> api) {
+      super(name, providerMetadata, creds, utils, closer);
+      checkNotNull(injector, "injector");
+      this.api = injector.getInstance(Key.get(checkNotNull(api, "api")));
+   }
+
+   @Override
+   public A getApi() {
+      return api;
+   }
+}
diff --git a/core/src/main/java/org/jclouds/rest/internal/BaseHttpApiMetadata.java b/core/src/main/java/org/jclouds/rest/internal/BaseHttpApiMetadata.java
new file mode 100644
index 0000000..cbc0ef3
--- /dev/null
+++ b/core/src/main/java/org/jclouds/rest/internal/BaseHttpApiMetadata.java
@@ -0,0 +1,121 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rest.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.reflect.Reflection2.typeToken;
+import static org.jclouds.reflect.Types2.checkBound;
+
+import java.util.Properties;
+
+import org.jclouds.apis.ApiMetadata;
+import org.jclouds.apis.internal.BaseApiMetadata;
+import org.jclouds.rest.ApiContext;
+import org.jclouds.rest.HttpApiMetadata;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.reflect.TypeParameter;
+import com.google.common.reflect.TypeToken;
+
+/**
+ * Useful in creating http apis.
+ * 
+ * @author Adrian Cole
+ */
+@Beta
+public abstract class BaseHttpApiMetadata<A> extends BaseApiMetadata implements HttpApiMetadata<A> {
+
+   protected final Class<A> api;
+
+   protected BaseHttpApiMetadata(Builder<A, ?> builder) {
+      super(builder);
+      this.api = checkNotNull(builder.api, "api");
+   }
+
+   public static Properties defaultProperties() {
+      Properties props = BaseApiMetadata.defaultProperties();
+      return props;
+   }
+
+   public static <S, A> TypeToken<ApiContext<A>> contextToken(TypeToken<A> apiToken) {
+      return new TypeToken<ApiContext<A>>() {
+         private static final long serialVersionUID = 1L;
+      }.where(new TypeParameter<A>() {
+      }, apiToken);
+   }
+
+   public static abstract class Builder<A, T extends Builder<A, T>> extends BaseApiMetadata.Builder<T> implements
+         HttpApiMetadata.Builder<A, T> {
+      protected Class<A> api;
+
+      /**
+       * Note that this ctor requires that you instantiate w/resolved generic
+       * params. For example, via a subclass of a bound type, or natural
+       * instantiation w/resolved type params.
+       */
+      @SuppressWarnings("unchecked")
+      protected Builder() {
+         this.api = Class.class.cast(checkBound(new TypeToken<A>(getClass()) {
+            private static final long serialVersionUID = 1L;
+         }).getRawType());
+         init();
+      }
+
+      protected Builder(Class<A> api) {
+         this.api = checkNotNull(api, "api");
+         init();
+      }
+
+      private void init() {
+         api(api)
+         .name(api.getSimpleName())
+         .context(contextToken(typeToken(api)))
+         .defaultProperties(BaseHttpApiMetadata.defaultProperties());
+      }
+
+      @Override
+      public T api(Class<A> api) {
+         this.api = checkNotNull(api, "api");
+         return self();
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public T fromApiMetadata(ApiMetadata in) {
+         if (in instanceof HttpApiMetadata) {
+            HttpApiMetadata<?> http = HttpApiMetadata.class.cast(in);
+            api(Class.class.cast(http.getApi()));
+         }
+         super.fromApiMetadata(in);
+         return self();
+      }
+
+   }
+
+   @Override
+   public Class<A> getApi() {
+      return api;
+   }
+
+   @Override
+   protected ToStringHelper string() {
+      return super.string().add("api", getApi());
+   }
+}
diff --git a/core/src/main/java/org/jclouds/rest/internal/BaseRestApiMetadata.java b/core/src/main/java/org/jclouds/rest/internal/BaseRestApiMetadata.java
index 4c4c899..c10efb5 100644
--- a/core/src/main/java/org/jclouds/rest/internal/BaseRestApiMetadata.java
+++ b/core/src/main/java/org/jclouds/rest/internal/BaseRestApiMetadata.java
@@ -26,7 +26,6 @@
 import org.jclouds.apis.ApiMetadata;
 import org.jclouds.apis.internal.BaseApiMetadata;
 import org.jclouds.rest.RestApiMetadata;
-import org.jclouds.rest.RestContext;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Objects.ToStringHelper;
@@ -37,6 +36,8 @@
  * Useful in creating rest apis.
  * 
  * @author Adrian Cole
+ * @deprecated please use {@link BaseHttpApiMetadata} as
+ *             async interface will be removed in jclouds 1.7.
  */
 @Beta
 public abstract class BaseRestApiMetadata extends BaseApiMetadata implements RestApiMetadata {
@@ -55,8 +56,8 @@
       return props;
    }
    
-   public static <S, A> TypeToken<RestContext<S, A>> contextToken(TypeToken<S> apiToken, TypeToken<A> asyncApiToken) {
-      return new TypeToken<RestContext<S, A>>() {
+   public static <S, A> TypeToken<org.jclouds.rest.RestContext<S, A>> contextToken(TypeToken<S> apiToken, TypeToken<A> asyncApiToken) {
+      return new TypeToken<org.jclouds.rest.RestContext<S, A>>() {
          private static final long serialVersionUID = 1L;
       }.where(new TypeParameter<S>() {
       }, apiToken).where(new TypeParameter<A>() {
diff --git a/core/src/main/java/org/jclouds/rest/internal/DelegatesToInvocationFunction.java b/core/src/main/java/org/jclouds/rest/internal/DelegatesToInvocationFunction.java
index 014b911..f0a1055 100644
--- a/core/src/main/java/org/jclouds/rest/internal/DelegatesToInvocationFunction.java
+++ b/core/src/main/java/org/jclouds/rest/internal/DelegatesToInvocationFunction.java
@@ -39,7 +39,6 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 
 import javax.inject.Inject;
 import javax.inject.Qualifier;
@@ -78,7 +77,7 @@
  *           The function that implements this dynamic proxy
  */
 @Beta
-public final class DelegatesToInvocationFunction<S, F extends Function<Invocation, Object>> implements
+public class DelegatesToInvocationFunction<S, F extends Function<Invocation, Object>> implements
       InvocationHandler {
 
    private static final Object[] NO_ARGS = {};
@@ -161,20 +160,18 @@
       }
    }
 
-   private final Injector injector;
-   private final TypeToken<S> ownerType;
-   private final SetCaller setCaller;
-   private final Map<Class<?>, Class<?>> syncToAsync;
-   private final Function<InvocationSuccess, Optional<Object>> optionalConverter;
-   private final F methodInvoker;
+   protected final Injector injector;
+   protected final TypeToken<S> ownerType;
+   protected final SetCaller setCaller;
+   protected final Function<InvocationSuccess, Optional<Object>> optionalConverter;
+   protected final F methodInvoker;
 
    @Inject
-   DelegatesToInvocationFunction(Injector injector, SetCaller setCaller, Map<Class<?>, Class<?>> syncToAsync,
+   DelegatesToInvocationFunction(Injector injector, SetCaller setCaller, 
          Class<S> ownerType, Function<InvocationSuccess, Optional<Object>> optionalConverter, F methodInvoker) {
       this.injector = checkNotNull(injector, "injector");
       this.ownerType = typeToken(checkNotNull(ownerType, "ownerType"));
       this.setCaller = checkNotNull(setCaller, "setCaller");
-      this.syncToAsync = checkNotNull(syncToAsync, "syncToAsync");
       this.optionalConverter = checkNotNull(optionalConverter, "optionalConverter");
       this.methodInvoker = checkNotNull(methodInvoker, "methodInvoker");
    }
@@ -200,20 +197,12 @@
    /**
     * attempts to guess the generic type params for the delegate's invocation function based on the supplied type
     */
-   private Key<?> methodInvokerFor(Class<?> returnType) {
+   protected Key<?> methodInvokerFor(Class<?> returnType) {
       switch (methodInvoker.getClass().getTypeParameters().length) {
       case 0:
          return Key.get(methodInvoker.getClass());
       case 1:
          return Key.get(Types.newParameterizedType(methodInvoker.getClass(), returnType));
-      case 2:
-         if (syncToAsync.containsValue(returnType))
-            return Key.get(Types.newParameterizedType(methodInvoker.getClass(), returnType, returnType));
-         return Key.get(Types.newParameterizedType(
-               methodInvoker.getClass(),
-               returnType,
-               checkNotNull(syncToAsync.get(returnType), "need async type of %s for %s", returnType,
-                     methodInvoker.getClass())));
       }
       throw new IllegalArgumentException(returnType + " has too many type parameters");
    }
diff --git a/core/src/main/java/org/jclouds/rest/internal/DelegatesToPotentiallySyncToAsyncInvocationFunction.java b/core/src/main/java/org/jclouds/rest/internal/DelegatesToPotentiallySyncToAsyncInvocationFunction.java
new file mode 100644
index 0000000..f6843fb
--- /dev/null
+++ b/core/src/main/java/org/jclouds/rest/internal/DelegatesToPotentiallySyncToAsyncInvocationFunction.java
@@ -0,0 +1,74 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rest.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.jclouds.reflect.Invocation;
+import org.jclouds.reflect.InvocationSuccess;
+import org.jclouds.rest.config.SetCaller;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.util.Types;
+
+/**
+ * @param <S>
+ *           The enclosing type of the interface that a dynamic proxy like this
+ *           implements
+ * @param <F>
+ *           The function that implements this dynamic proxy
+ * 
+ * @deprecated please use {@link DelegatesToInvocationFunction} as
+ *             async interface will be removed in jclouds 1.7.
+ */
+@Deprecated
+@Beta
+public final class DelegatesToPotentiallySyncToAsyncInvocationFunction<S, F extends Function<Invocation, Object>> extends
+      DelegatesToInvocationFunction<S, F> {
+   private final Map<Class<?>, Class<?>> syncToAsync;
+
+   @Inject
+   DelegatesToPotentiallySyncToAsyncInvocationFunction(Injector injector, SetCaller setCaller, Class<S> ownerType,
+         Function<InvocationSuccess, Optional<Object>> optionalConverter, F methodInvoker,
+         Map<Class<?>, Class<?>> syncToAsync) {
+      super(injector, setCaller, ownerType, optionalConverter, methodInvoker);
+      this.syncToAsync = checkNotNull(syncToAsync, "syncToAsync");
+   }
+
+   protected Key<?> methodInvokerFor(Class<?> returnType) {
+      if (methodInvoker.getClass().getTypeParameters().length == 2) {
+         if (syncToAsync.containsValue(returnType))
+            return Key.get(Types.newParameterizedType(methodInvoker.getClass(), returnType, returnType));
+         return Key.get(Types.newParameterizedType(
+               methodInvoker.getClass(),
+               returnType,
+               checkNotNull(syncToAsync.get(returnType), "need async type of %s for %s", returnType,
+                     methodInvoker.getClass())));
+      }
+      return super.methodInvokerFor(returnType);
+   }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/jclouds/rest/internal/InvokeAndCallGetOnFutures.java b/core/src/main/java/org/jclouds/rest/internal/InvokeAndCallGetOnFutures.java
index cda07b0..a132b8a 100644
--- a/core/src/main/java/org/jclouds/rest/internal/InvokeAndCallGetOnFutures.java
+++ b/core/src/main/java/org/jclouds/rest/internal/InvokeAndCallGetOnFutures.java
@@ -37,7 +37,9 @@
 /**
  * 
  * @author Adrian Cole
+ * @deprecated will be removed in jclouds 1.7, as async interfaces are no longer supported.
  */
+@Deprecated
 public final class InvokeAndCallGetOnFutures<R> implements Function<Invocation, Object> {
 
    @Resource
diff --git a/core/src/main/java/org/jclouds/rest/internal/InvokeHttpMethod.java b/core/src/main/java/org/jclouds/rest/internal/InvokeHttpMethod.java
index e97a01a..7a358dd 100644
--- a/core/src/main/java/org/jclouds/rest/internal/InvokeHttpMethod.java
+++ b/core/src/main/java/org/jclouds/rest/internal/InvokeHttpMethod.java
@@ -20,19 +20,14 @@
 
 import static com.google.common.base.Objects.equal;
 import static com.google.common.base.Objects.toStringHelper;
-import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.base.Throwables.propagate;
-import static com.google.common.util.concurrent.Futures.transform;
-import static com.google.common.util.concurrent.Futures.withFallback;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
-import static org.jclouds.Constants.PROPERTY_USER_THREADS;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
 
 import javax.annotation.Resource;
 import javax.inject.Inject;
-import javax.inject.Named;
 
 import org.jclouds.http.HttpCommand;
 import org.jclouds.http.HttpCommandExecutorService;
@@ -47,9 +42,6 @@
 import com.google.common.base.Function;
 import com.google.common.base.Objects;
 import com.google.common.base.Optional;
-import com.google.common.reflect.Invokable;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.TimeLimiter;
 import com.google.common.util.concurrent.UncheckedTimeoutException;
 
@@ -61,24 +53,19 @@
    @Resource
    private Logger logger = Logger.NULL;
 
-   private final Function<Invocation, Invocation> sync2async;
    private final Function<Invocation, HttpRequest> annotationProcessor;
    private final HttpCommandExecutorService http;
-   private final ListeningExecutorService userExecutor;
    private final TimeLimiter timeLimiter;
    private final Function<HttpRequest, Function<HttpResponse, ?>> transformerForRequest;
    private final InvocationConfig config;
 
    @Inject
    @VisibleForTesting
-   InvokeHttpMethod(Function<Invocation, Invocation> sync2async, Function<Invocation, HttpRequest> annotationProcessor,
+   InvokeHttpMethod(Function<Invocation, HttpRequest> annotationProcessor,
          HttpCommandExecutorService http, Function<HttpRequest, Function<HttpResponse, ?>> transformerForRequest,
-         TimeLimiter timeLimiter, InvocationConfig config,
-         @Named(PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
-      this.sync2async = sync2async;
+         TimeLimiter timeLimiter, InvocationConfig config) {
       this.annotationProcessor = annotationProcessor;
       this.http = http;
-      this.userExecutor = userExecutor;
       this.timeLimiter = timeLimiter;
       this.transformerForRequest = transformerForRequest;
       this.config = config;
@@ -86,32 +73,11 @@
 
    @Override
    public Object apply(Invocation in) {
-      if (isFuture(in.getInvokable())) {
-         return submit(in);
-      }
-      Invocation async = toAsync(in);
-      Optional<Long> timeoutNanos = config.getTimeoutNanos(async);
+      Optional<Long> timeoutNanos = config.getTimeoutNanos(in);
       if (timeoutNanos.isPresent()) {
-         return invokeWithTimeout(async, timeoutNanos.get());
+         return invokeWithTimeout(in, timeoutNanos.get());
       }
-      return invoke(async);
-   }
-
-   /**
-    * submits the {@linkplain HttpCommand} associated with {@code invocation},
-    * {@link #getTransformer(String, HttpCommand) parses its response}, and
-    * applies a {@link #getFallback(String, Invocation, HttpCommand) fallback}
-    * if a {@code Throwable} is encountered. Parsing and Fallback occur on the
-    * {@code userExecutor} thread.
-    */
-   public ListenableFuture<?> submit(Invocation invocation) {
-      String commandName = config.getCommandName(invocation);
-      HttpCommand command = toCommand(commandName, invocation);
-      Function<HttpResponse, ?> transformer = getTransformer(commandName, command);
-      org.jclouds.Fallback<?> fallback = getFallback(commandName, invocation, command);
-
-      logger.debug(">> submitting %s", commandName);
-      return withFallback(transform(http.submit(command), transformer, userExecutor), fallback);
+      return invoke(in);
    }
 
    /**
@@ -224,17 +190,6 @@
       }
    }
 
-   /**
-    * looks up the corresponding {@code Invocation} that returns a
-    * {@code Future}. Only Invokables that return {@code Futures} are annotated
-    * in a way that can be parsed into an {@linkplain HttpRequest}.
-    */
-   private Invocation toAsync(Invocation in) {
-      Invocation async = sync2async.apply(in);
-      checkState(isFuture(async.getInvokable()), "not a future: %s", async);
-      return async;
-   }
-
    private HttpCommand toCommand(String commandName, Invocation invocation) {
       logger.trace(">> converting %s", commandName);
       HttpRequest request = annotationProcessor.apply(invocation);
@@ -249,10 +204,6 @@
       return transformer;
    }
 
-   private boolean isFuture(Invokable<?, ?> in) {
-      return in.getReturnType().getRawType().equals(ListenableFuture.class);
-   }
-
    @Override
    public boolean equals(Object o) {
       if (this == o)
diff --git a/core/src/main/java/org/jclouds/rest/internal/InvokeSyncToAsyncHttpMethod.java b/core/src/main/java/org/jclouds/rest/internal/InvokeSyncToAsyncHttpMethod.java
new file mode 100644
index 0000000..c63f90a
--- /dev/null
+++ b/core/src/main/java/org/jclouds/rest/internal/InvokeSyncToAsyncHttpMethod.java
@@ -0,0 +1,277 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rest.internal;
+
+import static com.google.common.base.Objects.equal;
+import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.base.Throwables.propagate;
+import static com.google.common.util.concurrent.Futures.transform;
+import static com.google.common.util.concurrent.Futures.withFallback;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+import static org.jclouds.Constants.PROPERTY_USER_THREADS;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.jclouds.http.HttpCommand;
+import org.jclouds.http.HttpCommandExecutorService;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.logging.Logger;
+import org.jclouds.reflect.Invocation;
+import org.jclouds.rest.InvocationContext;
+import org.jclouds.rest.config.InvocationConfig;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.reflect.Invokable;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.TimeLimiter;
+import com.google.common.util.concurrent.UncheckedTimeoutException;
+
+/**
+ * @author Adrian Cole
+ * @deprecated will be replaced in jclouds 1.7 with {@link InvokeHttpMethod}, as async interfaces are no longer supported.
+ */
+@Deprecated
+public class InvokeSyncToAsyncHttpMethod implements Function<Invocation, Object> {
+
+   @Resource
+   private Logger logger = Logger.NULL;
+
+   private final Function<Invocation, Invocation> sync2async;
+   private final Function<Invocation, HttpRequest> annotationProcessor;
+   private final HttpCommandExecutorService http;
+   private final ListeningExecutorService userExecutor;
+   private final TimeLimiter timeLimiter;
+   private final Function<HttpRequest, Function<HttpResponse, ?>> transformerForRequest;
+   private final InvocationConfig config;
+
+   @Inject
+   @VisibleForTesting
+   InvokeSyncToAsyncHttpMethod(Function<Invocation, Invocation> sync2async, Function<Invocation, HttpRequest> annotationProcessor,
+         HttpCommandExecutorService http, Function<HttpRequest, Function<HttpResponse, ?>> transformerForRequest,
+         TimeLimiter timeLimiter, InvocationConfig config,
+         @Named(PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
+      this.sync2async = sync2async;
+      this.annotationProcessor = annotationProcessor;
+      this.http = http;
+      this.userExecutor = userExecutor;
+      this.timeLimiter = timeLimiter;
+      this.transformerForRequest = transformerForRequest;
+      this.config = config;
+   }
+
+   @Override
+   public Object apply(Invocation in) {
+      if (isFuture(in.getInvokable())) {
+         return submit(in);
+      }
+      Invocation async = toAsync(in);
+      Optional<Long> timeoutNanos = config.getTimeoutNanos(async);
+      if (timeoutNanos.isPresent()) {
+         return invokeWithTimeout(async, timeoutNanos.get());
+      }
+      return invoke(async);
+   }
+
+   /**
+    * submits the {@linkplain HttpCommand} associated with {@code invocation},
+    * {@link #getTransformer(String, HttpCommand) parses its response}, and
+    * applies a {@link #getFallback(String, Invocation, HttpCommand) fallback}
+    * if a {@code Throwable} is encountered. Parsing and Fallback occur on the
+    * {@code userExecutor} thread.
+    */
+   public ListenableFuture<?> submit(Invocation invocation) {
+      String commandName = config.getCommandName(invocation);
+      HttpCommand command = toCommand(commandName, invocation);
+      Function<HttpResponse, ?> transformer = getTransformer(commandName, command);
+      org.jclouds.Fallback<?> fallback = getFallback(commandName, invocation, command);
+
+      logger.debug(">> submitting %s", commandName);
+      return withFallback(transform(http.submit(command), transformer, userExecutor), fallback);
+   }
+
+   /**
+    * invokes the {@linkplain HttpCommand} associated with {@code invocation},
+    * {@link #getTransformer(String, HttpCommand) parses its response}, and
+    * applies a {@link #getFallback(String, Invocation, HttpCommand) fallback}
+    * if a {@code Throwable} is encountered.
+    */
+   public Object invoke(Invocation invocation) {
+      String commandName = config.getCommandName(invocation);
+      HttpCommand command = toCommand(commandName, invocation);
+      Function<HttpResponse, ?> transformer = getTransformer(commandName, command);
+      org.jclouds.Fallback<?> fallback = getFallback(commandName, invocation, command);
+
+      logger.debug(">> invoking %s", commandName);
+      try {
+         return transformer.apply(http.invoke(command));
+      } catch (Throwable t) {
+         try {
+            return fallback.createOrPropagate(t);
+         } catch (Exception e) {
+            throw propagate(e);
+         }
+      }
+   }
+
+   /**
+    * calls {@link #invoke(Invocation)}, timing out after the specified time
+    * limit. If the target method call finished before the limit is reached, the
+    * return value or exception is propagated to the caller exactly as-is. If,
+    * on the other hand, the time limit is reached, we attempt to abort the call
+    * to the target, and throw an {@link UncheckedTimeoutException} to the
+    * caller.
+    * 
+    * @param invocation
+    *           the Invocation to invoke via {@link #invoke(Invocation)}
+    * @param limitNanos
+    *           with timeoutUnit, the maximum length of time to wait in
+    *           nanoseconds
+    * @throws InterruptedException
+    *            if our thread is interrupted during execution
+    * @throws UncheckedTimeoutException
+    *            if the time limit is reached
+    * @see TimeLimiter#callWithTimeout(Callable, long, TimeUnit, boolean)
+    */
+   public Object invokeWithTimeout(final Invocation invocation, final long limitNanos) {
+      String commandName = config.getCommandName(invocation);
+      HttpCommand command = toCommand(commandName, invocation);
+      org.jclouds.Fallback<?> fallback = getFallback(commandName, invocation, command);
+
+      logger.debug(">> blocking on %s for %s", invocation, limitNanos);
+      try {
+         return timeLimiter
+               .callWithTimeout(new InvokeAndTransform(commandName, command), limitNanos, NANOSECONDS, true);
+      } catch (Throwable t) {
+         try {
+            return fallback.createOrPropagate(t);
+         } catch (Exception e) {
+            throw propagate(e);
+         }
+      }
+   }
+
+   private org.jclouds.Fallback<?> getFallback(String commandName, Invocation invocation, HttpCommand command) {
+      HttpRequest request = command.getCurrentRequest();
+      org.jclouds.Fallback<?> fallback = config.getFallback(invocation);
+      if (fallback instanceof InvocationContext)
+         InvocationContext.class.cast(fallback).setContext(request);
+      logger.trace("<< exceptions from %s are parsed by %s", commandName, fallback.getClass().getSimpleName());
+      return fallback;
+   }
+
+   @VisibleForTesting
+   final class InvokeAndTransform implements Callable<Object> {
+      private final String commandName;
+      private final HttpCommand command;
+      private final Function<HttpResponse, ?> transformer;
+
+      InvokeAndTransform(String commandName, HttpCommand command) {
+         this.commandName = commandName;
+         this.command = command;
+         this.transformer = getTransformer(commandName, command);
+      }
+
+      @Override
+      public Object call() throws Exception {
+         return transformer.apply(http.invoke(command));
+      }
+
+      @Override
+      public int hashCode() {
+         return Objects.hashCode(commandName, command, transformer);
+      }
+
+      @Override
+      public boolean equals(Object obj) {
+         if (this == obj)
+            return true;
+         if (obj == null || getClass() != obj.getClass())
+            return false;
+         InvokeAndTransform that = InvokeAndTransform.class.cast(obj);
+         return equal(this.commandName, that.commandName) && equal(this.command, that.command)
+               && equal(this.transformer, that.transformer);
+      }
+
+      @Override
+      public String toString() {
+         return toStringHelper(this).add("commandName", commandName).add("command", command)
+               .add("transformer", transformer).toString();
+      }
+   }
+
+   /**
+    * looks up the corresponding {@code Invocation} that returns a
+    * {@code Future}. Only Invokables that return {@code Futures} are annotated
+    * in a way that can be parsed into an {@linkplain HttpRequest}.
+    */
+   private Invocation toAsync(Invocation in) {
+      Invocation async = sync2async.apply(in);
+      checkState(isFuture(async.getInvokable()), "not a future: %s", async);
+      return async;
+   }
+
+   private HttpCommand toCommand(String commandName, Invocation invocation) {
+      logger.trace(">> converting %s", commandName);
+      HttpRequest request = annotationProcessor.apply(invocation);
+      logger.trace("<< converted %s to %s", commandName, request.getRequestLine());
+      return new HttpCommand(request);
+   }
+
+   private Function<HttpResponse, ?> getTransformer(String commandName, HttpCommand command) {
+      HttpRequest request = command.getCurrentRequest();
+      Function<HttpResponse, ?> transformer = transformerForRequest.apply(request);
+      logger.trace("<< response from %s is parsed by %s", commandName, transformer.getClass().getSimpleName());
+      return transformer;
+   }
+
+   private boolean isFuture(Invokable<?, ?> in) {
+      return in.getReturnType().getRawType().equals(ListenableFuture.class);
+   }
+
+   @Override
+   public boolean equals(Object o) {
+      if (this == o)
+         return true;
+      if (o == null || getClass() != o.getClass())
+         return false;
+      InvokeSyncToAsyncHttpMethod that = InvokeSyncToAsyncHttpMethod.class.cast(o);
+      return equal(this.annotationProcessor, that.annotationProcessor);
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(annotationProcessor);
+   }
+
+   @Override
+   public String toString() {
+      return Objects.toStringHelper("").omitNullValues().add("annotationParser", annotationProcessor).toString();
+   }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/jclouds/rest/internal/UtilsImpl.java b/core/src/main/java/org/jclouds/rest/internal/UtilsImpl.java
index 8ac8246..5dd2bb1 100644
--- a/core/src/main/java/org/jclouds/rest/internal/UtilsImpl.java
+++ b/core/src/main/java/org/jclouds/rest/internal/UtilsImpl.java
@@ -29,7 +29,6 @@
 import org.jclouds.domain.Credentials;
 import org.jclouds.json.Json;
 import org.jclouds.logging.Logger.LoggerFactory;
-import org.jclouds.rest.HttpAsyncClient;
 import org.jclouds.rest.HttpClient;
 import org.jclouds.rest.Utils;
 import org.jclouds.xml.XMLParser;
@@ -48,7 +47,7 @@
 
    private final Json json;
    private final HttpClient simpleClient;
-   private final HttpAsyncClient simpleAsyncClient;
+   private final org.jclouds.rest.HttpAsyncClient simpleAsyncClient;
    private final Crypto encryption;
    private final DateService date;
    private final ListeningExecutorService userExecutor;
@@ -60,7 +59,7 @@
    private XMLParser xml;
 
    @Inject
-   protected UtilsImpl(Injector injector, Json json, XMLParser xml, HttpClient simpleClient, HttpAsyncClient simpleAsyncClient,
+   protected UtilsImpl(Injector injector, Json json, XMLParser xml, HttpClient simpleClient, org.jclouds.rest.HttpAsyncClient simpleAsyncClient,
          Crypto encryption, DateService date, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
             @Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor, EventBus eventBus,
             Map<String, Credentials> credentialStore, LoggerFactory loggerFactory) {
@@ -79,7 +78,8 @@
    }
 
    @Override
-   public HttpAsyncClient asyncHttp() {
+   @Deprecated
+   public org.jclouds.rest.HttpAsyncClient asyncHttp() {
       return simpleAsyncClient;
    }
 
@@ -104,7 +104,8 @@
    }
 
    @Override
-   public HttpAsyncClient getHttpAsyncClient() {
+   @Deprecated
+   public org.jclouds.rest.HttpAsyncClient getHttpAsyncClient() {
       return simpleAsyncClient;
    }
 
diff --git a/core/src/test/java/org/jclouds/config/BindApiContextWithWildcardExtendsExplicitAndRawTypeTest.java b/core/src/test/java/org/jclouds/config/BindApiContextWithWildcardExtendsExplicitAndRawTypeTest.java
new file mode 100644
index 0000000..ed078a2
--- /dev/null
+++ b/core/src/test/java/org/jclouds/config/BindApiContextWithWildcardExtendsExplicitAndRawTypeTest.java
@@ -0,0 +1,123 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.config;
+
+import static com.google.common.base.Suppliers.ofInstance;
+import static org.easymock.EasyMock.createMock;
+import static org.testng.Assert.assertEquals;
+
+import javax.inject.Inject;
+
+import org.jclouds.Context;
+import org.jclouds.domain.Credentials;
+import org.jclouds.http.IntegrationTestAsyncClient;
+import org.jclouds.http.IntegrationTestClient;
+import org.jclouds.providers.AnonymousProviderMetadata;
+import org.jclouds.providers.ProviderMetadata;
+import org.jclouds.providers.config.BindProviderMetadataContextAndCredentials;
+import org.jclouds.rest.ApiContext;
+import org.jclouds.rest.HttpApiMetadata;
+import org.jclouds.rest.Utils;
+import org.jclouds.rest.internal.BaseRestApiTest.MockModule;
+import org.testng.annotations.Test;
+
+import com.google.common.reflect.TypeToken;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "BindApiContextWithWildcardExtendsExplicitAndRawTypeTest")
+public class BindApiContextWithWildcardExtendsExplicitAndRawTypeTest {
+
+   @SuppressWarnings("rawtypes")
+   private static class ExpectedBindings {
+
+      private final ApiContext raw;
+      private final ApiContext<IntegrationTestClient> explicit;
+
+      @Inject
+      public ExpectedBindings(ApiContext raw, ApiContext<IntegrationTestClient> explicit) {
+         this.raw = raw;
+         this.explicit = explicit;
+      }
+
+   }
+
+   @Test
+   public void testRawAndExplicit() {
+      ProviderMetadata md = AnonymousProviderMetadata.forApiOnEndpoint(IntegrationTestClient.class, "http://localhost");
+
+      ExpectedBindings bindings = injectorFor(md).getInstance(ExpectedBindings.class);
+      assertEquals(bindings.raw, bindings.explicit);
+   }
+
+   private Injector injectorFor(ProviderMetadata md) {
+      return Guice.createInjector(new BindNameToContext("test"), new BindProviderMetadataContextAndCredentials(md,
+            ofInstance(new Credentials("user", "pass"))), new BindApiContextWithWildcardExtendsExplicitAndRawType(
+            HttpApiMetadata.class.cast(md.getApiMetadata())),
+
+            // stuff needed for ApiContextImpl
+            new MockModule(), new AbstractModule() {
+
+               @Override
+               protected void configure() {
+                  bind(Utils.class).toInstance(createMock(Utils.class));
+                  bind(IntegrationTestClient.class).toInstance(createMock(IntegrationTestClient.class));
+                  bind(IntegrationTestAsyncClient.class).toInstance(createMock(IntegrationTestAsyncClient.class));
+               }
+            });
+   }
+
+   @SuppressWarnings("rawtypes")
+   private static class ExpectedBindingsWithWildCardExtends {
+
+      private final ApiContext raw;
+      private final ApiContext<IntegrationTestClient> explicit;
+      private final ApiContext<? extends IntegrationTestClient> wildcardExtends;
+
+      @Inject
+      public ExpectedBindingsWithWildCardExtends(ApiContext raw, ApiContext<IntegrationTestClient> explicit,
+            ApiContext<? extends IntegrationTestClient> wildcardExtends) {
+         this.raw = raw;
+         this.explicit = explicit;
+         this.wildcardExtends = wildcardExtends;
+      }
+
+   }
+
+   @Test
+   public void testRawExplicitAndWildCardExtends() {
+      ProviderMetadata md = AnonymousProviderMetadata.forApiOnEndpoint(IntegrationTestClient.class, "http://localhost");
+
+      TypeToken<? extends Context> wildCardExtendsType = new TypeToken<ApiContext<? extends IntegrationTestClient>>() {
+         private static final long serialVersionUID = 1L;
+      };
+
+      md = md.toBuilder().apiMetadata(md.getApiMetadata().toBuilder().context(wildCardExtendsType).build()).build();
+
+      ExpectedBindingsWithWildCardExtends bindings = injectorFor(md).getInstance(
+            ExpectedBindingsWithWildCardExtends.class);
+      assertEquals(bindings.raw, bindings.explicit);
+      assertEquals(bindings.explicit, bindings.wildcardExtends);
+   }
+}
diff --git a/core/src/test/java/org/jclouds/http/IntegrationTestClient.java b/core/src/test/java/org/jclouds/http/IntegrationTestClient.java
index 822abb1..f111963 100644
--- a/core/src/test/java/org/jclouds/http/IntegrationTestClient.java
+++ b/core/src/test/java/org/jclouds/http/IntegrationTestClient.java
@@ -18,12 +18,42 @@
  */
 package org.jclouds.http;
 
-import java.io.Closeable;
+import static com.google.common.util.concurrent.Futures.immediateFuture;
 
+import java.io.Closeable;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.inject.Singleton;
+import javax.ws.rs.GET;
+import javax.ws.rs.HEAD;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.http.functions.ParseSax;
 import org.jclouds.http.options.HttpRequestOptions;
 import org.jclouds.io.Payload;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.XMLResponseParser;
+import org.jclouds.rest.binders.BindToJsonPayload;
+import org.jclouds.rest.binders.BindToStringPayload;
+import org.jclouds.util.Strings2;
 
+import com.google.common.base.Function;
 import com.google.common.collect.Multimap;
+import com.google.common.util.concurrent.ListenableFuture;
 import com.google.inject.Provides;
 
 /**
@@ -32,37 +62,144 @@
  * @author Adrian Cole
  */
 public interface IntegrationTestClient extends Closeable {
-   String rowdy(String path);
+   @Target({ ElementType.METHOD })
+   @Retention(RetentionPolicy.RUNTIME)
+   @HttpMethod("ROWDY")
+   public @interface ROWDY {
+   }
 
-   boolean exists(String path);
+   @ROWDY
+   @Path("/objects/{id}")
+   String rowdy(@PathParam("id") String path);
 
-   String synch(String id);
+   @HEAD
+   @Path("/objects/{id}")
+   @Fallback(FalseOnNotFoundOr404.class)
+   boolean exists(@PathParam("id") String path);
 
-   String download(String id);
+   @GET
+   @Path("/objects/{id}")
+   String download(@PathParam("id") String id);
 
    HttpResponse invoke(HttpRequest request);
+   
+   @GET
+   @Path("/{path}")
+   String synch(@PathParam("path") String id);
 
-   String downloadException(String id, HttpRequestOptions options);
+   @GET
+   @Path("/objects/{id}")
+   @Fallback(FooOnException.class)
+   String downloadException(@PathParam("id") String id, HttpRequestOptions options);
 
-   String synchException(String id, String header);
+   static class FooOnException implements org.jclouds.Fallback<String> {
+      public ListenableFuture<String> create(Throwable t) throws Exception {
+         return immediateFuture("foo");
+      }
 
-   String upload(String id, String toPut);
+      public String createOrPropagate(Throwable t) throws Exception {
+         return "foo";
+      }
+   }
 
-   String post(String id, String toPut);
+   @GET
+   @Path("/objects/{id}")
+   @Fallback(FooOnException.class)
+   String synchException(@PathParam("id") String id, @HeaderParam("Range") String header);
 
-   String postAsInputStream(String id, String toPut);
+   @PUT
+   @Path("/objects/{id}")
+   String upload(@PathParam("id") String id, @BinderParam(BindToStringPayload.class) String toPut);
 
-   Multimap<String, String> postPayloadAndReturnHeaders(String id, Payload payload);
+   @POST
+   @Path("/objects/{id}")
+   String post(@PathParam("id") String id, @BinderParam(BindToStringPayload.class) String toPut);
 
-   String postJson(String id, String toPut);
+   @POST
+   @Path("/objects/{id}")
+   String postAsInputStream(@PathParam("id") String id,
+         @BinderParam(BindToInputStreamPayload.class) String toPut);
 
-   String downloadFilter(String id, String header);
+   static class BindToInputStreamPayload extends BindToStringPayload {
+      @Override
+      public <R extends HttpRequest> R bindToRequest(R request, Object payload) {
+         request.setPayload(Strings2.toInputStream(payload.toString()));
+         request.getPayload().getContentMetadata().setContentLength((long) payload.toString().getBytes().length);
+         return request;
+      }
+   }
 
-   String download(String id, String header);
+   @Singleton
+   static class ResponsePayload implements Function<HttpResponse, Multimap<String, String>> {
 
-   String downloadAndParse(String id);
+      public Multimap<String, String> apply(HttpResponse from) {
+         return from.getHeaders();
+      }
 
-   void putNothing(String id);
+   }
+
+   @POST
+   @Path("/objects/{id}")
+   @ResponseParser(ResponsePayload.class)
+   Multimap<String, String> postPayloadAndReturnHeaders(@PathParam("id") String id, Payload payload);
+
+   @POST
+   @Path("/objects/{id}")
+   @MapBinder(BindToJsonPayload.class)
+   String postJson(@PathParam("id") String id, @PayloadParam("key") String toPut);
+
+   @GET
+   @Path("/objects/{id}")
+   @RequestFilters(Filter.class)
+   String downloadFilter(@PathParam("id") String id, @HeaderParam("filterme") String header);
+
+   static class Filter implements HttpRequestFilter {
+      public HttpRequest filter(HttpRequest request) throws HttpException {
+         if (request.getHeaders().containsKey("filterme")) {
+            request = request.toBuilder().replaceHeader("test", "test").build();
+         }
+         return request;
+      }
+   }
+
+   @GET
+   @Path("/objects/{id}")
+   String download(@PathParam("id") String id, @HeaderParam("test") String header);
+
+   @GET
+   @Path("/objects/{id}")
+   @XMLResponseParser(BarHandler.class)
+   String downloadAndParse(@PathParam("id") String id);
+
+   public static class BarHandler extends ParseSax.HandlerWithResult<String> {
+
+      private String bar = null;
+      private StringBuilder currentText = new StringBuilder();
+
+      @Override
+      public void endElement(String uri, String name, String qName) {
+         if (qName.equals("bar")) {
+            bar = currentText.toString();
+         }
+         currentText = new StringBuilder();
+      }
+
+      @Override
+      public void characters(char ch[], int start, int length) {
+         currentText.append(ch, start, length);
+
+      }
+
+      @Override
+      public String getResult() {
+         return bar;
+      }
+
+   }
+
+   @PUT
+   @Path("/objects/{id}")
+   void putNothing(@PathParam("id") String id);
 
    @Provides
    StringBuilder newStringBuilder();
diff --git a/core/src/test/java/org/jclouds/rest/config/RestModuleTest.java b/core/src/test/java/org/jclouds/rest/config/MappedHttpInvocationModuleTest.java
similarity index 88%
rename from core/src/test/java/org/jclouds/rest/config/RestModuleTest.java
rename to core/src/test/java/org/jclouds/rest/config/MappedHttpInvocationModuleTest.java
index 0a48f1e..1460ec5 100644
--- a/core/src/test/java/org/jclouds/rest/config/RestModuleTest.java
+++ b/core/src/test/java/org/jclouds/rest/config/MappedHttpInvocationModuleTest.java
@@ -43,7 +43,7 @@
  * @author Adrian Cole
  */
 @Test(groups = "unit")
-public class RestModuleTest {
+public class MappedHttpInvocationModuleTest {
    static interface Sync {
       String get();
    }
@@ -54,7 +54,7 @@
 
    public void testPutInvokablesWhenInterfacesMatch() {
       Cache<Invokable<?, ?>, Invokable<?, ?>> cache = CacheBuilder.newBuilder().build();
-      RestModule.putInvokables(Sync.class, Async.class, cache);
+      SyncToAsyncHttpInvocationModule.putInvokables(Sync.class, Async.class, cache);
 
       assertEquals(cache.size(), 1);
 
@@ -78,7 +78,7 @@
    @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = ".* has different typed exceptions than target .*")
    public void testPutInvokablesWhenInterfacesMatchExceptExceptions() {
       Cache<Invokable<?, ?>, Invokable<?, ?>> cache = CacheBuilder.newBuilder().build();
-      RestModule.putInvokables(Sync.class, AsyncWithException.class, cache);
+      SyncToAsyncHttpInvocationModule.putInvokables(Sync.class, AsyncWithException.class, cache);
    }
 
    private static interface AsyncWithMisnamedMethod {
@@ -88,7 +88,7 @@
    @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "no such method .*")
    public void testPutInvokablesWhenTargetMethodNotFound() {
       Cache<Invokable<?, ?>, Invokable<?, ?>> cache = CacheBuilder.newBuilder().build();
-      RestModule.putInvokables(Sync.class, AsyncWithMisnamedMethod.class, cache);
+      SyncToAsyncHttpInvocationModule.putInvokables(Sync.class, AsyncWithMisnamedMethod.class, cache);
    }
 
    static final Predicate<Entry<Invokable<?, ?>, Invokable<?, ?>>> isHttpInvokable = new Predicate<Map.Entry<Invokable<?, ?>, Invokable<?, ?>>>() {
@@ -99,7 +99,7 @@
    };
 
    public void testSeedKnownSync2AsyncIncludesHttpClientByDefault() {
-      Map<Invokable<?, ?>, Invokable<?, ?>> cache = RestModule.seedKnownSync2AsyncInvokables(
+      Map<Invokable<?, ?>, Invokable<?, ?>> cache = SyncToAsyncHttpInvocationModule.seedKnownSync2AsyncInvokables(
             ImmutableMap.<Class<?>, Class<?>> of()).asMap();
 
       assertEquals(cache.size(), 6);
@@ -107,7 +107,7 @@
    }
 
    public void testSeedKnownSync2AsyncInvokablesInterfacesMatch() {
-      Map<Invokable<?, ?>, Invokable<?, ?>> cache = RestModule.seedKnownSync2AsyncInvokables(
+      Map<Invokable<?, ?>, Invokable<?, ?>> cache = SyncToAsyncHttpInvocationModule.seedKnownSync2AsyncInvokables(
             ImmutableMap.<Class<?>, Class<?>> of(Sync.class, Async.class)).asMap();
 
       assertEquals(cache.size(), 7);
diff --git a/core/src/test/java/org/jclouds/rest/internal/BaseHttpApiMetadataTest.java b/core/src/test/java/org/jclouds/rest/internal/BaseHttpApiMetadataTest.java
new file mode 100644
index 0000000..2a58867
--- /dev/null
+++ b/core/src/test/java/org/jclouds/rest/internal/BaseHttpApiMetadataTest.java
@@ -0,0 +1,52 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rest.internal;
+import static org.jclouds.reflect.Reflection2.typeToken;
+
+import java.util.Set;
+
+import org.jclouds.View;
+import org.jclouds.apis.ApiMetadata;
+import org.jclouds.apis.Apis;
+import org.jclouds.apis.internal.BaseApiMetadataTest;
+import org.jclouds.rest.ApiContext;
+import org.jclouds.rest.HttpApiMetadata;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.reflect.TypeToken;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "unit")
+public abstract class BaseHttpApiMetadataTest extends BaseApiMetadataTest {
+
+   public BaseHttpApiMetadataTest(HttpApiMetadata<?> toTest, Set<TypeToken<? extends View>> views) {
+     super(toTest, views);
+   }
+
+   @Test
+   public void testContextAssignableFromRestContext() {
+      Set<ApiMetadata> all = ImmutableSet.copyOf(Apis.contextAssignableFrom(typeToken(ApiContext.class)));
+      assert all.contains(toTest) : String.format("%s not found in %s", toTest, all);
+   }
+
+}
diff --git a/core/src/test/java/org/jclouds/rest/internal/BaseRestApiExpectTest.java b/core/src/test/java/org/jclouds/rest/internal/BaseRestApiExpectTest.java
index 4154bab..b857ced 100644
--- a/core/src/test/java/org/jclouds/rest/internal/BaseRestApiExpectTest.java
+++ b/core/src/test/java/org/jclouds/rest/internal/BaseRestApiExpectTest.java
@@ -70,7 +70,7 @@
 import org.jclouds.io.Payloads;
 import org.jclouds.logging.config.NullLoggingModule;
 import org.jclouds.providers.ProviderMetadata;
-import org.jclouds.rest.RestApiMetadata;
+import org.jclouds.rest.HttpApiMetadata;
 import org.jclouds.rest.config.CredentialStoreModule;
 import org.jclouds.util.Strings2;
 import org.w3c.dom.Node;
@@ -557,11 +557,16 @@
          ApiMetadata am = (pm != null) ? pm.getApiMetadata() : checkNotNull(createApiMetadata(),
                   "either createApiMetadata or createProviderMetadata must be overridden");
 
-         builder = pm != null ? ContextBuilder.newBuilder(pm) : ContextBuilder.newBuilder(RestApiMetadata.class.cast(am));
+         builder = pm != null ? ContextBuilder.newBuilder(pm) : ContextBuilder.newBuilder(am);
       }
-
-      this.api = RestApiMetadata.class.cast(builder.getApiMetadata()).getApi();
-
+      ApiMetadata am = builder.getApiMetadata();
+      if (am instanceof HttpApiMetadata) {
+         this.api = HttpApiMetadata.class.cast(am).getApi();
+      } else if (am instanceof org.jclouds.rest.RestApiMetadata) {
+         this.api = org.jclouds.rest.RestApiMetadata.class.cast(am).getApi();
+      } else {
+         throw new UnsupportedOperationException("unsupported base type: " + am);
+      }
       // isolate tests from eachother, as default credentialStore is static
       return builder.credentials(identity, credential).modules(
                ImmutableSet.of(new ExpectModule(fn), new NullLoggingModule(), new CredentialStoreModule(new CopyInputStreamInputSupplierMap(
diff --git a/core/src/test/java/org/jclouds/rest/internal/InvokeHttpMethodTest.java b/core/src/test/java/org/jclouds/rest/internal/InvokeHttpMethodTest.java
index 71dade0..dc9f5ec 100644
--- a/core/src/test/java/org/jclouds/rest/internal/InvokeHttpMethodTest.java
+++ b/core/src/test/java/org/jclouds/rest/internal/InvokeHttpMethodTest.java
@@ -18,9 +18,7 @@
  */
 package org.jclouds.rest.internal;
 
-import static org.easymock.EasyMock.anyObject;
 import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.eq;
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.verify;
@@ -48,10 +46,7 @@
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
-import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
 import com.google.common.util.concurrent.TimeLimiter;
 
 /**
@@ -62,17 +57,11 @@
 public class InvokeHttpMethodTest {
 
    public static interface ThingApi {
+      @Named("ns:get")
       HttpResponse get();
    }
 
-   public static interface ThingAsyncApi {
-      @Named("ns:get")
-      ListenableFuture<HttpResponse> get();
-   }
-
    private Invocation get;
-   private Invocation asyncGet;
-   private Function<Invocation, Invocation> sync2async;
    private HttpRequest getRequest = HttpRequest.builder().method("GET").endpoint("http://get").build();
    private HttpCommand getCommand = new HttpCommand(getRequest);
    private Function<Invocation, HttpRequest> toRequest;
@@ -80,15 +69,12 @@
    @BeforeClass
    void setupInvocations() throws SecurityException, NoSuchMethodException {
       get = Invocation.create(method(ThingApi.class, "get"), ImmutableList.of());
-      asyncGet = Invocation.create(method(ThingAsyncApi.class, "get"), ImmutableList.of());
-      sync2async = Functions.forMap(ImmutableMap.of(get, asyncGet));
-      toRequest = Functions.forMap(ImmutableMap.of(asyncGet, getRequest));
+      toRequest = Functions.forMap(ImmutableMap.of(get, getRequest));
    }
 
    @SuppressWarnings("unchecked")
    private Function<HttpRequest, Function<HttpResponse, ?>> transformerForRequest = Function.class.cast(Functions
          .constant(Functions.identity()));
-   private ListeningExecutorService userThreads = MoreExecutors.sameThreadExecutor();
 
    private HttpResponse response = HttpResponse.builder().statusCode(200).payload("foo").build();
    private HttpCommandExecutorService http;
@@ -108,10 +94,9 @@
       fallback = createMock(org.jclouds.Fallback.class);
       config = createMock(InvocationConfig.class);
       future = createMock(ListenableFuture.class);
-      invokeHttpMethod = new InvokeHttpMethod(sync2async, toRequest, http, transformerForRequest, timeLimiter, config,
-            userThreads);
-      expect(config.getCommandName(asyncGet)).andReturn("ns:get");
-      expect(config.getFallback(asyncGet)).andReturn(fallback);
+      invokeHttpMethod = new InvokeHttpMethod(toRequest, http, transformerForRequest, timeLimiter, config);
+      expect(config.getCommandName(get)).andReturn("ns:get");
+      expect(config.getFallback(get)).andReturn(fallback);
    }
 
    @AfterMethod
@@ -120,7 +105,7 @@
    }
 
    public void testMethodWithTimeoutRunsTimeLimiter() throws Exception {
-      expect(config.getTimeoutNanos(asyncGet)).andReturn(Optional.of(250000000l));
+      expect(config.getTimeoutNanos(get)).andReturn(Optional.of(250000000l));
       InvokeAndTransform invoke = invokeHttpMethod.new InvokeAndTransform("ns:get", getCommand);
       expect(timeLimiter.callWithTimeout(invoke, 250000000, TimeUnit.NANOSECONDS, true)).andReturn(response);
       replay(http, timeLimiter, fallback, config, future);
@@ -128,24 +113,17 @@
    }
 
    public void testMethodWithNoTimeoutCallGetDirectly() throws Exception {
-      expect(config.getTimeoutNanos(asyncGet)).andReturn(Optional.<Long> absent());
+      expect(config.getTimeoutNanos(get)).andReturn(Optional.<Long> absent());
       expect(http.invoke(new HttpCommand(getRequest))).andReturn(response);
       replay(http, timeLimiter, fallback, config, future);
       invokeHttpMethod.apply(get);
    }
 
-   public void testAsyncMethodSubmitsRequest() throws Exception {
-      expect(http.submit(new HttpCommand(getRequest))).andReturn(future);
-      future.addListener(anyObject(Runnable.class), eq(userThreads));
-      replay(http, timeLimiter, fallback, config, future);
-      invokeHttpMethod.apply(asyncGet);
-   }
-
    private HttpResponse fallbackResponse = HttpResponse.builder().statusCode(200).payload("bar").build();
 
    public void testDirectCallRunsFallbackCreateOrPropagate() throws Exception {
       IllegalStateException exception = new IllegalStateException();
-      expect(config.getTimeoutNanos(asyncGet)).andReturn(Optional.<Long> absent());
+      expect(config.getTimeoutNanos(get)).andReturn(Optional.<Long> absent());
       expect(http.invoke(new HttpCommand(getRequest))).andThrow(exception);
       expect(fallback.createOrPropagate(exception)).andReturn(fallbackResponse);
       replay(http, timeLimiter, fallback, config, future);
@@ -154,24 +132,11 @@
 
    public void testTimeLimitedRunsFallbackCreateOrPropagate() throws Exception {
       IllegalStateException exception = new IllegalStateException();
-      expect(config.getTimeoutNanos(asyncGet)).andReturn(Optional.of(250000000l));
+      expect(config.getTimeoutNanos(get)).andReturn(Optional.of(250000000l));
       InvokeAndTransform invoke = invokeHttpMethod.new InvokeAndTransform("ns:get", getCommand);
       expect(timeLimiter.callWithTimeout(invoke, 250000000, TimeUnit.NANOSECONDS, true)).andThrow(exception);
       expect(fallback.createOrPropagate(exception)).andReturn(fallbackResponse);
       replay(http, timeLimiter, fallback, config, future);
       assertEquals(invokeHttpMethod.apply(get), fallbackResponse);
    }
-
-   @SuppressWarnings("unchecked")
-   public void testSubmitRunsFallbackCreateOnGet() throws Exception {
-      IllegalStateException exception = new IllegalStateException();
-      expect(http.submit(new HttpCommand(getRequest))).andReturn(
-            Futures.<HttpResponse> immediateFailedFuture(exception));
-      expect(fallback.create(exception)).andReturn(Futures.<HttpResponse> immediateFuture(fallbackResponse));
-      // not using the field, as you can see above we are making an immediate
-      // failed future instead.
-      future = createMock(ListenableFuture.class);
-      replay(http, timeLimiter, fallback, config, future);
-      assertEquals(ListenableFuture.class.cast(invokeHttpMethod.apply(asyncGet)).get(), fallbackResponse);
-   }
 }
diff --git a/core/src/test/java/org/jclouds/rest/internal/InvokeMappedHttpMethodTest.java b/core/src/test/java/org/jclouds/rest/internal/InvokeMappedHttpMethodTest.java
new file mode 100644
index 0000000..811a9ba
--- /dev/null
+++ b/core/src/test/java/org/jclouds/rest/internal/InvokeMappedHttpMethodTest.java
@@ -0,0 +1,177 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.rest.internal;
+
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.jclouds.reflect.Reflection2.method;
+import static org.testng.Assert.assertEquals;
+
+import java.util.concurrent.TimeUnit;
+
+import javax.inject.Named;
+
+import org.jclouds.http.HttpCommand;
+import org.jclouds.http.HttpCommandExecutorService;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.reflect.Invocation;
+import org.jclouds.rest.config.InvocationConfig;
+import org.jclouds.rest.internal.InvokeSyncToAsyncHttpMethod.InvokeAndTransform;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.TimeLimiter;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", singleThreaded = true)
+public class InvokeMappedHttpMethodTest {
+
+   public static interface ThingApi {
+      HttpResponse get();
+   }
+
+   public static interface ThingAsyncApi {
+      @Named("ns:get")
+      ListenableFuture<HttpResponse> get();
+   }
+
+   private Invocation get;
+   private Invocation asyncGet;
+   private Function<Invocation, Invocation> sync2async;
+   private HttpRequest getRequest = HttpRequest.builder().method("GET").endpoint("http://get").build();
+   private HttpCommand getCommand = new HttpCommand(getRequest);
+   private Function<Invocation, HttpRequest> toRequest;
+
+   @BeforeClass
+   void setupInvocations() throws SecurityException, NoSuchMethodException {
+      get = Invocation.create(method(ThingApi.class, "get"), ImmutableList.of());
+      asyncGet = Invocation.create(method(ThingAsyncApi.class, "get"), ImmutableList.of());
+      sync2async = Functions.forMap(ImmutableMap.of(get, asyncGet));
+      toRequest = Functions.forMap(ImmutableMap.of(asyncGet, getRequest));
+   }
+
+   @SuppressWarnings("unchecked")
+   private Function<HttpRequest, Function<HttpResponse, ?>> transformerForRequest = Function.class.cast(Functions
+         .constant(Functions.identity()));
+   private ListeningExecutorService userThreads = MoreExecutors.sameThreadExecutor();
+
+   private HttpResponse response = HttpResponse.builder().statusCode(200).payload("foo").build();
+   private HttpCommandExecutorService http;
+   private TimeLimiter timeLimiter;
+   @SuppressWarnings("rawtypes")
+   private org.jclouds.Fallback fallback;
+   private InvocationConfig config;
+   private InvokeSyncToAsyncHttpMethod invokeHttpMethod;
+
+   private ListenableFuture<HttpResponse> future;
+
+   @SuppressWarnings("unchecked")
+   @BeforeMethod
+   void createMocks() {
+      http = createMock(HttpCommandExecutorService.class);
+      timeLimiter = createMock(TimeLimiter.class);
+      fallback = createMock(org.jclouds.Fallback.class);
+      config = createMock(InvocationConfig.class);
+      future = createMock(ListenableFuture.class);
+      invokeHttpMethod = new InvokeSyncToAsyncHttpMethod(sync2async, toRequest, http, transformerForRequest, timeLimiter, config,
+            userThreads);
+      expect(config.getCommandName(asyncGet)).andReturn("ns:get");
+      expect(config.getFallback(asyncGet)).andReturn(fallback);
+   }
+
+   @AfterMethod
+   void verifyMocks() {
+      verify(http, timeLimiter, fallback, config, future);
+   }
+
+   public void testMethodWithTimeoutRunsTimeLimiter() throws Exception {
+      expect(config.getTimeoutNanos(asyncGet)).andReturn(Optional.of(250000000l));
+      InvokeAndTransform invoke = invokeHttpMethod.new InvokeAndTransform("ns:get", getCommand);
+      expect(timeLimiter.callWithTimeout(invoke, 250000000, TimeUnit.NANOSECONDS, true)).andReturn(response);
+      replay(http, timeLimiter, fallback, config, future);
+      invokeHttpMethod.apply(get);
+   }
+
+   public void testMethodWithNoTimeoutCallGetDirectly() throws Exception {
+      expect(config.getTimeoutNanos(asyncGet)).andReturn(Optional.<Long> absent());
+      expect(http.invoke(new HttpCommand(getRequest))).andReturn(response);
+      replay(http, timeLimiter, fallback, config, future);
+      invokeHttpMethod.apply(get);
+   }
+
+   public void testAsyncMethodSubmitsRequest() throws Exception {
+      expect(http.submit(new HttpCommand(getRequest))).andReturn(future);
+      future.addListener(anyObject(Runnable.class), eq(userThreads));
+      replay(http, timeLimiter, fallback, config, future);
+      invokeHttpMethod.apply(asyncGet);
+   }
+
+   private HttpResponse fallbackResponse = HttpResponse.builder().statusCode(200).payload("bar").build();
+
+   public void testDirectCallRunsFallbackCreateOrPropagate() throws Exception {
+      IllegalStateException exception = new IllegalStateException();
+      expect(config.getTimeoutNanos(asyncGet)).andReturn(Optional.<Long> absent());
+      expect(http.invoke(new HttpCommand(getRequest))).andThrow(exception);
+      expect(fallback.createOrPropagate(exception)).andReturn(fallbackResponse);
+      replay(http, timeLimiter, fallback, config, future);
+      assertEquals(invokeHttpMethod.apply(get), fallbackResponse);
+   }
+
+   public void testTimeLimitedRunsFallbackCreateOrPropagate() throws Exception {
+      IllegalStateException exception = new IllegalStateException();
+      expect(config.getTimeoutNanos(asyncGet)).andReturn(Optional.of(250000000l));
+      InvokeAndTransform invoke = invokeHttpMethod.new InvokeAndTransform("ns:get", getCommand);
+      expect(timeLimiter.callWithTimeout(invoke, 250000000, TimeUnit.NANOSECONDS, true)).andThrow(exception);
+      expect(fallback.createOrPropagate(exception)).andReturn(fallbackResponse);
+      replay(http, timeLimiter, fallback, config, future);
+      assertEquals(invokeHttpMethod.apply(get), fallbackResponse);
+   }
+
+   @SuppressWarnings("unchecked")
+   public void testSubmitRunsFallbackCreateOnGet() throws Exception {
+      IllegalStateException exception = new IllegalStateException();
+      expect(http.submit(new HttpCommand(getRequest))).andReturn(
+            Futures.<HttpResponse> immediateFailedFuture(exception));
+      expect(fallback.create(exception)).andReturn(Futures.<HttpResponse> immediateFuture(fallbackResponse));
+      // not using the field, as you can see above we are making an immediate
+      // failed future instead.
+      future = createMock(ListenableFuture.class);
+      replay(http, timeLimiter, fallback, config, future);
+      assertEquals(ListenableFuture.class.cast(invokeHttpMethod.apply(asyncGet)).get(), fallbackResponse);
+   }
+}
diff --git a/providers/dynect/src/main/java/org/jclouds/dynect/v3/DynECTApi.java b/providers/dynect/src/main/java/org/jclouds/dynect/v3/DynECTApi.java
index fcf6778..19119f4 100644
--- a/providers/dynect/src/main/java/org/jclouds/dynect/v3/DynECTApi.java
+++ b/providers/dynect/src/main/java/org/jclouds/dynect/v3/DynECTApi.java
@@ -18,24 +18,34 @@
  */
 package org.jclouds.dynect.v3;
 
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+
 import java.io.Closeable;
 
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.dynect.v3.domain.Job;
 import org.jclouds.dynect.v3.features.RecordApi;
 import org.jclouds.dynect.v3.features.SessionApi;
 import org.jclouds.dynect.v3.features.ZoneApi;
+import org.jclouds.dynect.v3.filters.AlwaysAddContentType;
+import org.jclouds.dynect.v3.filters.SessionManager;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.rest.annotations.Delegate;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.RequestFilters;
 
 /**
  * Provides access to DynECT Managed DNS through the API2 api
  * <p/>
  * 
- * @see DynECTAsyncApi
- * @see <a href="https://manage.dynect.net/help/docs/api2/rest/"
- *      />
+ * @see <a href="https://manage.dynect.net/help/docs/api2/rest/" />
  * @author Adrian Cole
  */
 public interface DynECTApi extends Closeable {
@@ -46,8 +56,15 @@
     *           The ID of the job
     * @return null, if not found
     */
+   @Named("GetJob")
+   @GET
+   @Path("/Job/{jobId}")
+   @RequestFilters({ AlwaysAddContentType.class, SessionManager.class })
+   @Headers(keys = "API-Version", values = "{jclouds.api-version}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Consumes(APPLICATION_JSON)
    @Nullable
-   Job getJob(long jobId);
+   Job getJob(@PathParam("jobId") long jobId);
 
    /**
     * Provides synchronous access to Session features.
@@ -60,7 +77,7 @@
     */
    @Delegate
    ZoneApi getZoneApi();
-   
+
    /**
     * Provides synchronous access to Record features
     */
diff --git a/providers/dynect/src/main/java/org/jclouds/dynect/v3/DynECTApiMetadata.java b/providers/dynect/src/main/java/org/jclouds/dynect/v3/DynECTApiMetadata.java
index 89be1af..614d7fa 100644
--- a/providers/dynect/src/main/java/org/jclouds/dynect/v3/DynECTApiMetadata.java
+++ b/providers/dynect/src/main/java/org/jclouds/dynect/v3/DynECTApiMetadata.java
@@ -23,8 +23,8 @@
 
 import org.jclouds.apis.ApiMetadata;
 import org.jclouds.dynect.v3.config.DynECTParserModule;
-import org.jclouds.dynect.v3.config.DynECTRestClientModule;
-import org.jclouds.rest.internal.BaseRestApiMetadata;
+import org.jclouds.dynect.v3.config.DynECTHttpApiModule;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
 
 import com.google.common.collect.ImmutableSet;
 import com.google.inject.Module;
@@ -34,10 +34,8 @@
  * 
  * @author Adrian Cole
  */
-public class DynECTApiMetadata extends BaseRestApiMetadata {
+public class DynECTApiMetadata extends BaseHttpApiMetadata<DynECTApi> {
    
-   public static final String ANONYMOUS_IDENTITY = "ANONYMOUS";
-
    @Override
    public Builder toBuilder() {
       return new Builder().fromApiMetadata(this);
@@ -52,27 +50,24 @@
    }
 
    public static Properties defaultProperties() {
-      Properties properties = BaseRestApiMetadata.defaultProperties();
+      Properties properties = BaseHttpApiMetadata.defaultProperties();
       return properties;
    }
 
-   public static class Builder extends BaseRestApiMetadata.Builder<Builder> {
+   public static class Builder extends BaseHttpApiMetadata.Builder<DynECTApi, Builder> {
 
       protected Builder() {
-         super(DynECTApi.class, DynECTAsyncApi.class);
           id("dynect")
          .name("DynECT API2")
-         .identityName("Username (or " + ANONYMOUS_IDENTITY + " if anonymous)")
-         .defaultIdentity(ANONYMOUS_IDENTITY)
-         .credentialName("Password")
-         .defaultCredential(ANONYMOUS_IDENTITY)
+         .identityName("${customer}:${userName}")
+         .credentialName("${password}")
          .documentation(URI.create("https://manage.dynect.net/help/docs/api2/rest/"))
          .version("3.3.8")
          .defaultEndpoint("https://api2.dynect.net/REST")
          .defaultProperties(DynECTApiMetadata.defaultProperties())
          .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
                                      .add(DynECTParserModule.class)
-                                     .add(DynECTRestClientModule.class).build());
+                                     .add(DynECTHttpApiModule.class).build());
       }
       
       @Override
diff --git a/providers/dynect/src/main/java/org/jclouds/dynect/v3/DynECTAsyncApi.java b/providers/dynect/src/main/java/org/jclouds/dynect/v3/DynECTAsyncApi.java
deleted file mode 100644
index 14f86b2..0000000
--- a/providers/dynect/src/main/java/org/jclouds/dynect/v3/DynECTAsyncApi.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.dynect.v3;
-
-import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
-
-import java.io.Closeable;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.dynect.v3.domain.Job;
-import org.jclouds.dynect.v3.features.RecordAsyncApi;
-import org.jclouds.dynect.v3.features.SessionAsyncApi;
-import org.jclouds.dynect.v3.features.ZoneAsyncApi;
-import org.jclouds.dynect.v3.filters.AlwaysAddContentType;
-import org.jclouds.dynect.v3.filters.SessionManager;
-import org.jclouds.rest.annotations.Delegate;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.Headers;
-import org.jclouds.rest.annotations.RequestFilters;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to DynECT Managed DNS through the API2 api
- * <p/>
- * 
- * @see DynECTApi
- * @see <a href="https://manage.dynect.net/help/docs/api2/rest/" />
- * @author Adrian Cole
- * @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(DynECTApi.class)} as
- *             {@link DynECTAsyncApi} interface will be removed in jclouds 1.7.
- */
-
-public interface DynECTAsyncApi extends Closeable {
-   /**
-    * @see DynECTApi#getJob
-    */
-   @Named("GetJob")
-   @GET
-   @Path("/Job/{jobId}")
-   @RequestFilters({ AlwaysAddContentType.class, SessionManager.class })
-   @Headers(keys = "API-Version", values = "{jclouds.api-version}")
-   @Fallback(NullOnNotFoundOr404.class)
-   @Consumes(APPLICATION_JSON)
-   ListenableFuture<Job> getJob(@PathParam("jobId") long jobId);
-
-   /**
-    * Provides asynchronous access to Session features.
-    */
-   @Delegate
-   SessionAsyncApi getSessionApi();
-
-   /**
-    * Provides asynchronous access to Zone features.
-    */
-   @Delegate
-   ZoneAsyncApi getZoneApi();
-
-   /**
-    * Provides asynchronous access to Record features
-    */
-   @Delegate
-   RecordAsyncApi getRecordApiForZone(@PathParam("zone") String zone);
-}
diff --git a/providers/dynect/src/main/java/org/jclouds/dynect/v3/binders/CreateRecordBinder.java b/providers/dynect/src/main/java/org/jclouds/dynect/v3/binders/CreateRecordBinder.java
new file mode 100644
index 0000000..6efd16b
--- /dev/null
+++ b/providers/dynect/src/main/java/org/jclouds/dynect/v3/binders/CreateRecordBinder.java
@@ -0,0 +1,55 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.dynect.v3.binders;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.http.Uris.uriBuilder;
+
+import java.net.URI;
+
+import javax.inject.Inject;
+
+import org.jclouds.dynect.v3.domain.CreateRecord;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.json.Json;
+import org.jclouds.rest.Binder;
+
+import com.google.common.collect.ImmutableMap;
+
+public class CreateRecordBinder implements Binder {
+   private final Json json;
+
+   @Inject
+   CreateRecordBinder(Json json){
+      this.json = checkNotNull(json, "json");
+   }
+
+   @SuppressWarnings("unchecked")
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Object arg) {
+      CreateRecord<?> in = CreateRecord.class.cast(checkNotNull(arg, "record to create"));
+      URI path = uriBuilder(request.getEndpoint())
+                  .build(ImmutableMap.<String, Object> builder()
+                                     .put("type", in.getType())
+                                     .put("fqdn", in.getFQDN()).build());
+      return (R) request.toBuilder()
+                        .endpoint(path)
+                        .payload(json.toJson(ImmutableMap.of("rdata", in.getRData(), "ttl", in.getTTL()))).build();
+   }
+}
diff --git a/providers/dynect/src/main/java/org/jclouds/dynect/v3/binders/RecordIdBinder.java b/providers/dynect/src/main/java/org/jclouds/dynect/v3/binders/RecordIdBinder.java
new file mode 100644
index 0000000..e2ed0fe
--- /dev/null
+++ b/providers/dynect/src/main/java/org/jclouds/dynect/v3/binders/RecordIdBinder.java
@@ -0,0 +1,45 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.dynect.v3.binders;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.http.Uris.uriBuilder;
+
+import java.net.URI;
+
+import org.jclouds.dynect.v3.domain.RecordId;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+import com.google.common.collect.ImmutableMap;
+
+public class RecordIdBinder implements Binder {
+   @SuppressWarnings("unchecked")
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Object recordId) {
+      RecordId valueToAppend = RecordId.class.cast(checkNotNull(recordId, "recordId"));
+      URI path = uriBuilder(request.getEndpoint()).appendPath("/{type}Record/{zone}/{fqdn}/{id}").build(
+            ImmutableMap.<String, Object> builder()
+                        .put("type", valueToAppend.getType())
+                        .put("zone", valueToAppend.getZone())
+                        .put("fqdn", valueToAppend.getFQDN())
+                        .put("id", valueToAppend.getId()).build());
+      return (R) request.toBuilder().endpoint(path).build();
+   }
+}
\ No newline at end of file
diff --git a/providers/dynect/src/main/java/org/jclouds/dynect/v3/config/DynECTRestClientModule.java b/providers/dynect/src/main/java/org/jclouds/dynect/v3/config/DynECTHttpApiModule.java
similarity index 77%
rename from providers/dynect/src/main/java/org/jclouds/dynect/v3/config/DynECTRestClientModule.java
rename to providers/dynect/src/main/java/org/jclouds/dynect/v3/config/DynECTHttpApiModule.java
index dbfda6b..a20c5ef 100644
--- a/providers/dynect/src/main/java/org/jclouds/dynect/v3/config/DynECTRestClientModule.java
+++ b/providers/dynect/src/main/java/org/jclouds/dynect/v3/config/DynECTHttpApiModule.java
@@ -25,7 +25,6 @@
 import java.net.HttpURLConnection;
 import java.net.Proxy;
 import java.net.URI;
-import java.util.Map;
 
 import javax.inject.Inject;
 import javax.inject.Named;
@@ -36,13 +35,7 @@
 import org.jclouds.Constants;
 import org.jclouds.concurrent.SingleThreaded;
 import org.jclouds.dynect.v3.DynECTApi;
-import org.jclouds.dynect.v3.DynECTAsyncApi;
-import org.jclouds.dynect.v3.features.RecordApi;
-import org.jclouds.dynect.v3.features.RecordAsyncApi;
 import org.jclouds.dynect.v3.features.SessionApi;
-import org.jclouds.dynect.v3.features.SessionAsyncApi;
-import org.jclouds.dynect.v3.features.ZoneApi;
-import org.jclouds.dynect.v3.features.ZoneAsyncApi;
 import org.jclouds.dynect.v3.filters.SessionManager;
 import org.jclouds.dynect.v3.handlers.DynECTErrorHandler;
 import org.jclouds.dynect.v3.handlers.GetJobRedirectionRetryHandler;
@@ -60,12 +53,11 @@
 import org.jclouds.http.internal.HttpWire;
 import org.jclouds.http.internal.JavaUrlHttpCommandExecutorService;
 import org.jclouds.io.ContentMetadataCodec;
-import org.jclouds.rest.ConfiguresRestClient;
-import org.jclouds.rest.config.RestClientModule;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.config.HttpApiModule;
 
 import com.google.common.base.Function;
 import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.util.concurrent.ListeningExecutorService;
 
 /**
@@ -73,18 +65,12 @@
  * 
  * @author Adrian Cole
  */
-@ConfiguresRestClient
+@ConfiguresHttpApi
 // only one job at a time or error "This session already has a job running"
 @SingleThreaded
-public class DynECTRestClientModule extends RestClientModule<DynECTApi, DynECTAsyncApi> {
+public class DynECTHttpApiModule extends HttpApiModule<DynECTApi> {
 
-   public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()
-         .put(SessionApi.class, SessionAsyncApi.class)
-         .put(ZoneApi.class, ZoneAsyncApi.class)
-         .put(RecordApi.class, RecordAsyncApi.class).build();
-
-   public DynECTRestClientModule() {
-      super(DELEGATE_MAP);
+   public DynECTHttpApiModule() {
    }
 
    @Override
@@ -105,16 +91,15 @@
       bind(SessionManager.class);
       bind(RedirectionRetryHandler.class).to(GetJobRedirectionRetryHandler.class);
       super.configure();
-      // Bind apis that are used directly vs via DynECTApi
-      bindHttpApi(binder(), SessionApi.class, SessionAsyncApi.class);
-
-      // dynect returns the following as a 200.
-      // {"status": "failure", "data": {}, "job_id": 274509427, "msgs":
-      // [{"INFO": "token: This session already has a job running", "SOURCE":
-      // "API-B", "ERR_CD": "OPERATION_FAILED", "LVL": "ERROR"}]}
+      // for authentication filters
+      bindHttpApi(binder(), SessionApi.class);
       bind(JavaUrlHttpCommandExecutorService.class).to(SillyRabbit200sAreForSuccess.class);
    }
 
+   // dynect returns the following as a 200.
+   // {"status": "failure", "data": {}, "job_id": 274509427, "msgs":
+   // [{"INFO": "token: This session already has a job running", "SOURCE":
+   // "API-B", "ERR_CD": "OPERATION_FAILED", "LVL": "ERROR"}]}
    @Singleton
    private static class SillyRabbit200sAreForSuccess extends JavaUrlHttpCommandExecutorService {
 
@@ -129,8 +114,11 @@
                untrustedSSLContextProvider, proxyForURI);
       }
 
+      /**
+       * synchronized to prevent multiple callers from overlapping requests on the same session
+       */
       @Override
-      protected HttpResponse invoke(HttpURLConnection connection) throws IOException, InterruptedException {
+      synchronized protected HttpResponse invoke(HttpURLConnection connection) throws IOException, InterruptedException {
          HttpResponse response = super.invoke(connection);
          if (response.getStatusCode() == 200) {
             byte[] data = closeClientButKeepContentStream(response);
diff --git a/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/RecordApi.java b/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/RecordApi.java
index b4352e4..e026a41 100644
--- a/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/RecordApi.java
+++ b/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/RecordApi.java
@@ -18,9 +18,24 @@
  */
 package org.jclouds.dynect.v3.features;
 
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+
 import java.util.Map;
 
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.dynect.v3.DynECTExceptions.JobStillRunningException;
+import org.jclouds.dynect.v3.binders.CreateRecordBinder;
+import org.jclouds.dynect.v3.binders.RecordIdBinder;
 import org.jclouds.dynect.v3.domain.CreateRecord;
 import org.jclouds.dynect.v3.domain.Job;
 import org.jclouds.dynect.v3.domain.Record;
@@ -36,42 +51,71 @@
 import org.jclouds.dynect.v3.domain.rdata.SRVData;
 import org.jclouds.dynect.v3.domain.rdata.SSHFPData;
 import org.jclouds.dynect.v3.domain.rdata.TXTData;
+import org.jclouds.dynect.v3.filters.AlwaysAddContentType;
+import org.jclouds.dynect.v3.filters.SessionManager;
+import org.jclouds.dynect.v3.functions.ToRecordIds;
 import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
 
 import com.google.common.collect.FluentIterable;
 
 /**
- * @see RecordAsyncApi
  * @author Adrian Cole
  */
+@Headers(keys = "API-Version", values = "{jclouds.api-version}")
+@RequestFilters({ AlwaysAddContentType.class, SessionManager.class })
 public interface RecordApi {
    /**
-    * Retrieves a list of resource record ids for all records of any type in the given zone.
+    * Retrieves a list of resource record ids for all records of any type in the
+    * given zone.
     * 
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
+   @Named("GetAllRecord")
+   @GET
+   @Path("/AllRecord/{zone}")
+   @ResponseParser(ToRecordIds.class)
    FluentIterable<RecordId> list() throws JobStillRunningException;
 
    /**
-    * Retrieves a list of resource record ids for all records of the fqdn in the given zone
+    * Retrieves a list of resource record ids for all records of the fqdn in the
+    * given zone
     * 
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
-   FluentIterable<RecordId> listByFQDN(String fqdn) throws JobStillRunningException;
+   @Named("GetRecord")
+   @GET
+   @Path("/AllRecord/{zone}/{fqdn}")
+   @ResponseParser(ToRecordIds.class)
+   @Fallback(EmptyFluentIterableOnNotFoundOr404.class)
+   FluentIterable<RecordId> listByFQDN(@PathParam("fqdn") String fqdn) throws JobStillRunningException;
 
    /**
-    * Retrieves a list of resource record ids for all records of the fqdn and type in the given zone
+    * Retrieves a list of resource record ids for all records of the fqdn and
+    * type in the given zone
     * 
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
-   FluentIterable<RecordId> listByFQDNAndType(String fqdn, String type) throws JobStillRunningException;
+   @Named("GetRecord")
+   @GET
+   @Path("/{type}Record/{zone}/{fqdn}")
+   @ResponseParser(ToRecordIds.class)
+   @Fallback(EmptyFluentIterableOnNotFoundOr404.class)
+   FluentIterable<RecordId> listByFQDNAndType(@PathParam("fqdn") String fqdn, @PathParam("type") String type)
+         throws JobStillRunningException;
 
    /**
-    * Schedules addition of a new record into the current session. Calling {@link ZoneApi#publish(String)} will publish
-    * the zone, creating the record.
+    * Schedules addition of a new record into the current session. Calling
+    * {@link ZoneApi#publish(String)} will publish the zone, creating the
+    * record.
     * 
     * @param newRecord
     *           record to create
@@ -79,20 +123,31 @@
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
-   Job scheduleCreate(CreateRecord<?> newRecord) throws JobStillRunningException;
+   @Named("CreateRecord")
+   @POST
+   @Path("/{type}Record/{zone}/{fqdn}")
+   @Consumes(APPLICATION_JSON)
+   @Produces(APPLICATION_JSON)
+   Job scheduleCreate(@BinderParam(CreateRecordBinder.class) CreateRecord<?> newRecord) throws JobStillRunningException;
 
    /**
-    * Schedules deletion of a record into the current session. Calling {@link ZoneApi#publish(String)} will publish the
-    * changes, deleting the record.
+    * Schedules deletion of a record into the current session. Calling
+    * {@link ZoneApi#publish(String)} will publish the changes, deleting the
+    * record.
     * 
     * @param recordId
     *           record to delete
-    * @return job relating to the scheduled deletion or null, if the record never existed.
+    * @return job relating to the scheduled deletion or null, if the record
+    *         never existed.
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
    @Nullable
-   Job scheduleDelete(RecordId recordId) throws JobStillRunningException;
+   @Named("DeleteRecord")
+   @DELETE
+   @Fallback(NullOnNotFoundOr404.class)
+   @Consumes(APPLICATION_JSON)
+   Job scheduleDelete(@BinderParam(RecordIdBinder.class) RecordId recordId) throws JobStillRunningException;
 
    /**
     * retrieves a resource record without regard to type
@@ -101,7 +156,13 @@
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
-   Record<? extends Map<String, Object>> get(RecordId recordId) throws JobStillRunningException;
+   @Named("GetRecord")
+   @GET
+   @SelectJson("data")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Record<? extends Map<String, Object>> get(@BinderParam(RecordIdBinder.class) RecordId recordId)
+         throws JobStillRunningException;
 
    /**
     * Gets the {@link AAAARecord} or null if not present.
@@ -114,7 +175,14 @@
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
-   Record<AAAAData> getAAAA(String fqdn, long recordId) throws JobStillRunningException;
+   @Named("GetAAAARecord")
+   @GET
+   @Path("/AAAARecord/{zone}/{fqdn}/{id}")
+   @SelectJson("data")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Record<AAAAData> getAAAA(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId)
+         throws JobStillRunningException;
 
    /**
     * Gets the {@link ARecord} or null if not present.
@@ -127,7 +195,13 @@
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
-   Record<AData> getA(String fqdn, long recordId) throws JobStillRunningException;
+   @Named("GetARecord")
+   @GET
+   @Path("/ARecord/{zone}/{fqdn}/{id}")
+   @SelectJson("data")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Record<AData> getA(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId) throws JobStillRunningException;
 
    /**
     * Gets the {@link CNAMERecord} or null if not present.
@@ -140,7 +214,14 @@
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
-   Record<CNAMEData> getCNAME(String fqdn, long recordId) throws JobStillRunningException;
+   @Named("GetCNAMERecord")
+   @GET
+   @Path("/CNAMERecord/{zone}/{fqdn}/{id}")
+   @SelectJson("data")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Record<CNAMEData> getCNAME(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId)
+         throws JobStillRunningException;
 
    /**
     * Gets the {@link MXRecord} or null if not present.
@@ -153,7 +234,13 @@
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
-   Record<MXData> getMX(String fqdn, long recordId) throws JobStillRunningException;
+   @Named("GetMXRecord")
+   @GET
+   @Path("/MXRecord/{zone}/{fqdn}/{id}")
+   @SelectJson("data")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Record<MXData> getMX(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId) throws JobStillRunningException;
 
    /**
     * Gets the {@link NSRecord} or null if not present.
@@ -166,7 +253,13 @@
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
-   Record<NSData> getNS(String fqdn, long recordId) throws JobStillRunningException;
+   @Named("GetNSRecord")
+   @GET
+   @Path("/NSRecord/{zone}/{fqdn}/{id}")
+   @SelectJson("data")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Record<NSData> getNS(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId) throws JobStillRunningException;
 
    /**
     * Gets the {@link PTRRecord} or null if not present.
@@ -179,7 +272,14 @@
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
-   Record<PTRData> getPTR(String fqdn, long recordId) throws JobStillRunningException;
+   @Named("GetPTRRecord")
+   @GET
+   @Path("/PTRRecord/{zone}/{fqdn}/{id}")
+   @SelectJson("data")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Record<PTRData> getPTR(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId)
+         throws JobStillRunningException;
 
    /**
     * Gets the {@link SOARecord} or null if not present.
@@ -192,7 +292,13 @@
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
-   SOARecord getSOA(String fqdn, long recordId) throws JobStillRunningException;
+   @Named("GetSOARecord")
+   @GET
+   @Path("/SOARecord/{zone}/{fqdn}/{id}")
+   @SelectJson("data")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   SOARecord getSOA(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId) throws JobStillRunningException;
 
    /**
     * Gets the {@link SPFRecord} or null if not present.
@@ -205,7 +311,14 @@
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
-   Record<SPFData> getSPF(String fqdn, long recordId) throws JobStillRunningException;
+   @Named("GetSPFRecord")
+   @GET
+   @Path("/SPFRecord/{zone}/{fqdn}/{id}")
+   @SelectJson("data")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Record<SPFData> getSPF(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId)
+         throws JobStillRunningException;
 
    /**
     * Gets the {@link SRVRecord} or null if not present.
@@ -218,7 +331,14 @@
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
-   Record<SRVData> getSRV(String fqdn, long recordId) throws JobStillRunningException;
+   @Named("GetSRVRecord")
+   @GET
+   @Path("/SRVRecord/{zone}/{fqdn}/{id}")
+   @SelectJson("data")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Record<SRVData> getSRV(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId)
+         throws JobStillRunningException;
 
    /**
     * Gets the {@link SSHFPRecord} or null if not present.
@@ -231,7 +351,14 @@
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
-   Record<SSHFPData> getSSHFP(String fqdn, long recordId) throws JobStillRunningException;
+   @Named("GetSSHFPRecord")
+   @GET
+   @Path("/SSHFPRecord/{zone}/{fqdn}/{id}")
+   @SelectJson("data")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Record<SSHFPData> getSSHFP(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId)
+         throws JobStillRunningException;
 
    /**
     * Gets the {@link TXTRecord} or null if not present.
@@ -244,5 +371,12 @@
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
-   Record<TXTData> getTXT(String fqdn, long recordId) throws JobStillRunningException;
+   @Named("GetTXTRecord")
+   @GET
+   @Path("/TXTRecord/{zone}/{fqdn}/{id}")
+   @SelectJson("data")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   Record<TXTData> getTXT(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId)
+         throws JobStillRunningException;
 }
\ No newline at end of file
diff --git a/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/RecordAsyncApi.java b/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/RecordAsyncApi.java
deleted file mode 100644
index b6badf1..0000000
--- a/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/RecordAsyncApi.java
+++ /dev/null
@@ -1,291 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, String 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.dynect.v3.features;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
-import static org.jclouds.http.Uris.uriBuilder;
-
-import java.net.URI;
-import java.util.Map;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-
-import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.dynect.v3.DynECTExceptions.JobStillRunningException;
-import org.jclouds.dynect.v3.domain.CreateRecord;
-import org.jclouds.dynect.v3.domain.Job;
-import org.jclouds.dynect.v3.domain.Record;
-import org.jclouds.dynect.v3.domain.RecordId;
-import org.jclouds.dynect.v3.domain.SOARecord;
-import org.jclouds.dynect.v3.domain.rdata.AAAAData;
-import org.jclouds.dynect.v3.domain.rdata.AData;
-import org.jclouds.dynect.v3.domain.rdata.CNAMEData;
-import org.jclouds.dynect.v3.domain.rdata.MXData;
-import org.jclouds.dynect.v3.domain.rdata.NSData;
-import org.jclouds.dynect.v3.domain.rdata.PTRData;
-import org.jclouds.dynect.v3.domain.rdata.SPFData;
-import org.jclouds.dynect.v3.domain.rdata.SRVData;
-import org.jclouds.dynect.v3.domain.rdata.SSHFPData;
-import org.jclouds.dynect.v3.domain.rdata.TXTData;
-import org.jclouds.dynect.v3.filters.AlwaysAddContentType;
-import org.jclouds.dynect.v3.filters.SessionManager;
-import org.jclouds.dynect.v3.functions.ToRecordIds;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.json.Json;
-import org.jclouds.rest.Binder;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.Headers;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.ResponseParser;
-import org.jclouds.rest.annotations.SelectJson;
-
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * 
- * @see RecordApi
- * @see <a
- *      href="https://manage.dynect.net/help/docs/api2/rest/resources/AllRecord.html">doc</a>
- * @author Adrian Cole
- */
-@Headers(keys = "API-Version", values = "{jclouds.api-version}")
-@RequestFilters({ AlwaysAddContentType.class, SessionManager.class })
-public interface RecordAsyncApi {
-
-   /**
-    * @see RecordApi#list
-    */
-   @Named("GetAllRecord")
-   @GET
-   @Path("/AllRecord/{zone}")
-   @ResponseParser(ToRecordIds.class)
-   ListenableFuture<FluentIterable<RecordId>> list() throws JobStillRunningException;
-
-   /**
-    * @see RecordApi#listByFQDN
-    */
-   @Named("GetRecord")
-   @GET
-   @Path("/AllRecord/{zone}/{fqdn}")
-   @ResponseParser(ToRecordIds.class)
-   @Fallback(EmptyFluentIterableOnNotFoundOr404.class)
-   ListenableFuture<FluentIterable<RecordId>> listByFQDN(@PathParam("fqdn") String fqdn)
-         throws JobStillRunningException;
-
-   /**
-    * @see RecordApi#listByFQDNAndType
-    */
-   @Named("GetRecord")
-   @GET
-   @Path("/{type}Record/{zone}/{fqdn}")
-   @ResponseParser(ToRecordIds.class)
-   @Fallback(EmptyFluentIterableOnNotFoundOr404.class)
-   ListenableFuture<FluentIterable<RecordId>> listByFQDNAndType(@PathParam("fqdn") String fqdn,
-         @PathParam("type") String type) throws JobStillRunningException;
-
-   /**
-    * @see RecordApi#scheduleCreate
-    */
-   @Named("CreateRecord")
-   @POST
-   @Path("/{type}Record/{zone}/{fqdn}")
-   @Consumes(APPLICATION_JSON)
-   @Produces(APPLICATION_JSON)
-   ListenableFuture<Job> scheduleCreate(@BinderParam(CreateRecordBinder.class) CreateRecord<?> newRecord)
-         throws JobStillRunningException;
-
-   static class CreateRecordBinder implements Binder {
-      private final Json json;
-
-      @Inject
-      CreateRecordBinder(Json json){
-         this.json = checkNotNull(json, "json");
-      }
-
-      @SuppressWarnings("unchecked")
-      @Override
-      public <R extends HttpRequest> R bindToRequest(R request, Object arg) {
-         CreateRecord<?> in = CreateRecord.class.cast(checkNotNull(arg, "record to create"));
-         URI path = uriBuilder(request.getEndpoint())
-                     .build(ImmutableMap.<String, Object> builder()
-                                        .put("type", in.getType())
-                                        .put("fqdn", in.getFQDN()).build());
-         return (R) request.toBuilder()
-                           .endpoint(path)
-                           .payload(json.toJson(ImmutableMap.of("rdata", in.getRData(), "ttl", in.getTTL()))).build();
-      }
-   }
-
-   /**
-    * @see RecordApi#scheduleDelete
-    */
-   @Named("DeleteRecord")
-   @DELETE
-   @Fallback(NullOnNotFoundOr404.class)
-   @Consumes(APPLICATION_JSON)
-   ListenableFuture<Job> scheduleDelete(@BinderParam(RecordIdBinder.class) RecordId recordId) throws JobStillRunningException;
-
-   /**
-    * @see RecordApi#get
-    */
-   @Named("GetRecord")
-   @GET
-   @SelectJson("data")
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Record<? extends Map<String, Object>>> get(@BinderParam(RecordIdBinder.class) RecordId recordId) throws JobStillRunningException;
-
-   static class RecordIdBinder implements Binder {
-      @SuppressWarnings("unchecked")
-      @Override
-      public <R extends HttpRequest> R bindToRequest(R request, Object recordId) {
-         RecordId valueToAppend = RecordId.class.cast(checkNotNull(recordId, "recordId"));
-         URI path = uriBuilder(request.getEndpoint())
-                     .appendPath("/{type}Record/{zone}/{fqdn}/{id}")
-                     .build(ImmutableMap.<String, Object> builder()
-                                        .put("type", valueToAppend.getType())
-                                        .put("zone", valueToAppend.getZone())
-                                        .put("fqdn", valueToAppend.getFQDN())
-                                        .put("id", valueToAppend.getId()).build());
-         return (R) request.toBuilder().endpoint(path).build();
-      }
-   }
-
-   /**
-    * @see RecordApi#getAAAA
-    */
-   @Named("GetAAAARecord")
-   @GET
-   @Path("/AAAARecord/{zone}/{fqdn}/{id}")
-   @SelectJson("data")
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Record<AAAAData>> getAAAA(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId) throws JobStillRunningException;
-
-   /**
-    * @see RecordApi#getA
-    */
-   @Named("GetARecord")
-   @GET
-   @Path("/ARecord/{zone}/{fqdn}/{id}")
-   @SelectJson("data")
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Record<AData>> getA(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId) throws JobStillRunningException;
-
-   /**
-    * @see RecordApi#getCNAME
-    */
-   @Named("GetCNAMERecord")
-   @GET
-   @Path("/CNAMERecord/{zone}/{fqdn}/{id}")
-   @SelectJson("data")
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Record<CNAMEData>> getCNAME(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId) throws JobStillRunningException;
-
-   /**
-    * @see RecordApi#getMX
-    */
-   @Named("GetMXRecord")
-   @GET
-   @Path("/MXRecord/{zone}/{fqdn}/{id}")
-   @SelectJson("data")
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Record<MXData>> getMX(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId) throws JobStillRunningException;
-
-   /**
-    * @see RecordApi#getNS
-    */
-   @Named("GetNSRecord")
-   @GET
-   @Path("/NSRecord/{zone}/{fqdn}/{id}")
-   @SelectJson("data")
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Record<NSData>> getNS(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId) throws JobStillRunningException;
-
-   /**
-    * @see RecordApi#getPTR
-    */
-   @Named("GetPTRRecord")
-   @GET
-   @Path("/PTRRecord/{zone}/{fqdn}/{id}")
-   @SelectJson("data")
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Record<PTRData>> getPTR(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId) throws JobStillRunningException;
-
-   /**
-    * @see RecordApi#getSOA
-    */
-   @Named("GetSOARecord")
-   @GET
-   @Path("/SOARecord/{zone}/{fqdn}/{id}")
-   @SelectJson("data")
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<SOARecord> getSOA(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId) throws JobStillRunningException;
-
-   /**
-    * @see RecordApi#getSPF
-    */
-   @Named("GetSPFRecord")
-   @GET
-   @Path("/SPFRecord/{zone}/{fqdn}/{id}")
-   @SelectJson("data")
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Record<SPFData>> getSPF(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId) throws JobStillRunningException;
-
-   /**
-    * @see RecordApi#getSRV
-    */
-   @Named("GetSRVRecord")
-   @GET
-   @Path("/SRVRecord/{zone}/{fqdn}/{id}")
-   @SelectJson("data")
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Record<SRVData>> getSRV(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId) throws JobStillRunningException;
-
-   /**
-    * @see RecordApi#getSSHFP
-    */
-   @Named("GetSSHFPRecord")
-   @GET
-   @Path("/SSHFPRecord/{zone}/{fqdn}/{id}")
-   @SelectJson("data")
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Record<SSHFPData>> getSSHFP(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId) throws JobStillRunningException;
-
-   /**
-    * @see RecordApi#getTXT
-    */
-   @Named("GetTXTRecord")
-   @GET
-   @Path("/TXTRecord/{zone}/{fqdn}/{id}")
-   @SelectJson("data")
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Record<TXTData>> getTXT(@PathParam("fqdn") String fqdn, @PathParam("id") long recordId) throws JobStillRunningException;
-}
diff --git a/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/SessionApi.java b/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/SessionApi.java
index fc6fcf2..ce0505b 100644
--- a/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/SessionApi.java
+++ b/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/SessionApi.java
@@ -18,21 +18,46 @@
  */
 package org.jclouds.dynect.v3.features;
 
+import javax.inject.Named;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.dynect.v3.DynECTFallbacks.FalseOn400;
 import org.jclouds.dynect.v3.domain.Session;
 import org.jclouds.dynect.v3.domain.SessionCredentials;
+import org.jclouds.dynect.v3.filters.AlwaysAddContentType;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.binders.BindToJsonPayload;
 
 /**
- * @see SessionAsyncApi
  * @see <a
  *      href="https://manage.dynect.net/help/docs/api2/rest/resources/Session.html"
  *      />
  * @author Adrian Cole
  */
+@Headers(keys = "API-Version", values = "{jclouds.api-version}")
+@Path("/Session")
+@RequestFilters(AlwaysAddContentType.class)
 public interface SessionApi {
 
-   Session login(SessionCredentials credentials);
+   @Named("POST:Session")
+   @POST
+   @SelectJson("data")
+   Session login(@BinderParam(BindToJsonPayload.class) SessionCredentials credentials);
 
-   boolean isValid(String token);
+   @Named("GET:Session")
+   @GET
+   @Fallback(FalseOn400.class)
+   boolean isValid(@HeaderParam("Auth-Token") String token);
 
-   void logout(String token);
+   @Named("DELETE:Session")
+   @DELETE
+   void logout(@HeaderParam("Auth-Token") String token);
 }
\ No newline at end of file
diff --git a/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/SessionAsyncApi.java b/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/SessionAsyncApi.java
deleted file mode 100644
index 5eabd50..0000000
--- a/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/SessionAsyncApi.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.dynect.v3.features;
-
-import javax.inject.Named;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.HeaderParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.dynect.v3.DynECTFallbacks.FalseOn400;
-import org.jclouds.dynect.v3.domain.Session;
-import org.jclouds.dynect.v3.domain.SessionCredentials;
-import org.jclouds.dynect.v3.filters.AlwaysAddContentType;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.Headers;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SelectJson;
-import org.jclouds.rest.binders.BindToJsonPayload;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to DynECT Managed DNS through the API2 api
- * <p/>
- * 
- * @see SessionApi
- * @see <a href="https://manage.dynect.net/help/docs/api2/rest/" />
- * @author Adrian Cole
- */
-@Headers(keys = "API-Version", values = "{jclouds.api-version}")
-@Path("/Session")
-@RequestFilters(AlwaysAddContentType.class)
-public interface SessionAsyncApi {
-
-   /**
-    * @see SessionApi#create
-    */
-   @Named("POST:Session")
-   @POST
-   @SelectJson("data")
-   ListenableFuture<Session> login(@BinderParam(BindToJsonPayload.class) SessionCredentials credentials);
-
-   /**
-    * @see SessionApi#isValid
-    */
-   @Named("GET:Session")
-   @GET
-   @Fallback(FalseOn400.class)
-   ListenableFuture<Boolean> isValid(@HeaderParam("Auth-Token") String token);
-
-   /**
-    * @see SessionApi#logout
-    */
-   @Named("DELETE:Session")
-   @DELETE
-   ListenableFuture<Void> logout(@HeaderParam("Auth-Token") String token);
-}
diff --git a/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/ZoneApi.java b/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/ZoneApi.java
index 0ebde9f..e90d1d4 100644
--- a/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/ZoneApi.java
+++ b/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/ZoneApi.java
@@ -18,21 +18,49 @@
  */
 package org.jclouds.dynect.v3.features;
 
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
 import org.jclouds.dynect.v3.DynECTExceptions.JobStillRunningException;
 import org.jclouds.dynect.v3.DynECTExceptions.TargetExistsException;
 import org.jclouds.dynect.v3.domain.CreatePrimaryZone;
+import org.jclouds.dynect.v3.domain.CreatePrimaryZone.ToFQDN;
 import org.jclouds.dynect.v3.domain.Job;
 import org.jclouds.dynect.v3.domain.Zone;
 import org.jclouds.dynect.v3.domain.Zone.SerialStyle;
+import org.jclouds.dynect.v3.filters.AlwaysAddContentType;
+import org.jclouds.dynect.v3.filters.SessionManager;
+import org.jclouds.dynect.v3.functions.ExtractZoneNames;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.rest.ResourceNotFoundException;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.ParamParser;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.Transform;
+import org.jclouds.rest.binders.BindToJsonPayload;
 
 import com.google.common.collect.FluentIterable;
 
 /**
- * @see ZoneAsyncApi
  * @author Adrian Cole
  */
+@Headers(keys = "API-Version", values = "{jclouds.api-version}")
+@RequestFilters({ AlwaysAddContentType.class, SessionManager.class })
 public interface ZoneApi {
    /**
     * Lists all zone ids.
@@ -40,11 +68,16 @@
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
+   @Named("ListZones")
+   @GET
+   @Path("/Zone")
+   @SelectJson("data")
+   @Transform(ExtractZoneNames.class)
    FluentIterable<String> list() throws JobStillRunningException;
 
    /**
-    * Schedules addition of a new primary zone into the current session. Calling {@link ZoneApi#publish(String)} will
-    * publish the zone, creating the zone.
+    * Schedules addition of a new primary zone into the current session. Calling
+    * {@link ZoneApi#publish(String)} will publish the zone, creating the zone.
     * 
     * @param zone
     *           required parameters to create the zone.
@@ -54,11 +87,18 @@
     * @throws TargetExistsException
     *            if the same fqdn exists
     */
-   Job scheduleCreate(CreatePrimaryZone zone) throws JobStillRunningException, TargetExistsException;
+   @Named("CreatePrimaryZone")
+   @POST
+   @Path("/Zone/{fqdn}")
+   @Consumes(APPLICATION_JSON)
+   Job scheduleCreate(
+         @PathParam("fqdn") @ParamParser(ToFQDN.class) @BinderParam(BindToJsonPayload.class) CreatePrimaryZone createZone)
+         throws JobStillRunningException, TargetExistsException;
 
    /**
-    * Schedules addition of a new primary zone with one hour default TTL and {@link SerialStyle#INCREMENT} into the
-    * current session. Calling {@link ZoneApi#publish(String)} will publish the zone, creating the zone.
+    * Schedules addition of a new primary zone with one hour default TTL and
+    * {@link SerialStyle#INCREMENT} into the current session. Calling
+    * {@link ZoneApi#publish(String)} will publish the zone, creating the zone.
     * 
     * @param fqdn
     *           fqdn of the zone to create {@ex. jclouds.org}
@@ -70,42 +110,65 @@
     * @throws TargetExistsException
     *            if the same fqdn exists
     */
-   Job scheduleCreateWithContact(String fqdn, String contact) throws JobStillRunningException, TargetExistsException;
+   @Named("CreatePrimaryZone")
+   @POST
+   @Produces(APPLICATION_JSON)
+   @Payload("%7B\"rname\":\"{contact}\",\"serial_style\":\"increment\",\"ttl\":3600%7D")
+   @Path("/Zone/{fqdn}")
+   @Consumes(APPLICATION_JSON)
+   Job scheduleCreateWithContact(@PathParam("fqdn") String fqdn, @PayloadParam("contact") String contact)
+         throws JobStillRunningException, TargetExistsException;
 
    /**
     * Retrieves information about the specified zone.
     * 
     * @param fqdn
-    *           fqdn of the zone to get information about. ex {@code jclouds.org}
+    *           fqdn of the zone to get information about. ex
+    *           {@code jclouds.org}
     * @return null if not found
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
+   @Named("GetZone")
+   @GET
+   @Path("/Zone/{fqdn}")
+   @SelectJson("data")
+   @Fallback(NullOnNotFoundOr404.class)
    @Nullable
-   Zone get(String fqdn) throws JobStillRunningException;
+   Zone get(@PathParam("fqdn") String fqdn) throws JobStillRunningException;
 
    /**
-    * Deletes the zone.  No need to call @link ZoneApi#publish(String)}.
+    * Deletes the zone. No need to call @link ZoneApi#publish(String)}.
     * 
     * @param fqdn
     *           zone to delete
-    * @return job relating to the scheduled deletion or null, if the zone never existed.
+    * @return job relating to the scheduled deletion or null, if the zone never
+    *         existed.
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
+   @Named("DeleteZone")
+   @DELETE
+   @Path("/Zone/{fqdn}")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Consumes(APPLICATION_JSON)
    @Nullable
-   Job delete(String fqdn) throws JobStillRunningException;
+   Job delete(@PathParam("fqdn") String fqdn) throws JobStillRunningException;
 
    /**
-    * Deletes changes to the specified zone that have been created during the current session but not yet published to
-    * the zone.
+    * Deletes changes to the specified zone that have been created during the
+    * current session but not yet published to the zone.
     * 
     * @param fqdn
     *           fqdn of the zone to delete changes from ex {@code jclouds.org}
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
-   Job deleteChanges(String fqdn) throws JobStillRunningException;
+   @Named("DeleteZoneChanges")
+   @DELETE
+   @Path("/ZoneChanges/{fqdn}")
+   @Consumes(APPLICATION_JSON)
+   Job deleteChanges(@PathParam("fqdn") String fqdn) throws JobStillRunningException;
 
    /**
     * Publishes the current zone
@@ -117,7 +180,13 @@
     * @throws ResourceNotFoundException
     *            if the zone doesn't exist
     */
-   Zone publish(String fqdn) throws JobStillRunningException, ResourceNotFoundException;
+   @Named("PublishZone")
+   @PUT
+   @Path("/Zone/{fqdn}")
+   @Produces(APPLICATION_JSON)
+   @Payload("{\"publish\":true}")
+   @SelectJson("data")
+   Zone publish(@PathParam("fqdn") String fqdn) throws JobStillRunningException, ResourceNotFoundException;
 
    /**
     * freezes the specified zone.
@@ -127,7 +196,13 @@
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
-   Job freeze(String fqdn) throws JobStillRunningException;
+   @Named("FreezeZone")
+   @PUT
+   @Path("/Zone/{fqdn}")
+   @Produces(APPLICATION_JSON)
+   @Payload("{\"freeze\":true}")
+   @Consumes(APPLICATION_JSON)
+   Job freeze(@PathParam("fqdn") String fqdn) throws JobStillRunningException;
 
    /**
     * thaws the specified zone.
@@ -137,5 +212,11 @@
     * @throws JobStillRunningException
     *            if a different job in the session is still running
     */
-   Job thaw(String fqdn) throws JobStillRunningException;
+   @Named("ThawZone")
+   @PUT
+   @Path("/Zone/{fqdn}")
+   @Produces(APPLICATION_JSON)
+   @Payload("{\"thaw\":true}")
+   @Consumes(APPLICATION_JSON)
+   Job thaw(@PathParam("fqdn") String fqdn) throws JobStillRunningException;
 }
\ No newline at end of file
diff --git a/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/ZoneAsyncApi.java b/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/ZoneAsyncApi.java
deleted file mode 100644
index 8569b81..0000000
--- a/providers/dynect/src/main/java/org/jclouds/dynect/v3/features/ZoneAsyncApi.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, String 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.dynect.v3.features;
-
-import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.dynect.v3.DynECTExceptions.JobStillRunningException;
-import org.jclouds.dynect.v3.DynECTExceptions.TargetExistsException;
-import org.jclouds.dynect.v3.domain.CreatePrimaryZone;
-import org.jclouds.dynect.v3.domain.CreatePrimaryZone.ToFQDN;
-import org.jclouds.dynect.v3.domain.Job;
-import org.jclouds.dynect.v3.domain.Zone;
-import org.jclouds.dynect.v3.filters.AlwaysAddContentType;
-import org.jclouds.dynect.v3.filters.SessionManager;
-import org.jclouds.dynect.v3.functions.ExtractZoneNames;
-import org.jclouds.rest.ResourceNotFoundException;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.Headers;
-import org.jclouds.rest.annotations.ParamParser;
-import org.jclouds.rest.annotations.Payload;
-import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SelectJson;
-import org.jclouds.rest.annotations.Transform;
-import org.jclouds.rest.binders.BindToJsonPayload;
-
-import com.google.common.collect.FluentIterable;
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * 
- * @see ZoneApi
- * @see <a
- *      href="https://manage.dynect.net/help/docs/api2/rest/resources/Zone.html">doc</a>
- * @author Adrian Cole
- */
-@Headers(keys = "API-Version", values = "{jclouds.api-version}")
-@RequestFilters({ AlwaysAddContentType.class, SessionManager.class })
-public interface ZoneAsyncApi {
-
-   /**
-    * @see ZoneApi#list
-    */
-   @Named("ListZones")
-   @GET
-   @Path("/Zone")
-   @SelectJson("data")
-   @Transform(ExtractZoneNames.class)
-   ListenableFuture<FluentIterable<String>> list() throws JobStillRunningException;
-
-   /**
-    * @see ZoneApi#get
-    */
-   @Named("GetZone")
-   @GET
-   @Path("/Zone/{fqdn}")
-   @SelectJson("data")
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Zone> get(@PathParam("fqdn") String fqdn) throws JobStillRunningException;
-
-   /**
-    * @see ZoneApi#scheduleCreate
-    */
-   @Named("CreatePrimaryZone")
-   @POST
-   @Path("/Zone/{fqdn}")
-   @Consumes(APPLICATION_JSON)
-   ListenableFuture<Job> scheduleCreate(
-         @PathParam("fqdn") @ParamParser(ToFQDN.class) @BinderParam(BindToJsonPayload.class) CreatePrimaryZone createZone)
-         throws JobStillRunningException, TargetExistsException;
-
-   /**
-    * @see ZoneApi#scheduleCreateWithContact
-    */
-   @Named("CreatePrimaryZone")
-   @POST
-   @Produces(APPLICATION_JSON)
-   @Payload("%7B\"rname\":\"{contact}\",\"serial_style\":\"increment\",\"ttl\":3600%7D")
-   @Path("/Zone/{fqdn}")
-   @Consumes(APPLICATION_JSON)
-   ListenableFuture<Job> scheduleCreateWithContact(@PathParam("fqdn") String fqdn,
-         @PayloadParam("contact") String contact) throws JobStillRunningException, TargetExistsException;
-
-   /**
-    * @see ZoneApi#delete
-    */
-   @Named("DeleteZone")
-   @DELETE
-   @Path("/Zone/{fqdn}")
-   @Fallback(NullOnNotFoundOr404.class)
-   @Consumes(APPLICATION_JSON)
-   ListenableFuture<Job> delete(@PathParam("fqdn") String fqdn) throws JobStillRunningException;
-
-   /**
-    * @see ZoneApi#deleteChanges
-    */
-   @Named("DeleteZoneChanges")
-   @DELETE
-   @Path("/ZoneChanges/{fqdn}")
-   @Consumes(APPLICATION_JSON)
-   ListenableFuture<Job> deleteChanges(@PathParam("fqdn") String fqdn) throws JobStillRunningException;
-
-   /**
-    * @see ZoneApi#publish
-    */
-   @Named("PublishZone")
-   @PUT
-   @Path("/Zone/{fqdn}")
-   @Produces(APPLICATION_JSON)
-   @Payload("{\"publish\":true}")
-   @SelectJson("data")
-   ListenableFuture<Zone> publish(@PathParam("fqdn") String fqdn) throws JobStillRunningException, ResourceNotFoundException;
-   
-   /**
-    * @see ZoneApi#freeze
-    */
-   @Named("FreezeZone")
-   @PUT
-   @Path("/Zone/{fqdn}")
-   @Produces(APPLICATION_JSON)
-   @Payload("{\"freeze\":true}")
-   @Consumes(APPLICATION_JSON)
-   ListenableFuture<Job> freeze(@PathParam("fqdn") String fqdn) throws JobStillRunningException;
-
-   /**
-    * @see ZoneApi#thaw
-    */
-   @Named("ThawZone")
-   @PUT
-   @Path("/Zone/{fqdn}")
-   @Produces(APPLICATION_JSON)
-   @Payload("{\"thaw\":true}")
-   @Consumes(APPLICATION_JSON)
-   ListenableFuture<Job> thaw(@PathParam("fqdn") String fqdn) throws JobStillRunningException;
-}
diff --git a/providers/dynect/src/test/java/org/jclouds/dynect/v3/internal/BaseDynECTExpectTest.java b/providers/dynect/src/test/java/org/jclouds/dynect/v3/internal/BaseDynECTExpectTest.java
index 9dd5fd0..ac28059 100644
--- a/providers/dynect/src/test/java/org/jclouds/dynect/v3/internal/BaseDynECTExpectTest.java
+++ b/providers/dynect/src/test/java/org/jclouds/dynect/v3/internal/BaseDynECTExpectTest.java
@@ -22,13 +22,13 @@
 import static javax.ws.rs.core.Response.Status.NOT_FOUND;
 import static javax.ws.rs.core.Response.Status.OK;
 
-import org.jclouds.dynect.v3.config.DynECTRestClientModule;
+import org.jclouds.dynect.v3.config.DynECTHttpApiModule;
 import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
 import org.jclouds.http.config.SSLModule;
 import org.jclouds.io.Payload;
 import org.jclouds.io.Payloads;
-import org.jclouds.rest.ConfiguresRestClient;
+import org.jclouds.rest.ConfiguresHttpApi;
 import org.jclouds.rest.internal.BaseRestApiExpectTest;
 
 import com.google.inject.Module;
@@ -47,11 +47,11 @@
 
    @Override
    protected Module createModule() {
-      return new TestDynECTRestClientModule();
+      return new TestDynECTHttpApiModule();
    }
 
-   @ConfiguresRestClient
-   private static final class TestDynECTRestClientModule extends DynECTRestClientModule {
+   @ConfiguresHttpApi
+   private static final class TestDynECTHttpApiModule extends DynECTHttpApiModule {
       @Override
       protected void configure() {
          install(new SSLModule());
diff --git a/providers/hpcloud-compute/src/main/java/org/jclouds/hpcloud/compute/HPCloudComputeProviderMetadata.java b/providers/hpcloud-compute/src/main/java/org/jclouds/hpcloud/compute/HPCloudComputeProviderMetadata.java
index 8501043..1a85c96 100644
--- a/providers/hpcloud-compute/src/main/java/org/jclouds/hpcloud/compute/HPCloudComputeProviderMetadata.java
+++ b/providers/hpcloud-compute/src/main/java/org/jclouds/hpcloud/compute/HPCloudComputeProviderMetadata.java
@@ -29,6 +29,7 @@
 
 import org.jclouds.hpcloud.compute.config.HPCloudComputeServiceContextModule;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
+import org.jclouds.openstack.keystone.v2_0.config.MappedAuthenticationApiModule;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule;
 import org.jclouds.openstack.nova.v2_0.NovaApiMetadata;
 import org.jclouds.openstack.nova.v2_0.config.NovaParserModule;
@@ -84,6 +85,7 @@
                   .endpointName("identity service url ending in /v2.0/")
                   .defaultEndpoint("https://region-a.geo-1.identity.hpcloudsvc.com:35357/v2.0/")
                   .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                                              .add(MappedAuthenticationApiModule.class)
                                               .add(KeystoneAuthenticationModule.class)
                                               .add(ZoneModule.class)
                                               .add(NovaParserModule.class)
diff --git a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageApiMetadata.java b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageApiMetadata.java
index 4aa072e..bc9f985 100644
--- a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageApiMetadata.java
+++ b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/HPCloudObjectStorageApiMetadata.java
@@ -18,7 +18,7 @@
  */
 package org.jclouds.hpcloud.objectstorage;
 
-import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
+import static org.jclouds.rest.config.BinderUtils.bindSyncToAsyncHttpApi;
 
 import java.net.URI;
 import java.util.Properties;
@@ -27,6 +27,7 @@
 import org.jclouds.hpcloud.objectstorage.blobstore.HPCloudObjectStorageBlobRequestSigner;
 import org.jclouds.hpcloud.objectstorage.blobstore.config.HPCloudObjectStorageBlobStoreContextModule;
 import org.jclouds.hpcloud.objectstorage.config.HPCloudObjectStorageRestClientModule;
+import org.jclouds.openstack.keystone.v2_0.config.MappedAuthenticationApiModule;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.RegionModule;
 import org.jclouds.openstack.swift.SwiftKeystoneApiMetadata;
 import org.jclouds.openstack.swift.blobstore.config.TemporaryUrlExtensionModule;
@@ -83,6 +84,7 @@
          .defaultProperties(HPCloudObjectStorageApiMetadata.defaultProperties())
          .context(CONTEXT_TOKEN)
          .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                                     .add(MappedAuthenticationApiModule.class)
                                      .add(KeystoneStorageEndpointModule.class)
                                      .add(RegionModule.class)
                                      .add(HPCloudObjectStorageRestClientModule.class)
@@ -112,7 +114,7 @@
       }
       @Override
       protected void bindTemporaryUrlKeyApi() {
-         bindHttpApi(binder(), TemporaryUrlKeyApi.class, KeystoneTemporaryUrlKeyAsyncApi.class);
+         bindSyncToAsyncHttpApi(binder(), TemporaryUrlKeyApi.class, KeystoneTemporaryUrlKeyAsyncApi.class);
       }
    }
 }
diff --git a/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/blobstore/HPCloudObjectStorageBlobSignerExpectTest.java b/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/blobstore/HPCloudObjectStorageBlobSignerExpectTest.java
index 7dc156b..00a70e3 100644
--- a/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/blobstore/HPCloudObjectStorageBlobSignerExpectTest.java
+++ b/providers/hpcloud-objectstorage/src/test/java/org/jclouds/hpcloud/objectstorage/blobstore/HPCloudObjectStorageBlobSignerExpectTest.java
@@ -30,6 +30,7 @@
 import org.jclouds.hpcloud.objectstorage.config.HPCloudObjectStorageRestClientModule;
 import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
+import org.jclouds.openstack.keystone.v2_0.config.MappedAuthenticationApiModule;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.RegionModule;
 import org.jclouds.openstack.swift.config.SwiftRestClientModule.KeystoneStorageEndpointModule;
 import org.testng.annotations.Test;
@@ -132,6 +133,7 @@
    protected ApiMetadata createApiMetadata() {
       return new HPCloudObjectStorageApiMetadata().toBuilder()
                                    .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                                         .add(MappedAuthenticationApiModule.class)
                                          .add(KeystoneStorageEndpointModule.class)
                                          .add(RegionModule.class)
                                          .add(HPCloudObjectStorageRestClientModule.class)
diff --git a/providers/rackspace-cloudblockstorage-uk/src/main/java/org/jclouds/rackspace/cloudblockstorage/uk/CloudBlockStorageUKProviderMetadata.java b/providers/rackspace-cloudblockstorage-uk/src/main/java/org/jclouds/rackspace/cloudblockstorage/uk/CloudBlockStorageUKProviderMetadata.java
index c231067..e2b50c5 100644
--- a/providers/rackspace-cloudblockstorage-uk/src/main/java/org/jclouds/rackspace/cloudblockstorage/uk/CloudBlockStorageUKProviderMetadata.java
+++ b/providers/rackspace-cloudblockstorage-uk/src/main/java/org/jclouds/rackspace/cloudblockstorage/uk/CloudBlockStorageUKProviderMetadata.java
@@ -34,6 +34,7 @@
 import org.jclouds.providers.internal.BaseProviderMetadata;
 import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule;
 import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.SyncToAsyncCloudIdentityAuthenticationApiModule;
 
 import com.google.common.collect.ImmutableSet;
 import com.google.inject.Module;
@@ -82,6 +83,7 @@
                   .endpointName("identity service url ending in /v2.0/")
                   .documentation(URI.create("http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/overview.html"))
                   .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                                              .add(SyncToAsyncCloudIdentityAuthenticationApiModule.class)
                                               .add(CloudIdentityAuthenticationModule.class)
                                               .add(ZoneModule.class)
                                               .add(CinderParserModule.class)
diff --git a/providers/rackspace-cloudblockstorage-us/src/main/java/org/jclouds/rackspace/cloudblockstorage/us/CloudBlockStorageUSProviderMetadata.java b/providers/rackspace-cloudblockstorage-us/src/main/java/org/jclouds/rackspace/cloudblockstorage/us/CloudBlockStorageUSProviderMetadata.java
index 69fafc1..0c7174b 100644
--- a/providers/rackspace-cloudblockstorage-us/src/main/java/org/jclouds/rackspace/cloudblockstorage/us/CloudBlockStorageUSProviderMetadata.java
+++ b/providers/rackspace-cloudblockstorage-us/src/main/java/org/jclouds/rackspace/cloudblockstorage/us/CloudBlockStorageUSProviderMetadata.java
@@ -34,6 +34,7 @@
 import org.jclouds.providers.internal.BaseProviderMetadata;
 import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule;
 import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.SyncToAsyncCloudIdentityAuthenticationApiModule;
 
 import com.google.common.collect.ImmutableSet;
 import com.google.inject.Module;
@@ -83,6 +84,7 @@
                   .endpointName("identity service url ending in /v2.0/")
                   .documentation(URI.create("http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/overview.html"))
                   .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                                              .add(SyncToAsyncCloudIdentityAuthenticationApiModule.class)
                                               .add(CloudIdentityAuthenticationModule.class)
                                               .add(ZoneModule.class)
                                               .add(CinderParserModule.class)
diff --git a/providers/rackspace-cloudloadbalancers-uk/src/main/java/org/jclouds/rackspace/cloudloadbalancers/uk/CloudLoadBalancersUKProviderMetadata.java b/providers/rackspace-cloudloadbalancers-uk/src/main/java/org/jclouds/rackspace/cloudloadbalancers/uk/CloudLoadBalancersUKProviderMetadata.java
index addb24e..c3bdd2c 100644
--- a/providers/rackspace-cloudloadbalancers-uk/src/main/java/org/jclouds/rackspace/cloudloadbalancers/uk/CloudLoadBalancersUKProviderMetadata.java
+++ b/providers/rackspace-cloudloadbalancers-uk/src/main/java/org/jclouds/rackspace/cloudloadbalancers/uk/CloudLoadBalancersUKProviderMetadata.java
@@ -25,16 +25,9 @@
 import java.net.URI;
 import java.util.Properties;
 
-import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule;
 import org.jclouds.providers.ProviderMetadata;
 import org.jclouds.providers.internal.BaseProviderMetadata;
-import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule;
 import org.jclouds.rackspace.cloudloadbalancers.v1.CloudLoadBalancersApiMetadata;
-import org.jclouds.rackspace.cloudloadbalancers.v1.config.CloudLoadBalancersRestClientModule;
-import org.jclouds.rackspace.cloudloadbalancers.v1.loadbalancer.config.CloudLoadBalancersLoadBalancerContextModule;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.inject.Module;
 
 /**
  * Implementation of {@link org.jclouds.types.ProviderMetadata} for Rackspace Cloud LoadBalancers UK.
@@ -72,18 +65,7 @@
          id("rackspace-cloudloadbalancers-uk")
          .name("Rackspace Cloud Load Balancers UK")
          .apiMetadata(new CloudLoadBalancersApiMetadata().toBuilder()
-                  .identityName("${userName}")
-                  .credentialName("${apiKey}")
-                  .version("1.0")
                   .defaultEndpoint("https://lon.identity.api.rackspacecloud.com/v2.0/")
-                  .endpointName("Identity service URL ending in /v2.0/")
-                  .documentation(URI.create("http://docs.rackspace.com/loadbalancers/api/clb-devguide-latest/index.html"))
-                  .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
-                                              .add(CloudIdentityAuthenticationModule.class)
-                                              .add(ZoneModule.class)
-                                              .add(CloudLoadBalancersRestClientModule.class)
-                                              .add(CloudLoadBalancersLoadBalancerContextModule.class)
-                                              .build())
                   .build())
          .homepage(URI.create("http://www.rackspace.co.uk/cloud-load-balancers/"))
          .console(URI.create("https://mycloud.rackspace.co.uk"))
diff --git a/providers/rackspace-cloudloadbalancers-us/src/main/java/org/jclouds/rackspace/cloudloadbalancers/us/CloudLoadBalancersUSProviderMetadata.java b/providers/rackspace-cloudloadbalancers-us/src/main/java/org/jclouds/rackspace/cloudloadbalancers/us/CloudLoadBalancersUSProviderMetadata.java
index 2dd9f62..adc0a47 100644
--- a/providers/rackspace-cloudloadbalancers-us/src/main/java/org/jclouds/rackspace/cloudloadbalancers/us/CloudLoadBalancersUSProviderMetadata.java
+++ b/providers/rackspace-cloudloadbalancers-us/src/main/java/org/jclouds/rackspace/cloudloadbalancers/us/CloudLoadBalancersUSProviderMetadata.java
@@ -25,16 +25,9 @@
 import java.net.URI;
 import java.util.Properties;
 
-import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule;
 import org.jclouds.providers.ProviderMetadata;
 import org.jclouds.providers.internal.BaseProviderMetadata;
-import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule;
 import org.jclouds.rackspace.cloudloadbalancers.v1.CloudLoadBalancersApiMetadata;
-import org.jclouds.rackspace.cloudloadbalancers.v1.config.CloudLoadBalancersRestClientModule;
-import org.jclouds.rackspace.cloudloadbalancers.v1.loadbalancer.config.CloudLoadBalancersLoadBalancerContextModule;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.inject.Module;
 
 /**
  * Implementation of {@link org.jclouds.types.ProviderMetadata} for Rackspace Cloud LoadBalancers US.
@@ -74,18 +67,7 @@
          id("rackspace-cloudloadbalancers-us")
          .name("Rackspace Cloud Load Balancers US")
          .apiMetadata(new CloudLoadBalancersApiMetadata().toBuilder()
-                  .identityName("${userName}")
-                  .credentialName("${apiKey}")
-                  .version("1.0")
                   .defaultEndpoint("https://identity.api.rackspacecloud.com/v2.0/")
-                  .endpointName("Identity service URL ending in /v2.0/")
-                  .documentation(URI.create("http://docs.rackspace.com/loadbalancers/api/clb-devguide-latest/index.html"))
-                  .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
-                                              .add(CloudIdentityAuthenticationModule.class)
-                                              .add(ZoneModule.class)
-                                              .add(CloudLoadBalancersRestClientModule.class)
-                                              .add(CloudLoadBalancersLoadBalancerContextModule.class)
-                                              .build())
                   .build())
          .homepage(URI.create("http://www.rackspace.com/cloud/public/loadbalancers/"))
          .console(URI.create("https://mycloud.rackspace.com"))
diff --git a/providers/rackspace-cloudservers-uk/src/main/java/org/jclouds/rackspace/cloudservers/uk/CloudServersUKProviderMetadata.java b/providers/rackspace-cloudservers-uk/src/main/java/org/jclouds/rackspace/cloudservers/uk/CloudServersUKProviderMetadata.java
index 9202e9c..b50c8ee 100644
--- a/providers/rackspace-cloudservers-uk/src/main/java/org/jclouds/rackspace/cloudservers/uk/CloudServersUKProviderMetadata.java
+++ b/providers/rackspace-cloudservers-uk/src/main/java/org/jclouds/rackspace/cloudservers/uk/CloudServersUKProviderMetadata.java
@@ -34,6 +34,7 @@
 import org.jclouds.providers.internal.BaseProviderMetadata;
 import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule;
 import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.SyncToAsyncCloudIdentityAuthenticationApiModule;
 import org.jclouds.rackspace.cloudservers.uk.config.CloudServersUKComputeServiceContextModule;
 
 import com.google.common.collect.ImmutableSet;
@@ -84,6 +85,7 @@
                   .endpointName("identity service url ending in /v2.0/")
                   .documentation(URI.create("http://docs.rackspace.com/servers/api/v2/cs-devguide/content/ch_preface.html#webhelp-currentid"))
                   .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                                              .add(SyncToAsyncCloudIdentityAuthenticationApiModule.class)
                                               .add(CloudIdentityAuthenticationModule.class)
                                               .add(ZoneModule.class)
                                               .add(NovaParserModule.class)
diff --git a/providers/rackspace-cloudservers-us/src/main/java/org/jclouds/rackspace/cloudservers/us/CloudServersUSProviderMetadata.java b/providers/rackspace-cloudservers-us/src/main/java/org/jclouds/rackspace/cloudservers/us/CloudServersUSProviderMetadata.java
index 1480a1f..dae907c 100644
--- a/providers/rackspace-cloudservers-us/src/main/java/org/jclouds/rackspace/cloudservers/us/CloudServersUSProviderMetadata.java
+++ b/providers/rackspace-cloudservers-us/src/main/java/org/jclouds/rackspace/cloudservers/us/CloudServersUSProviderMetadata.java
@@ -34,6 +34,7 @@
 import org.jclouds.providers.internal.BaseProviderMetadata;
 import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityAuthenticationModule;
 import org.jclouds.rackspace.cloudidentity.v2_0.config.CloudIdentityCredentialTypes;
+import org.jclouds.rackspace.cloudidentity.v2_0.config.SyncToAsyncCloudIdentityAuthenticationApiModule;
 import org.jclouds.rackspace.cloudservers.us.config.CloudServersUSComputeServiceContextModule;
 
 import com.google.common.collect.ImmutableSet;
@@ -85,6 +86,7 @@
                   .endpointName("identity service url ending in /v2.0/")
                   .documentation(URI.create("http://docs.rackspace.com/loadbalancers/api/v1.0/clb-devguide/content/index.html"))
                   .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                                              .add(SyncToAsyncCloudIdentityAuthenticationApiModule.class)
                                               .add(CloudIdentityAuthenticationModule.class)
                                               .add(ZoneModule.class)
                                               .add(NovaParserModule.class)
diff --git a/providers/trystack-nova/src/main/java/org/jclouds/trystack/nova/TryStackNovaProviderMetadata.java b/providers/trystack-nova/src/main/java/org/jclouds/trystack/nova/TryStackNovaProviderMetadata.java
index 72205dd..16299e5 100644
--- a/providers/trystack-nova/src/main/java/org/jclouds/trystack/nova/TryStackNovaProviderMetadata.java
+++ b/providers/trystack-nova/src/main/java/org/jclouds/trystack/nova/TryStackNovaProviderMetadata.java
@@ -26,6 +26,7 @@
 
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.ZoneModule;
+import org.jclouds.openstack.keystone.v2_0.config.MappedAuthenticationApiModule;
 import org.jclouds.openstack.nova.v2_0.NovaApiMetadata;
 import org.jclouds.openstack.nova.v2_0.config.NovaParserModule;
 import org.jclouds.openstack.nova.v2_0.config.NovaRestClientModule;
@@ -75,6 +76,7 @@
                .apiMetadata(
                      new NovaApiMetadata().toBuilder()
                                           .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                                                 .add(MappedAuthenticationApiModule.class)
                                                  .add(KeystoneAuthenticationModule.class)
                                                  .add(ZoneModule.class)
                                                  .add(NovaParserModule.class)
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/UltraDNSWSApi.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/UltraDNSWSApi.java
index 4109cad..827038d 100644
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/UltraDNSWSApi.java
+++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/UltraDNSWSApi.java
@@ -20,27 +20,41 @@
 
 import java.io.Closeable;
 
+import javax.inject.Named;
+import javax.ws.rs.POST;
+
 import org.jclouds.rest.annotations.Delegate;
+import org.jclouds.rest.annotations.Payload;
 import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
 import org.jclouds.ultradns.ws.domain.Account;
 import org.jclouds.ultradns.ws.features.ResourceRecordApi;
 import org.jclouds.ultradns.ws.features.RoundRobinPoolApi;
 import org.jclouds.ultradns.ws.features.TaskApi;
 import org.jclouds.ultradns.ws.features.TrafficControllerPoolApi;
 import org.jclouds.ultradns.ws.features.ZoneApi;
+import org.jclouds.ultradns.ws.filters.SOAPWrapWithPasswordAuth;
+import org.jclouds.ultradns.ws.xml.AccountHandler;
 
 /**
  * Provides access to Neustar UltraDNS via the SOAP API
  * <p/>
  * 
- * @see UltraDNSWSAsyncApi
  * @see <a href="https://www.ultradns.net/api/NUS_API_XML_SOAP.pdf" />
  * @author Adrian Cole
  */
+@RequestFilters(SOAPWrapWithPasswordAuth.class)
+@VirtualHost
 public interface UltraDNSWSApi extends Closeable {
    /**
     * Returns the account of the current user.
     */
+   @Named("getAccountsListOfUser")
+   @POST
+   @XMLResponseParser(AccountHandler.class)
+   @Payload("<v01:getAccountsListOfUser/>")
    Account getCurrentAccount();
 
    /**
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/UltraDNSWSApiMetadata.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/UltraDNSWSApiMetadata.java
index de7127e..f0131fd 100644
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/UltraDNSWSApiMetadata.java
+++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/UltraDNSWSApiMetadata.java
@@ -22,38 +22,37 @@
 import java.util.Properties;
 
 import org.jclouds.apis.ApiMetadata;
-import org.jclouds.rest.internal.BaseRestApiMetadata;
-import org.jclouds.ultradns.ws.config.UltraDNSWSRestClientModule;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
+import org.jclouds.ultradns.ws.config.UltraDNSWSHttpApiModule;
 
 /**
  * Implementation of {@link ApiMetadata} for Neustar's UltraDNSWS api.
  * 
  * @author Adrian Cole
  */
-public class UltraDNSWSApiMetadata extends BaseRestApiMetadata {
+public class UltraDNSWSApiMetadata extends BaseHttpApiMetadata<UltraDNSWSApi> {
 
    @Override
    public Builder toBuilder() {
-      return new Builder(getApi(), getAsyncApi()).fromApiMetadata(this);
+      return new Builder().fromApiMetadata(this);
    }
 
    public UltraDNSWSApiMetadata() {
-      this(new Builder(UltraDNSWSApi.class, UltraDNSWSAsyncApi.class));
+      this(new Builder());
    }
 
    protected UltraDNSWSApiMetadata(Builder builder) {
-      super(Builder.class.cast(builder));
+      super(builder);
    }
 
    public static Properties defaultProperties() {
-      Properties properties = BaseRestApiMetadata.defaultProperties();
+      Properties properties = BaseHttpApiMetadata.defaultProperties();
       return properties;
    }
 
-   public static class Builder extends BaseRestApiMetadata.Builder<Builder> {
+   public static class Builder extends BaseHttpApiMetadata.Builder<UltraDNSWSApi, Builder> {
 
-      protected Builder(Class<?> api, Class<?> asyncApi) {
-         super(api, asyncApi);
+      protected Builder() {
          id("ultradns-ws")
          .name("Neustar UltraDNS WS Api")
          .identityName("Username")
@@ -62,7 +61,7 @@
          .documentation(URI.create("https://portal.ultradns.com/static/docs/NUS_API_XML_SOAP.pdf"))
          .defaultEndpoint("https://ultra-api.ultradns.com:8443/UltraDNS_WS/v01")
          .defaultProperties(UltraDNSWSApiMetadata.defaultProperties())
-         .defaultModule(UltraDNSWSRestClientModule.class);
+         .defaultModule(UltraDNSWSHttpApiModule.class);
       }
 
       @Override
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/UltraDNSWSAsyncApi.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/UltraDNSWSAsyncApi.java
deleted file mode 100644
index fea3f8d..0000000
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/UltraDNSWSAsyncApi.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.ultradns.ws;
-
-import java.io.Closeable;
-
-import javax.inject.Named;
-import javax.ws.rs.POST;
-
-import org.jclouds.rest.annotations.Delegate;
-import org.jclouds.rest.annotations.Payload;
-import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-import org.jclouds.ultradns.ws.domain.Account;
-import org.jclouds.ultradns.ws.features.ResourceRecordAsyncApi;
-import org.jclouds.ultradns.ws.features.RoundRobinPoolAsyncApi;
-import org.jclouds.ultradns.ws.features.TaskAsyncApi;
-import org.jclouds.ultradns.ws.features.TrafficControllerPoolAsyncApi;
-import org.jclouds.ultradns.ws.features.ZoneAsyncApi;
-import org.jclouds.ultradns.ws.filters.SOAPWrapWithPasswordAuth;
-import org.jclouds.ultradns.ws.xml.AccountHandler;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to Neustar UltraDNS via the SOAP API
- * <p/>
- * 
- * @see <a href="https://ultra-api.ultradns.com:8443/UltraDNS_WS/v01?wsdl" />
- * @see <a href="https://www.ultradns.net/api/NUS_API_XML_SOAP.pdf" />
- * @author Adrian Cole
- * @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(UltraDNSWSApi.class)} as
- *             {@link UltraDNSWSAsyncApi} interface will be removed in jclouds 1.7.
- */
-@Deprecated
-@RequestFilters(SOAPWrapWithPasswordAuth.class)
-@VirtualHost
-public interface UltraDNSWSAsyncApi extends Closeable {
-
-   /**
-    * @see UltraDNSWSApi#getCurrentAccount()
-    */
-   @Named("getAccountsListOfUser")
-   @POST
-   @XMLResponseParser(AccountHandler.class)
-   @Payload("<v01:getAccountsListOfUser/>")
-   ListenableFuture<Account> getCurrentAccount();
-
-   /**
-    * Provides asynchronous access to Zone features.
-    */
-   @Delegate
-   ZoneAsyncApi getZoneApi();
-
-   /**
-    * Provides asynchronous access to Resource Record features.
-    * 
-    * @param zoneName
-    *           zoneName including a trailing dot
-    */
-   @Delegate
-   ResourceRecordAsyncApi getResourceRecordApiForZone(@PayloadParam("zoneName") String zoneName);
-
-   /**
-    * Provides asynchronous access to Round Robin Pool features.
-    * 
-    * @param zoneName
-    *           zoneName including a trailing dot
-    */
-   @Delegate
-   RoundRobinPoolAsyncApi getRoundRobinPoolApiForZone(@PayloadParam("zoneName") String zoneName);
-
-   /**
-    * Provides asynchronous access to Traffic Controller Pool features.
-    * 
-    * @param zoneName
-    *           zoneName including a trailing dot
-    */
-   @Delegate
-   TrafficControllerPoolAsyncApi getTrafficControllerPoolApiForZone(@PayloadParam("zoneName") String zoneName);
-
-   /**
-    * Provides asynchronous access to Task features.
-    */
-   @Delegate
-   TaskAsyncApi getTaskApi();
-}
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/config/UltraDNSWSHttpApiModule.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/config/UltraDNSWSHttpApiModule.java
new file mode 100644
index 0000000..9c23387
--- /dev/null
+++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/config/UltraDNSWSHttpApiModule.java
@@ -0,0 +1,52 @@
+/**
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jclouds.ultradns.ws.config;
+
+import org.jclouds.http.HttpErrorHandler;
+import org.jclouds.http.HttpRetryHandler;
+import org.jclouds.http.annotation.ClientError;
+import org.jclouds.http.annotation.Redirection;
+import org.jclouds.http.annotation.ServerError;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.config.HttpApiModule;
+import org.jclouds.ultradns.ws.UltraDNSWSApi;
+import org.jclouds.ultradns.ws.handlers.UltraDNSWSErrorHandler;
+
+/**
+ * Configures the UltraDNSWS connection.
+ * 
+ * @author Adrian Cole
+ */
+@ConfiguresHttpApi
+public class UltraDNSWSHttpApiModule extends HttpApiModule<UltraDNSWSApi> {
+   public UltraDNSWSHttpApiModule() {
+   }
+
+   @Override
+   protected void bindErrorHandlers() {
+      bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(UltraDNSWSErrorHandler.class);
+      bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(UltraDNSWSErrorHandler.class);
+      bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(UltraDNSWSErrorHandler.class);
+   }
+
+   @Override
+   protected void bindRetryHandlers() {
+      bind(HttpRetryHandler.class).annotatedWith(ServerError.class).toInstance(HttpRetryHandler.NEVER_RETRY);
+   }
+}
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/config/UltraDNSWSRestClientModule.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/config/UltraDNSWSRestClientModule.java
deleted file mode 100644
index a5aa13b..0000000
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/config/UltraDNSWSRestClientModule.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.ultradns.ws.config;
-
-import java.util.Map;
-
-import org.jclouds.http.HttpErrorHandler;
-import org.jclouds.http.HttpRetryHandler;
-import org.jclouds.http.annotation.ClientError;
-import org.jclouds.http.annotation.Redirection;
-import org.jclouds.http.annotation.ServerError;
-import org.jclouds.rest.ConfiguresRestClient;
-import org.jclouds.rest.config.RestClientModule;
-import org.jclouds.ultradns.ws.UltraDNSWSApi;
-import org.jclouds.ultradns.ws.UltraDNSWSAsyncApi;
-import org.jclouds.ultradns.ws.features.ResourceRecordApi;
-import org.jclouds.ultradns.ws.features.ResourceRecordAsyncApi;
-import org.jclouds.ultradns.ws.features.RoundRobinPoolApi;
-import org.jclouds.ultradns.ws.features.RoundRobinPoolAsyncApi;
-import org.jclouds.ultradns.ws.features.TaskApi;
-import org.jclouds.ultradns.ws.features.TaskAsyncApi;
-import org.jclouds.ultradns.ws.features.TrafficControllerPoolApi;
-import org.jclouds.ultradns.ws.features.TrafficControllerPoolAsyncApi;
-import org.jclouds.ultradns.ws.features.ZoneApi;
-import org.jclouds.ultradns.ws.features.ZoneAsyncApi;
-import org.jclouds.ultradns.ws.handlers.UltraDNSWSErrorHandler;
-
-import com.google.common.collect.ImmutableMap;
-
-/**
- * Configures the UltraDNSWS connection.
- * 
- * @author Adrian Cole
- */
-@ConfiguresRestClient
-public class UltraDNSWSRestClientModule extends RestClientModule<UltraDNSWSApi, UltraDNSWSAsyncApi> {
-
-   public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()
-         .put(ZoneApi.class, ZoneAsyncApi.class)
-         .put(ResourceRecordApi.class, ResourceRecordAsyncApi.class)
-         .put(RoundRobinPoolApi.class, RoundRobinPoolAsyncApi.class)
-         .put(TrafficControllerPoolApi.class, TrafficControllerPoolAsyncApi.class)
-         .put(TaskApi.class, TaskAsyncApi.class).build();
-
-   public UltraDNSWSRestClientModule() {
-      super(DELEGATE_MAP);
-   }
-
-   @Override
-   protected void bindErrorHandlers() {
-      bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(UltraDNSWSErrorHandler.class);
-      bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(UltraDNSWSErrorHandler.class);
-      bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(UltraDNSWSErrorHandler.class);
-   }
-
-   @Override
-   protected void bindRetryHandlers() {
-      bind(HttpRetryHandler.class).annotatedWith(ServerError.class).toInstance(HttpRetryHandler.NEVER_RETRY);
-   }
-}
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/PoolRecordSpec.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/PoolRecordSpec.java
index f9d3b8a..02f14d6 100644
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/PoolRecordSpec.java
+++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/PoolRecordSpec.java
@@ -47,13 +47,13 @@
       this.probingEnabled = probingEnabled;
       this.allFailEnabled = allFailEnabled;
       this.weight = weight;
-      checkArgument(weight >= 0, "weight of %s must be unsigned", description);
+      checkArgument(weight >= 0, "weight of %s must be >= 0", description);
       this.failOverDelay = failOverDelay;
-      checkArgument(failOverDelay >= 0, "failOverDelay of %s must be unsigned", description);
+      checkArgument(failOverDelay >= 0, "failOverDelay of %s must be >= 0", description);
       this.threshold = threshold;
-      checkArgument(threshold >= 0, "threshold of %s must be unsigned", description);
+      checkArgument(threshold >= 0, "threshold of %s must be >= 0", description);
       this.ttl = ttl;
-      checkArgument(ttl >= 0, "ttl of %s must be unsigned", description);
+      checkArgument(ttl >= 0, "ttl of %s must be >= 0", description);
    }
 
    /**
@@ -114,8 +114,8 @@
 
    @Override
    public int hashCode() {
-      return Objects
-            .hashCode(description, state, probingEnabled, allFailEnabled, weight, failOverDelay, threshold, ttl);
+      return Objects.hashCode(description, state, probingEnabled, allFailEnabled, weight, failOverDelay, threshold,
+            ttl);
    }
 
    @Override
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/ResourceRecord.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/ResourceRecord.java
index 3ade4b9..08dc673 100644
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/ResourceRecord.java
+++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/ResourceRecord.java
@@ -42,9 +42,9 @@
 
    private ResourceRecord(String dName, int type, int ttl, List<String> infoValues) {
       this.dName = checkNotNull(dName, "dName");
-      checkArgument(type >= 0, "type of %s must be unsigned", dName);
+      checkArgument(type >= 0, "type of %s must be >= 0", dName);
       this.type = type;
-      checkArgument(ttl >= 0, "ttl of %s must be unsigned", dName);
+      checkArgument(ttl >= 0, "ttl of %s must be >= 0", dName);
       this.ttl = ttl;
       this.infoValues = checkNotNull(infoValues, "infoValues of %s", dName);
    }
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/TrafficControllerPoolRecord.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/TrafficControllerPoolRecord.java
index 061aaf6..1a05fce 100644
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/TrafficControllerPoolRecord.java
+++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/TrafficControllerPoolRecord.java
@@ -46,9 +46,9 @@
       this.id = checkNotNull(id, "id");
       this.poolId = checkNotNull(poolId, "poolId for %s", id);
       this.pointsTo = checkNotNull(pointsTo, "pointsTo for %s", poolId);
-      checkArgument(weight >= 0, "weight of %s must be unsigned", id);
+      checkArgument(weight >= 0, "weight of %s must be >= 0", id);
       this.weight = weight;
-      checkArgument(priority >= 0, "priority of %s must be unsigned", id);
+      checkArgument(priority >= 0, "priority of %s must be >= 0", id);
       this.priority = priority;
       this.type = checkNotNull(type, "type for %s", poolId);
       this.forceAnswer = checkNotNull(forceAnswer, "forceAnswer for %s", poolId);
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/UpdatePoolRecord.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/UpdatePoolRecord.java
index a7883b4..b8117cd 100644
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/UpdatePoolRecord.java
+++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/UpdatePoolRecord.java
@@ -54,13 +54,13 @@
       this.mode = checkNotNull(mode, "mode for %s", pointsTo);
       this.priority = priority;
       this.weight = weight;
-      checkArgument(weight >= 0, "weight of %s must be unsigned", pointsTo);
+      checkArgument(weight >= 0, "weight of %s must be >= 0", pointsTo);
       this.failOverDelay = failOverDelay;
-      checkArgument(failOverDelay >= 0, "failOverDelay of %s must be unsigned", pointsTo);
+      checkArgument(failOverDelay >= 0, "failOverDelay of %s must be >= 0", pointsTo);
       this.threshold = threshold;
-      checkArgument(threshold >= 0, "threshold of %s must be unsigned", pointsTo);
+      checkArgument(threshold >= 0, "threshold of %s must be >= 0", pointsTo);
       this.ttl = ttl;
-      checkArgument(ttl >= 0, "ttl of %s must be unsigned", pointsTo);
+      checkArgument(ttl >= 0, "ttl of %s must be >= 0", pointsTo);
    }
 
    /**
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/Zone.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/Zone.java
index 45b6e83..60370f6 100644
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/Zone.java
+++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/Zone.java
@@ -43,7 +43,7 @@
          DNSSECStatus dnssecStatus, Optional<String> primarySrc) {
       this.id = checkNotNull(id, "id");
       this.name = checkNotNull(name, "name for %s", id);
-      checkArgument(typeCode >= 0, "typeCode of %s must be unsigned", id);
+      checkArgument(typeCode >= 0, "typeCode of %s must be >= 0", id);
       this.typeCode = typeCode;
       this.type = checkNotNull(type, "type for %s", name);
       this.accountId = checkNotNull(accountId, "accountId for %s", name);
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/ZoneProperties.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/ZoneProperties.java
index 014a7f8..e2cd047 100644
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/ZoneProperties.java
+++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/domain/ZoneProperties.java
@@ -41,7 +41,7 @@
 
    private ZoneProperties(String name, Type type, int typeCode, Date modified, int resourceRecordCount) {
       this.name = checkNotNull(name, "name");
-      checkArgument(typeCode >= 0, "typeCode of %s must be unsigned", name);
+      checkArgument(typeCode >= 0, "typeCode of %s must be >= 0", name);
       this.typeCode = typeCode;
       this.type = checkNotNull(type, "type for %s", name);
       this.modified = checkNotNull(modified, "modified for %s", name);
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ResourceRecordApi.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ResourceRecordApi.java
index f81ef40..77c309b 100644
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ResourceRecordApi.java
+++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ResourceRecordApi.java
@@ -18,17 +18,35 @@
  */
 package org.jclouds.ultradns.ws.features;
 
+import javax.inject.Named;
+import javax.ws.rs.POST;
+
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
 import org.jclouds.rest.ResourceNotFoundException;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
 import org.jclouds.ultradns.ws.UltraDNSWSExceptions.ResourceAlreadyExistsException;
+import org.jclouds.ultradns.ws.binders.ZoneAndResourceRecordToXML;
 import org.jclouds.ultradns.ws.domain.ResourceRecord;
 import org.jclouds.ultradns.ws.domain.ResourceRecordMetadata;
+import org.jclouds.ultradns.ws.filters.SOAPWrapWithPasswordAuth;
+import org.jclouds.ultradns.ws.xml.ElementTextHandler;
+import org.jclouds.ultradns.ws.xml.ResourceRecordListHandler;
 
 import com.google.common.collect.FluentIterable;
 
 /**
- * @see ResourceRecordAsyncApi
+ * @see <a href="https://ultra-api.ultradns.com:8443/UltraDNS_WS/v01?wsdl" />
+ * @see <a href="https://www.ultradns.net/api/NUS_API_XML_SOAP.pdf" />
  * @author Adrian Cole
  */
+@RequestFilters(SOAPWrapWithPasswordAuth.class)
+@VirtualHost
 public interface ResourceRecordApi {
 
    /**
@@ -40,7 +58,12 @@
     * @throws ResourceAlreadyExistsException
     *            if a record already exists with the same attrs
     */
-   String create(ResourceRecord toCreate) throws ResourceAlreadyExistsException;
+   @Named("createResourceRecord")
+   @POST
+   @XMLResponseParser(ElementTextHandler.Guid.class)
+   @MapBinder(ZoneAndResourceRecordToXML.class)
+   String create(@PayloadParam("resourceRecord") ResourceRecord toCreate)
+         throws ResourceAlreadyExistsException;
 
    /**
     * updates an existing resource record in the zone.
@@ -53,7 +76,11 @@
     * @throws ResourceNotFoundException
     *            if the guid doesn't exist
     */
-   void update(String guid, ResourceRecord updated) throws ResourceNotFoundException;
+   @Named("updateResourceRecord")
+   @POST
+   @MapBinder(ZoneAndResourceRecordToXML.class)
+   void update(@PayloadParam("guid") String guid,
+         @PayloadParam("resourceRecord") ResourceRecord toCreate) throws ResourceNotFoundException;
 
    /**
     * Returns all the specified record types in the zone.
@@ -61,6 +88,10 @@
     * @throws ResourceNotFoundException
     *            if the zone doesn't exist
     */
+   @Named("getResourceRecordsOfZone")
+   @POST
+   @XMLResponseParser(ResourceRecordListHandler.class)
+   @Payload("<v01:getResourceRecordsOfZone><zoneName>{zoneName}</zoneName><rrType>0</rrType></v01:getResourceRecordsOfZone>")
    FluentIterable<ResourceRecordMetadata> list() throws ResourceNotFoundException;
 
    /**
@@ -72,7 +103,12 @@
     * @throws ResourceNotFoundException
     *            if the zone doesn't exist
     */
-   FluentIterable<ResourceRecordMetadata> listByName(String hostName) throws ResourceNotFoundException;
+   @Named("getResourceRecordsOfDNameByType")
+   @POST
+   @XMLResponseParser(ResourceRecordListHandler.class)
+   @Payload("<v01:getResourceRecordsOfDNameByType><zoneName>{zoneName}</zoneName><hostName>{hostName}</hostName><rrType>0</rrType></v01:getResourceRecordsOfDNameByType>")
+   FluentIterable<ResourceRecordMetadata> listByName(@PayloadParam("hostName") String hostName)
+         throws ResourceNotFoundException;
 
    /**
     * Returns all the specified record types in the zone with the fully
@@ -86,7 +122,12 @@
     * @throws ResourceNotFoundException
     *            if the zone doesn't exist
     */
-   FluentIterable<ResourceRecordMetadata> listByNameAndType(String hostName, int rrType)
+   @Named("getResourceRecordsOfDNameByType")
+   @POST
+   @XMLResponseParser(ResourceRecordListHandler.class)
+   @Payload("<v01:getResourceRecordsOfDNameByType><zoneName>{zoneName}</zoneName><hostName>{hostName}</hostName><rrType>{rrType}</rrType></v01:getResourceRecordsOfDNameByType>")
+   FluentIterable<ResourceRecordMetadata> listByNameAndType(
+         @PayloadParam("hostName") String hostName, @PayloadParam("rrType") int rrType)
          throws ResourceNotFoundException;
 
    /**
@@ -96,5 +137,9 @@
     *           the global unique identifier for the resource record {@see
     *           ResourceRecordMetadata#getGuid()}
     */
-   void delete(String guid);
+   @Named("deleteResourceRecord")
+   @POST
+   @Payload("<v01:deleteResourceRecord><transactionID /><guid>{guid}</guid></v01:deleteResourceRecord>")
+   @Fallback(VoidOnNotFoundOr404.class)
+   void delete(@PayloadParam("guid") String guid);
 }
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ResourceRecordAsyncApi.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ResourceRecordAsyncApi.java
deleted file mode 100644
index d8fab36..0000000
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ResourceRecordAsyncApi.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.ultradns.ws.features;
-
-import javax.inject.Named;
-import javax.ws.rs.POST;
-
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.rest.ResourceNotFoundException;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.MapBinder;
-import org.jclouds.rest.annotations.Payload;
-import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-import org.jclouds.ultradns.ws.UltraDNSWSExceptions.ResourceAlreadyExistsException;
-import org.jclouds.ultradns.ws.binders.ZoneAndResourceRecordToXML;
-import org.jclouds.ultradns.ws.domain.ResourceRecord;
-import org.jclouds.ultradns.ws.domain.ResourceRecordMetadata;
-import org.jclouds.ultradns.ws.filters.SOAPWrapWithPasswordAuth;
-import org.jclouds.ultradns.ws.xml.TextHandler;
-import org.jclouds.ultradns.ws.xml.ResourceRecordListHandler;
-
-import com.google.common.collect.FluentIterable;
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * @see ResourceRecordApi
- * @see <a href="https://ultra-api.ultradns.com:8443/UltraDNS_WS/v01?wsdl" />
- * @see <a href="https://www.ultradns.net/api/NUS_API_XML_SOAP.pdf" />
- * @author Adrian Cole
- */
-@RequestFilters(SOAPWrapWithPasswordAuth.class)
-@VirtualHost
-public interface ResourceRecordAsyncApi {
-
-   /**
-    * @see ResourceRecordApi#create(ResourceRecordMetadata)
-    */
-   @Named("createResourceRecord")
-   @POST
-   @XMLResponseParser(TextHandler.Guid.class)
-   @MapBinder(ZoneAndResourceRecordToXML.class)
-   ListenableFuture<String> create(@PayloadParam("resourceRecord") ResourceRecord toCreate)
-         throws ResourceAlreadyExistsException;
-
-   /**
-    * @see ResourceRecordApi#update(String guid, BasicResourceRecord)
-    */
-   @Named("updateResourceRecord")
-   @POST
-   @MapBinder(ZoneAndResourceRecordToXML.class)
-   ListenableFuture<Void> update(@PayloadParam("guid") String guid,
-         @PayloadParam("resourceRecord") ResourceRecord toCreate) throws ResourceNotFoundException;
-
-   /**
-    * @see ResourceRecordApi#list()
-    */
-   @Named("getResourceRecordsOfZone")
-   @POST
-   @XMLResponseParser(ResourceRecordListHandler.class)
-   @Payload("<v01:getResourceRecordsOfZone><zoneName>{zoneName}</zoneName><rrType>0</rrType></v01:getResourceRecordsOfZone>")
-   ListenableFuture<FluentIterable<ResourceRecord>> list() throws ResourceNotFoundException;
-
-   /**
-    * @see ResourceRecordApi#listByName(String)
-    */
-   @Named("getResourceRecordsOfDNameByType")
-   @POST
-   @XMLResponseParser(ResourceRecordListHandler.class)
-   @Payload("<v01:getResourceRecordsOfDNameByType><zoneName>{zoneName}</zoneName><hostName>{hostName}</hostName><rrType>0</rrType></v01:getResourceRecordsOfDNameByType>")
-   ListenableFuture<FluentIterable<ResourceRecordMetadata>> listByName(@PayloadParam("hostName") String hostName)
-         throws ResourceNotFoundException;
-
-   /**
-    * @see ResourceRecordApi#listByNameAndType(String, int)
-    */
-   @Named("getResourceRecordsOfDNameByType")
-   @POST
-   @XMLResponseParser(ResourceRecordListHandler.class)
-   @Payload("<v01:getResourceRecordsOfDNameByType><zoneName>{zoneName}</zoneName><hostName>{hostName}</hostName><rrType>{rrType}</rrType></v01:getResourceRecordsOfDNameByType>")
-   ListenableFuture<FluentIterable<ResourceRecordMetadata>> listByNameAndType(
-         @PayloadParam("hostName") String hostName, @PayloadParam("rrType") int rrType)
-         throws ResourceNotFoundException;
-
-   /**
-    * @see ResourceRecordApi#delete(String)
-    */
-   @Named("deleteResourceRecord")
-   @POST
-   @Payload("<v01:deleteResourceRecord><transactionID /><guid>{guid}</guid></v01:deleteResourceRecord>")
-   @Fallback(VoidOnNotFoundOr404.class)
-   ListenableFuture<Void> delete(@PayloadParam("guid") String guid);
-}
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/RoundRobinPoolApi.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/RoundRobinPoolApi.java
index 9c4eb87..80c1984 100644
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/RoundRobinPoolApi.java
+++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/RoundRobinPoolApi.java
@@ -18,19 +18,62 @@
  */
 package org.jclouds.ultradns.ws.features;
 
+import javax.inject.Named;
+import javax.ws.rs.POST;
+
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
 import org.jclouds.rest.ResourceNotFoundException;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
 import org.jclouds.ultradns.ws.UltraDNSWSExceptions.ResourceAlreadyExistsException;
 import org.jclouds.ultradns.ws.domain.ResourceRecord;
 import org.jclouds.ultradns.ws.domain.ResourceRecordMetadata;
 import org.jclouds.ultradns.ws.domain.RoundRobinPool;
+import org.jclouds.ultradns.ws.filters.SOAPWrapWithPasswordAuth;
+import org.jclouds.ultradns.ws.xml.ElementTextHandler;
+import org.jclouds.ultradns.ws.xml.ResourceRecordListHandler;
+import org.jclouds.ultradns.ws.xml.RoundRobinPoolListHandler;
 
 import com.google.common.collect.FluentIterable;
 
 /**
- * @see RoundRobinPoolAsyncApi
+ * @see <a href="https://ultra-api.ultradns.com:8443/UltraDNS_WS/v01?wsdl" />
+ * @see <a href="https://www.ultradns.net/api/NUS_API_XML_SOAP.pdf" />
  * @author Adrian Cole
  */
+@RequestFilters(SOAPWrapWithPasswordAuth.class)
+@VirtualHost
 public interface RoundRobinPoolApi {
+
+   /**
+    * Returns all round robin pools in the zone.
+    * 
+    * @throws ResourceNotFoundException
+    *            if the zone doesn't exist
+    */
+   @Named("getLoadBalancingPoolsByZone")
+   @POST
+   @XMLResponseParser(RoundRobinPoolListHandler.class)
+   @Payload("<v01:getLoadBalancingPoolsByZone><zoneName>{zoneName}</zoneName><lbPoolType>RR</lbPoolType></v01:getLoadBalancingPoolsByZone>")
+   FluentIterable<RoundRobinPool> list() throws ResourceNotFoundException;
+
+   /**
+    * Returns all records in the round robin pool.
+    * 
+    * @throws ResourceNotFoundException
+    *            if the pool doesn't exist
+    */
+   @Named("getRRPoolRecords")
+   @POST
+   @XMLResponseParser(ResourceRecordListHandler.class)
+   @Payload("<v01:getRRPoolRecords><lbPoolId>{poolId}</lbPoolId></v01:getRRPoolRecords>")
+   FluentIterable<ResourceRecordMetadata> listRecords(@PayloadParam("poolId") String poolId)
+         throws ResourceNotFoundException;
+
    /**
     * creates a round robin pool for {@code A} (ipv4) records
     * 
@@ -43,7 +86,12 @@
     * @throws ResourceAlreadyExistsException
     *            if a pool already exists with the same attrs
     */
-   String createAPoolForHostname(String name, String hostname) throws ResourceAlreadyExistsException;
+   @Named("addRRLBPool")
+   @POST
+   @XMLResponseParser(ElementTextHandler.RRPoolID.class)
+   @Payload("<v01:addRRLBPool><transactionID /><zoneName>{zoneName}</zoneName><hostName>{hostName}</hostName><description>{description}</description><poolRecordType>1</poolRecordType><rrGUID /></v01:addRRLBPool>")
+   String createAPoolForHostname(@PayloadParam("description") String name,
+         @PayloadParam("hostName") String hostname) throws ResourceAlreadyExistsException;
 
    /**
     * adds a new {@code A} record to the pool
@@ -58,37 +106,12 @@
     * @throws ResourceAlreadyExistsException
     *            if a record already exists with the same attrs
     */
-   String addARecordWithAddressAndTTL(String lbPoolID, String ipv4Address, int ttl)
-         throws ResourceAlreadyExistsException;
-
-   /**
-    * creates a round robin pool for {@code AAAA} (ipv6) records
-    * 
-    * @param name
-    *           {@link RoundRobinPool#getName() name} of the RR pool
-    * @param hostname
-    *           {@link RoundRobinPool#getDName() hostname} {ex.
-    *           www.jclouds.org.}
-    * @return the {@code guid} of the new record
-    * @throws ResourceAlreadyExistsException
-    *            if a pool already exists with the same attrs
-    */
-   String createAAAAPoolForHostname(String name, String hostname) throws ResourceAlreadyExistsException;
-
-   /**
-    * adds a new {@code AAAA} record to the pool
-    * 
-    * @param lbPoolID
-    *           the pool to add the record to.
-    * @param ipv6Address
-    *           the ipv6 address
-    * @param ttl
-    *           the {@link ResourceRecord#getTTL ttl} of the record
-    * @return the {@code guid} of the new record
-    * @throws ResourceAlreadyExistsException
-    *            if a record already exists with the same attrs
-    */
-   String addAAAARecordWithAddressAndTTL(String lbPoolID, String ipv6Address, int ttl)
+   @Named("addRecordToRRPool")
+   @POST
+   @XMLResponseParser(ElementTextHandler.Guid.class)
+   @Payload("<v01:addRecordToRRPool><transactionID /><roundRobinRecord lbPoolID=\"{lbPoolID}\" info1Value=\"{address}\" ZoneName=\"{zoneName}\" Type=\"1\" TTL=\"{ttl}\"/></v01:addRecordToRRPool>")
+   String addARecordWithAddressAndTTL(@PayloadParam("lbPoolID") String lbPoolID,
+         @PayloadParam("address") String ipv4Address, @PayloadParam("ttl") int ttl)
          throws ResourceAlreadyExistsException;
 
    /**
@@ -107,24 +130,12 @@
     * @throws ResourceNotFoundException
     *            if the guid doesn't exist
     */
-   void updateRecordWithAddressAndTTL(String lbPoolID, String guid, String address, int ttl)
-         throws ResourceNotFoundException;
-
-   /**
-    * Returns all round robin pools in the zone.
-    * 
-    * @throws ResourceNotFoundException
-    *            if the zone doesn't exist
-    */
-   FluentIterable<RoundRobinPool> list() throws ResourceNotFoundException;
-
-   /**
-    * Returns all records in the round robin pool.
-    * 
-    * @throws ResourceNotFoundException
-    *            if the pool doesn't exist
-    */
-   FluentIterable<ResourceRecordMetadata> listRecords(String poolId) throws ResourceNotFoundException;
+   @Named("updateRecordOfRRPool")
+   @POST
+   @Payload("<v01:updateRecordOfRRPool><transactionID /><resourceRecord rrGuid=\"{guid}\" lbPoolID=\"{lbPoolID}\" info1Value=\"{address}\" TTL=\"{ttl}\"/></v01:updateRecordOfRRPool>")
+   void updateRecordWithAddressAndTTL(@PayloadParam("lbPoolID") String lbPoolID,
+         @PayloadParam("guid") String guid, @PayloadParam("address") String ipv4Address,
+         @PayloadParam("ttl") int ttl) throws ResourceNotFoundException;
 
    /**
     * deletes a specific pooled resource record
@@ -133,7 +144,51 @@
     *           the global unique identifier for the resource record {@see
     *           ResourceRecordMetadata#getGuid()}
     */
-   void deleteRecord(String guid);
+   @Named("deleteRecordOfRRPool")
+   @POST
+   @Payload("<v01:deleteRecordOfRRPool><transactionID /><guid>{guid}</guid></v01:deleteRecordOfRRPool>")
+   @Fallback(VoidOnNotFoundOr404.class)
+   void deleteRecord(@PayloadParam("guid") String guid);
+
+   /**
+    * creates a round robin pool for {@code AAAA} (ipv6) records
+    * 
+    * @param name
+    *           {@link RoundRobinPool#getName() name} of the RR pool
+    * @param hostname
+    *           {@link RoundRobinPool#getDName() hostname} {ex.
+    *           www.jclouds.org.}
+    * @return the {@code guid} of the new record
+    * @throws ResourceAlreadyExistsException
+    *            if a pool already exists with the same attrs
+    */
+   @Named("addRRLBPool")
+   @POST
+   @XMLResponseParser(ElementTextHandler.RRPoolID.class)
+   @Payload("<v01:addRRLBPool><transactionID /><zoneName>{zoneName}</zoneName><hostName>{hostName}</hostName><description>{description}</description><poolRecordType>28</poolRecordType><rrGUID /></v01:addRRLBPool>")
+   String createAAAAPoolForHostname(@PayloadParam("description") String name,
+         @PayloadParam("hostName") String hostname) throws ResourceAlreadyExistsException;
+
+   /**
+    * adds a new {@code AAAA} record to the pool
+    * 
+    * @param lbPoolID
+    *           the pool to add the record to.
+    * @param ipv6Address
+    *           the ipv6 address
+    * @param ttl
+    *           the {@link ResourceRecord#getTTL ttl} of the record
+    * @return the {@code guid} of the new record
+    * @throws ResourceAlreadyExistsException
+    *            if a record already exists with the same attrs
+    */
+   @Named("addRecordToRRPool")
+   @POST
+   @XMLResponseParser(ElementTextHandler.Guid.class)
+   @Payload("<v01:addRecordToRRPool><transactionID /><roundRobinRecord lbPoolID=\"{lbPoolID}\" info1Value=\"{address}\" ZoneName=\"{zoneName}\" Type=\"28\" TTL=\"{ttl}\"/></v01:addRecordToRRPool>")
+   String addAAAARecordWithAddressAndTTL(@PayloadParam("lbPoolID") String lbPoolID,
+         @PayloadParam("address") String ipv6Address, @PayloadParam("ttl") int ttl)
+         throws ResourceAlreadyExistsException;
 
    /**
     * removes a pool and all its records and probes
@@ -141,5 +196,9 @@
     * @param id
     *           the {@link RoundRobinPool#getId() id}
     */
-   void delete(String id);
+   @Named("deleteLBPool")
+   @POST
+   @Payload("<v01:deleteLBPool><transactionID /><lbPoolID>{lbPoolID}</lbPoolID><DeleteAll>Yes</DeleteAll><retainRecordId /></v01:deleteLBPool>")
+   @Fallback(VoidOnNotFoundOr404.class)
+   void delete(@PayloadParam("lbPoolID") String id);
 }
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/RoundRobinPoolAsyncApi.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/RoundRobinPoolAsyncApi.java
deleted file mode 100644
index ab27999..0000000
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/RoundRobinPoolAsyncApi.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.ultradns.ws.features;
-
-import javax.inject.Named;
-import javax.ws.rs.POST;
-
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.rest.ResourceNotFoundException;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.Payload;
-import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-import org.jclouds.ultradns.ws.UltraDNSWSExceptions.ResourceAlreadyExistsException;
-import org.jclouds.ultradns.ws.domain.ResourceRecord;
-import org.jclouds.ultradns.ws.domain.RoundRobinPool;
-import org.jclouds.ultradns.ws.filters.SOAPWrapWithPasswordAuth;
-import org.jclouds.ultradns.ws.xml.TextHandler;
-import org.jclouds.ultradns.ws.xml.ResourceRecordListHandler;
-import org.jclouds.ultradns.ws.xml.RoundRobinPoolListHandler;
-
-import com.google.common.collect.FluentIterable;
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * @see RoundRobinPoolApi
- * @see <a href="https://ultra-api.ultradns.com:8443/UltraDNS_WS/v01?wsdl" />
- * @see <a href="https://www.ultradns.net/api/NUS_API_XML_SOAP.pdf" />
- * @author Adrian Cole
- */
-@RequestFilters(SOAPWrapWithPasswordAuth.class)
-@VirtualHost
-public interface RoundRobinPoolAsyncApi {
-
-   /**
-    * @see RoundRobinPoolApi#list()
-    */
-   @Named("getLoadBalancingPoolsByZone")
-   @POST
-   @XMLResponseParser(RoundRobinPoolListHandler.class)
-   @Payload("<v01:getLoadBalancingPoolsByZone><zoneName>{zoneName}</zoneName><lbPoolType>RR</lbPoolType></v01:getLoadBalancingPoolsByZone>")
-   ListenableFuture<FluentIterable<RoundRobinPool>> list() throws ResourceNotFoundException;
-
-   /**
-    * @see RoundRobinPoolApi#listRecords(String)
-    */
-   @Named("getRRPoolRecords")
-   @POST
-   @XMLResponseParser(ResourceRecordListHandler.class)
-   @Payload("<v01:getRRPoolRecords><lbPoolId>{poolId}</lbPoolId></v01:getRRPoolRecords>")
-   ListenableFuture<FluentIterable<ResourceRecord>> listRecords(@PayloadParam("poolId") String poolId)
-         throws ResourceNotFoundException;
-
-   /**
-    * @see RoundRobinPoolApi#createAPoolForHostname
-    */
-   @Named("addRRLBPool")
-   @POST
-   @XMLResponseParser(TextHandler.RRPoolID.class)
-   @Payload("<v01:addRRLBPool><transactionID /><zoneName>{zoneName}</zoneName><hostName>{hostName}</hostName><description>{description}</description><poolRecordType>1</poolRecordType><rrGUID /></v01:addRRLBPool>")
-   ListenableFuture<String> createAPoolForHostname(@PayloadParam("description") String name,
-         @PayloadParam("hostName") String hostname) throws ResourceAlreadyExistsException;
-
-   /**
-    * @see RoundRobinPoolApi#addARecordWithAddressAndTTL
-    */
-   @Named("addRecordToRRPool")
-   @POST
-   @XMLResponseParser(TextHandler.Guid.class)
-   @Payload("<v01:addRecordToRRPool><transactionID /><roundRobinRecord lbPoolID=\"{lbPoolID}\" info1Value=\"{address}\" ZoneName=\"{zoneName}\" Type=\"1\" TTL=\"{ttl}\"/></v01:addRecordToRRPool>")
-   ListenableFuture<String> addARecordWithAddressAndTTL(@PayloadParam("lbPoolID") String lbPoolID,
-         @PayloadParam("address") String ipv4Address, @PayloadParam("ttl") int ttl)
-         throws ResourceAlreadyExistsException;
-
-   /**
-    * @see RoundRobinPoolApi#updateRecordWithAddressAndTTL
-    */
-   @Named("updateRecordOfRRPool")
-   @POST
-   @Payload("<v01:updateRecordOfRRPool><transactionID /><resourceRecord rrGuid=\"{guid}\" lbPoolID=\"{lbPoolID}\" info1Value=\"{address}\" TTL=\"{ttl}\"/></v01:updateRecordOfRRPool>")
-   ListenableFuture<Void> updateRecordWithAddressAndTTL(@PayloadParam("lbPoolID") String lbPoolID,
-         @PayloadParam("guid") String guid, @PayloadParam("address") String ipv4Address,
-         @PayloadParam("ttl") int ttl) throws ResourceNotFoundException;
-
-   /**
-    * @see RoundRobinPoolApi#deleteRecord(String)
-    */
-   @Named("deleteRecordOfRRPool")
-   @POST
-   @Payload("<v01:deleteRecordOfRRPool><transactionID /><guid>{guid}</guid></v01:deleteRecordOfRRPool>")
-   @Fallback(VoidOnNotFoundOr404.class)
-   ListenableFuture<Void> deleteRecord(@PayloadParam("guid") String guid);
-
-   /**
-    * @see RoundRobinPoolApi#createAAAAPoolForHostname
-    */
-   @Named("addRRLBPool")
-   @POST
-   @XMLResponseParser(TextHandler.RRPoolID.class)
-   @Payload("<v01:addRRLBPool><transactionID /><zoneName>{zoneName}</zoneName><hostName>{hostName}</hostName><description>{description}</description><poolRecordType>28</poolRecordType><rrGUID /></v01:addRRLBPool>")
-   ListenableFuture<String> createAAAAPoolForHostname(@PayloadParam("description") String name,
-         @PayloadParam("hostName") String hostname) throws ResourceAlreadyExistsException;
-
-   /**
-    * @see RoundRobinPoolApi#addAAAARecordWithAddressAndTTL
-    */
-   @Named("addRecordToRRPool")
-   @POST
-   @XMLResponseParser(TextHandler.Guid.class)
-   @Payload("<v01:addRecordToRRPool><transactionID /><roundRobinRecord lbPoolID=\"{lbPoolID}\" info1Value=\"{address}\" ZoneName=\"{zoneName}\" Type=\"28\" TTL=\"{ttl}\"/></v01:addRecordToRRPool>")
-   ListenableFuture<String> addAAAARecordWithAddressAndTTL(@PayloadParam("lbPoolID") String lbPoolID,
-         @PayloadParam("address") String ipv6Address, @PayloadParam("ttl") int ttl)
-         throws ResourceAlreadyExistsException;
-
-   /**
-    * @see RoundRobinPoolApi#delete(String)
-    */
-   @Named("deleteLBPool")
-   @POST
-   @Payload("<v01:deleteLBPool><transactionID /><lbPoolID>{lbPoolID}</lbPoolID><DeleteAll>Yes</DeleteAll><retainRecordId /></v01:deleteLBPool>")
-   @Fallback(VoidOnNotFoundOr404.class)
-   ListenableFuture<Void> delete(@PayloadParam("lbPoolID") String id);
-}
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TaskApi.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TaskApi.java
index 5e35e6a..a378ba6 100644
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TaskApi.java
+++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TaskApi.java
@@ -18,43 +18,76 @@
  */
 package org.jclouds.ultradns.ws.features;
 
+import javax.inject.Named;
+import javax.ws.rs.POST;
+
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
 import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
 import org.jclouds.ultradns.ws.domain.Task;
+import org.jclouds.ultradns.ws.filters.SOAPWrapWithPasswordAuth;
+import org.jclouds.ultradns.ws.xml.ElementTextHandler;
+import org.jclouds.ultradns.ws.xml.TaskHandler;
+import org.jclouds.ultradns.ws.xml.TaskListHandler;
 
 import com.google.common.collect.FluentIterable;
 
 /**
- * @see TaskAsyncApi
+ * @see <a href="https://ultra-api.ultradns.com:8443/UltraDNS_WS/v01?wsdl" />
+ * @see <a href="https://www.ultradns.net/api/NUS_API_XML_SOAP.pdf" />
  * @author Adrian Cole
  */
+@RequestFilters(SOAPWrapWithPasswordAuth.class)
+@VirtualHost
 public interface TaskApi {
    /**
     * Runs a test task
     * 
     * @return guid of the task created
     */
-   String runTest(String value);
+   @Named("runTest")
+   @POST
+   @XMLResponseParser(ElementTextHandler.Guid.class)
+   @Payload("<v01:runTest><value>{value}</value></v01:runTest>")
+   String runTest(@PayloadParam("value") String value);
 
    /**
-    * Retrieves information about the specified task
-    * 
     * @param guid
     *           guid of the task to get information about.
     * @return null if not found
     */
+   @Named("getStatusForTask")
+   @POST
+   @XMLResponseParser(TaskHandler.class)
+   @Payload("<v01:getStatusForTask><id><guid>{guid}</guid></id></v01:getStatusForTask>")
+   @Fallback(NullOnNotFoundOr404.class)
    @Nullable
-   Task get(String guid);
+   Task get(@PayloadParam("guid") String name);
 
    /**
     * Lists all tasks.
     */
+   @Named("getAllTasks")
+   @POST
+   @XMLResponseParser(TaskListHandler.class)
+   @Payload("<v01:getAllTasks/>")
    FluentIterable<Task> list();
-   
+
    /**
     * clears a background task in either a COMPLETE or ERROR state. 
     * 
     * @param guid
     *           guid of the task to clear.
     */
-   void clear(String guid);
+   @Named("clearTask")
+   @POST
+   @Payload("<v01:clearTask><id><guid>{guid}</guid></id></v01:clearTask>")
+   @Fallback(VoidOnNotFoundOr404.class)
+   void clear(@PayloadParam("guid") String name);
 }
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TaskAsyncApi.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TaskAsyncApi.java
deleted file mode 100644
index 919c37e..0000000
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TaskAsyncApi.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.ultradns.ws.features;
-
-import javax.inject.Named;
-import javax.ws.rs.POST;
-
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.Payload;
-import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-import org.jclouds.ultradns.ws.domain.Task;
-import org.jclouds.ultradns.ws.filters.SOAPWrapWithPasswordAuth;
-import org.jclouds.ultradns.ws.xml.TextHandler;
-import org.jclouds.ultradns.ws.xml.TaskHandler;
-import org.jclouds.ultradns.ws.xml.TaskListHandler;
-
-import com.google.common.collect.FluentIterable;
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * @see TaskApi
- * @see <a href="https://ultra-api.ultradns.com:8443/UltraDNS_WS/v01?wsdl" />
- * @see <a href="https://www.ultradns.net/api/NUS_API_XML_SOAP.pdf" />
- * @author Adrian Cole
- */
-@RequestFilters(SOAPWrapWithPasswordAuth.class)
-@VirtualHost
-public interface TaskAsyncApi {
-   /**
-    * @see TaskApi#runTest(String)
-    */
-   @Named("runTest")
-   @POST
-   @XMLResponseParser(TextHandler.Guid.class)
-   @Payload("<v01:runTest><value>{value}</value></v01:runTest>")
-   ListenableFuture<String> runTest(@PayloadParam("value") String value);
-
-   /**
-    * @see TaskApi#get(String)
-    */
-   @Named("getStatusForTask")
-   @POST
-   @XMLResponseParser(TaskHandler.class)
-   @Payload("<v01:getStatusForTask><id><guid>{guid}</guid></id></v01:getStatusForTask>")
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<Task> get(@PayloadParam("guid") String name);
-
-   /**
-    * @see TaskApi#list()
-    */
-   @Named("getAllTasks")
-   @POST
-   @XMLResponseParser(TaskListHandler.class)
-   @Payload("<v01:getAllTasks/>")
-   ListenableFuture<FluentIterable<Task>> list();
-
-   /**
-    * @see TaskApi#clear(String)
-    */
-   @Named("clearTask")
-   @POST
-   @Payload("<v01:clearTask><id><guid>{guid}</guid></id></v01:clearTask>")
-   @Fallback(VoidOnNotFoundOr404.class)
-   ListenableFuture<Void> clear(@PayloadParam("guid") String name);
-}
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApi.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApi.java
index 4ad9b5e..7975994 100644
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApi.java
+++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApi.java
@@ -18,31 +18,45 @@
  */
 package org.jclouds.ultradns.ws.features;
 
+import javax.inject.Named;
+import javax.ws.rs.POST;
+
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.rest.ResourceNotFoundException;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
 import org.jclouds.ultradns.ws.UltraDNSWSExceptions.ResourceAlreadyExistsException;
+import org.jclouds.ultradns.ws.binders.UpdatePoolRecordToXML;
 import org.jclouds.ultradns.ws.domain.PoolRecordSpec;
 import org.jclouds.ultradns.ws.domain.TrafficControllerPool;
 import org.jclouds.ultradns.ws.domain.TrafficControllerPoolRecord;
 import org.jclouds.ultradns.ws.domain.UpdatePoolRecord;
+import org.jclouds.ultradns.ws.filters.SOAPWrapWithPasswordAuth;
+import org.jclouds.ultradns.ws.xml.AttributeHandler;
+import org.jclouds.ultradns.ws.xml.ElementTextHandler;
+import org.jclouds.ultradns.ws.xml.PoolRecordSpecHandler;
+import org.jclouds.ultradns.ws.xml.TrafficControllerPoolListHandler;
+import org.jclouds.ultradns.ws.xml.TrafficControllerPoolRecordListHandler;
 
 import com.google.common.collect.FluentIterable;
 
 /**
- * @see TrafficControllerPoolAsyncApi
+ * @see <a href="https://ultra-api.ultradns.com:8443/UltraDNS_WS/v01?wsdl" />
+ * @see <a href="https://www.ultradns.net/api/NUS_API_XML_SOAP.pdf" />
  * @author Adrian Cole
  */
+@RequestFilters(SOAPWrapWithPasswordAuth.class)
+@VirtualHost
 public interface TrafficControllerPoolApi {
 
    /**
-    * Returns all traffic controller pools in the zone.
-    * 
-    * @throws ResourceNotFoundException
-    *            if the zone doesn't exist
-    */
-   FluentIterable<TrafficControllerPool> list() throws ResourceNotFoundException;
-
-   /**
     * creates a traffic controller pool.
     * 
     * @param name
@@ -54,7 +68,37 @@
     * @throws ResourceAlreadyExistsException
     *            if a pool already exists with the same attrs
     */
-   String createPoolForHostname(String name, String hostname) throws ResourceAlreadyExistsException;
+   @Named("addTCLBPool")
+   @POST
+   @XMLResponseParser(ElementTextHandler.TCPoolID.class)
+   @Payload("<v01:addTCLBPool><transactionID /><zoneName>{zoneName}</zoneName><hostName>{hostName}</hostName><description>{description}</description><poolRecordType>1</poolRecordType><failOver>Enabled</failOver><probing>Enabled</probing><maxActive>0</maxActive><rrGUID /></v01:addTCLBPool>")
+   String createPoolForHostname(@PayloadParam("description") String name, @PayloadParam("hostName") String hostname)
+         throws ResourceAlreadyExistsException;
+
+   /**
+    * Returns all traffic controller pools in the zone.
+    * 
+    * @throws ResourceNotFoundException
+    *            if the zone doesn't exist
+    */
+   @Named("getLoadBalancingPoolsByZone")
+   @POST
+   @XMLResponseParser(TrafficControllerPoolListHandler.class)
+   @Payload("<v01:getLoadBalancingPoolsByZone><zoneName>{zoneName}</zoneName><lbPoolType>TC</lbPoolType></v01:getLoadBalancingPoolsByZone>")
+   FluentIterable<TrafficControllerPool> list() throws ResourceNotFoundException;
+
+   /**
+    * Returns all records in the traffic controller pool.
+    * 
+    * @throws ResourceNotFoundException
+    *            if the pool doesn't exist
+    */
+   @Named("getPoolRecords")
+   @POST
+   @XMLResponseParser(TrafficControllerPoolRecordListHandler.class)
+   @Payload("<v01:getPoolRecords><poolId>{poolId}</poolId></v01:getPoolRecords>")
+   FluentIterable<TrafficControllerPoolRecord> listRecords(@PayloadParam("poolId") String poolId)
+         throws ResourceNotFoundException;
 
    /**
     * Retrieves the name of the specified pool by dname.
@@ -64,7 +108,12 @@
     * @return null if not found
     */
    @Nullable
-   String getNameByDName(String dname);
+   @Named("getPoolForPoolHostName>")
+   @POST
+   @Payload("<v01:getPoolForPoolHostName><hostName>{hostName}</hostName></v01:getPoolForPoolHostName>")
+   @XMLResponseParser(AttributeHandler.PoolName.class)
+   @Fallback(NullOnNotFoundOr404.class)
+   String getNameByDName(@PayloadParam("hostName") String dname);
 
    /**
     * removes a pool and all its records and probes
@@ -72,15 +121,11 @@
     * @param id
     *           the {@link TrafficControllerPool#getId() id}
     */
-   void delete(String id);
-
-   /**
-    * Returns all records in the traffic controller pool.
-    * 
-    * @throws ResourceNotFoundException
-    *            if the pool doesn't exist
-    */
-   FluentIterable<TrafficControllerPoolRecord> listRecords(String poolId) throws ResourceNotFoundException;
+   @Named("deleteLBPool")
+   @POST
+   @Payload("<v01:deleteLBPool><transactionID /><lbPoolID>{lbPoolID}</lbPoolID><DeleteAll>Yes</DeleteAll><retainRecordId /></v01:deleteLBPool>")
+   @Fallback(VoidOnNotFoundOr404.class)
+   void delete(@PayloadParam("lbPoolID") String id);
 
    /**
     * adds a new record to the pool with default weight.
@@ -96,7 +141,12 @@
     * @throws ResourceAlreadyExistsException
     *            if a record already exists with the same attrs
     */
-   String addRecordToPoolWithTTL(String pointsTo, String lbPoolID, int ttl) throws ResourceAlreadyExistsException;
+   @Named("addPoolRecord")
+   @POST
+   @XMLResponseParser(ElementTextHandler.PoolRecordID.class)
+   @Payload("<v01:addPoolRecord><transactionID /><poolID>{poolID}</poolID><pointsTo>{pointsTo}</pointsTo><priority /><failOverDelay /><ttl>{ttl}</ttl><weight /><mode /><threshold /></v01:addPoolRecord>")
+   String addRecordToPoolWithTTL(@PayloadParam("pointsTo") String pointsTo, @PayloadParam("poolID") String lbPoolID,
+         @PayloadParam("ttl") int ttl) throws ResourceAlreadyExistsException;
 
    /**
     * adds a new record to the pool with a specified weight.
@@ -114,18 +164,26 @@
     * @throws ResourceAlreadyExistsException
     *            if a record already exists with the same attrs
     */
-   String addRecordToPoolWithTTLAndWeight(String pointsTo, String lbPoolID, int ttl, int weight)
+   @Named("addPoolRecord")
+   @POST
+   @XMLResponseParser(ElementTextHandler.PoolRecordID.class)
+   @Payload("<v01:addPoolRecord><transactionID /><poolID>{poolID}</poolID><pointsTo>{pointsTo}</pointsTo><priority /><failOverDelay /><ttl>{ttl}</ttl><weight>{weight}</weight><mode /><threshold /></v01:addPoolRecord>")
+   String addRecordToPoolWithTTLAndWeight(@PayloadParam("pointsTo") String pointsTo,
+         @PayloadParam("poolID") String lbPoolID, @PayloadParam("ttl") int ttl, @PayloadParam("weight") int weight)
          throws ResourceAlreadyExistsException;
 
    /**
-    * Retrieves information about the specified pool record
-    * 
     * @param poolRecordID
     *           {@link TrafficControllerPoolRecord#getId()}
     * @return null if not found
     */
+   @Named("getPoolRecordSpec>")
+   @POST
+   @Payload("<v01:getPoolRecordSpec><poolRecordId>{poolRecordId}</poolRecordId></v01:getPoolRecordSpec>")
+   @XMLResponseParser(PoolRecordSpecHandler.class)
+   @Fallback(NullOnNotFoundOr404.class)
    @Nullable
-   PoolRecordSpec getRecordSpec(String poolRecordID);
+   PoolRecordSpec getRecordSpec(@PayloadParam("poolRecordId") String poolRecordID);
 
    /**
     * This request updates an existing pool record.
@@ -139,7 +197,11 @@
     * @throws ResourceNotFoundException
     *            if the record doesn't exist
     */
-   void updateRecord(String poolRecordID, UpdatePoolRecord update) throws ResourceNotFoundException;
+   @Named("updatePoolRecord>")
+   @POST
+   @MapBinder(UpdatePoolRecordToXML.class)
+   void updateRecord(@PayloadParam("poolRecordID") String poolRecordID, @PayloadParam("update") UpdatePoolRecord update)
+         throws ResourceNotFoundException;
 
    /**
     * deletes a specific pooled resource record
@@ -147,6 +209,10 @@
     * @param poolRecordID
     *           {@see TrafficControllerPoolRecord#getId()}
     */
-   void deleteRecord(String poolRecordID);
+   @Named("deletePoolRecord")
+   @POST
+   @Payload("<v01:deletePoolRecord><transactionID /><poolRecordID>{poolRecordID}</poolRecordID><parentPoolId /><childPoolId /></v01:deletePoolRecord>")
+   @Fallback(VoidOnNotFoundOr404.class)
+   void deleteRecord(@PayloadParam("poolRecordID") String poolRecordID);
 
 }
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolAsyncApi.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolAsyncApi.java
deleted file mode 100644
index 75e1f39..0000000
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolAsyncApi.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.ultradns.ws.features;
-
-import javax.inject.Named;
-import javax.ws.rs.POST;
-
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.rest.ResourceNotFoundException;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.MapBinder;
-import org.jclouds.rest.annotations.Payload;
-import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-import org.jclouds.ultradns.ws.UltraDNSWSExceptions.ResourceAlreadyExistsException;
-import org.jclouds.ultradns.ws.binders.UpdatePoolRecordToXML;
-import org.jclouds.ultradns.ws.domain.PoolRecordSpec;
-import org.jclouds.ultradns.ws.domain.TrafficControllerPool;
-import org.jclouds.ultradns.ws.domain.TrafficControllerPoolRecord;
-import org.jclouds.ultradns.ws.domain.UpdatePoolRecord;
-import org.jclouds.ultradns.ws.filters.SOAPWrapWithPasswordAuth;
-import org.jclouds.ultradns.ws.xml.AttributeHandler;
-import org.jclouds.ultradns.ws.xml.PoolRecordSpecHandler;
-import org.jclouds.ultradns.ws.xml.TextHandler;
-import org.jclouds.ultradns.ws.xml.TrafficControllerPoolListHandler;
-import org.jclouds.ultradns.ws.xml.TrafficControllerPoolRecordListHandler;
-
-import com.google.common.collect.FluentIterable;
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * @see TrafficControllerPoolApi
- * @see <a href="https://ultra-api.ultradns.com:8443/UltraDNS_WS/v01?wsdl" />
- * @see <a href="https://www.ultradns.net/api/NUS_API_XML_SOAP.pdf" />
- * @author Adrian Cole
- */
-@RequestFilters(SOAPWrapWithPasswordAuth.class)
-@VirtualHost
-public interface TrafficControllerPoolAsyncApi {
-
-   /**
-    * @see RoundRobinPoolApi#createPoolForHostname
-    */
-   @Named("addTCLBPool")
-   @POST
-   @XMLResponseParser(TextHandler.TCPoolID.class)
-   @Payload("<v01:addTCLBPool><transactionID /><zoneName>{zoneName}</zoneName><hostName>{hostName}</hostName><description>{description}</description><poolRecordType>1</poolRecordType><failOver>Enabled</failOver><probing>Enabled</probing><maxActive>0</maxActive><rrGUID /></v01:addTCLBPool>")
-   ListenableFuture<String> createPoolForHostname(@PayloadParam("description") String name,
-         @PayloadParam("hostName") String hostname) throws ResourceAlreadyExistsException;
-
-   /**
-    * @see TrafficControllerPoolApi#list()
-    */
-   @Named("getLoadBalancingPoolsByZone")
-   @POST
-   @XMLResponseParser(TrafficControllerPoolListHandler.class)
-   @Payload("<v01:getLoadBalancingPoolsByZone><zoneName>{zoneName}</zoneName><lbPoolType>TC</lbPoolType></v01:getLoadBalancingPoolsByZone>")
-   ListenableFuture<FluentIterable<TrafficControllerPool>> list() throws ResourceNotFoundException;
-
-   /**
-    * @see TrafficControllerPoolApi#listRecords(String)
-    */
-   @Named("getPoolRecords")
-   @POST
-   @XMLResponseParser(TrafficControllerPoolRecordListHandler.class)
-   @Payload("<v01:getPoolRecords><poolId>{poolId}</poolId></v01:getPoolRecords>")
-   ListenableFuture<FluentIterable<TrafficControllerPoolRecord>> listRecords(@PayloadParam("poolId") String poolId)
-         throws ResourceNotFoundException;
-
-   /**
-    * @see TrafficControllerPoolApi#getByDName(String)
-    */
-   @Named("getPoolForPoolHostName>")
-   @POST
-   @Payload("<v01:getPoolForPoolHostName><hostName>{hostName}</hostName></v01:getPoolForPoolHostName>")
-   @XMLResponseParser(AttributeHandler.PoolName.class)
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<String> getNameByDName(@PayloadParam("hostName") String dname);
-
-   /**
-    * @see TrafficControllerPoolApi#delete(String)
-    */
-   @Named("deleteLBPool")
-   @POST
-   @Payload("<v01:deleteLBPool><transactionID /><lbPoolID>{lbPoolID}</lbPoolID><DeleteAll>Yes</DeleteAll><retainRecordId /></v01:deleteLBPool>")
-   @Fallback(VoidOnNotFoundOr404.class)
-   ListenableFuture<Void> delete(@PayloadParam("lbPoolID") String id);
-
-   /**
-    * @see TrafficControllerPoolApi#addRecordToPoolWithTTL
-    */
-   @Named("addPoolRecord")
-   @POST
-   @XMLResponseParser(TextHandler.PoolRecordID.class)
-   @Payload("<v01:addPoolRecord><transactionID /><poolID>{poolID}</poolID><pointsTo>{pointsTo}</pointsTo><priority /><failOverDelay /><ttl>{ttl}</ttl><weight /><mode /><threshold /></v01:addPoolRecord>")
-   ListenableFuture<String> addRecordToPoolWithTTL(@PayloadParam("pointsTo") String pointsTo,
-         @PayloadParam("poolID") String lbPoolID, @PayloadParam("ttl") int ttl) throws ResourceAlreadyExistsException;
-
-   /**
-    * @see TrafficControllerPoolApi#addRecordToPoolWithTTLAndWeight
-    */
-   @Named("addPoolRecord")
-   @POST
-   @XMLResponseParser(TextHandler.PoolRecordID.class)
-   @Payload("<v01:addPoolRecord><transactionID /><poolID>{poolID}</poolID><pointsTo>{pointsTo}</pointsTo><priority /><failOverDelay /><ttl>{ttl}</ttl><weight>{weight}</weight><mode /><threshold /></v01:addPoolRecord>")
-   ListenableFuture<String> addRecordToPoolWithTTLAndWeight(@PayloadParam("pointsTo") String pointsTo,
-         @PayloadParam("poolID") String lbPoolID, @PayloadParam("ttl") int ttl, @PayloadParam("weight") int weight)
-         throws ResourceAlreadyExistsException;
-
-   /**
-    * @see TrafficControllerPoolApi#getRecordSpec(String)
-    */
-   @Named("getPoolRecordSpec>")
-   @POST
-   @Payload("<v01:getPoolRecordSpec><poolRecordId>{poolRecordId}</poolRecordId></v01:getPoolRecordSpec>")
-   @XMLResponseParser(PoolRecordSpecHandler.class)
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<PoolRecordSpec> getRecordSpec(@PayloadParam("poolRecordId") String poolRecordID);
-
-   /**
-    * @see TrafficControllerPoolApi#getRecordSpec(String)
-    */
-   @Named("updatePoolRecord>")
-   @POST
-   @MapBinder(UpdatePoolRecordToXML.class)
-   ListenableFuture<Void> updateRecord(@PayloadParam("poolRecordID") String poolRecordID,
-         @PayloadParam("update") UpdatePoolRecord update) throws ResourceNotFoundException;
-
-   /**
-    * @see TrafficControllerPoolApi#deleteRecord(String)
-    */
-   @Named("deletePoolRecord")
-   @POST
-   @Payload("<v01:deletePoolRecord><transactionID /><poolRecordID>{poolRecordID}</poolRecordID><parentPoolId /><childPoolId /></v01:deletePoolRecord>")
-   @Fallback(VoidOnNotFoundOr404.class)
-   ListenableFuture<Void> deleteRecord(@PayloadParam("poolRecordID") String poolRecordID);
-
-}
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ZoneApi.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ZoneApi.java
index ad631f6..5466e43 100644
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ZoneApi.java
+++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ZoneApi.java
@@ -18,19 +18,36 @@
  */
 package org.jclouds.ultradns.ws.features;
 
+import javax.inject.Named;
+import javax.ws.rs.POST;
+
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.rest.ResourceNotFoundException;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Payload;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
 import org.jclouds.ultradns.ws.UltraDNSWSExceptions.ResourceAlreadyExistsException;
 import org.jclouds.ultradns.ws.domain.Zone;
 import org.jclouds.ultradns.ws.domain.Zone.Type;
 import org.jclouds.ultradns.ws.domain.ZoneProperties;
+import org.jclouds.ultradns.ws.filters.SOAPWrapWithPasswordAuth;
+import org.jclouds.ultradns.ws.xml.ZoneListHandler;
+import org.jclouds.ultradns.ws.xml.ZonePropertiesHandler;
 
 import com.google.common.collect.FluentIterable;
 
 /**
- * @see ZoneAsyncApi
+ * @see <a href="https://ultra-api.ultradns.com:8443/UltraDNS_WS/v01?wsdl" />
+ * @see <a href="https://www.ultradns.net/api/NUS_API_XML_SOAP.pdf" />
  * @author Adrian Cole
  */
+@RequestFilters(SOAPWrapWithPasswordAuth.class)
+@VirtualHost
 public interface ZoneApi {
 
    /**
@@ -42,25 +59,36 @@
     * @param accountId
     *           the account to create the zone in
     */
-   void createInAccount(String name, String accountId) throws ResourceAlreadyExistsException;
+   @Named("createPrimaryZone")
+   @POST
+   @Payload("<v01:createPrimaryZone><transactionID /><accountId>{accountId}</accountId><zoneName>{zoneName}</zoneName><forceImport>false</forceImport></v01:createPrimaryZone>")
+   void createInAccount(@PayloadParam("zoneName") String name, @PayloadParam("accountId") String accountId)
+         throws ResourceAlreadyExistsException;
 
    /**
-    * Retrieves information about the specified zone
-    * 
     * @param name
     *           the fully-qualified name, including the trailing dot, of the
     *           zone to get information about.
     * @return null if not found
     */
+   @Named("getGeneralPropertiesForZone")
+   @POST
+   @XMLResponseParser(ZonePropertiesHandler.class)
+   @Payload("<v01:getGeneralPropertiesForZone><zoneName>{zoneName}</zoneName></v01:getGeneralPropertiesForZone>")
+   @Fallback(NullOnNotFoundOr404.class)
    @Nullable
-   ZoneProperties get(String name);
+   ZoneProperties get(@PayloadParam("zoneName") String name);
 
    /**
     * Lists all zones in the specified account.
     * 
     * @returns empty if no zones, or account doesn't exist
     */
-   FluentIterable<Zone> listByAccount(String accountId);
+   @Named("getZonesOfAccount")
+   @POST
+   @XMLResponseParser(ZoneListHandler.class)
+   @Payload("<v01:getZonesOfAccount><accountId>{accountId}</accountId><zoneType>all</zoneType></v01:getZonesOfAccount>")
+   FluentIterable<Zone> listByAccount(@PayloadParam("accountId") String accountId);
 
    /**
     * Lists all zones in the specified account of type
@@ -68,7 +96,12 @@
     * @throws ResourceNotFoundException
     *            if the account doesn't exist
     */
-   FluentIterable<Zone> listByAccountAndType(String accountId, Type type) throws ResourceNotFoundException;
+   @Named("getZonesOfAccount")
+   @POST
+   @XMLResponseParser(ZoneListHandler.class)
+   @Payload("<v01:getZonesOfAccount><accountId>{accountId}</accountId><zoneType>{zoneType}</zoneType></v01:getZonesOfAccount>")
+   FluentIterable<Zone> listByAccountAndType(@PayloadParam("accountId") String accountId,
+         @PayloadParam("zoneType") Type type) throws ResourceNotFoundException;
 
    /**
     * deletes a zone and all its resource records
@@ -78,5 +111,9 @@
     *           zone you want to delete.
     * @return null if not found
     */
-   void delete(String name);
+   @Named("deleteZone")
+   @POST
+   @Payload("<v01:deleteZone><transactionID /><zoneName>{zoneName}</zoneName></v01:deleteZone>")
+   @Fallback(VoidOnNotFoundOr404.class)
+   void delete(@PayloadParam("zoneName") String name);
 }
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ZoneAsyncApi.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ZoneAsyncApi.java
deleted file mode 100644
index d8d955b..0000000
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/features/ZoneAsyncApi.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- * Licensed to jclouds, Inc. (jclouds) under one or more
- * contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  jclouds licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.jclouds.ultradns.ws.features;
-
-import javax.inject.Named;
-import javax.ws.rs.POST;
-
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.rest.ResourceNotFoundException;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.Payload;
-import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-import org.jclouds.ultradns.ws.UltraDNSWSExceptions.ResourceAlreadyExistsException;
-import org.jclouds.ultradns.ws.domain.Zone;
-import org.jclouds.ultradns.ws.domain.Zone.Type;
-import org.jclouds.ultradns.ws.domain.ZoneProperties;
-import org.jclouds.ultradns.ws.filters.SOAPWrapWithPasswordAuth;
-import org.jclouds.ultradns.ws.xml.ZoneListHandler;
-import org.jclouds.ultradns.ws.xml.ZonePropertiesHandler;
-
-import com.google.common.collect.FluentIterable;
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * @see ZoneApi
- * @see <a href="https://ultra-api.ultradns.com:8443/UltraDNS_WS/v01?wsdl" />
- * @see <a href="https://www.ultradns.net/api/NUS_API_XML_SOAP.pdf" />
- * @author Adrian Cole
- */
-@RequestFilters(SOAPWrapWithPasswordAuth.class)
-@VirtualHost
-public interface ZoneAsyncApi {
-
-   /**
-    * @see ZoneApi#createInAccount(String, String
-    */
-   @Named("createPrimaryZone")
-   @POST
-   @Payload("<v01:createPrimaryZone><transactionID /><accountId>{accountId}</accountId><zoneName>{zoneName}</zoneName><forceImport>false</forceImport></v01:createPrimaryZone>")
-   ListenableFuture<Void> createInAccount(@PayloadParam("zoneName") String name,
-         @PayloadParam("accountId") String accountId) throws ResourceAlreadyExistsException;
-   
-   /**
-    * @see ZoneApi#get(String)
-    */
-   @Named("getGeneralPropertiesForZone")
-   @POST
-   @XMLResponseParser(ZonePropertiesHandler.class)
-   @Payload("<v01:getGeneralPropertiesForZone><zoneName>{zoneName}</zoneName></v01:getGeneralPropertiesForZone>")
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<ZoneProperties> get(@PayloadParam("zoneName") String name);
-
-   /**
-    * @see ZoneApi#listByAccount(String)
-    */
-   @Named("getZonesOfAccount")
-   @POST
-   @XMLResponseParser(ZoneListHandler.class)
-   @Payload("<v01:getZonesOfAccount><accountId>{accountId}</accountId><zoneType>all</zoneType></v01:getZonesOfAccount>")
-   ListenableFuture<FluentIterable<Zone>> listByAccount(@PayloadParam("accountId") String accountId);
-
-   /**
-    * @see ZoneApi#listByAccountAndType(String, Type)
-    */
-   @Named("getZonesOfAccount")
-   @POST
-   @XMLResponseParser(ZoneListHandler.class)
-   @Payload("<v01:getZonesOfAccount><accountId>{accountId}</accountId><zoneType>{zoneType}</zoneType></v01:getZonesOfAccount>")
-   ListenableFuture<FluentIterable<Zone>> listByAccountAndType(@PayloadParam("accountId") String accountId,
-         @PayloadParam("zoneType") Type type) throws ResourceNotFoundException;
-
-   /**
-    * @see ZoneApi#delete(String)
-    */
-   @Named("deleteZone")
-   @POST
-   @Payload("<v01:deleteZone><transactionID /><zoneName>{zoneName}</zoneName></v01:deleteZone>")
-   @Fallback(VoidOnNotFoundOr404.class)
-   ListenableFuture<Void> delete(@PayloadParam("zoneName") String name);
-}
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/predicates/TrafficControllerPoolPredicates.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/predicates/TrafficControllerPoolPredicates.java
index 89067ab..3a358be 100644
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/predicates/TrafficControllerPoolPredicates.java
+++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/predicates/TrafficControllerPoolPredicates.java
@@ -32,15 +32,6 @@
  */
 public class TrafficControllerPoolPredicates {
 
-   /**
-    * evaluates to true if the input {@link TrafficControllerPool} exists
-    * with {@link TrafficControllerPool#getId() id} corresponding to the
-    * {@code id} parameter.
-    * 
-    * @param id
-    *           the {@link TrafficControllerPool#getId() id} of the
-    *           desired pool record
-    */
    public static Predicate<TrafficControllerPool> idEqualTo(String id) {
       return new IdEqualToPredicate(id);
    }
@@ -54,9 +45,7 @@
 
       @Override
       public boolean apply(TrafficControllerPool input) {
-         if (input == null)
-            return false;
-         return id.equals(input.getId());
+         return input != null && id.equals(input.getId());
       }
 
       @Override
@@ -65,36 +54,25 @@
       }
    }
 
-   /**
-    * evaluates to true if the input {@link TrafficControllerPoolRecord} exists
-    * with {@link TrafficControllerPoolRecord#getId() id} corresponding to the
-    * {@code recordId} parameter.
-    * 
-    * @param recordId
-    *           the {@link TrafficControllerPoolRecord#getId() id} of the
-    *           desired pool record
-    */
    public static Predicate<TrafficControllerPoolRecord> recordIdEqualTo(String recordId) {
       return new RecordIdEqualToPredicate(recordId);
    }
 
    private static final class RecordIdEqualToPredicate implements Predicate<TrafficControllerPoolRecord> {
-      private final String id;
+      private final String recordId;
 
-      public RecordIdEqualToPredicate(String id) {
-         this.id = checkNotNull(id, "recordId");
+      public RecordIdEqualToPredicate(String recordId) {
+         this.recordId = checkNotNull(recordId, "recordId");
       }
 
       @Override
       public boolean apply(TrafficControllerPoolRecord input) {
-         if (input == null)
-            return false;
-         return id.equals(input.getId());
+         return input != null && recordId.equals(input.getId());
       }
 
       @Override
       public String toString() {
-         return "RecordIdEqualTo(" + id + ")";
+         return "RecordIdEqualTo(" + recordId + ")";
       }
    }
 }
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/predicates/ZonePredicates.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/predicates/ZonePredicates.java
index 72e6b84..21d8a68 100644
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/predicates/ZonePredicates.java
+++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/predicates/ZonePredicates.java
@@ -32,22 +32,25 @@
  */
 public class ZonePredicates {
 
-   /**
-    * matches zones of the given type
-    */
-   public static Predicate<Zone> typeEquals(final Type type) {
-      checkNotNull(type, "type must be defined");
+   public static Predicate<Zone> typeEqualTo(Type type) {
+      return new TypeEqualToPredicate(type);
+   }
 
-      return new Predicate<Zone>() {
-         @Override
-         public boolean apply(Zone zone) {
-            return type.equals(zone.getType());
-         }
+   private static final class TypeEqualToPredicate implements Predicate<Zone> {
+      private final Type type;
 
-         @Override
-         public String toString() {
-            return "typeEquals(" + type + ")";
-         }
-      };
+      public TypeEqualToPredicate(Type type) {
+         this.type = checkNotNull(type, "type");
+      }
+
+      @Override
+      public boolean apply(Zone input) {
+         return input != null && type.equals(input.getType());
+      }
+
+      @Override
+      public String toString() {
+         return "TypeEqualTo(" + type + ")";
+      }
    }
 }
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/xml/AttributeHandler.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/xml/AttributeHandler.java
index 5dc9b32..1173645 100644
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/xml/AttributeHandler.java
+++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/xml/AttributeHandler.java
@@ -37,7 +37,7 @@
       }
    }
 
-   private String attributeName;
+   private final String attributeName;
    private String attribute = null;
 
    private AttributeHandler(String attributeName) {
@@ -46,11 +46,7 @@
 
    @Override
    public String getResult() {
-      try {
-         return checkNotNull(attribute, "%s not present in the response", attributeName);
-      } finally {
-         attribute = null;
-      }
+      return checkNotNull(attribute, "%s not present in the response", attributeName);
    }
 
    @Override
diff --git a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/xml/TextHandler.java b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/xml/ElementTextHandler.java
similarity index 78%
rename from providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/xml/TextHandler.java
rename to providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/xml/ElementTextHandler.java
index ce59512..3fa4fa9 100644
--- a/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/xml/TextHandler.java
+++ b/providers/ultradns-ws/src/main/java/org/jclouds/ultradns/ws/xml/ElementTextHandler.java
@@ -28,48 +28,44 @@
  * 
  * @author Adrian Cole
  */
-public abstract class TextHandler extends ParseSax.HandlerForGeneratedRequestWithResult<String> {
+public abstract class ElementTextHandler extends ParseSax.HandlerForGeneratedRequestWithResult<String> {
 
-   public static class Guid extends TextHandler {
+   public static class Guid extends ElementTextHandler {
       public Guid() {
          super("guid");
       }
    }
 
-   public static class RRPoolID extends TextHandler {
+   public static class RRPoolID extends ElementTextHandler {
       public RRPoolID() {
          super("RRPoolID");
       }
    }
 
-   public static class TCPoolID extends TextHandler {
+   public static class TCPoolID extends ElementTextHandler {
       public TCPoolID() {
          super("TCPoolID");
       }
    }
 
-   public static class PoolRecordID extends TextHandler {
+   public static class PoolRecordID extends ElementTextHandler {
       public PoolRecordID() {
          super("poolRecordID");
       }
    }
 
-   private String textElement;
+   private final String textElement;
 
    private StringBuilder currentText = new StringBuilder();
    private String text = null;
 
-   private TextHandler(String textElement) {
+   private ElementTextHandler(String textElement) {
       this.textElement = checkNotNull(textElement, "textElement");
    }
 
    @Override
    public String getResult() {
-      try {
-         return checkNotNull(text, "%s not present in the response", textElement);
-      } finally {
-         text = null;
-      }
+      return checkNotNull(text, "%s not present in the response", textElement);
    }
 
    @Override
diff --git a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/UltraDNSWSApiLiveTest.java b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/UltraDNSWSApiLiveTest.java
index 66a3293..bfc2f49 100644
--- a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/UltraDNSWSApiLiveTest.java
+++ b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/UltraDNSWSApiLiveTest.java
@@ -18,7 +18,7 @@
  */
 package org.jclouds.ultradns.ws;
 
-import static com.google.common.base.Preconditions.checkNotNull;
+import static org.testng.Assert.assertNotNull;
 
 import org.jclouds.ultradns.ws.domain.Account;
 import org.jclouds.ultradns.ws.internal.BaseUltraDNSWSApiLiveTest;
@@ -37,7 +37,7 @@
    }
 
    private void checkAccount(Account account) {
-      checkNotNull(account.getId(), "Id cannot be null for an Account.");
-      checkNotNull(account.getName(), "Name cannot be null for Account %s", account);
+      assertNotNull(account.getId(), "Id cannot be null for " + account);
+      assertNotNull(account.getName(), "Name cannot be null for " + account);
    }
 }
diff --git a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/ResourceRecordApiLiveTest.java b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/ResourceRecordApiLiveTest.java
index d7cfb53..ea8f08e 100644
--- a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/ResourceRecordApiLiveTest.java
+++ b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/ResourceRecordApiLiveTest.java
@@ -17,12 +17,12 @@
  * under the License.
  */
 package org.jclouds.ultradns.ws.features;
-
-import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Predicates.equalTo;
+import static java.lang.String.format;
 import static java.util.logging.Logger.getAnonymousLogger;
 import static org.jclouds.ultradns.ws.domain.ResourceRecord.rrBuilder;
 import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
@@ -72,20 +72,20 @@
    }
 
    static void checkResourceRecord(ResourceRecord rr) {
-      checkNotNull(rr.getName(), "DName cannot be null for a ResourceRecord %s", rr);
-      checkNotNull(rr.getType(), "Type cannot be null for a ResourceRecord %s", rr);
-      assertTrue(rr.getType() > 0, "Type must be unsigned for a ResourceRecord " + rr);
-      checkNotNull(rr.getType(), "Type cannot be null for a ResourceRecord %s", rr);
-      checkNotNull(rr.getTTL(), "TTL cannot be null for a ResourceRecord %s", rr);
-      checkNotNull(rr.getRData(), "InfoValues cannot be null for a ResourceRecord %s", rr);
+      assertNotNull(rr.getName(), "DName cannot be null for " +  rr);
+      assertNotNull(rr.getType(), "Type cannot be null for " +  rr);
+      assertTrue(rr.getType() > 0, "Type must be unsigned for " + rr);
+      assertNotNull(rr.getType(), "Type cannot be null for " +  rr);
+      assertNotNull(rr.getTTL(), "TTL cannot be null for " +  rr);
+      assertNotNull(rr.getRData(), "InfoValues cannot be null for " +  rr);
    }
 
    static void checkResourceRecordMetadata(ResourceRecordMetadata rr) {
-      checkNotNull(rr.getZoneId(), "ZoneId cannot be null for a ResourceRecordMetadata %s", rr);
-      checkNotNull(rr.getGuid(), "Guid cannot be null for a ResourceRecordMetadata %s", rr);
-      checkNotNull(rr.getZoneName(), "ZoneName cannot be null for a ResourceRecordMetadata %s", rr);
-      checkNotNull(rr.getCreated(), "Created cannot be null for a ResourceRecordMetadata %s", rr);
-      checkNotNull(rr.getModified(), "Modified cannot be null for a ResourceRecordMetadata %s", rr);
+      assertNotNull(rr.getZoneId(), "ZoneId cannot be null for " +  rr);
+      assertNotNull(rr.getGuid(), "Guid cannot be null for " +  rr);
+      assertNotNull(rr.getZoneName(), "ZoneName cannot be null for " +  rr);
+      assertNotNull(rr.getCreated(), "Created cannot be null for " +  rr);
+      assertNotNull(rr.getModified(), "Modified cannot be null for " +  rr);
       checkResourceRecord(rr.getRecord());
    }
 
@@ -113,8 +113,7 @@
    void logSummary() {
       getAnonymousLogger().info("zoneCount: " + zones);
       for (Entry<Integer, AtomicLong> entry : recordTypeCounts.asMap().entrySet())
-         getAnonymousLogger().info(
-               String.format("type: %s, count: %s", entry.getKey(), entry.getValue()));
+         getAnonymousLogger().info(format("type: %s, count: %s", entry.getKey(), entry.getValue()));
    }
 
    @Test(expectedExceptions = ResourceNotFoundException.class, expectedExceptionsMessageRegExp = "Zone does not exist in the system.")
diff --git a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/RoundRobinPoolApiLiveTest.java b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/RoundRobinPoolApiLiveTest.java
index 830b79d..29ee70a 100644
--- a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/RoundRobinPoolApiLiveTest.java
+++ b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/RoundRobinPoolApiLiveTest.java
@@ -18,12 +18,12 @@
  */
 package org.jclouds.ultradns.ws.features;
 
-import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Predicates.equalTo;
 import static java.util.logging.Logger.getAnonymousLogger;
 import static org.jclouds.ultradns.ws.domain.ResourceRecord.rrBuilder;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
@@ -62,10 +62,10 @@
    }
 
    private void checkRRPool(RoundRobinPool pool) {
-      checkNotNull(pool.getZoneId(), "ZoneId cannot be null for a RoundRobinPool %s", pool);
-      checkNotNull(pool.getId(), "Id cannot be null for a RoundRobinPool %s", pool);
-      checkNotNull(pool.getName(), "Name cannot be null for a RoundRobinPool %s", pool);
-      checkNotNull(pool.getDName(), "DName cannot be null for a RoundRobinPool %s", pool);
+      assertNotNull(pool.getZoneId(), "ZoneId cannot be null for " + pool);
+      assertNotNull(pool.getId(), "Id cannot be null for " + pool);
+      assertNotNull(pool.getName(), "Name cannot be null for " + pool);
+      assertNotNull(pool.getDName(), "DName cannot be null for " + pool);
    }
 
    @Test
diff --git a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/TaskApiLiveTest.java b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/TaskApiLiveTest.java
index 29dc6bb..e20afc9 100644
--- a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/TaskApiLiveTest.java
+++ b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/TaskApiLiveTest.java
@@ -18,8 +18,8 @@
  */
 package org.jclouds.ultradns.ws.features;
 
-import static com.google.common.base.Preconditions.checkNotNull;
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
 
 import org.jclouds.ultradns.ws.domain.Task;
@@ -33,10 +33,10 @@
 public class TaskApiLiveTest extends BaseUltraDNSWSApiLiveTest {
 
    private void checkTask(Task task) {
-      checkNotNull(task.getGuid(), "Guid cannot be null for a Task %s", task);
-      checkNotNull(task.getStatusCode(), "StatusCode cannot be null for a Task %s", task);
-      checkNotNull(task.getMessage(), "While Message can be null for a Task, its Optional wrapper cannot %s", task);
-      checkNotNull(task.getResultUrl(), "While ResultUrl can be null for a Task, its Optional wrapper cannot %s", task);
+      assertNotNull(task.getGuid(), "Guid cannot be null for " + task);
+      assertNotNull(task.getStatusCode(), "StatusCode cannot be null for " + task);
+      assertNotNull(task.getMessage(), "While Message can be null, its Optional wrapper cannot " + task);
+      assertNotNull(task.getResultUrl(), "While ResultUrl can be null, its Optional wrapper cannot " + task);
    }
 
    @Test
diff --git a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApiLiveTest.java b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApiLiveTest.java
index cacdb6c..f048069 100644
--- a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApiLiveTest.java
+++ b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/TrafficControllerPoolApiLiveTest.java
@@ -18,12 +18,12 @@
  */
 package org.jclouds.ultradns.ws.features;
 
-import static com.google.common.base.Preconditions.checkNotNull;
 import static java.util.logging.Logger.getAnonymousLogger;
 import static org.jclouds.ultradns.ws.predicates.TrafficControllerPoolPredicates.idEqualTo;
 import static org.jclouds.ultradns.ws.predicates.TrafficControllerPoolPredicates.recordIdEqualTo;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
@@ -65,10 +65,10 @@
    }
 
    private void checkTCPool(TrafficControllerPool pool) {
-      checkNotNull(pool.getZoneId(), "ZoneId cannot be null for  %s", pool);
-      checkNotNull(pool.getId(), "Id cannot be null for  %s", pool);
-      checkNotNull(pool.getName(), "Name cannot be null for  %s", pool);
-      checkNotNull(pool.getDName(), "DName cannot be null for  %s", pool);
+      assertNotNull(pool.getZoneId(), "ZoneId cannot be null " + pool);
+      assertNotNull(pool.getId(), "Id cannot be null " + pool);
+      assertNotNull(pool.getName(), "Name cannot be null " + pool);
+      assertNotNull(pool.getDName(), "DName cannot be null " + pool);
       assertEquals(api(zoneName).getNameByDName(pool.getDName()), pool.getName());
    }
 
@@ -104,21 +104,21 @@
    }
 
    static TrafficControllerPoolRecord checkTrafficControllerPoolRecord(TrafficControllerPoolRecord record) {
-      checkNotNull(record.getId(), "Id cannot be null for %s", record);
-      checkNotNull(record.getPoolId(), "PoolId cannot be null for %s", record);
-      checkNotNull(record.getPointsTo(), "PointsTo cannot be null for %s", record);
+      assertNotNull(record.getId(), "Id cannot be null for " + record);
+      assertNotNull(record.getPoolId(), "PoolId cannot be null for " + record);
+      assertNotNull(record.getPointsTo(), "PointsTo cannot be null for " + record);
       assertTrue(record.getWeight() >= 0, "Weight must be unsigned for " + record);
       assertTrue(record.getPriority() >= 0, "Priority must be unsigned for " + record);
-      checkNotNull(record.getType(), "Type cannot be null for %s", record);
-      checkNotNull(record.getStatus(), "Status cannot be null for %s", record);
+      assertNotNull(record.getType(), "Type cannot be null for " + record);
+      assertNotNull(record.getStatus(), "Status cannot be null for " + record);
       assertTrue(record.getStatus() != Status.UNRECOGNIZED, "unrecognized status for " + record);
-      checkNotNull(record.getDescription(), "Description cannot be null for %s", record);
+      assertNotNull(record.getDescription(), "Description cannot be null for " + record);
       return record;
    }
 
    static PoolRecordSpec checkPoolRecordSpec(PoolRecordSpec record) {
-      checkNotNull(record.getDescription(), "Description cannot be null for %s", record);
-      checkNotNull(record.getState(), "State cannot be null for %s", record);
+      assertNotNull(record.getDescription(), "Description cannot be null for " + record);
+      assertNotNull(record.getState(), "State cannot be null for " + record);
       // TODO: collect all possible states then consider enum
       assertTrue(ImmutableSet.of("Normal", "Normal-NoTest").contains(record.getState()), "Unknown State for " + record);
       assertTrue(record.getWeight() >= 0, "Weight must be unsigned for " + record);
diff --git a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/ZoneApiLiveTest.java b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/ZoneApiLiveTest.java
index 430259a..3c4df6a 100644
--- a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/ZoneApiLiveTest.java
+++ b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/features/ZoneApiLiveTest.java
@@ -18,11 +18,11 @@
  */
 package org.jclouds.ultradns.ws.features;
 
-import static com.google.common.base.Preconditions.checkNotNull;
 import static java.util.logging.Logger.getAnonymousLogger;
 import static org.jclouds.ultradns.ws.domain.Zone.Type.PRIMARY;
-import static org.jclouds.ultradns.ws.predicates.ZonePredicates.typeEquals;
+import static org.jclouds.ultradns.ws.predicates.ZonePredicates.typeEqualTo;
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
@@ -55,17 +55,16 @@
    }
 
    private void checkZone(Zone zone) {
-      checkNotNull(zone.getId(), "Id cannot be null for a Zone %s", zone);
-      checkNotNull(zone.getName(), "Name cannot be null for a Zone %s", zone);
-      checkNotNull(zone.getType(), "Type cannot be null for a Zone %s", zone);
-      checkNotNull(zone.getTypeCode(), "TypeCode cannot be null for a Zone %s", zone);
+      assertNotNull(zone.getId(), "Id cannot be null for " + zone);
+      assertNotNull(zone.getName(), "Name cannot be null for " + zone);
+      assertNotNull(zone.getType(), "Type cannot be null for " + zone);
+      assertNotNull(zone.getTypeCode(), "TypeCode cannot be null for " + zone);
       assertEquals(zone.getTypeCode(), zone.getType().getCode());
-      checkNotNull(zone.getAccountId(), "AccountId cannot be null for a Zone %s", zone);
+      assertNotNull(zone.getAccountId(), "AccountId cannot be null for " + zone);
       assertEquals(zone.getAccountId(), account.getId());
-      checkNotNull(zone.getOwnerId(), "OwnerId cannot be null for a Zone %s", zone);
-      checkNotNull(zone.getDNSSECStatus(), "DNSSECStatus cannot be null for a Zone %s", zone);
-      checkNotNull(zone.getPrimarySrc(), "While PrimarySrc can be null for a Zone, its Optional wrapper cannot %s",
-            zone);
+      assertNotNull(zone.getOwnerId(), "OwnerId cannot be null for " + zone);
+      assertNotNull(zone.getDNSSECStatus(), "DNSSECStatus cannot be null for " + zone);
+      assertNotNull(zone.getPrimarySrc(), "While PrimarySrc can be null, its Optional wrapper cannot " + zone);
    }
 
    @Test
@@ -76,9 +75,9 @@
          checkZone(zone);
       }
 
-      if (response.anyMatch(typeEquals(PRIMARY))) {
+      if (response.anyMatch(typeEqualTo(PRIMARY))) {
          assertEquals(api().listByAccountAndType(account.getId(), PRIMARY).toSet(), response
-               .filter(typeEquals(PRIMARY)).toSet());
+               .filter(typeEqualTo(PRIMARY)).toSet());
       }
    }
 
@@ -94,7 +93,7 @@
          assertEquals(zoneProperties.getName(), zone.getName());
          assertEquals(zoneProperties.getType(), zone.getType());
          assertEquals(zoneProperties.getTypeCode(), zone.getTypeCode());
-         checkNotNull(zoneProperties.getModified(), "Modified cannot be null for a Zone %s", zone);
+         assertNotNull(zoneProperties.getModified(), "Modified cannot be null for " + zone);
          assertTrue(zoneProperties.getResourceRecordCount() >= 0,
                "ResourceRecordCount must be positive or zero for a Zone " + zone);
       }
@@ -134,7 +133,7 @@
          assertEquals(newZone.getName(), name);
          assertEquals(newZone.getType(), Type.PRIMARY);
          assertEquals(newZone.getTypeCode(), Type.PRIMARY.getCode());
-         checkNotNull(newZone.getModified(), "Modified cannot be null for a Zone %s", newZone);
+         assertNotNull(newZone.getModified(), "Modified cannot be null for " + newZone);
          assertEquals(newZone.getResourceRecordCount(), 5);
       } finally {
          api().delete(name);
diff --git a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/parse/RunTestResponseTest.java b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/parse/RunTestResponseTest.java
index 70b6edb..2845237 100644
--- a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/parse/RunTestResponseTest.java
+++ b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/parse/RunTestResponseTest.java
@@ -23,7 +23,7 @@
 import java.io.InputStream;
 
 import org.jclouds.http.functions.BaseHandlerTest;
-import org.jclouds.ultradns.ws.xml.TextHandler;
+import org.jclouds.ultradns.ws.xml.ElementTextHandler;
 import org.testng.annotations.Test;
 
 /**
@@ -35,7 +35,7 @@
    public void test() {
       InputStream is = getClass().getResourceAsStream("/taskid.xml");
 
-      TextHandler.Guid handler = injector.getInstance(TextHandler.Guid.class);
+      ElementTextHandler.Guid handler = injector.getInstance(ElementTextHandler.Guid.class);
       assertEquals(factory.create(handler).parse(is), "8d7a1725-4f4a-4b70-affa-f01dcce1526e");
    }
 }
diff --git a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/predicates/TrafficControllerPoolPredicatesTest.java b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/predicates/TrafficControllerPoolPredicatesTest.java
index 0ffadd6..528ae26 100644
--- a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/predicates/TrafficControllerPoolPredicatesTest.java
+++ b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/predicates/TrafficControllerPoolPredicatesTest.java
@@ -20,6 +20,8 @@
 
 import static org.jclouds.ultradns.ws.predicates.TrafficControllerPoolPredicates.idEqualTo;
 import static org.jclouds.ultradns.ws.predicates.TrafficControllerPoolPredicates.recordIdEqualTo;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
 
 import org.jclouds.ultradns.ws.domain.TrafficControllerPool;
 import org.jclouds.ultradns.ws.domain.TrafficControllerPoolRecord;
@@ -43,12 +45,12 @@
 
    @Test
    public void testIdEqualToWhenEqual() {
-      assert idEqualTo("000000000000002").apply(pool);
+      assertTrue(idEqualTo("000000000000002").apply(pool));
    }
 
    @Test
    public void testIdEqualToWhenNotEqual() {
-      assert !idEqualTo("000000000000003").apply(pool);
+      assertFalse(idEqualTo("000000000000003").apply(pool));
    }
 
    TrafficControllerPoolRecord record = TrafficControllerPoolRecord.builder()
@@ -66,11 +68,11 @@
 
    @Test
    public void testRecordIdEqualToWhenEqual() {
-      assert recordIdEqualTo("0000000000000001").apply(record);
+      assertTrue(recordIdEqualTo("0000000000000001").apply(record));
    }
 
    @Test
    public void testRecordIdEqualToWhenNotEqual() {
-      assert !recordIdEqualTo("0000000000000002").apply(record);
+      assertFalse(recordIdEqualTo("0000000000000002").apply(record));
    }
 }
diff --git a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/predicates/ZonePredicatesTest.java b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/predicates/ZonePredicatesTest.java
index 88d3883..1466044 100644
--- a/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/predicates/ZonePredicatesTest.java
+++ b/providers/ultradns-ws/src/test/java/org/jclouds/ultradns/ws/predicates/ZonePredicatesTest.java
@@ -18,7 +18,9 @@
  */
 package org.jclouds.ultradns.ws.predicates;
 
-import static org.jclouds.ultradns.ws.predicates.ZonePredicates.typeEquals;
+import static org.jclouds.ultradns.ws.predicates.ZonePredicates.typeEqualTo;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
 
 import org.jclouds.ultradns.ws.domain.Zone;
 import org.jclouds.ultradns.ws.domain.Zone.DNSSECStatus;
@@ -41,11 +43,11 @@
 
    @Test
    public void testTypeEqualsWhenEqual() {
-      assert typeEquals(Type.PRIMARY).apply(zone);
+      assertTrue(typeEqualTo(Type.PRIMARY).apply(zone));
    }
 
    @Test
    public void testTypeEqualsWhenNotEqual() {
-      assert !typeEquals(Type.SECONDARY).apply(zone);
+      assertFalse(typeEqualTo(Type.SECONDARY).apply(zone));
    }
 }