You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by dh...@apache.org on 2014/06/18 07:50:55 UTC

[5/6] git commit: Major refactor of API component framework to generify base classes, added AbstractApiComponent to reduce boilderplate code, minor compiler warnings removed

Major refactor of API component framework to generify base classes, added AbstractApiComponent to reduce boilderplate code, minor compiler warnings removed


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/7dc2bb13
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/7dc2bb13
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/7dc2bb13

Branch: refs/heads/master
Commit: 7dc2bb13a645c2c2a4dbfc9ec0ed0e5b2a63b914
Parents: 5dd9cc0
Author: Dhiraj Bokde <dh...@yahoo.com>
Authored: Tue Jun 17 13:50:34 2014 -0700
Committer: Dhiraj Bokde <dh...@yahoo.com>
Committed: Tue Jun 17 13:51:39 2014 -0700

----------------------------------------------------------------------
 .../util/component/AbstractApiComponent.java    | 267 +++++++++++++++++++
 .../util/component/AbstractApiConsumer.java     |  25 +-
 .../util/component/AbstractApiEndpoint.java     |  35 ++-
 .../util/component/AbstractApiProducer.java     |  28 +-
 .../camel/util/component/ApiCollection.java     |  18 +-
 .../apache/camel/util/component/ApiMethod.java  |  11 +-
 .../camel/util/component/ApiMethodHelper.java   |  76 +++---
 .../camel/util/component/ApiMethodImpl.java     |   1 -
 .../util/component/ApiMethodHelperTest.java     |  26 +-
 .../ApiMethodPropertiesHelperTest.java          |   4 +-
 .../src/main/java/__name__Component.java        |  82 +-----
 .../src/main/java/__name__Consumer.java         |   4 +-
 .../src/main/java/__name__Endpoint.java         |  19 +-
 .../src/main/java/__name__Producer.java         |   3 +-
 .../org/apache/camel/maven/ApiMethodAlias.java  |   1 +
 .../java/org/apache/camel/maven/ApiProxy.java   |   3 +-
 16 files changed, 408 insertions(+), 195 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/7dc2bb13/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiComponent.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiComponent.java b/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiComponent.java
