You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by lb...@apache.org on 2017/03/30 16:05:50 UTC

[2/6] camel git commit: Polished ComponentVerifier interface

Polished ComponentVerifier interface

The following major changes are suggested:

* Using of interfaces and class constants instead of string constants for error fields. This has the advantage of being typesafe but still extensible (custom fields can be easily added)
* Renamed Error to VerificationError as it conflicts with java.lang.Error which is allways imported
* Documentation to the interface
* Consolidation of provided constants, together with @lburgazzoli
* Adapted the using components (mainly http, http4, twitter, salesforce)


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

Branch: refs/heads/master
Commit: c810328ebaf8c08af56c956baccc1cbf0aa1f8ce
Parents: e1d82ab
Author: Roland Hu� <ro...@ro14nd.de>
Authored: Wed Mar 29 10:25:03 2017 +0200
Committer: Roland Hu� <ro...@ro14nd.de>
Committed: Thu Mar 30 16:33:00 2017 +0200

----------------------------------------------------------------------
 camel-core/pom.xml                              |  10 +-
 .../org/apache/camel/ComponentVerifier.java     | 359 +++++++++++++++----
 .../apache/camel/ComponentVerifierHelper.java   | 132 +++++++
 .../impl/verifier/DefaultComponentVerifier.java |   4 +-
 .../camel/impl/verifier/DefaultResult.java      |  18 +-
 .../camel/impl/verifier/DefaultResultError.java |  66 ----
 .../DefaultResultVerificationError.java         |  66 ++++
 .../camel/impl/verifier/ResultBuilder.java      |  25 +-
 .../camel/impl/verifier/ResultErrorBuilder.java |  93 +++--
 .../camel/impl/verifier/ResultErrorHelper.java  |  22 +-
 .../org/apache/camel/ComponentVerifierTest.java |  83 +++++
 .../java/org/apache/camel/LoggingLevelTest.java |   2 +
 .../verifier/DefaultComponentVerifierTest.java  |   9 +-
 .../component/http/HttpComponentVerifier.java   |  13 +-
 .../http/CamelComponentVerifierTest.java        |  27 +-
 .../component/http4/HttpComponentVerifier.java  |  13 +-
 .../http4/CamelComponentVerifierTest.java       |  37 +-
 .../salesforce/SalesforceComponentVerifier.java |   8 +-
 .../SalesforceComponentVerifierTest.java        |  25 +-
 .../servicenow/ServiceNowComponentVerifier.java |  18 +-
 .../ServiceNowComponentVerifierTest.java        |  39 +-
 .../twitter/TwitterComponentVerifier.java       |  18 +-
 .../twitter/CamelComponentVerifierTest.java     |  34 +-
 .../connector/DefaultConnectorComponent.java    |   8 +-
 24 files changed, 793 insertions(+), 336 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/camel-core/pom.xml
----------------------------------------------------------------------
diff --git a/camel-core/pom.xml b/camel-core/pom.xml
index b9f6430..ac5a673 100644
--- a/camel-core/pom.xml
+++ b/camel-core/pom.xml
@@ -159,7 +159,7 @@
       <scope>test</scope>
     </dependency>
 
-    <!-- logging -->         
+    <!-- logging -->
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-api</artifactId>
@@ -196,6 +196,12 @@
       <version>${xml-resolver-version}</version>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>com.consol.citrus</groupId>
+      <artifactId>citrus-core</artifactId>
+      <version>2.7.1</version>
+      <scope>test</scope>
+    </dependency>
 
   </dependencies>
 
@@ -682,5 +688,5 @@
       </build>
     </profile>
   </profiles>