new file mode 100644
index 0000000..9d20455
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiComponent.java
@@ -0,0 +1,267 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.apache.camel.util.component;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelException;
+import org.apache.camel.ComponentConfiguration;
+import org.apache.camel.Endpoint;
+import org.apache.camel.impl.UriEndpointComponent;
+import org.apache.camel.spi.EndpointCompleter;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * Abstract base class for API Component Camel {@link org.apache.camel.Component} classes.
+ */
+public abstract class AbstractApiComponent<E extends Enum<E> & ApiName, T, S extends ApiCollection<E, T>>
+        extends UriEndpointComponent implements EndpointCompleter {
+
+    @UriParam
+    protected T configuration;
+
+    // API collection
+    protected final S collection;
+
+    // API name class
+    protected final Class<E> apiNameClass;
+
+    public AbstractApiComponent(Class<? extends Endpoint> endpointClass,
+                                Class<E> apiNameClass, S collection) {
+        super(endpointClass);
+        this.collection = collection;
+        this.apiNameClass = apiNameClass;
+    }
+
+    public AbstractApiComponent(CamelContext context, Class<? extends Endpoint> endpointClass,
+                                Class<E> apiNameClass, S collection) {
+        super(context, endpointClass);
+        this.collection = collection;
+        this.apiNameClass = apiNameClass;
+    }
+
+    protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
+        // split remaining path to get API name and method
+        final String[] pathElements = remaining.split("/");
+        String apiNameStr;
+        String methodName;
+        switch (pathElements.length) {
+        case 1:
+            apiNameStr = "";
+            methodName = pathElements[0];
+            break;
+        case 2:
+            apiNameStr = pathElements[0];
+            methodName = pathElements[1];
+            break;
+        default:
+            throw new CamelException("Invalid URI path [" + remaining
+                + "], must be of the format " + collection.getApiNames() + "/<operation-name>");
+        }
+
+        try {
+            // get API enum from apiName string
+            final E apiName = getApiName(apiNameStr);
+
+            final T endpointConfiguration = createEndpointConfiguration(apiName);
+            final Endpoint endpoint = createEndpoint(uri, methodName, apiName, endpointConfiguration);
+
+            // set endpoint property inBody
+            setProperties(endpoint, parameters);
+
+            // configure endpoint properties and initialize state
+            endpoint.configureProperties(parameters);
+
+            return endpoint;
+        } catch (InvocationTargetException e) {
+            if (e.getCause() instanceof IllegalArgumentException) {
+                throw new CamelException("Invalid URI path prefix [" + remaining
+                    + "], must be one of " + collection.getApiNames());
+            }
+            throw e;
+        }
+    }
+
+    protected abstract E getApiName(String apiNameStr) throws IllegalArgumentException;
+
+    protected abstract Endpoint createEndpoint(String uri, String methodName, E apiName, T endpointConfiguration);
+
+    protected T createEndpointConfiguration(E name) throws Exception {
+        final Map<String, Object> componentProperties = new HashMap<String, Object>();
+        // copy component configuration, if set
+        if (configuration != null) {
+            IntrospectionSupport.getProperties(configuration, componentProperties, null, false);
+        }
+
+        // create endpoint configuration with component properties
+        final T endpointConfiguration = collection.getEndpointConfiguration(name);
+        IntrospectionSupport.setProperties(endpointConfiguration, componentProperties);
+        return endpointConfiguration;
+    }
+
+    public T getConfiguration() {
+        return configuration;
+    }
+
+    public void setConfiguration(T configuration) {
+        this.configuration = configuration;
+    }
+
+    @Override
+    public List<String> completeEndpointPath(ComponentConfiguration configuration, String completionText) {
+        final List<String> result = new ArrayList<String>();
+
+        final Set<String> apiNames = collection.getApiNames();
+        boolean useDefaultName = apiNames.size() == 1 && apiNames.contains("");
+
+        // check if there is an API name present
+        completionText = ObjectHelper.isEmpty(completionText) ? "" : completionText;
+        final int prefixEnd = completionText.indexOf('/');
+        final int pathEnd = completionText.lastIndexOf('?');
+
+        // empty or incomplete API prefix, and no options, add API names or method names if useDefaultName
+        final Map<E, ? extends ApiMethodHelper<? extends ApiMethod>> apiHelpers = collection.getApiHelpers();
+        if (prefixEnd == -1 && pathEnd == -1) {
+
+            if (useDefaultName) {
+
+                // complete method names for default API
+                final Set<Class<? extends ApiMethod>> apiMethods = collection.getApiMethods().keySet();
+                final Class<? extends ApiMethod> apiMethod = apiMethods.iterator().next();
+                final ApiMethodHelper<? extends ApiMethod> helper = apiHelpers.values().iterator().next();
+                getCompletedMethods(result, completionText, apiMethod, helper);
+            } else {
+
+                // complete API names
+                for (String name : apiNames) {
+                    if (!name.isEmpty() || name.startsWith(completionText)) {
+                        result.add(name);
+                    }
+                }
+            }
+
+        // path with complete API name prefix, but no options
+        } else if (prefixEnd != -1 && pathEnd == -1) {
+
+            // complete method names for specified API
+            final E apiName = getApiNameOrNull(completionText.substring(0, prefixEnd));
+            if (apiName != null) {
+                final ApiMethodHelper<? extends ApiMethod> helper = apiHelpers.get(apiName);
+                completionText = completionText.substring(prefixEnd + 1);
+                for (Map.Entry<Class<? extends ApiMethod>, E> entry : collection.getApiMethods().entrySet()) {
+                    if (entry.getValue().equals(apiName)) {
+                        getCompletedMethods(result, completionText, entry.getKey(), helper);
+                        break;
+                    }
+                }
+            }
+
+        // complete options
+        } else {
+
+            // get last option text
+            final int lastParam = completionText.lastIndexOf('&');
+            String optionText;
+            if (lastParam != -1) {
+                optionText = completionText.substring(lastParam + 1);
+            } else {
+                optionText = completionText.substring(pathEnd);
+            }
+
+            String methodName = null;
+            ApiMethodHelper<? extends ApiMethod> helper = null;
+            if (useDefaultName) {
+
+                // get default endpoint configuration and helper
+                methodName = completionText.substring(0, pathEnd);
+                helper = apiHelpers.values().iterator().next();
+            } else {
+
+                // get API name and method name, if they exist
+                final String[] pathElements = completionText.substring(0, pathEnd).split("/");
+                if (pathElements.length == 2) {
+                    final E apiName = getApiNameOrNull(pathElements[0]);
+                    methodName = pathElements[1];
+                    helper = collection.getHelper(apiName);
+                }
+            }
+            if (helper != null && !ObjectHelper.isEmpty(methodName)) {
+                // get other options from configuration
+                Set<String> existingOptions = configuration.getParameters().keySet();
+                // get all method options
+                try {
+                    final List arguments = helper.getArguments(methodName);
+                    final int nArgs = arguments.size();
+                    final Set<String> options = new HashSet<String>();
+                    for (int i = 1; i < nArgs; i += 2) {
+                        options.add((String) arguments.get(i));
+                    }
+                    options.removeAll(existingOptions);
+
+                    // return matching options
+                    for (String option : options) {
+                        if (option.startsWith(optionText)) {
+                            result.add(option);
+                        }
+                    }
+                } catch (IllegalArgumentException ignore) {
+                    // thrown from getArguments() when no matching methods,
+                    // return an empty result
+                }
+            }
+        }
+
+        return result;
+    }
+
+    // returns null instead of throwing IllegalArgumentException for invalid name
+    protected E getApiNameOrNull(String nameStr) {
+        try {
+            return getApiName(nameStr);
+        } catch (IllegalArgumentException ignore) {
+            return null;
+        }
+    }
+
+    protected void getCompletedMethods(List<String> result, String completionText,
+                                     Class<? extends ApiMethod> apiMethod, ApiMethodHelper<? extends ApiMethod> helper) {
+        // add potential method names
+        final ApiMethod[] methods = apiMethod.getEnumConstants();
+        for (ApiMethod method : methods) {
+            final String name = method.getName();
+            if (name.startsWith(completionText)) {
+                result.add(name);
+            }
+        }
+        // add potential aliases
+        final Map<String, Set<String>> aliases = helper.getAliases();
+        for (String alias : aliases.keySet()) {
+            if (alias.startsWith(completionText)) {
+                result.add(alias);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/7dc2bb13/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiConsumer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiConsumer.java b/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiConsumer.java
index 1d63339..44fad39 100644
--- a/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiConsumer.java
+++ b/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiConsumer.java
@@ -35,25 +35,25 @@ import org.slf4j.LoggerFactory;
 /**
  * Abstract base class for API Component Consumers.
  */
-public abstract class AbstractApiConsumer extends ScheduledPollConsumer {
+public abstract class AbstractApiConsumer<E extends Enum<E> & ApiName, T> extends ScheduledPollConsumer {
 
     // logger
     protected final Logger log = LoggerFactory.getLogger(getClass());
 
     // API Endpoint
-    protected final AbstractApiEndpoint endpoint;
+    protected final AbstractApiEndpoint<E, T> endpoint;
 
     // helpers
-    protected final ApiMethodPropertiesHelper propertiesHelper;
-    protected final ApiMethodHelper methodHelper;
+    protected final ApiMethodPropertiesHelper<T> propertiesHelper;
+    protected final ApiMethodHelper<? extends ApiMethod> methodHelper;
 
     // API method to invoke
-    protected final Enum<? extends ApiMethod> method;
+    protected final ApiMethod method;
 
     // properties used to invoke
     protected final Map<String, Object> endpointProperties;
 
-    public AbstractApiConsumer(AbstractApiEndpoint endpoint, Processor processor) {
+    public AbstractApiConsumer(AbstractApiEndpoint<E, T> endpoint, Processor processor) {
         super(endpoint, processor);
 
         this.endpoint = endpoint;
@@ -76,10 +76,9 @@ public abstract class AbstractApiConsumer extends ScheduledPollConsumer {
         return false;
     }
 
-    @SuppressWarnings("unchecked")
-    private Enum<? extends ApiMethod> findMethod() {
+    private ApiMethod findMethod() {
 
-        Enum<? extends ApiMethod> result;
+        ApiMethod result;
         // find one that takes the largest subset of endpoint parameters
         final Set<String> argNames = new HashSet<String>();
         argNames.addAll(propertiesHelper.getEndpointPropertyNames(endpoint.getConfiguration()));
@@ -87,7 +86,7 @@ public abstract class AbstractApiConsumer extends ScheduledPollConsumer {
         interceptArgumentNames(argNames);
 
         final String[] argNamesArray = argNames.toArray(new String[argNames.size()]);
-        List<Enum<? extends ApiMethod>> filteredMethods = methodHelper.filterMethods(
+        List<ApiMethod> filteredMethods = ApiMethodHelper.filterMethods(
                 endpoint.getCandidates(), ApiMethodHelper.MatchType.SUPER_SET, argNamesArray);
 
         if (filteredMethods.isEmpty()) {
@@ -99,9 +98,10 @@ public abstract class AbstractApiConsumer extends ScheduledPollConsumer {
             // single match
             result = filteredMethods.get(0);
         } else {
-            result = methodHelper.getHighestPriorityMethod(filteredMethods);
+            result = ApiMethodHelper.getHighestPriorityMethod(filteredMethods);
             log.warn("Using highest priority operation {} from operations {}", method, filteredMethods);
         }
+
         return result;
     }
 
@@ -147,9 +147,8 @@ public abstract class AbstractApiConsumer extends ScheduledPollConsumer {
      * @param args method arguments from endpoint parameters.
      * @return method invocation result.
      */
-    @SuppressWarnings("unchecked")
     protected Object doInvokeMethod(Map<String, Object> args) {
-        return methodHelper.invokeMethod(endpoint.getApiProxy(), method, args);
+        return ApiMethodHelper.invokeMethod(endpoint.getApiProxy(), method, args);
     }
 
     private void processResult(Object result) throws Exception {

http://git-wip-us.apache.org/repos/asf/camel/blob/7dc2bb13/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiEndpoint.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiEndpoint.java b/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiEndpoint.java
index 4217c4a..2a4ef13 100644
--- a/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiEndpoint.java
+++ b/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiEndpoint.java
@@ -34,34 +34,39 @@ import org.slf4j.LoggerFactory;
 /**
  * Abstract base class for API Component Endpoints.
  */
-public abstract class AbstractApiEndpoint extends DefaultEndpoint {
+public abstract class AbstractApiEndpoint<E extends ApiName, T> extends DefaultEndpoint {
 
     // logger
     protected final Logger log = LoggerFactory.getLogger(getClass());
 
     // API name
-    protected final ApiName apiName;
+    protected final E apiName;
 
     // API method name
     protected final String methodName;
 
     // API method helper
-    protected final ApiMethodHelper methodHelper;
+    protected final ApiMethodHelper<? extends ApiMethod> methodHelper;
+
+    // endpoint configuration
+    @UriParam
+    protected final T configuration;
 
     // property name for Exchange 'In' message body
     @UriParam
     protected String inBody;
 
     // candidate methods based on method name and endpoint configuration
-    private List<Enum<? extends ApiMethod>> candidates;
+    private List<ApiMethod> candidates;
 
     public AbstractApiEndpoint(String endpointUri, Component component,
-                               ApiName apiName, String methodName, ApiMethodHelper methodHelper) {
+                               E apiName, String methodName, ApiMethodHelper<? extends ApiMethod> methodHelper, T endpointConfiguration) {
         super(endpointUri, component);
 
         this.apiName = apiName;
         this.methodName = methodName;
         this.methodHelper = methodHelper;
+        this.configuration = endpointConfiguration;
     }
 
     public boolean isSingleton() {
@@ -72,7 +77,7 @@ public abstract class AbstractApiEndpoint extends DefaultEndpoint {
      * Returns generated helper that extends {@link ApiMethodPropertiesHelper} to work with API properties.
      * @return properties helper.
      */
-    protected abstract ApiMethodPropertiesHelper getPropertiesHelper();
+    protected abstract ApiMethodPropertiesHelper<T> getPropertiesHelper();
 
     @Override
     public void configureProperties(Map<String, Object> options) {
@@ -80,11 +85,11 @@ public abstract class AbstractApiEndpoint extends DefaultEndpoint {
 
         // set configuration properties first
         try {
-            Object configuration = getConfiguration();
+            T configuration = getConfiguration();
             EndpointHelper.setReferenceProperties(getCamelContext(), configuration, options);
             EndpointHelper.setProperties(getCamelContext(), configuration, options);
         } catch (Exception e) {
-            throw new IllegalArgumentException(e.getMessage(), e);
+            throw new IllegalArgumentException(e);
         }
 
         // validate and initialize state
@@ -101,7 +106,6 @@ public abstract class AbstractApiEndpoint extends DefaultEndpoint {
     /**
      * Initialize endpoint state, including endpoint arguments, find candidate methods, etc.
      */
-    @SuppressWarnings("unchecked")
     protected void initState() {
 
         // get endpoint property names
@@ -117,7 +121,7 @@ public abstract class AbstractApiEndpoint extends DefaultEndpoint {
         final String[] argNames = arguments.toArray(new String[arguments.size()]);
 
         // create a list of candidate methods
-        candidates = new ArrayList<Enum<? extends ApiMethod>>();
+        candidates = new ArrayList<ApiMethod>();
         candidates.addAll(methodHelper.getCandidateMethods(methodName, argNames));
 
         // error if there are no candidates
@@ -148,15 +152,18 @@ public abstract class AbstractApiEndpoint extends DefaultEndpoint {
     /**
      * Returns endpoint configuration object.
      * One of the generated *EndpointConfiguration classes that extends component configuration class.
+     *
      * @return endpoint configuration object
      */
-    public abstract Object getConfiguration();
+    public T getConfiguration() {
+        return configuration;
+    }
 
     /**
      * Returns API name.
      * @return apiName property.
      */
-    public ApiName getApiName() {
+    public E getApiName() {
         return apiName;
     }
 
@@ -172,7 +179,7 @@ public abstract class AbstractApiEndpoint extends DefaultEndpoint {
      * Returns method helper.
      * @return methodHelper property.
      */
-    public ApiMethodHelper getMethodHelper() {
+    public ApiMethodHelper<? extends ApiMethod> getMethodHelper() {
         return methodHelper;
     }
 
@@ -180,7 +187,7 @@ public abstract class AbstractApiEndpoint extends DefaultEndpoint {
      * Returns candidate methods for this endpoint.
      * @return list of candidate methods.
      */
-    public List<Enum<? extends ApiMethod>> getCandidates() {
+    public List<ApiMethod> getCandidates() {
         return Collections.unmodifiableList(candidates);
     }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/7dc2bb13/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiProducer.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiProducer.java b/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiProducer.java
index a9795f2..cb0d7f1 100644
--- a/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiProducer.java
+++ b/camel-core/src/main/java/org/apache/camel/util/component/AbstractApiProducer.java
@@ -36,24 +36,24 @@ import org.slf4j.LoggerFactory;
 /**
  * Base class for API based Producers
  */
-public abstract class AbstractApiProducer extends DefaultAsyncProducer {
+public abstract class AbstractApiProducer<E extends Enum<E> & ApiName, T> extends DefaultAsyncProducer {
 
     // thread pool executor
     protected static ExecutorService executorService;
 
     // API Endpoint
-    protected final AbstractApiEndpoint endpoint;
+    protected final AbstractApiEndpoint<E, T> endpoint;
 
     // properties helper
     protected final ApiMethodPropertiesHelper propertiesHelper;
 
     // method helper
-    protected final ApiMethodHelper methodHelper;
+    protected final ApiMethodHelper<?> methodHelper;
 
     // logger
     private final transient Logger log = LoggerFactory.getLogger(getClass());
 
-    public AbstractApiProducer(AbstractApiEndpoint endpoint, ApiMethodPropertiesHelper propertiesHelper) {
+    public AbstractApiProducer(AbstractApiEndpoint<E, T> endpoint, ApiMethodPropertiesHelper propertiesHelper) {
         super(endpoint);
         this.propertiesHelper = propertiesHelper;
         this.endpoint = endpoint;
@@ -70,7 +70,7 @@ public abstract class AbstractApiProducer extends DefaultAsyncProducer {
         interceptProperties(properties);
 
         // decide which method to invoke
-        final Enum<? extends ApiMethod> method = findMethod(exchange, properties);
+        final ApiMethod method = findMethod(exchange, properties);
         if (method == null) {
             // synchronous failure
             callback.done(true);
@@ -84,7 +84,7 @@ public abstract class AbstractApiProducer extends DefaultAsyncProducer {
             public void run() {
                 try {
                     if (log.isDebugEnabled()) {
-                        log.debug("Invoking operation {} with {}", ((ApiMethod) method).getName(), properties.keySet());
+                        log.debug("Invoking operation {} with {}", method.getName(), properties.keySet());
                     }
 
                     Object result = doInvokeMethod(method, properties);
@@ -125,9 +125,8 @@ public abstract class AbstractApiProducer extends DefaultAsyncProducer {
      * @return API method invocation result.
      * @throws RuntimeCamelException on error. Exceptions thrown by API method are wrapped.
      */
-    @SuppressWarnings("unchecked")
-    protected Object doInvokeMethod(Enum<? extends ApiMethod> method, Map<String, Object> properties) throws RuntimeCamelException {
-        return methodHelper.invokeMethod(endpoint.getApiProxy(), method, properties);
+    protected Object doInvokeMethod(ApiMethod method, Map<String, Object> properties) throws RuntimeCamelException {
+        return ApiMethodHelper.invokeMethod(endpoint.getApiProxy(), method, properties);
     }
 
     /**
@@ -139,16 +138,15 @@ public abstract class AbstractApiProducer extends DefaultAsyncProducer {
         // do nothing by default
     }
 
-    @SuppressWarnings("unchecked")
-    private Enum<? extends ApiMethod> findMethod(Exchange exchange, Map<String, Object> properties) {
+    private ApiMethod findMethod(Exchange exchange, Map<String, Object> properties) {
 
-        Enum<? extends ApiMethod> method = null;
-        final List<Enum<? extends ApiMethod>> candidates = endpoint.getCandidates();
+        ApiMethod method = null;
+        final List<ApiMethod> candidates = endpoint.getCandidates();
         if (processInBody(exchange, properties)) {
 
             // filter candidates based on endpoint and exchange properties
             final Set<String> argNames = properties.keySet();
-            final List<Enum<? extends ApiMethod>> filteredMethods = methodHelper.filterMethods(candidates,
+            final List<ApiMethod> filteredMethods = ApiMethodHelper.filterMethods(candidates,
                     ApiMethodHelper.MatchType.SUPER_SET,
                     argNames.toArray(new String[argNames.size()]));
 
@@ -161,7 +159,7 @@ public abstract class AbstractApiProducer extends DefaultAsyncProducer {
                 // found an exact match
                 method = filteredMethods.get(0);
             } else {
-                method = methodHelper.getHighestPriorityMethod(filteredMethods);
+                method = ApiMethodHelper.getHighestPriorityMethod(filteredMethods);
                 log.warn("Calling highest priority operation {} from operations {}", method, filteredMethods);
             }
         }

http://git-wip-us.apache.org/repos/asf/camel/blob/7dc2bb13/camel-core/src/main/java/org/apache/camel/util/component/ApiCollection.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/util/component/ApiCollection.java b/camel-core/src/main/java/org/apache/camel/util/component/ApiCollection.java
index 2231ceb..f39440f 100644
--- a/camel-core/src/main/java/org/apache/camel/util/component/ApiCollection.java
+++ b/camel-core/src/main/java/org/apache/camel/util/component/ApiCollection.java
@@ -26,16 +26,16 @@ import java.util.Set;
  * Base class for a collection of ApiMethods. Meant to be extended by Components to create the api name map.
  */
 @SuppressWarnings("unused")
-public abstract class ApiCollection<T extends Enum & ApiName, C> {
+public abstract class ApiCollection<E extends Enum<E> & ApiName, T> {
 
-    protected final Map<T, ApiMethodHelper> apis = new HashMap<T, ApiMethodHelper>();
-    protected final HashMap<Class<? extends ApiMethod>, T> apiMethods = new HashMap<Class<? extends ApiMethod>, T>();
+    protected final Map<E, ApiMethodHelper<? extends ApiMethod>> apis = new HashMap<E, ApiMethodHelper<? extends ApiMethod>>();
+    protected final HashMap<Class<? extends ApiMethod>, E> apiMethods = new HashMap<Class<? extends ApiMethod>, E>();
 
-    public final Map<T, ApiMethodHelper> getApiHelpers() {
+    public final Map<E, ApiMethodHelper<? extends ApiMethod>> getApiHelpers() {
         return Collections.unmodifiableMap(apis);
     }
 
-    public final Map<Class<? extends ApiMethod>, T> getApiMethods() {
+    public final Map<Class<? extends ApiMethod>, E> getApiMethods() {
         return Collections.unmodifiableMap(apiMethods);
     }
 
@@ -44,7 +44,7 @@ public abstract class ApiCollection<T extends Enum & ApiName, C> {
      * @param apiName name of the API
      * @return helper class to work with {@link ApiMethod}
      */
-    public final ApiMethodHelper getHelper(T apiName) {
+    public final ApiMethodHelper<? extends ApiMethod> getHelper(E apiName) {
         return apis.get(apiName);
     }
 
@@ -54,13 +54,13 @@ public abstract class ApiCollection<T extends Enum & ApiName, C> {
      */
     public final Set<String> getApiNames() {
         final Set<String> result = new HashSet<String>();
-        for (T api : apis.keySet()) {
+        for (E api : apis.keySet()) {
             result.add(api.getName());
         }
         return Collections.unmodifiableSet(result);
     }
 
-    public final T getApiName(Class<? extends ApiMethod> apiMethod) {
+    public final E getApiName(Class<? extends ApiMethod> apiMethod) {
         return apiMethods.get(apiMethod);
     }
 
@@ -69,5 +69,5 @@ public abstract class ApiCollection<T extends Enum & ApiName, C> {
      * @param apiName name of the API.
      * @return Endpoint configuration object for the API.
      */
-    public abstract C getEndpointConfiguration(T apiName);
+    public abstract T getEndpointConfiguration(E apiName);
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/7dc2bb13/camel-core/src/main/java/org/apache/camel/util/component/ApiMethod.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethod.java b/camel-core/src/main/java/org/apache/camel/util/component/ApiMethod.java
index 7ee7cb9..a2274bf 100644
--- a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethod.java
+++ b/camel-core/src/main/java/org/apache/camel/util/component/ApiMethod.java
@@ -26,32 +26,31 @@ public interface ApiMethod {
 
     /**
      * Returns method name.
-     * @return
+     * @return name
      */
     String getName();
 
     /**
      * Returns method result type.
-     * @return
+     * @return result type
      */
     Class<?> getResultType();
 
     /**
      * Returns method argument names.
-     * @return
+     * @return argument names
      */
     List<String> getArgNames();
 
     /**
      * Return method argument types.
-     * @return
+     * @return argument types
      */
     List<Class<?>> getArgTypes();
 
     /**
      * Returns {@link Method} in proxy type.
-     * @return
+     * @return method
      */
     Method getMethod();
-
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/7dc2bb13/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodHelper.java b/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodHelper.java
index 7ce841b..27ba116 100644
--- a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodHelper.java
+++ b/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodHelper.java
@@ -42,16 +42,16 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
     private static final Logger LOG = LoggerFactory.getLogger(ApiMethodHelper.class);
 
     // maps method name to ApiMethod
-    private final Map<String, List<T>> METHOD_MAP = new HashMap<String, List<T>>();
+    private final Map<String, List<T>> methodMap = new HashMap<String, List<T>>();
 
     // maps method name to method arguments of the form Class type1, String name1, Class type2, String name2,...
-    private final Map<String, List<Object>> ARGUMENTS_MAP = new HashMap<String, List<Object>>();
+    private final Map<String, List<Object>> argumentsMap = new HashMap<String, List<Object>>();
 
     // maps argument name to argument type
-    private final Map<String, Class<?>> VALID_ARGUMENTS = new HashMap<String, Class<?>>();
+    private final Map<String, Class<?>> validArguments = new HashMap<String, Class<?>>();
 
     // maps aliases to actual method names
-    private final HashMap<String, Set<String>> ALIASES = new HashMap<String, Set<String>>();
+    private final HashMap<String, Set<String>> aliases = new HashMap<String, Set<String>>();
 
     /**
      * Create a helper to work with a {@link ApiMethod}, using optional method aliases.
@@ -95,28 +95,28 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
                         builder.append(Character.toLowerCase(firstChar)).append(alias.substring(1));
                         alias = builder.toString();
                     }
-                    Set<String> names = ALIASES.get(alias);
+                    Set<String> names = this.aliases.get(alias);
                     if (names == null) {
                         names = new HashSet<String>();
-                        ALIASES.put(alias, names);
+                        this.aliases.put(alias, names);
                     }
                     names.add(name);
                 }
             }
 
             // map method name to Enum
-            List<T> overloads = METHOD_MAP.get(name);
+            List<T> overloads = methodMap.get(name);
             if (overloads == null) {
                 overloads = new ArrayList<T>();
-                METHOD_MAP.put(method.getName(), overloads);
+                methodMap.put(method.getName(), overloads);
             }
             overloads.add(method);
 
             // add arguments for this method
-            List<Object> arguments = ARGUMENTS_MAP.get(name);
+            List<Object> arguments = argumentsMap.get(name);
             if (arguments == null) {
                 arguments = new ArrayList<Object>();
-                ARGUMENTS_MAP.put(name, arguments);
+                argumentsMap.put(name, arguments);
             }
 
             // process all arguments for this method
@@ -132,35 +132,36 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
                 }
 
                 // also collect argument names for all methods, and detect clashes here
-                final Class<?> previousType = VALID_ARGUMENTS.get(argName);
+                final Class<?> previousType = validArguments.get(argName);
                 if (previousType != null && previousType != argType) {
                     throw new IllegalArgumentException(String.format(
                         "Argument %s has ambiguous types (%s, %s) across methods!",
                         name, previousType, argType));
                 } else if (previousType == null) {
-                    VALID_ARGUMENTS.put(argName, argType);
+                    validArguments.put(argName, argType);
                 }
             }
 
         }
 
-        LOG.debug("Found {} unique method names in {} methods", METHOD_MAP.size(), methods.length);
+        LOG.debug("Found {} unique method names in {} methods", methodMap.size(), methods.length);
     }
 
     /**
      * Gets methods that match the given name and arguments.<p/>
      * Note that the args list is a required subset of arguments for returned methods.
+     *
      * @param name case sensitive method name or alias to lookup
      * @param argNames unordered required argument names
      * @return non-null unmodifiable list of methods that take all of the given arguments, empty if there is no match
      */
-    public List<T> getCandidateMethods(String name, String... argNames) {
-        List<T> methods = METHOD_MAP.get(name);
+    public List<ApiMethod> getCandidateMethods(String name, String... argNames) {
+        List<T> methods = methodMap.get(name);
         if (methods == null) {
-            if (ALIASES.containsKey(name)) {
+            if (aliases.containsKey(name)) {
                 methods = new ArrayList<T>();
-                for (String method : ALIASES.get(name)) {
-                    methods.addAll(METHOD_MAP.get(method));
+                for (String method : aliases.get(name)) {
+                    methods.addAll(methodMap.get(method));
                 }
             }
         }
@@ -171,9 +172,9 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
         int nArgs = argNames != null ? argNames.length : 0;
         if (nArgs == 0) {
             LOG.debug("Found {} methods for method {}", methods.size(), name);
-            return Collections.unmodifiableList(methods);
+            return Collections.<ApiMethod>unmodifiableList(methods);
         } else {
-            final List<T> filteredSet = filterMethods(methods, MatchType.SUBSET, argNames);
+            final List<ApiMethod> filteredSet = filterMethods(methods, MatchType.SUBSET, argNames);
             if (LOG.isDebugEnabled()) {
                 LOG.debug("Found {} filtered methods for {}",
                     filteredSet.size(), name + Arrays.toString(argNames).replace('[', '(').replace(']', ')'));
@@ -191,14 +192,14 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
      * @return methods with arguments that satisfy the match type.<p/>
      * For SUPER_SET match, if methods with exact match are found, methods that take a subset are ignored
      */
-    public List<T> filterMethods(List<T> methods, MatchType matchType,
+    public static List<ApiMethod> filterMethods(List<? extends ApiMethod> methods, MatchType matchType,
                                                           String... argNames) {
         List<String> argsList = Arrays.asList(argNames);
         // list of methods that have all args in the given names
-        final List<T> result = new ArrayList<T>();
-        final List<T> extraArgs = new ArrayList<T>();
+        final List<ApiMethod> result = new ArrayList<ApiMethod>();
+        final List<ApiMethod> extraArgs = new ArrayList<ApiMethod>();
 
-        for (T method : methods) {
+        for (ApiMethod method : methods) {
             final List<String> methodArgs = method.getArgNames();
             switch (matchType) {
             case EXACT:
@@ -238,12 +239,12 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
      * @return list of arguments of the form Class type1, String name1, Class type2, String name2,...
      */
     public List<Object> getArguments(final String name) throws IllegalArgumentException {
-        List<Object> arguments = ARGUMENTS_MAP.get(name);
+        List<Object> arguments = argumentsMap.get(name);
         if (arguments == null) {
-            if (ALIASES.containsKey(name)) {
+            if (aliases.containsKey(name)) {
                 arguments = new ArrayList<Object>();
-                for (String method : ALIASES.get(name)) {
-                    arguments.addAll(ARGUMENTS_MAP.get(method));
+                for (String method : aliases.get(name)) {
+                    arguments.addAll(argumentsMap.get(method));
                 }
             }
         }
@@ -278,7 +279,7 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
      * @return alias names mapped to method names.
      */
     public Map<String, Set<String>> getAliases() {
-        return Collections.unmodifiableMap(ALIASES);
+        return Collections.unmodifiableMap(aliases);
     }
 
     /**
@@ -286,7 +287,7 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
      * @return map with argument names as keys, and types as values
      */
     public Map<String, Class<?>> allArguments() {
-        return Collections.unmodifiableMap(VALID_ARGUMENTS);
+        return Collections.unmodifiableMap(validArguments);
     }
 
     /**
@@ -295,17 +296,20 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
      * @return argument type
      */
     public Class<?> getType(String argName) throws IllegalArgumentException {
-        final Class<?> type = VALID_ARGUMENTS.get(argName);
+        final Class<?> type = validArguments.get(argName);
         if (type == null) {
             throw new IllegalArgumentException(argName);
         }
         return type;
     }
 
-    public T getHighestPriorityMethod(List<T> filteredMethods) {
-        T highest = null;
-        for (T method : filteredMethods) {
-            if (highest == null || method.compareTo(highest) > 0) {
+    // this method is always called with Enum value lists, so the cast inside is safe
+    // the alternative of trying to convert ApiMethod and associated classes to generic classes would a bear!!!
+    @SuppressWarnings("unchecked")
+    public static ApiMethod getHighestPriorityMethod(List<? extends ApiMethod> filteredMethods) {
+        ApiMethod highest = null;
+        for (ApiMethod method : filteredMethods) {
+            if (highest == null || ((Enum)method).compareTo((Enum) highest) > 0) {
                 highest = method;
             }
         }
@@ -321,7 +325,7 @@ public final class ApiMethodHelper<T extends Enum<T> & ApiMethod> {
      * @return result of method invocation
      * @throws org.apache.camel.RuntimeCamelException on errors
      */
-    public Object invokeMethod(Object proxy, T method, Map<String, Object> properties)
+    public static Object invokeMethod(Object proxy, ApiMethod method, Map<String, Object> properties)
         throws RuntimeCamelException {
 
         if (LOG.isDebugEnabled()) {

http://git-wip-us.apache.org/repos/asf/camel/blob/7dc2bb13/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodImpl.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodImpl.java b/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodImpl.java
index 2884164..75c66a6 100644
--- a/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodImpl.java
+++ b/camel-core/src/main/java/org/apache/camel/util/component/ApiMethodImpl.java
@@ -119,5 +119,4 @@ public final class ApiMethodImpl implements ApiMethod {
             .append("}");
         return builder.toString();
     }
-
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/7dc2bb13/camel-core/src/test/java/org/apache/camel/util/component/ApiMethodHelperTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/util/component/ApiMethodHelperTest.java b/camel-core/src/test/java/org/apache/camel/util/component/ApiMethodHelperTest.java
index 12bc877..1fb84b7 100644
--- a/camel-core/src/test/java/org/apache/camel/util/component/ApiMethodHelperTest.java
+++ b/camel-core/src/test/java/org/apache/camel/util/component/ApiMethodHelperTest.java
@@ -39,7 +39,7 @@ public class ApiMethodHelperTest {
 
     @Test
     public void testGetCandidateMethods() {
-        List<TestMethod> methods = apiMethodHelper.getCandidateMethods("sayHi");
+        List<ApiMethod> methods = apiMethodHelper.getCandidateMethods("sayHi");
         assertEquals("Can't find sayHi(*)", 2, methods.size());
 
         methods = apiMethodHelper.getCandidateMethods("hi");
@@ -57,22 +57,22 @@ public class ApiMethodHelperTest {
 
     @Test
     public void testFilterMethods() {
-        List<TestMethod> methods = apiMethodHelper.filterMethods(Arrays.asList(sayHis), ApiMethodHelper.MatchType.EXACT);
+        List<ApiMethod> methods = ApiMethodHelper.filterMethods(Arrays.asList(sayHis), ApiMethodHelper.MatchType.EXACT);
         assertEquals("Exact match failed for sayHi()", 1, methods.size());
         assertEquals("Exact match failed for sayHi()", TestMethod.SAYHI, methods.get(0));
 
-        methods = apiMethodHelper.filterMethods(Arrays.asList(sayHis), ApiMethodHelper.MatchType.SUBSET);
+        methods = ApiMethodHelper.filterMethods(Arrays.asList(sayHis), ApiMethodHelper.MatchType.SUBSET);
         assertEquals("Subset match failed for sayHi(*)", 2, methods.size());
 
-        methods = apiMethodHelper.filterMethods(Arrays.asList(sayHis), ApiMethodHelper.MatchType.SUBSET, "name");
+        methods = ApiMethodHelper.filterMethods(Arrays.asList(sayHis), ApiMethodHelper.MatchType.SUBSET, "name");
         assertEquals("Subset match failed for sayHi(name)", 1, methods.size());
         assertEquals("Exact match failed for sayHi()", TestMethod.SAYHI_1, methods.get(0));
 
-        methods = apiMethodHelper.filterMethods(Arrays.asList(sayHis), ApiMethodHelper.MatchType.SUPER_SET, "name");
+        methods = ApiMethodHelper.filterMethods(Arrays.asList(sayHis), ApiMethodHelper.MatchType.SUPER_SET, "name");
         assertEquals("Super set match failed for sayHi(name)", 1, methods.size());
         assertEquals("Exact match failed for sayHi()", TestMethod.SAYHI_1, methods.get(0));
 
-        methods = apiMethodHelper.filterMethods(Arrays.asList(TestMethod.values()), ApiMethodHelper.MatchType.SUPER_SET, "name");
+        methods = ApiMethodHelper.filterMethods(Arrays.asList(TestMethod.values()), ApiMethodHelper.MatchType.SUPER_SET, "name");
         assertEquals("Super set match failed for sayHi(name)", 2, methods.size());
     }
 
@@ -114,28 +114,28 @@ public class ApiMethodHelperTest {
     @Test
     public void testGetHighestPriorityMethod() throws Exception {
         assertEquals("Get highest priority method",
-                TestMethod.SAYHI_1, apiMethodHelper.getHighestPriorityMethod(Arrays.asList(sayHis)));
+                TestMethod.SAYHI_1, ApiMethodHelper.getHighestPriorityMethod(Arrays.asList(sayHis)));
     }
 
     @Test
     public void testInvokeMethod() throws Exception {
         TestProxy proxy = new TestProxy();
-        assertEquals("sayHi()", "Hello!", apiMethodHelper.invokeMethod(proxy, TestMethod.SAYHI, Collections.EMPTY_MAP));
+        assertEquals("sayHi()", "Hello!", ApiMethodHelper.invokeMethod(proxy, TestMethod.SAYHI, Collections.<String, Object>emptyMap()));
 
         final HashMap<String, Object> properties = new HashMap<String, Object>();
         properties.put("name", "Dave");
 
-        assertEquals("sayHi(name)", "Hello Dave", apiMethodHelper.invokeMethod(proxy, TestMethod.SAYHI_1, properties));
-        assertEquals("greetMe(name)", "Greetings Dave", apiMethodHelper.invokeMethod(proxy, TestMethod.GREETME, properties));
+        assertEquals("sayHi(name)", "Hello Dave", ApiMethodHelper.invokeMethod(proxy, TestMethod.SAYHI_1, properties));
+        assertEquals("greetMe(name)", "Greetings Dave", ApiMethodHelper.invokeMethod(proxy, TestMethod.GREETME, properties));
 
         properties.clear();
         properties.put("name1", "Dave");
         properties.put("name2", "Frank");
-        assertEquals("greetUs(name1, name2)", "Greetings Dave, Frank", apiMethodHelper.invokeMethod(proxy, TestMethod.GREETUS, properties));
+        assertEquals("greetUs(name1, name2)", "Greetings Dave, Frank", ApiMethodHelper.invokeMethod(proxy, TestMethod.GREETUS, properties));
 
         properties.clear();
         properties.put("names", new String[] { "Dave", "Frank" });
-        assertEquals("greetAll(names)", "Greetings Dave, Frank", apiMethodHelper.invokeMethod(proxy, TestMethod.GREETALL, properties));
+        assertEquals("greetAll(names)", "Greetings Dave, Frank", ApiMethodHelper.invokeMethod(proxy, TestMethod.GREETALL, properties));
 
         // test with a derived proxy
         proxy = new TestProxy() {
@@ -146,7 +146,7 @@ public class ApiMethodHelperTest {
         };
         properties.clear();
         properties.put("name", "Dave");
-        assertEquals("Derived sayHi(name)", "Howdy Dave", apiMethodHelper.invokeMethod(proxy, TestMethod.SAYHI_1, properties));
+        assertEquals("Derived sayHi(name)", "Howdy Dave", ApiMethodHelper.invokeMethod(proxy, TestMethod.SAYHI_1, properties));
     }
 
     static enum TestMethod implements ApiMethod {

http://git-wip-us.apache.org/repos/asf/camel/blob/7dc2bb13/camel-core/src/test/java/org/apache/camel/util/component/ApiMethodPropertiesHelperTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/util/component/ApiMethodPropertiesHelperTest.java b/camel-core/src/test/java/org/apache/camel/util/component/ApiMethodPropertiesHelperTest.java
index cfc29d1..65b7538 100644
--- a/camel-core/src/test/java/org/apache/camel/util/component/ApiMethodPropertiesHelperTest.java
+++ b/camel-core/src/test/java/org/apache/camel/util/component/ApiMethodPropertiesHelperTest.java
@@ -38,7 +38,7 @@ public class ApiMethodPropertiesHelperTest {
     private static final String VALUE_4 = "true";
 
     private static ApiMethodPropertiesHelper propertiesHelper =
-            new ApiMethodPropertiesHelper(TestComponentConfiguration.class, TEST_PREFIX){};
+            new ApiMethodPropertiesHelper<TestComponentConfiguration>(TestComponentConfiguration.class, TEST_PREFIX){};
 
     @Test
     public void testGetExchangeProperties() throws Exception {
@@ -77,6 +77,7 @@ public class ApiMethodPropertiesHelperTest {
         assertEquals(2, propertiesHelper.getValidEndpointProperties(new TestEndpointConfiguration()).size());
     }
 
+    @SuppressWarnings("unused")
     private static class TestComponentConfiguration {
         private String property1;
         private Long property2;
@@ -98,6 +99,7 @@ public class ApiMethodPropertiesHelperTest {
         }
     }
 
+    @SuppressWarnings("unused")
     private static class TestEndpointConfiguration extends TestComponentConfiguration {
         private String property3;
         private Boolean property4;

http://git-wip-us.apache.org/repos/asf/camel/blob/7dc2bb13/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Component.java
----------------------------------------------------------------------
diff --git a/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Component.java b/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Component.java
index 34ce74c..05fd2d0 100644
--- a/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Component.java
+++ b/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Component.java
@@ -16,16 +16,10 @@
 ## ------------------------------------------------------------------------
 package ${package};
 
-import java.util.HashMap;
-import java.util.Map;
-
 import org.apache.camel.CamelContext;
-import org.apache.camel.CamelException;
 import org.apache.camel.Endpoint;
-import org.apache.camel.impl.UriEndpointComponent;
 import org.apache.camel.spi.UriEndpoint;
-import org.apache.camel.spi.UriParam;
-import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.util.component.AbstractApiComponent;
 
 import ${package}.internal.${name}ApiCollection;
 import ${package}.internal.${name}ApiName;
@@ -34,78 +28,24 @@ import ${package}.internal.${name}ApiName;
  * Represents the component that manages {@link ${name}Endpoint}.
  */
 @UriEndpoint(scheme = "${scheme}", consumerClass = ${name}Consumer.class, consumerPrefix = "consumer")
-public class ${name}Component extends UriEndpointComponent {
-
-    @UriParam
-    private ${name}Configuration configuration;
-
-    private final ${name}ApiCollection collection = ${name}ApiCollection.getCollection();
+public class ${name}Component extends AbstractApiComponent<${name}ApiName, ${name}Configuration, ${name}ApiCollection> {
 
     public ${name}Component() {
-        super(${name}Endpoint.class);
+        super(${name}Endpoint.class, ${name}ApiName.class, ${name}ApiCollection.getCollection());
     }
 
     public ${name}Component(CamelContext context) {
-        super(context, ${name}Endpoint.class);
-    }
-
-    protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
-        // split remaining path to get API name and method
-        final String[] pathElements = remaining.split("/");
-        String apiNameStr;
-        String methodName;
-        switch (pathElements.length) {
-        case 1:
-            apiNameStr = "";
-            methodName = pathElements[0];
-            break;
-        case 2:
-            apiNameStr = pathElements[0];
-            methodName = pathElements[1];
-            break;
-        default:
-            throw new CamelException("Invalid URI path [" + remaining
-                + "], must be of the format " + collection.getApiNames() + "/<operation-name>");
-        }
-
-        // get API enum from apiName string
-        final ${name}ApiName apiName;
-        try {
-            apiName = ${name}ApiName.fromValue(apiNameStr);
-        } catch (IllegalArgumentException e) {
-            throw new CamelException("Invalid URI path prefix [" + remaining
-                + "], must be one of " + collection.getApiNames());
-        }
-
-        final ${name}Configuration endpointConfiguration = createEndpointConfiguration(apiName);
-        final Endpoint endpoint = new ${name}Endpoint(uri, this, apiName, methodName, endpointConfiguration);
-
-        // set endpoint property inBody
-        setProperties(endpoint, parameters);
-
-        // configure endpoint properties and initialize state
-        endpoint.configureProperties(parameters);
-
-        return endpoint;
-    }
-
-    private ${name}Configuration createEndpointConfiguration(${name}ApiName name) throws Exception {
-        final Map<String, Object> componentProperties = new HashMap<String, Object>();
-        if (configuration != null) {
-            IntrospectionSupport.getProperties(configuration, componentProperties, null, false);
-        }
-
-        // create endpoint configuration with component properties
-        final ${name}Configuration endpointConfiguration = collection.getEndpointConfiguration(name);
-        IntrospectionSupport.setProperties(endpointConfiguration, componentProperties);
-        return endpointConfiguration;
+        super(context, ${name}Endpoint.class, ${name}ApiName.class, ${name}ApiCollection.getCollection());
     }
 
-    public ${name}Configuration getConfiguration() {
-        return configuration;
+    @Override
+    protected ${name}ApiName getApiName(String apiNameStr) throws IllegalArgumentException {
+        return ${name}ApiName.fromValue(apiNameStr);
     }
 
-    public void setConfiguration(${name}Configuration configuration) {
-        this.configuration = configuration;
+    @Override
+    protected Endpoint createEndpoint(String uri, String methodName, ${name}ApiName apiName,
+                                      ${name}Configuration endpointConfiguration) {
+        return new ${name}Endpoint(uri, this, apiName, methodName, endpointConfiguration);
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/7dc2bb13/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Consumer.java
----------------------------------------------------------------------
diff --git a/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Consumer.java b/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Consumer.java
index 56ae89d..d493267 100644
--- a/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Consumer.java
+++ b/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Consumer.java
@@ -19,10 +19,12 @@ package ${package};
 import org.apache.camel.Processor;
 import org.apache.camel.util.component.AbstractApiConsumer;
 
+import ${package}.internal.${name}ApiName;
+
 /**
  * The ${name} consumer.
  */
-public class ${name}Consumer extends AbstractApiConsumer {
+public class ${name}Consumer extends AbstractApiConsumer<${name}ApiName, ${name}Configuration> {
 
     public ${name}Consumer(${name}Endpoint endpoint, Processor processor) {
         super(endpoint, processor);

http://git-wip-us.apache.org/repos/asf/camel/blob/7dc2bb13/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Endpoint.java
----------------------------------------------------------------------
diff --git a/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Endpoint.java b/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Endpoint.java
index 3b68f84..aaed38f 100644
--- a/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Endpoint.java
+++ b/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Endpoint.java
@@ -20,7 +20,6 @@ import org.apache.camel.Consumer;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
 import org.apache.camel.spi.UriEndpoint;
-import org.apache.camel.spi.UriParam;
 import org.apache.camel.util.component.AbstractApiEndpoint;
 import org.apache.camel.util.component.ApiMethodPropertiesHelper;
 
@@ -32,19 +31,15 @@ import ${package}.internal.${name}PropertiesHelper;
  * Represents a ${name} endpoint.
  */
 @UriEndpoint(scheme = "${scheme}", consumerClass = ${name}Consumer.class, consumerPrefix = "consumer")
-public class ${name}Endpoint extends AbstractApiEndpoint {
-
-    @UriParam
-    protected final ${name}Configuration configuration;
+public class ${name}Endpoint extends AbstractApiEndpoint<${name}ApiName, ${name}Configuration> {
 
     // TODO create and manage API proxy
     private Object apiProxy;
 
     public ${name}Endpoint(String uri, ${name}Component component,
                          ${name}ApiName apiName, String methodName, ${name}Configuration endpointConfiguration) {
-        super(uri, component, apiName, methodName, ${name}ApiCollection.getCollection().getHelper(apiName));
+        super(uri, component, apiName, methodName, ${name}ApiCollection.getCollection().getHelper(apiName), endpointConfiguration);
 
-        this.configuration = endpointConfiguration;
     }
 
     public Producer createProducer() throws Exception {
@@ -63,7 +58,7 @@ public class ${name}Endpoint extends AbstractApiEndpoint {
     }
 
     @Override
-    protected ApiMethodPropertiesHelper getPropertiesHelper() {
+    protected ApiMethodPropertiesHelper<${name}Configuration> getPropertiesHelper() {
         return ${name}PropertiesHelper.getHelper();
     }
 
@@ -76,15 +71,13 @@ public class ${name}Endpoint extends AbstractApiEndpoint {
                 break;
             case HELLO_JAVADOC:
                 apiProxy = new ${name}JavadocHello();
+                break;
+            default:
+                throw new IllegalArgumentException("Invalid API name " + apiName);
         }
     }
 
     @Override
-    public ${name}Configuration getConfiguration() {
-        return configuration;
-    }
-
-    @Override
     public Object getApiProxy() {
         return apiProxy;
     }

http://git-wip-us.apache.org/repos/asf/camel/blob/7dc2bb13/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Producer.java
----------------------------------------------------------------------
diff --git a/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Producer.java b/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Producer.java
index 46c4871..3a9adba 100644
--- a/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Producer.java
+++ b/tooling/archetypes/camel-archetype-api-component/src/main/resources/archetype-resources/__artifactId__-component/src/main/java/__name__Producer.java
@@ -18,13 +18,14 @@ package ${package};
 
 import org.apache.camel.util.component.AbstractApiProducer;
 
+import ${package}.internal.${name}ApiName;
 import ${package}.internal.${name}Constants;
 import ${package}.internal.${name}PropertiesHelper;
 
 /**
  * The ${name} producer.
  */
-public class ${name}Producer extends AbstractApiProducer {
+public class ${name}Producer extends AbstractApiProducer<${name}ApiName, ${name}Configuration> {
 
     public ${name}Producer(${name}Endpoint endpoint) {
         super(endpoint, ${name}PropertiesHelper.getHelper());

http://git-wip-us.apache.org/repos/asf/camel/blob/7dc2bb13/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/ApiMethodAlias.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/ApiMethodAlias.java b/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/ApiMethodAlias.java
index 71bb89e..8002fba 100644
--- a/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/ApiMethodAlias.java
+++ b/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/ApiMethodAlias.java
@@ -19,6 +19,7 @@ package org.apache.camel.maven;
 /**
  * Represents method alias
  */
+@SuppressWarnings("unused")
 public class ApiMethodAlias {
 
     private String methodPattern;

http://git-wip-us.apache.org/repos/asf/camel/blob/7dc2bb13/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/ApiProxy.java
----------------------------------------------------------------------
diff --git a/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/ApiProxy.java b/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/ApiProxy.java
index 69a759b..22c3870 100644
--- a/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/ApiProxy.java
+++ b/tooling/maven/camel-api-component-maven-plugin/src/main/java/org/apache/camel/maven/ApiProxy.java
@@ -22,11 +22,12 @@ import java.util.List;
 /**
  * Represents an API to use for generating Camel Component.
  */
+@SuppressWarnings("unused")
 public class ApiProxy {
     private String apiName;
     private String proxyClass;
 
-    private List<ApiMethodAlias> aliases = Collections.EMPTY_LIST;
+    private List<ApiMethodAlias> aliases = Collections.emptyList();
 
     public ApiProxy() {
     }