-  
+
 </project>

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/camel-core/src/main/java/org/apache/camel/ComponentVerifier.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/ComponentVerifier.java b/camel-core/src/main/java/org/apache/camel/ComponentVerifier.java
index 93f50c7..c091492 100644
--- a/camel-core/src/main/java/org/apache/camel/ComponentVerifier.java
+++ b/camel-core/src/main/java/org/apache/camel/ComponentVerifier.java
@@ -21,118 +21,341 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.camel.ComponentVerifierHelper.ExceptionErrorAttribute;
+import org.apache.camel.impl.verifier.ResultErrorBuilder;
 import org.apache.camel.util.ObjectHelper;
 
 /**
- * Defines the interface used to validate component/endpoint parameters.
+ * Defines the interface used for validating component/endpoint parameters. The central method of this
+ * interface is {@link #verify(Scope, Map)} which takes a scope and a set of parameters which should be verified.
+ * <p/>
+ * The return value is a {@link Result} of the verification
+ *
  */
 public interface ComponentVerifier {
-    String CODE_AUTHENTICATION = "authentication";
-    String CODE_EXCEPTION = "exception";
-    String CODE_INTERNAL = "internal";
-    String CODE_MISSING_OPTION = "missing-option";
-    String CODE_MISSING_OPTION_GROUP = "missing-option-group";
-    String CODE_UNKNOWN_OPTION = "unknown-option";
-    String CODE_ILLEGAL_OPTION = "illegal-option";
-    String CODE_ILLEGAL_OPTION_GROUP_COMBINATION = "illegal-option-group-combination";
-    String CODE_ILLEGAL_OPTION_VALUE = "illegal-option-value";
-    String CODE_INCOMPLETE_OPTION_GROUP = "incomplete-option-group";
-    String CODE_UNSUPPORTED = "unsupported";
-    String CODE_UNSUPPORTED_SCOPE = "unsupported-scope";
-    String ERROR_TYPE_ATTRIBUTE = "error.type";
-    String ERROR_TYPE_EXCEPTION = "exception";
-    String ERROR_TYPE_HTTP = "http";
-    String HTTP_CODE = "http.code";
-    String HTTP_TEXT = "http.text";
-    String HTTP_REDIRECT = "http.redirect";
-    String HTTP_REDIRECT_LOCATION = "http.redirect.location";
-    String EXCEPTION_CLASS = "exception.class";
-    String EXCEPTION_INSTANCE = "exception.instance";
-    String GROUP_NAME = "group.name";
-    String GROUP_OPTIONS = "group.options";
 
+    /**
+     * Verify the given parameters against a provided scope.
+     *
+     * <p>
+     * The supported scopes are:
+     * <ul>
+     *   <li><strong>{@link Scope#PARAMETERS}</strong>: to validate that all the mandatory options are provided and syntactically correct.</li>
+     *   <li><strong>{@link Scope#CONNECTIVITY}</strong>: to validate that the given options (i.e. credentials, addresses) are correct. Verifying with this
+     *       scope typically implies reaching out to the backend via some sort of network connection.</li>
+     * </ul>
+     *
+     * @param scope the scope of the verification
+     * @param parameters the parameters to verify which are interpreted individually by each component verifier
+     * @return the verification result
+     */
+    Result verify(Scope scope, Map<String, Object> parameters);
+
+    /**
+     * The result of a verification
+     */
+    interface Result extends Serializable {
+
+        /**
+         * Status of the verification
+         */
+        enum Status {
+            /**
+             * Verification succeeded
+             */
+            OK,
+            /**
+             * Error occurred during the verification
+             */
+            ERROR,
+            /**
+             * Verification is not supported. This can depend on the given scope.
+             */
+            UNSUPPORTED
+        }
+
+        /**
+         * Scope of the verification. This is the scope given to the call to {@link #verify(Scope, Map)}  and
+         * can be used for correlation.
+         *
+         * @return the scope against which the parameters have been validated.
+         */
+        Scope getScope();
+
+        /**
+         * Result of the validation as status. This should be the first datum to check after a verification
+         * happened.
+         *
+         * @return the status
+         */
+        Status getStatus();
+
+        /**
+         * Collection of errors happened for the verification. This list is empty (but non null) if the verification
+         * succeeded.
+         *
+         * @return a list of errors. Can be empty when verification was successful
+         */
+        List<VerificationError> getErrors();
+    }
+
+    /**
+     * The scope defines how the parameters should be verified.
+     */
     enum Scope {
-        NONE,
+        /**
+         * Only validate the parameters for their <em>syntactic</em> soundness. Verifications in this scope should
+         * be as fast as possible
+         */
         PARAMETERS,
+
+        /**
+         * Reach out to the backend and verify that a connection can be established. This means, if the verification
+         * in this scope succeeds, then it can safely be assumed that the component can be used.
+         */
         CONNECTIVITY;
 
         private static final Scope[] VALUES = values();
-
+        /**
+         * Get an instance of this scope from a string representation
+         *
+         * @param scope the scope as string, which can be in any case
+         * @return the scope enum represented by this string
+         */
         public static Scope fromString(String scope) {
-            for (int i = 0; i < VALUES.length; i++) {
-                if (ObjectHelper.equal(scope, VALUES[i].name(), true)) {
-                    return VALUES[i];
+            for (Scope value : VALUES) {
+                if (ObjectHelper.equal(scope, value.name(), true)) {
+                    return value;
                 }
             }
-
             throw new IllegalArgumentException("Unknown scope <" + scope + ">");
         }
     }
 
+    // =============================================================================================
+
     /**
-     * Represent an error
+     * This interface represents a detailed error in case when the verification fails.
      */
-    interface Error extends Serializable {
+    interface VerificationError extends Serializable {
+
         /**
-         * @return the error code
+         * The overall error code, which can be either a {@link StandardCode} or a custom code. It is
+         * recommended to stick to the predefined standard codes
+         *
+         * @return the general error code.
          */
-        String getCode();
+        Code getCode();
 
         /**
+         * A human readable description of the error in plain english
+         *
          * @return the error description (if available)
          */
         String getDescription();
 
         /**
-         * @return the parameters in error
+         * A set of input parameter names which fails the verification. These are keys to the parameter provided
+         * to {@link #verify(Scope, Map)}.
+         *
+         * @return the parameter names which are malformed and caused the failure of the validation
          */
-        Set<String> getParameters();
+        Set<String> getParameterKeys();
 
         /**
-         * @return a number of key/value pair with additional information related to the validation.
+         * Details about the failed verification. The keys can be either predefined values
+         * ({@link ExceptionAttribute}, {@link HttpAttribute}, {@link GroupAttribute}) or it can be free-form
+         * custom keys specific to a component. The standard attributes are defined as enums in all uppercase (with
+         * underscore as separator), custom attributes are supposed to be in all lower case (also with underscores
+         * as separators)
+         *
+         * @return a number of key/value pair with additional information related to the verification.
          */
-        Map<String, Object> getAttributes();
-    }
+        Map<Attribute, Object> getDetails();
 
-    /**
-     * Represent a validation Result.
-     */
-    interface Result extends Serializable {
-        enum Status {
-            OK,
-            ERROR,
-            UNSUPPORTED
+        /**
+         * Get a single detail for a given attribute
+         *
+         * @param attribute the attribute to lookup
+         * @return the detail value or null if no such attribute exists
+         */
+        default Object getDetail(Attribute attribute) {
+            Map<Attribute, Object> details = getDetails();
+            if (details != null) {
+                return details.get(attribute);
+            }
+            return null;
         }
 
         /**
-         * @return the scope against which the parameters have been validated.
+         * Get a single detail for a given attribute
+         *
+         * @param attribute the attribute to lookup
+         * @return the detail value or null if no such attribute exists
          */
-        Scope getScope();
+        default Object getDetail(String attribute) {
+            return getDetail(asAttribute(attribute));
+        }
 
         /**
-         * @return the status
+         * Convert a string to an {@link Code}
+         *
+         * @param code the code to convert. It should be in all lower case (with
+         *             underscore as a separator) to avoid overlap with {@link StandardCode}
+         * @return error code
          */
-        Status getStatus();
+        static Code asCode(String code) {
+            return new ComponentVerifierHelper.ErrorCode(code);
+        }
+
+        /**
+         * Convert a string to an {@link Attribute}
+         *
+         * @param attribute the string representation of an attribute to convert. It should be in all lower case (with
+         *                  underscore as a separator) to avoid overlap with standard attributes like {@link ExceptionAttribute},
+         *                  {@link HttpAttribute} or {@link GroupAttribute}
+         * @return generated attribute
+         */
+        static Attribute asAttribute(String attribute) {
+            return new ComponentVerifierHelper.ErrorAttribute(attribute);
+        }
+
+        /**
+         * Interface defining an error code. This is implemented by the {@link StandardCode} but also
+         * own code can be generated by implementing this interface. This is best done via {@link #asCode(String)}
+         * If possible, the standard codes should be reused
+         */
+        interface Code {
+            /**
+             * Name of the code. All uppercase for standard codes, all lower case for custom codes.
+             * Separator between two words is an underscore.
+             *
+             * @return code name
+             */
+            String name();
+        }
+
+        /**
+         * Standard set of error codes
+         */
+        interface StandardCode extends Code {
+            /**
+             * Authentication failed
+             */
+            StandardCode AUTHENTICATION = new ComponentVerifierHelper.StandardErrorCode("AUTHENTICATION");
+            /**
+             * An exception occurred
+             */
+            StandardCode EXCEPTION = new ComponentVerifierHelper.StandardErrorCode("EXCEPTION");
+            /**
+             * Internal error while performing the verification
+             */
+            StandardCode INTERNAL = new ComponentVerifierHelper.StandardErrorCode("INTERNAL");
+            /**
+             * A mandatory parameter is missing
+             */
+            StandardCode MISSING_PARAMETER = new ComponentVerifierHelper.StandardErrorCode("MISSING_PARAMETER");
+            /**
+             * A given parameter is not known to the component
+             */
+            StandardCode UNKNOWN_PARAMETER = new ComponentVerifierHelper.StandardErrorCode("UNKNOWN_PARAMETER");
+            /**
+             * A given parameter is illegal
+             */
+            StandardCode ILLEGAL_PARAMETER = new ComponentVerifierHelper.StandardErrorCode("ILLEGAL_PARAMETER");
+            /**
+             * A combination of parameters is illegal. See {@link VerificationError#getParameterKeys()} for the set
+             * of affected parameters
+             */
+            StandardCode ILLEGAL_PARAMETER_GROUP_COMBINATION = new ComponentVerifierHelper.StandardErrorCode("ILLEGAL_PARAMETER_GROUP_COMBINATION");
+            /**
+             * A parameter <em>value</em> is not valid
+             */
+            StandardCode ILLEGAL_PARAMETER_VALUE = new ComponentVerifierHelper.StandardErrorCode("ILLEGAL_PARAMETER_VALUE");
+            /**
+             * A group of parameters is not complete in order to be valid
+             */
+            StandardCode INCOMPLETE_PARAMETER_GROUP = new ComponentVerifierHelper.StandardErrorCode("INCOMPLETE_PARAMETER_GROUP");
+            /**
+             * The verification is not supported
+             */
+            StandardCode UNSUPPORTED = new ComponentVerifierHelper.StandardErrorCode("UNSUPPORTED");
+            /**
+             * The requested {@link Scope} is not supported
+             */
+            StandardCode UNSUPPORTED_SCOPE = new ComponentVerifierHelper.StandardErrorCode("UNSUPPORTED_SCOPE");
+            /**
+             * Generic error which is explained in more details with {@link VerificationError#getDetails()}
+             */
+            StandardCode GENERIC = new ComponentVerifierHelper.StandardErrorCode("GENERIC");
+        }
+
+        /**
+         * Interface defining an attribute which is a key for the detailed error messages. This is implemented by several
+         * standard enums like {@link ExceptionAttribute}, {@link HttpAttribute} or {@link GroupAttribute} but can also
+         * implemented for component specific details. This is best done via {@link #asAttribute(String)}
+         * or using one of the other builder method in this error builder (like {@link ResultErrorBuilder#detail(String, Object)}
+         * <p>
+         * With respecting to name, the same rules as for {@link Code} apply: Standard attributes are all upper case with _
+         * as separators, whereas custom attributes are lower case with underscore separators.
+         */
+        interface Attribute {
+            /**
+             * Name of the attribute. All uppercase for standard attributes and all lower case for custom attributes.
+             * Separator between words is an underscore.
+             *
+             * @return attribute name
+             */
+            String name();
+        }
 
         /**
-         * @return a list of errors
+         * Attributes for details about an exception that was raised
          */
-        List<Error> getErrors();
+        interface ExceptionAttribute extends Attribute {
+            /**
+             * The exception object that has been thrown. Note that this can be a complex
+             * object and can cause large content when e.g. serialized as JSON
+             */
+            ExceptionAttribute EXCEPTION_INSTANCE = new ExceptionErrorAttribute("EXCEPTION_INSTANCE");
+            /**
+             * The exception class
+             */
+            ExceptionAttribute EXCEPTION_CLASS = new ExceptionErrorAttribute("EXCEPTION_CLASS");
+        }
+
+        /**
+         * HTTP related error details
+         */
+        interface HttpAttribute extends Attribute {
+            /**
+             * The erroneous HTTP code that occurred
+             */
+            HttpAttribute HTTP_CODE = new ComponentVerifierHelper.HttpErrorAttribute("HTTP_CODE");
+            /**
+             * HTTP response's body
+             */
+            HttpAttribute HTTP_TEXT = new ComponentVerifierHelper.HttpErrorAttribute("HTTP_TEXT");
+            /**
+             * If given as details, specifies that a redirect happened and the
+             * content of this detail is the redirect URL
+             */
+            HttpAttribute HTTP_REDIRECT = new ComponentVerifierHelper.HttpErrorAttribute("HTTP_REDIRECT");
+        }
+
+        /**
+         * Group related details
+         */
+        interface GroupAttribute extends Attribute {
+            /**
+             * Group name
+             */
+            GroupAttribute GROUP_NAME = new ComponentVerifierHelper.GroupErrorAttribute("GROUP_NAME");
+            /**
+             * Options for the group
+             */
+            GroupAttribute GROUP_OPTIONS = new ComponentVerifierHelper.GroupErrorAttribute("GROUP_OPTIONS");
+        }
     }
 
-    /**
-     * Validate the given parameters against the provided scope.
-     *
-     * <p>
-     * The supported scopes are:
-     * <ul>
-     *   <li>PARAMETERS: to validate that all the mandatory options are provided and syntactically correct.
-     *   <li>CONNECTIVITY: to validate that the given options (i.e. credentials, addresses) are correct.
-     * </ul>
-     *
-     * @param scope the scope of the validation
-     * @param parameters the parameters to validate
-     * @return the validation result
-     */
-    Result verify(Scope scope, Map<String, Object> parameters);
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/camel-core/src/main/java/org/apache/camel/ComponentVerifierHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/ComponentVerifierHelper.java b/camel-core/src/main/java/org/apache/camel/ComponentVerifierHelper.java
new file mode 100644
index 0000000..1c6f288
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/ComponentVerifierHelper.java
@@ -0,0 +1,132 @@
+/**
+ * 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;
+
+import org.apache.camel.ComponentVerifier.VerificationError.Attribute;
+import org.apache.camel.ComponentVerifier.VerificationError.Code;
+
+/**
+ * Package visible helper class holding implementation classes for
+ * constant like error code and attributes in {@link ComponentVerifier.VerificationError}
+ */
+class ComponentVerifierHelper {
+
+    /**
+     * Custom class for error codes
+     */
+    static class ErrorCode implements Code {
+
+        private String name;
+
+        ErrorCode(String name) {
+            if (name == null) {
+                throw new IllegalArgumentException("Name of an error code must not be null");
+            }
+            this.name = name;
+        }
+
+        @Override
+        public String name() {
+            return name;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof Code)) return false;
+
+            Code errorCode = (Code) o;
+
+            return name.equals(errorCode.name());
+        }
+
+        @Override
+        public int hashCode() {
+            return name.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return name();
+        }
+    }
+
+    static class ErrorAttribute implements Attribute {
+
+        private String name;
+
+        ErrorAttribute(String name) {
+            if (name == null) {
+                throw new IllegalArgumentException("Name of an error attribute must not be null");
+            }
+            this.name = name;
+        }
+
+        @Override
+        public String name() {
+            return name;
+        }
+
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof Attribute)) return false;
+
+            Attribute that = (Attribute) o;
+
+            return name.equals(that.name());
+        }
+
+        @Override
+        public int hashCode() {
+            return name.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return name();
+        }
+    }
+
+    // ===========================================================================================================
+    // Helper classes for implementing the constants in ComponentVerifier:
+
+    static class StandardErrorCode extends ErrorCode implements ComponentVerifier.VerificationError.StandardCode {
+        StandardErrorCode(String name) {
+            super(name);
+        }
+    }
+
+    static class ExceptionErrorAttribute extends ErrorAttribute implements ComponentVerifier.VerificationError.ExceptionAttribute {
+        ExceptionErrorAttribute(String name) {
+            super(name);
+        }
+    }
+
+    static class HttpErrorAttribute extends ErrorAttribute implements ComponentVerifier.VerificationError.HttpAttribute {
+        HttpErrorAttribute(String name) {
+            super(name);
+        }
+    }
+
+    static class GroupErrorAttribute extends ErrorAttribute implements ComponentVerifier.VerificationError.GroupAttribute {
+        GroupErrorAttribute(String name) {
+            super(name);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java
index f102c6a..28908b0 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultComponentVerifier.java
@@ -51,7 +51,7 @@ public class DefaultComponentVerifier implements ComponentVerifier {
         // Camel context is mandatory
         if (this.camelContext == null) {
             return ResultBuilder.withStatusAndScope(Result.Status.ERROR, scope)
-                .error(ResultErrorBuilder.withCodeAndDescription(ComponentVerifier.CODE_INTERNAL, "Missing camel-context").build())
+                .error(ResultErrorBuilder.withCodeAndDescription(VerificationError.StandardCode.INTERNAL, "Missing camel-context").build())
                 .build();
         }
 
@@ -123,7 +123,7 @@ public class DefaultComponentVerifier implements ComponentVerifier {
             stream(result.getInvalidEnum())
                 .map(entry ->
                     ResultErrorBuilder.withIllegalOption(entry.getKey(), entry.getValue())
-                        .attribute("enum.values", result.getEnumChoices(entry.getKey()))
+                        .detail("enum.values", result.getEnumChoices(entry.getKey()))
                         .build())
                 .forEach(builder::error);
         }

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResult.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResult.java b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResult.java
index ef9c055..ad36d5f 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResult.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResult.java
@@ -23,12 +23,12 @@ import org.apache.camel.ComponentVerifier;
 public class DefaultResult implements ComponentVerifier.Result {
     private final ComponentVerifier.Scope scope;
     private final Status status;
-    private final List<ComponentVerifier.Error> errors;
+    private final List<ComponentVerifier.VerificationError> verificationErrors;
 
-    public DefaultResult(ComponentVerifier.Scope scope, Status status, List<ComponentVerifier.Error> errors) {
+    public DefaultResult(ComponentVerifier.Scope scope, Status status, List<ComponentVerifier.VerificationError> verificationErrors) {
         this.scope = scope;
         this.status = status;
-        this.errors = errors;
+        this.verificationErrors = verificationErrors;
     }
 
     @Override
@@ -42,16 +42,16 @@ public class DefaultResult implements ComponentVerifier.Result {
     }
 
     @Override
-    public List<ComponentVerifier.Error> getErrors() {
-        return errors;
+    public List<ComponentVerifier.VerificationError> getErrors() {
+        return verificationErrors;
     }
 
     @Override
     public String toString() {
         return "DefaultResult{"
-            + "scope=" + scope
-            + ", status=" + status
-            + ", errors=" + errors
-            + '}';
+               + "scope=" + scope
+               + ", status=" + status
+               + ", errors=" + verificationErrors
+               + '}';
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultError.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultError.java b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultError.java
deleted file mode 100644
index 0398f7c..0000000
--- a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultError.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * 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.impl.verifier;
-
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.camel.ComponentVerifier;
-
-public class DefaultResultError implements ComponentVerifier.Error {
-    private final String code;
-    private final String description;
-    private final Set<String> parameters;
-    private final Map<String, Object> attributes;
-
-    public DefaultResultError(String code, String description, Set<String> parameters, Map<String, Object> attributes) {
-        this.code = code;
-        this.description = description;
-        this.parameters = parameters;
-        this.attributes = attributes;
-    }
-
-    @Override
-    public String getCode() {
-        return code;
-    }
-
-    @Override
-    public String getDescription() {
-        return description;
-    }
-
-    @Override
-    public Set<String> getParameters() {
-        return parameters;
-    }
-
-    @Override
-    public Map<String, Object> getAttributes() {
-        return attributes;
-    }
-
-    @Override
-    public String toString() {
-        return "DefaultResultError{"
-            + "code='" + code + '\''
-            + ", description='" + description + '\''
-            + ", parameters=" + parameters
-            + ", attributes=" + attributes
-            + '}';
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultVerificationError.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultVerificationError.java b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultVerificationError.java
new file mode 100644
index 0000000..8bc8727
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/verifier/DefaultResultVerificationError.java
@@ -0,0 +1,66 @@
+/**
+ * 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.impl.verifier;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.ComponentVerifier.VerificationError;
+
+public class DefaultResultVerificationError implements VerificationError {
+    private final Code code;
+    private final String description;
+    private final Set<String> parameterKeys;
+    private final Map<Attribute, Object> details;
+
+    public DefaultResultVerificationError(Code code, String description, Set<String> parameterKeys, Map<Attribute, Object> details) {
+        this.code = code;
+        this.description = description;
+        this.parameterKeys = parameterKeys;
+        this.details = details;
+    }
+
+    @Override
+    public Code getCode() {
+        return code;
+    }
+
+    @Override
+    public String getDescription() {
+        return description;
+    }
+
+    @Override
+    public Set<String> getParameterKeys() {
+        return parameterKeys;
+    }
+
+    @Override
+    public Map<Attribute, Object> getDetails() {
+        return details;
+    }
+
+    @Override
+    public String toString() {
+        return "DefaultResultError{"
+               + "code='" + code + '\''
+               + ", description='" + description + '\''
+               + ", parameterKeys=" + parameterKeys
+               + ", details=" + details
+               + '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultBuilder.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultBuilder.java b/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultBuilder.java
index 8d90195..8b35a1e 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultBuilder.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultBuilder.java
@@ -31,7 +31,7 @@ import org.apache.camel.util.function.ThrowingConsumer;
 public final class ResultBuilder {
     private Optional<ComponentVerifier.Scope> scope;
     private Optional<ComponentVerifier.Result.Status> status;
-    private List<ComponentVerifier.Error> errors;
+    private List<ComponentVerifier.VerificationError> verificationErrors;
 
     public ResultBuilder() {
         this.scope = Optional.empty();
@@ -52,23 +52,23 @@ public final class ResultBuilder {
         return this;
     }
 
-    public ResultBuilder error(ComponentVerifier.Error error) {
-        if (this.errors == null) {
-            this.errors = new ArrayList<>();
+    public ResultBuilder error(ComponentVerifier.VerificationError verificationError) {
+        if (this.verificationErrors == null) {
+            this.verificationErrors = new ArrayList<>();
         }
 
-        this.errors.add(error);
+        this.verificationErrors.add(verificationError);
         this.status = Optional.of(ComponentVerifier.Result.Status.ERROR);
 
         return this;
     }
 
-    public ResultBuilder error(Optional<ComponentVerifier.Error> error) {
+    public ResultBuilder error(Optional<ComponentVerifier.VerificationError> error) {
         error.ifPresent(e -> error(e));
         return this;
     }
 
-    public ResultBuilder error(Supplier<Optional<ComponentVerifier.Error>> supplier) {
+    public ResultBuilder error(Supplier<Optional<ComponentVerifier.VerificationError>> supplier) {
         return error(supplier.get());
     }
 
@@ -100,8 +100,8 @@ public final class ResultBuilder {
         return this;
     }
 
-    public ResultBuilder errors(List<ComponentVerifier.Error> errors) {
-        errors.forEach(this::error);
+    public ResultBuilder errors(List<ComponentVerifier.VerificationError> verificationErrors) {
+        verificationErrors.forEach(this::error);
         return this;
     }
 
@@ -111,9 +111,9 @@ public final class ResultBuilder {
 
     public ComponentVerifier.Result build() {
         return new DefaultResult(
-            scope.orElseGet(() -> ComponentVerifier.Scope.NONE),
+            scope.orElseGet(() -> ComponentVerifier.Scope.PARAMETERS),
             status.orElseGet(() -> ComponentVerifier.Result.Status.UNSUPPORTED),
-            errors != null ? Collections.unmodifiableList(errors) : Collections.emptyList()
+            verificationErrors != null ? Collections.unmodifiableList(verificationErrors) : Collections.emptyList()
         );
     }
 
@@ -134,6 +134,7 @@ public final class ResultBuilder {
     }
 
     public static ResultBuilder unsupported() {
-        return withStatusAndScope(ComponentVerifier.Result.Status.UNSUPPORTED, ComponentVerifier.Scope.NONE);
+        return withStatusAndScope(ComponentVerifier.Result.Status.UNSUPPORTED, ComponentVerifier.Scope.PARAMETERS);
     }
+
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorBuilder.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorBuilder.java b/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorBuilder.java
index 12e24d0..8052bd0 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorBuilder.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorBuilder.java
@@ -16,23 +16,18 @@
  */
 package org.apache.camel.impl.verifier;
 
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
+import java.util.*;
 import java.util.function.Supplier;
 
 import org.apache.camel.ComponentVerifier;
+import org.apache.camel.ComponentVerifier.VerificationError;
 import org.apache.camel.util.ObjectHelper;
 
 public final class ResultErrorBuilder {
-    private String code;
+    private VerificationError.Code code;
     private String description;
     private Set<String> parameters;
-    private Map<String, Object> attributes;
+    private Map<VerificationError.Attribute, Object> attributes;
 
     public ResultErrorBuilder() {
     }
@@ -41,17 +36,22 @@ public final class ResultErrorBuilder {
     // Accessors
     // **********************************
 
-    public ResultErrorBuilder code(String code) {
+    public ResultErrorBuilder code(VerificationError.Code code) {
         this.code = code;
         return this;
     }
 
+    public ResultErrorBuilder code(String code) {
+        code(VerificationError.asCode(code));
+        return this;
+    }
+
     public ResultErrorBuilder description(String description) {
         this.description = description;
         return this;
     }
 
-    public ResultErrorBuilder parameter(String parameter) {
+    public ResultErrorBuilder parameterKey(String parameter) {
         if (parameter != null) {
             if (this.parameters == null) {
                 this.parameters = new HashSet<>();
@@ -62,15 +62,20 @@ public final class ResultErrorBuilder {
         return this;
     }
 
-    public ResultErrorBuilder parameters(Collection<String> parameterList) {
+    public ResultErrorBuilder parameterKeys(Collection<String> parameterList) {
         if (parameterList != null) {
-            parameterList.forEach(this::parameter);
+            parameterList.forEach(this::parameterKey);
         }
 
         return this;
     }
 
-    public ResultErrorBuilder attribute(String key, Object value) {
+    public ResultErrorBuilder detail(String key, Object value) {
+        detail(VerificationError.asAttribute(key), value);
+        return this;
+    }
+
+    public ResultErrorBuilder detail(VerificationError.Attribute key, Object value) {
         if (value != null) {
             if (this.attributes == null) {
                 this.attributes = new HashMap<>();
@@ -81,8 +86,13 @@ public final class ResultErrorBuilder {
         return this;
     }
 
-    public <T> ResultErrorBuilder attribute(String key, Supplier<Optional<T>> supplier) {
-        supplier.get().ifPresent(value -> attribute(key, value));
+    public <T> ResultErrorBuilder detail(String key, Supplier<Optional<T>> supplier) {
+        detail(VerificationError.asAttribute(key), supplier);
+        return this;
+    }
+
+    public <T> ResultErrorBuilder detail(VerificationError.Attribute key, Supplier<Optional<T>> supplier) {
+        supplier.get().ifPresent(value -> detail(key, value));
         return this;
     }
 
@@ -90,8 +100,8 @@ public final class ResultErrorBuilder {
     // Build
     // **********************************
 
-    public ComponentVerifier.Error build() {
-        return new DefaultResultError(
+    public VerificationError build() {
+        return new DefaultResultVerificationError(
             code,
             description,
             parameters != null ? Collections.unmodifiableSet(parameters) : Collections.emptySet(),
@@ -103,69 +113,74 @@ public final class ResultErrorBuilder {
     // Helpers
     // **********************************
 
+    public static ResultErrorBuilder withCode(VerificationError.Code code) {
+        return new ResultErrorBuilder().code(code);
+    }
+
     public static ResultErrorBuilder withCode(String code) {
         return new ResultErrorBuilder().code(code);
     }
 
     public static ResultErrorBuilder withHttpCode(int code) {
-        return withCode(Integer.toString(code))
-            .attribute(ComponentVerifier.ERROR_TYPE_ATTRIBUTE, ComponentVerifier.ERROR_TYPE_HTTP)
-            .attribute(ComponentVerifier.HTTP_CODE, code);
+        return withCode(convertHttpCodeToErrorCode(code))
+            .detail(VerificationError.HttpAttribute.HTTP_CODE, code);
     }
 
     public static ResultErrorBuilder withHttpCodeAndText(int code, String text) {
-        return withCodeAndDescription(Integer.toString(code), text)
-            .attribute(ComponentVerifier.ERROR_TYPE_ATTRIBUTE, ComponentVerifier.ERROR_TYPE_HTTP)
-            .attribute(ComponentVerifier.HTTP_CODE, code)
-            .attribute(ComponentVerifier.HTTP_TEXT, text);
+        return withCodeAndDescription(convertHttpCodeToErrorCode(code), text)
+            .detail(VerificationError.HttpAttribute.HTTP_CODE, code)
+            .detail(VerificationError.HttpAttribute.HTTP_TEXT, text);
+    }
+
+    private static VerificationError.StandardCode convertHttpCodeToErrorCode(int code) {
+        return code >= 400 && code < 500 ? VerificationError.StandardCode.AUTHENTICATION : VerificationError.StandardCode.GENERIC;
     }
 
-    public static ResultErrorBuilder withCodeAndDescription(String code, String description) {
+    public static ResultErrorBuilder withCodeAndDescription(VerificationError.Code code, String description) {
         return new ResultErrorBuilder().code(code).description(description);
     }
 
     public static ResultErrorBuilder withUnsupportedScope(String scope) {
         return new ResultErrorBuilder()
-            .code(ComponentVerifier.CODE_UNSUPPORTED_SCOPE)
+            .code(VerificationError.StandardCode.UNSUPPORTED_SCOPE)
             .description("Unsupported scope: " + scope);
     }
 
     public static ResultErrorBuilder withException(Exception exception) {
         return new ResultErrorBuilder()
-            .code(ComponentVerifier.CODE_EXCEPTION)
+            .code(VerificationError.StandardCode.EXCEPTION)
             .description(exception.getMessage())
-            .attribute(ComponentVerifier.ERROR_TYPE_ATTRIBUTE, ComponentVerifier.ERROR_TYPE_EXCEPTION)
-            .attribute(ComponentVerifier.EXCEPTION_INSTANCE, exception)
-            .attribute(ComponentVerifier.EXCEPTION_CLASS, exception.getClass().getName());
+            .detail(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE, exception)
+            .detail(VerificationError.ExceptionAttribute.EXCEPTION_CLASS, exception.getClass().getName());
     }
 
     public static ResultErrorBuilder withMissingOption(String optionName) {
         return new ResultErrorBuilder()
-            .code(ComponentVerifier.CODE_MISSING_OPTION)
+            .code(VerificationError.StandardCode.MISSING_PARAMETER)
             .description(optionName + " should be set")
-            .parameter(optionName);
+            .parameterKey(optionName);
     }
 
     public static ResultErrorBuilder withUnknownOption(String optionName) {
         return new ResultErrorBuilder()
-            .code(ComponentVerifier.CODE_UNKNOWN_OPTION)
+            .code(VerificationError.StandardCode.UNKNOWN_PARAMETER)
             .description("Unknown option " + optionName)
-            .parameter(optionName);
+            .parameterKey(optionName);
     }
 
     public static ResultErrorBuilder withIllegalOption(String optionName) {
         return new ResultErrorBuilder()
-            .code(ComponentVerifier.CODE_ILLEGAL_OPTION)
+            .code(VerificationError.StandardCode.ILLEGAL_PARAMETER)
             .description("Illegal option " + optionName)
-            .parameter(optionName);
+            .parameterKey(optionName);
     }
 
     public static ResultErrorBuilder withIllegalOption(String optionName, String optionValue) {
         return ObjectHelper.isNotEmpty(optionValue)
             ? new ResultErrorBuilder()
-                .code(ComponentVerifier.CODE_ILLEGAL_OPTION_VALUE)
+                .code(VerificationError.StandardCode.ILLEGAL_PARAMETER_VALUE)
                 .description(optionName + " has wrong value (" + optionValue + ")")
-                .parameter(optionName)
+                .parameterKey(optionName)
             : withIllegalOption(optionName);
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorHelper.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorHelper.java b/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorHelper.java
index d42b8cb..c8d7785 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorHelper.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/verifier/ResultErrorHelper.java
@@ -26,7 +26,7 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 
-import org.apache.camel.ComponentVerifier;
+import org.apache.camel.ComponentVerifier.VerificationError;
 import org.apache.camel.util.ObjectHelper;
 
 public final class ResultErrorHelper {
@@ -44,7 +44,7 @@ public final class ResultErrorHelper {
      * @param parameters the
      * @return
      */
-    public static Optional<ComponentVerifier.Error> requiresOption(String parameterName, Map<String, Object> parameters) {
+    public static Optional<VerificationError> requiresOption(String parameterName, Map<String, Object> parameters) {
         if (ObjectHelper.isEmpty(parameters.get(parameterName))) {
             return Optional.of(
                 ResultErrorBuilder.withMissingOption(parameterName).build()
@@ -54,12 +54,12 @@ public final class ResultErrorHelper {
         return Optional.empty();
     }
 
-    public static List<ComponentVerifier.Error> requiresAny(Map<String, Object> parameters, OptionsGroup... groups) {
+    public static List<VerificationError> requiresAny(Map<String, Object> parameters, OptionsGroup... groups) {
         return requiresAny(parameters, Arrays.asList(groups));
     }
 
-    public static List<ComponentVerifier.Error> requiresAny(Map<String, Object> parameters, Collection<OptionsGroup> groups) {
-        final List<ComponentVerifier.Error> errors = new ArrayList<>();
+    public static List<VerificationError> requiresAny(Map<String, Object> parameters, Collection<OptionsGroup> groups) {
+        final List<VerificationError> verificationErrors = new ArrayList<>();
         final Set<String> keys = new HashSet<>(parameters.keySet());
 
         for (OptionsGroup group : groups) {
@@ -68,20 +68,20 @@ public final class ResultErrorHelper {
                 return Collections.emptyList();
             } else {
                 ResultErrorBuilder builder = new ResultErrorBuilder()
-                    .code(ComponentVerifier.CODE_INCOMPLETE_OPTION_GROUP)
-                    .attribute(ComponentVerifier.GROUP_NAME, group.getName())
-                    .attribute(ComponentVerifier.GROUP_OPTIONS, String.join(",", group.getOptions()));
+                    .code(VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP)
+                    .detail(VerificationError.GroupAttribute.GROUP_NAME, group.getName())
+                    .detail(VerificationError.GroupAttribute.GROUP_OPTIONS, String.join(",", group.getOptions()));
 
                 for (String option : group.getOptions()) {
                     if (!parameters.containsKey(option)) {
-                        builder.parameter(option);
+                        builder.parameterKey(option);
                     }
                 }
 
-                errors.add(builder.build());
+                verificationErrors.add(builder.build());
             }
         }
 
-        return errors;
+        return verificationErrors;
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/camel-core/src/test/java/org/apache/camel/ComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/ComponentVerifierTest.java b/camel-core/src/test/java/org/apache/camel/ComponentVerifierTest.java
new file mode 100644
index 0000000..b14541b
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/ComponentVerifierTest.java
@@ -0,0 +1,83 @@
+/**
+ * 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;
+import junit.framework.TestCase;
+import org.apache.camel.ComponentVerifier.VerificationError;
+import org.apache.camel.impl.verifier.ResultErrorBuilder;
+import org.junit.Assert;
+
+public class ComponentVerifierTest extends TestCase {
+
+    public void testGetErrorDetails() {
+        VerificationError error =
+            ResultErrorBuilder.withCodeAndDescription(VerificationError.asCode("test_code"), "test error desc")
+                              .detail(VerificationError.asAttribute("test_attr_1"), "test_detail_1")
+                              .detail(VerificationError.HttpAttribute.HTTP_CODE,"test_detail_2")
+                              .build();
+        Assert.assertEquals("test_detail_1", error.getDetail(VerificationError.asAttribute("test_attr_1")));
+        Assert.assertEquals("test_detail_1", error.getDetail("test_attr_1"));
+        Assert.assertEquals("test_detail_2", error.getDetail(VerificationError.HttpAttribute.HTTP_CODE));
+Assert.assertNull(error.getDetail(VerificationError.HttpAttribute.HTTP_TEXT));
+
+        Assert.assertNull(error.getDetail(VerificationError.asAttribute("test_attr_non_existant")));
+    }
+
+    public void testInvalidAttribute() {
+        try {
+            VerificationError.asAttribute("HTTP_CODE");
+            fail();
+        } catch (IllegalArgumentException exp) {
+            Assert.assertTrue(exp.getMessage().contains("HTTP_CODE"));
+        }
+    }
+
+    public void testInvalidCode() {
+        try {
+            VerificationError.asCode("Authentication");
+            fail();
+        } catch (IllegalArgumentException exp) {
+            Assert.assertTrue(exp.getMessage().contains("Authentication"));
+        }
+    }
+
+    public void testNullCode() {
+        try {
+            VerificationError.asCode(null);
+            fail("Code must not be null");
+        } catch (IllegalArgumentException exp) {
+            Assert.assertTrue(exp.getMessage().contains("null"));
+        }
+    }
+
+    public void testNullAttribute() {
+        try {
+            VerificationError.asAttribute(null);
+            fail("Attribute must not be null");
+        } catch (IllegalArgumentException exp) {
+            Assert.assertTrue(exp.getMessage().contains("null"));
+        }
+    }
+
+    public void testScopeFromString() {
+        Assert.assertEquals(ComponentVerifier.Scope.PARAMETERS, ComponentVerifier.Scope.fromString("PaRaMeTeRS"));
+
+        try {
+            ComponentVerifier.Scope.fromString("unknown");
+            fail();
+        } catch (IllegalArgumentException exp) {}
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/camel-core/src/test/java/org/apache/camel/LoggingLevelTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/LoggingLevelTest.java b/camel-core/src/test/java/org/apache/camel/LoggingLevelTest.java
index 508d3bf..cf093d6 100644
--- a/camel-core/src/test/java/org/apache/camel/LoggingLevelTest.java
+++ b/camel-core/src/test/java/org/apache/camel/LoggingLevelTest.java
@@ -19,6 +19,8 @@ package org.apache.camel;
 import junit.framework.TestCase;
 import org.junit.Test;
 
+import org.junit.Test;
+
 public class LoggingLevelTest extends TestCase {
 
     @Test

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/camel-core/src/test/java/org/apache/camel/impl/verifier/DefaultComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/impl/verifier/DefaultComponentVerifierTest.java b/camel-core/src/test/java/org/apache/camel/impl/verifier/DefaultComponentVerifierTest.java
index 5b626b0..8a903b8 100644
--- a/camel-core/src/test/java/org/apache/camel/impl/verifier/DefaultComponentVerifierTest.java
+++ b/camel-core/src/test/java/org/apache/camel/impl/verifier/DefaultComponentVerifierTest.java
@@ -20,6 +20,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.camel.ComponentVerifier;
+import org.apache.camel.ComponentVerifier.VerificationError;
 import org.apache.camel.ContextTestSupport;
 import org.junit.Assert;
 
@@ -59,8 +60,8 @@ public class DefaultComponentVerifierTest extends ContextTestSupport {
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
 
         Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(ComponentVerifier.CODE_MISSING_OPTION, result.getErrors().get(0).getCode());
-        Assert.assertTrue(result.getErrors().get(0).getParameters().contains("timerName"));
+        Assert.assertEquals(VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("timerName"));
     }
 
     public void testParametersWithWrongOptions() throws Exception {
@@ -73,8 +74,8 @@ public class DefaultComponentVerifierTest extends ContextTestSupport {
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
 
         Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(ComponentVerifier.CODE_ILLEGAL_OPTION_VALUE, result.getErrors().get(0).getCode());
+        Assert.assertEquals(VerificationError.StandardCode.ILLEGAL_PARAMETER_VALUE, result.getErrors().get(0).getCode());
         Assert.assertEquals("fixedRate has wrong value (wrong)", result.getErrors().get(0).getDescription());
-        Assert.assertTrue(result.getErrors().get(0).getParameters().contains("fixedRate"));
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("fixedRate"));
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifier.java
----------------------------------------------------------------------
diff --git a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifier.java b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifier.java
index 2ef8c96..309ff3e 100644
--- a/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifier.java
+++ b/components/camel-http/src/main/java/org/apache/camel/component/http/HttpComponentVerifier.java
@@ -36,7 +36,7 @@ final class HttpComponentVerifier extends DefaultComponentVerifier {
 
     HttpComponentVerifier(HttpComponent component) {
         super("http", component.getCamelContext());
-        
+
         this.component = component;
     }
 
@@ -111,8 +111,8 @@ final class HttpComponentVerifier extends DefaultComponentVerifier {
                     builder.error(
                         ResultErrorBuilder.withHttpCode(code)
                             .description(method.getStatusText())
-                            .parameter("authUsername")
-                            .parameter("authPassword")
+                            .parameterKey("authUsername")
+                            .parameterKey("authPassword")
                             .build()
                     );
                 } else if (code >= 300 && code < 400) {
@@ -120,9 +120,8 @@ final class HttpComponentVerifier extends DefaultComponentVerifier {
                     builder.error(
                         ResultErrorBuilder.withHttpCode(code)
                             .description(method.getStatusText())
-                            .parameter("httpUri")
-                            .attribute(ComponentVerifier.HTTP_REDIRECT, true)
-                            .attribute(ComponentVerifier.HTTP_REDIRECT_LOCATION, () -> HttpUtil.responseHeaderValue(method, "location"))
+                            .parameterKey("httpUri")
+                            .detail(VerificationError.HttpAttribute.HTTP_REDIRECT, () -> HttpUtil.responseHeaderValue(method, "location"))
                             .build()
                     );
                 } else if (code >= 400) {
@@ -137,7 +136,7 @@ final class HttpComponentVerifier extends DefaultComponentVerifier {
         } catch (UnknownHostException e) {
             builder.error(
                 ResultErrorBuilder.withException(e)
-                    .parameter("httpUri")
+                    .parameterKey("httpUri")
                     .build()
             );
         }

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/components/camel-http/src/test/java/org/apache/camel/component/http/CamelComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-http/src/test/java/org/apache/camel/component/http/CamelComponentVerifierTest.java b/components/camel-http/src/test/java/org/apache/camel/component/http/CamelComponentVerifierTest.java
index c224946..76d918e 100644
--- a/components/camel-http/src/test/java/org/apache/camel/component/http/CamelComponentVerifierTest.java
+++ b/components/camel-http/src/test/java/org/apache/camel/component/http/CamelComponentVerifierTest.java
@@ -20,6 +20,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.camel.ComponentVerifier;
+import org.apache.camel.ComponentVerifier.VerificationError;
 import org.apache.camel.component.http.handler.BasicValidationHandler;
 import org.apache.camel.test.AvailablePortFinder;
 import org.eclipse.jetty.server.Server;
@@ -35,7 +36,7 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
     private static final int PORT = AvailablePortFinder.getNextAvailable();
 
     private Server localServer;
-    
+
     @Before
     @Override
     public void setUp() throws Exception {
@@ -107,10 +108,10 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
 
-        ComponentVerifier.Error error = result.getErrors().get(0);
+        VerificationError error = result.getErrors().get(0);
 
-        Assert.assertEquals(ComponentVerifier.CODE_MISSING_OPTION, error.getCode());
-        Assert.assertTrue(error.getParameters().contains("httpUri"));
+        Assert.assertEquals(VerificationError.StandardCode.MISSING_PARAMETER, error.getCode());
+        Assert.assertTrue(error.getParameterKeys().contains("httpUri"));
     }
 
     // *************************************************
@@ -143,11 +144,10 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
 
-        ComponentVerifier.Error error = result.getErrors().get(0);
+        VerificationError error = result.getErrors().get(0);
 
-        Assert.assertEquals(ComponentVerifier.CODE_EXCEPTION, error.getCode());
-        Assert.assertEquals(ComponentVerifier.ERROR_TYPE_EXCEPTION, error.getAttributes().get(ComponentVerifier.ERROR_TYPE_ATTRIBUTE));
-        Assert.assertTrue(error.getParameters().contains("httpUri"));
+        Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, error.getCode());
+        Assert.assertTrue(error.getParameterKeys().contains("httpUri"));
     }
 
     @Ignore
@@ -182,12 +182,11 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
 
-        ComponentVerifier.Error error = result.getErrors().get(0);
+        VerificationError error = result.getErrors().get(0);
 
-        Assert.assertEquals("401", error.getCode());
-        Assert.assertEquals(ComponentVerifier.ERROR_TYPE_HTTP, error.getAttributes().get(ComponentVerifier.ERROR_TYPE_ATTRIBUTE));
-        Assert.assertEquals(401, error.getAttributes().get(ComponentVerifier.HTTP_CODE));
-        Assert.assertTrue(error.getParameters().contains("authUsername"));
-        Assert.assertTrue(error.getParameters().contains("authPassword"));
+        Assert.assertEquals(VerificationError.StandardCode.AUTHENTICATION, error.getCode());
+        Assert.assertEquals(401, error.getDetails().get(VerificationError.HttpAttribute.HTTP_CODE));
+        Assert.assertTrue(error.getParameterKeys().contains("authUsername"));
+        Assert.assertTrue(error.getParameterKeys().contains("authPassword"));
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifier.java
----------------------------------------------------------------------
diff --git a/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifier.java b/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifier.java
index d2a47c9..ed55b12 100644
--- a/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifier.java
+++ b/components/camel-http4/src/main/java/org/apache/camel/component/http4/HttpComponentVerifier.java
@@ -38,7 +38,7 @@ final class HttpComponentVerifier extends DefaultComponentVerifier {
 
     HttpComponentVerifier(HttpComponent component) {
         super("http4", component.getCamelContext());
-        
+
         this.component = component;
     }
 
@@ -94,8 +94,8 @@ final class HttpComponentVerifier extends DefaultComponentVerifier {
                     builder.error(
                         ResultErrorBuilder.withHttpCode(code)
                             .description(response.getStatusLine().getReasonPhrase())
-                            .parameter("authUsername")
-                            .parameter("authPassword")
+                            .parameterKey("authUsername")
+                            .parameterKey("authPassword")
                             .build()
                     );
                 } else if (code >= 300 && code < 400) {
@@ -103,9 +103,8 @@ final class HttpComponentVerifier extends DefaultComponentVerifier {
                     builder.error(
                         ResultErrorBuilder.withHttpCode(code)
                             .description(response.getStatusLine().getReasonPhrase())
-                            .parameter("httpUri")
-                            .attribute(ComponentVerifier.HTTP_REDIRECT, true)
-                            .attribute(ComponentVerifier.HTTP_REDIRECT_LOCATION, () -> HttpUtil.responseHeaderValue(response, "location"))
+                            .parameterKey("httpUri")
+                            .detail(VerificationError.HttpAttribute.HTTP_REDIRECT, () -> HttpUtil.responseHeaderValue(response, "location"))
                             .build()
                     );
                 } else if (code >= 400) {
@@ -120,7 +119,7 @@ final class HttpComponentVerifier extends DefaultComponentVerifier {
         } catch (UnknownHostException e) {
             builder.error(
                 ResultErrorBuilder.withException(e)
-                    .parameter("httpUri")
+                    .parameterKey("httpUri")
                     .build()
             );
         }

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierTest.java b/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierTest.java
index 7671337..dc4ef3f 100644
--- a/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierTest.java
+++ b/components/camel-http4/src/test/java/org/apache/camel/component/http4/CamelComponentVerifierTest.java
@@ -22,6 +22,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.camel.ComponentVerifier;
+import org.apache.camel.ComponentVerifier.VerificationError;
 import org.apache.camel.component.http4.handler.AuthenticationValidationHandler;
 import org.apache.camel.component.http4.handler.BasicValidationHandler;
 import org.apache.http.HttpException;
@@ -47,7 +48,7 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
     private static final String AUTH_PASSWORD = "password";
 
     private HttpServer localServer;
-    
+
     @Before
     @Override
     public void setUp() throws Exception {
@@ -145,10 +146,10 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
 
-        ComponentVerifier.Error error = result.getErrors().get(0);
+        VerificationError error = result.getErrors().get(0);
 
-        Assert.assertEquals(ComponentVerifier.CODE_MISSING_OPTION, error.getCode());
-        Assert.assertTrue(error.getParameters().contains("httpUri"));
+        Assert.assertEquals(VerificationError.StandardCode.MISSING_PARAMETER, error.getCode());
+        Assert.assertTrue(error.getParameterKeys().contains("httpUri"));
     }
 
     @Test
@@ -177,11 +178,10 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
 
-        ComponentVerifier.Error error = result.getErrors().get(0);
+        VerificationError error = result.getErrors().get(0);
 
-        Assert.assertEquals(ComponentVerifier.CODE_EXCEPTION, error.getCode());
-        Assert.assertEquals(ComponentVerifier.ERROR_TYPE_EXCEPTION, error.getAttributes().get(ComponentVerifier.ERROR_TYPE_ATTRIBUTE));
-        Assert.assertTrue(error.getParameters().contains("httpUri"));
+        Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, error.getCode());
+        Assert.assertTrue(error.getParameterKeys().contains("httpUri"));
     }
 
     @Test
@@ -214,13 +214,12 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
 
-        ComponentVerifier.Error error = result.getErrors().get(0);
+        VerificationError error = result.getErrors().get(0);
 
-        Assert.assertEquals("401", error.getCode());
-        Assert.assertEquals(ComponentVerifier.ERROR_TYPE_HTTP, error.getAttributes().get(ComponentVerifier.ERROR_TYPE_ATTRIBUTE));
-        Assert.assertEquals(401, error.getAttributes().get(ComponentVerifier.HTTP_CODE));
-        Assert.assertTrue(error.getParameters().contains("authUsername"));
-        Assert.assertTrue(error.getParameters().contains("authPassword"));
+        Assert.assertEquals(VerificationError.StandardCode.AUTHENTICATION, error.getCode());
+        Assert.assertEquals(401, error.getDetails().get(VerificationError.HttpAttribute.HTTP_CODE));
+        Assert.assertTrue(error.getParameterKeys().contains("authUsername"));
+        Assert.assertTrue(error.getParameterKeys().contains("authPassword"));
     }
 
     @Test
@@ -250,12 +249,10 @@ public class CamelComponentVerifierTest extends BaseHttpTest {
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
 
-        ComponentVerifier.Error error = result.getErrors().get(0);
+        VerificationError error = result.getErrors().get(0);
 
-        Assert.assertEquals("301", error.getCode());
-        Assert.assertEquals(ComponentVerifier.ERROR_TYPE_HTTP, error.getAttributes().get(ComponentVerifier.ERROR_TYPE_ATTRIBUTE));
-        Assert.assertEquals(true, error.getAttributes().get("http.redirect"));
-        Assert.assertEquals(getLocalServerUri("/redirected"), error.getAttributes().get("http.redirect.location"));
-        Assert.assertTrue(error.getParameters().contains("httpUri"));
+        Assert.assertEquals(VerificationError.StandardCode.GENERIC, error.getCode());
+        Assert.assertEquals(getLocalServerUri("/redirected"), error.getDetails().get(VerificationError.HttpAttribute.HTTP_REDIRECT));
+        Assert.assertTrue(error.getParameterKeys().contains("httpUri"));
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java
index c7aa082..72b6f35 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponentVerifier.java
@@ -144,16 +144,16 @@ public class SalesforceComponentVerifier extends DefaultComponentVerifier {
         exception.ifPresent(e -> {
             builder.error(
                 ResultErrorBuilder.withException(e)
-                    .attribute(ComponentVerifier.HTTP_CODE, e.getStatusCode())
+                    .detail(VerificationError.HttpAttribute.HTTP_CODE, e.getStatusCode())
                     .build()
             );
 
             for (RestError error : e.getErrors()) {
                 builder.error(
-                    ResultErrorBuilder.withCode(error.getErrorCode())
+                    ResultErrorBuilder.withCode(VerificationError.StandardCode.GENERIC)
                         .description(error.getMessage())
-                        .attribute(ComponentVerifier.ERROR_TYPE_ATTRIBUTE, "salesforce")
-                        .parameters(error.getFields())
+                        .parameterKeys(error.getFields())
+                        .detail("salesforce_code",error.getErrorCode())
                         .build()
                 );
             }

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierTest.java
index 3b150e2..af8b6cd 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierTest.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/SalesforceComponentVerifierTest.java
@@ -20,6 +20,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.camel.ComponentVerifier;
+import org.apache.camel.ComponentVerifier.VerificationError;
 import org.apache.camel.component.salesforce.api.SalesforceException;
 import org.apache.camel.test.junit4.CamelTestSupport;
 import org.apache.camel.util.ObjectHelper;
@@ -119,9 +120,9 @@ public class SalesforceComponentVerifierTest extends CamelTestSupport {
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(3, result.getErrors().size());
 
-        Assert.assertEquals(ComponentVerifier.CODE_INCOMPLETE_OPTION_GROUP, result.getErrors().get(0).getCode());
-        Assert.assertEquals(ComponentVerifier.CODE_INCOMPLETE_OPTION_GROUP, result.getErrors().get(1).getCode());
-        Assert.assertEquals(ComponentVerifier.CODE_INCOMPLETE_OPTION_GROUP, result.getErrors().get(2).getCode());
+        Assert.assertEquals(VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(0).getCode());
+        Assert.assertEquals(VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(1).getCode());
+        Assert.assertEquals(VerificationError.StandardCode.INCOMPLETE_PARAMETER_GROUP, result.getErrors().get(2).getCode());
     }
 
     // *********************************
@@ -147,13 +148,12 @@ public class SalesforceComponentVerifierTest extends CamelTestSupport {
         Assert.assertEquals(2, result.getErrors().size());
 
         // Exception
-        Assert.assertEquals(ComponentVerifier.CODE_EXCEPTION, result.getErrors().get(0).getCode());
-        Assert.assertNotNull(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE));
-        Assert.assertTrue(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE) instanceof SalesforceException);
-        Assert.assertEquals(400, result.getErrors().get(0).getAttributes().get(ComponentVerifier.HTTP_CODE));
+        Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof SalesforceException);
+        Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(VerificationError.HttpAttribute.HTTP_CODE));
 
         // Salesforce Error
-        Assert.assertEquals("salesforce", result.getErrors().get(1).getAttributes().get(ComponentVerifier.ERROR_TYPE_ATTRIBUTE));
         Assert.assertEquals("authentication failure", result.getErrors().get(1).getDescription());
     }
 
@@ -171,13 +171,12 @@ public class SalesforceComponentVerifierTest extends CamelTestSupport {
         Assert.assertEquals(2, result.getErrors().size());
 
         // Exception
-        Assert.assertEquals(ComponentVerifier.CODE_EXCEPTION, result.getErrors().get(0).getCode());
-        Assert.assertNotNull(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE));
-        Assert.assertTrue(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE) instanceof SalesforceException);
-        Assert.assertEquals(400, result.getErrors().get(0).getAttributes().get(ComponentVerifier.HTTP_CODE));
+        Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof SalesforceException);
+        Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(ComponentVerifier.VerificationError.HttpAttribute.HTTP_CODE));
 
         // Salesforce Error
-        Assert.assertEquals("salesforce", result.getErrors().get(1).getAttributes().get(ComponentVerifier.ERROR_TYPE_ATTRIBUTE));
         Assert.assertEquals("client identifier invalid", result.getErrors().get(1).getDescription());
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifier.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifier.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifier.java
index cab1f82..8d4cf9d 100644
--- a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifier.java
+++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifier.java
@@ -88,17 +88,17 @@ public class ServiceNowComponentVerifier extends DefaultComponentVerifier {
             );
         } catch (ServiceNowException e) {
             ResultErrorBuilder errorBuilder = ResultErrorBuilder.withException(e)
-                .attribute(ComponentVerifier.HTTP_CODE, e.getCode())
-                .attribute("servicenow.error.message", e.getMessage())
-                .attribute("servicenow.error.status", e.getStatus())
-                .attribute("servicenow.error.detail", e.getDetail())
-                .attribute("servicenow.error.detail", e.getDetail());
+                .detail(VerificationError.HttpAttribute.HTTP_CODE, e.getCode())
+                .detail("servicenow_error_message", e.getMessage())
+                .detail("servicenow_error_status", e.getStatus())
+                .detail("servicenow_error_detail", e.getDetail());
 
             if (e.getCode() == 401) {
-                errorBuilder.parameter("userName");
-                errorBuilder.parameter("password");
-                errorBuilder.parameter("oauthClientId");
-                errorBuilder.parameter("oauthClientSecret");
+                errorBuilder.code(VerificationError.StandardCode.AUTHENTICATION);
+                errorBuilder.parameterKey("userName");
+                errorBuilder.parameterKey("password");
+                errorBuilder.parameterKey("oauthClientId");
+                errorBuilder.parameterKey("oauthClientSecret");
             }
 
             builder.error(errorBuilder.build());

http://git-wip-us.apache.org/repos/asf/camel/blob/c810328e/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java
----------------------------------------------------------------------
diff --git a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java
index 3cff7bb..80da7db 100644
--- a/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java
+++ b/components/camel-servicenow/src/test/java/org/apache/camel/component/servicenow/ServiceNowComponentVerifierTest.java
@@ -21,6 +21,7 @@ import java.util.Map;
 import javax.ws.rs.ProcessingException;
 
 import org.apache.camel.ComponentVerifier;
+import org.apache.camel.ComponentVerifier.VerificationError;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -61,8 +62,8 @@ public class ServiceNowComponentVerifierTest extends ServiceNowTestSupport {
 
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(ComponentVerifier.CODE_MISSING_OPTION, result.getErrors().get(0).getCode());
-        Assert.assertEquals("instanceName", result.getErrors().get(0).getParameters().iterator().next());
+        Assert.assertEquals(VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
+        Assert.assertEquals("instanceName", result.getErrors().get(0).getParameterKeys().iterator().next());
     }
 
     @Test
@@ -73,8 +74,8 @@ public class ServiceNowComponentVerifierTest extends ServiceNowTestSupport {
 
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(ComponentVerifier.CODE_MISSING_OPTION, result.getErrors().get(0).getCode());
-        Assert.assertEquals("userName", result.getErrors().get(0).getParameters().iterator().next());
+        Assert.assertEquals(VerificationError.StandardCode.MISSING_PARAMETER, result.getErrors().get(0).getCode());
+        Assert.assertEquals("userName", result.getErrors().get(0).getParameterKeys().iterator().next());
     }
 
     // *********************************
@@ -108,9 +109,9 @@ public class ServiceNowComponentVerifierTest extends ServiceNowTestSupport {
 
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(ComponentVerifier.CODE_EXCEPTION, result.getErrors().get(0).getCode());
-        Assert.assertNotNull(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE));
-        Assert.assertTrue(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE) instanceof ProcessingException);
+        Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ProcessingException);
     }
 
     @Test
@@ -122,10 +123,10 @@ public class ServiceNowComponentVerifierTest extends ServiceNowTestSupport {
 
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(ComponentVerifier.CODE_EXCEPTION, result.getErrors().get(0).getCode());
-        Assert.assertNotNull(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE));
-        Assert.assertEquals(400, result.getErrors().get(0).getAttributes().get(ComponentVerifier.HTTP_CODE));
-        Assert.assertTrue(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE) instanceof ServiceNowException);
+        Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertEquals(400, result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException);
     }
 
     @Test
@@ -139,13 +140,13 @@ public class ServiceNowComponentVerifierTest extends ServiceNowTestSupport {
 
         Assert.assertEquals(ComponentVerifier.Result.Status.ERROR, result.getStatus());
         Assert.assertEquals(1, result.getErrors().size());
-        Assert.assertEquals(ComponentVerifier.CODE_EXCEPTION, result.getErrors().get(0).getCode());
-        Assert.assertNotNull(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE));
-        Assert.assertEquals(401, result.getErrors().get(0).getAttributes().get(ComponentVerifier.HTTP_CODE));
-        Assert.assertTrue(result.getErrors().get(0).getAttributes().get(ComponentVerifier.EXCEPTION_INSTANCE) instanceof ServiceNowException);
-        Assert.assertTrue(result.getErrors().get(0).getParameters().contains("userName"));
-        Assert.assertTrue(result.getErrors().get(0).getParameters().contains("password"));
-        Assert.assertTrue(result.getErrors().get(0).getParameters().contains("oauthClientId"));
-        Assert.assertTrue(result.getErrors().get(0).getParameters().contains("oauthClientSecret"));
+        Assert.assertEquals(VerificationError.StandardCode.EXCEPTION, result.getErrors().get(0).getCode());
+        Assert.assertNotNull(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE));
+        Assert.assertEquals(401, result.getErrors().get(0).getDetails().get(VerificationError.HttpAttribute.HTTP_CODE));
+        Assert.assertTrue(result.getErrors().get(0).getDetails().get(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE) instanceof ServiceNowException);
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("userName"));
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("password"));
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("oauthClientId"));
+        Assert.assertTrue(result.getErrors().get(0).getParameterKeys().contains("oauthClientSecret"));
     }
 }