You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2017/02/22 14:27:48 UTC

[2/4] camel git commit: CAMEL-10538 Add declarative validator according to input/output type

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/examples/README.adoc
----------------------------------------------------------------------
diff --git a/examples/README.adoc b/examples/README.adoc
index 9eeae55..08e5ff5 100644
--- a/examples/README.adoc
+++ b/examples/README.adoc
@@ -93,7 +93,9 @@ Number of Examples: 84
 | link:camel-example-transformer-cdi/README.md[Transformer CDI] (camel-example-transformer-cdi) | Input/Output Type Contract | An example demonstrating declarative transformation along data type declaration using Java DSL and CDI
   
 
-| link:camel-example-transformer-demo/README.md[Transformer Spring XML] (camel-example-transformer-demo) | Input/Output Type Contract | An example demonstrating declarative transformation along data type declaration using Spring DSL
+| link:camel-example-transformer-demo/README.md[Transformer and Validator Spring XML] (camel-example-transformer-demo) | Input/Output Type Contract | An example demonstrating declarative transformation and validation along data type declaration using Spring DSL
+
+| link:camel-example-validator-spring-boot/README.md[Validator Spring Boot] (camel-example-validator-spring-boot) | Input/Output Type Contract | An example demonstrating declarative validation along data type declaration using Spring Boot
 
 | link:camel-example-bam/README.md[BAM (deprecated)] (camel-example-bam) | Management and Monitoring | *deprecated* An example showing how to use Camel as a Business Activity Monitoring tool
 

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/examples/camel-example-transformer-demo/README.md
----------------------------------------------------------------------
diff --git a/examples/camel-example-transformer-demo/README.md b/examples/camel-example-transformer-demo/README.md
index 8f203f8..11123d9 100644
--- a/examples/camel-example-transformer-demo/README.md
+++ b/examples/camel-example-transformer-demo/README.md
@@ -1,9 +1,9 @@
-# Declarative Transformer Demo using Spring XML
+# Declarative Transformer and Validator Demo using Spring XML
 
 
 ### Introduction
 
-This example shows how to work with declarative transformation by declaring data types.
+This example shows how to work with declarative transformation and validation by declaring data types.
 
 ### Build
 
@@ -20,6 +20,10 @@ To run the example type
 You can see the routing rules by looking at the Spring XML configuration lives in
 `src/main/resources/META-INF/spring`
 
+If you enable DEBUG level log for org.apache.camel.processor, you can see the details
+of when/which transformers & validators are applied. Check the
+`src/main/resources/log4j2.properties`
+
 
 ### Forum, Help, etc
 

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/examples/camel-example-transformer-demo/pom.xml
----------------------------------------------------------------------
diff --git a/examples/camel-example-transformer-demo/pom.xml b/examples/camel-example-transformer-demo/pom.xml
index af3759c..d81a437 100644
--- a/examples/camel-example-transformer-demo/pom.xml
+++ b/examples/camel-example-transformer-demo/pom.xml
@@ -27,12 +27,12 @@
 
   <artifactId>camel-example-transformer-demo</artifactId>
   <name>Camel :: Example :: Transformer :: Demo</name>
-  <description>An example demonstrating declarative transformation along data type declaration using Spring DSL</description>
+  <description>An example demonstrating declarative transformation and validation along data type declaration using Spring DSL</description>
   <packaging>jar</packaging>
 
   <properties>
     <category>Input/Output Type Contract</category>
-    <title>Transformer Spring XML</title>
+    <title>Transformer and Validator Spring XML</title>
   </properties>
 
   <dependencies>

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/examples/camel-example-transformer-demo/src/main/java/org/apache/camel/example/transformer/demo/OrderResponseValidator.java
----------------------------------------------------------------------
diff --git a/examples/camel-example-transformer-demo/src/main/java/org/apache/camel/example/transformer/demo/OrderResponseValidator.java b/examples/camel-example-transformer-demo/src/main/java/org/apache/camel/example/transformer/demo/OrderResponseValidator.java
new file mode 100644
index 0000000..2ebf9f3
--- /dev/null
+++ b/examples/camel-example-transformer-demo/src/main/java/org/apache/camel/example/transformer/demo/OrderResponseValidator.java
@@ -0,0 +1,26 @@
+package org.apache.camel.example.transformer.demo;
+
+import org.apache.camel.Message;
+import org.apache.camel.ValidationException;
+import org.apache.camel.spi.DataType;
+import org.apache.camel.spi.Validator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OrderResponseValidator extends Validator {
+    private static final Logger LOG = LoggerFactory.getLogger(OrderResponseValidator.class);
+
+    @Override
+    public void validate(Message message, DataType type) throws ValidationException {
+        Object body = message.getBody();
+        LOG.info("Validating message body: {}", body);
+        if (!(body instanceof OrderResponse)) {
+            throw new ValidationException(message.getExchange(), "Expected OrderResponse, but was " + body.getClass());
+        }
+        OrderResponse r = (OrderResponse)body;
+        if (!r.isAccepted()) {
+            throw new ValidationException(message.getExchange(), "Order was not accepted:" + r);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/examples/camel-example-transformer-demo/src/main/resources/META-INF/spring/camel-context.xml
----------------------------------------------------------------------
diff --git a/examples/camel-example-transformer-demo/src/main/resources/META-INF/spring/camel-context.xml b/examples/camel-example-transformer-demo/src/main/resources/META-INF/spring/camel-context.xml
index 09c3b72..fa22fe0 100644
--- a/examples/camel-example-transformer-demo/src/main/resources/META-INF/spring/camel-context.xml
+++ b/examples/camel-example-transformer-demo/src/main/resources/META-INF/spring/camel-context.xml
@@ -51,13 +51,23 @@
             <camel:dataFormatTransformer ref="jsondf" scheme="json"/>
         </camel:transformers>
         <!-- END SNIPPET: e3 -->
+        <!-- START SNIPPET: e8 -->
+        <camel:validators>
+            <camel:endpointValidator type="xml" uri="validator:xsd/schema.xsd"/>
+            <camel:predicateValidator type="json">
+                <camel:simple>${body} contains 'orderId' and ${body} not contains 'accepted'</camel:simple>
+            </camel:predicateValidator>
+            <camel:customValidator type="java:org.apache.camel.example.transformer.demo.OrderResponse"
+            className="org.apache.camel.example.transformer.demo.OrderResponseValidator"/>
+        </camel:validators>
+        <!-- END SNIPPET: e8 -->
 
         <!-- START SNIPPET: e4 -->
         <camel:route id="xml">
             <camel:from uri="direct:xml"/>
             <!--  This route expects XML as an input/output type -->
-            <camel:inputType urn="xml:XMLOrder"/>
-            <camel:outputType urn="xml:XMLOrderResponse"/>
+            <camel:inputType urn="xml:XMLOrder" validate="true"/>
+            <camel:outputType urn="xml:XMLOrderResponse" validate="true"/>
             <camel:to uri="direct:java"/>
         </camel:route>
         <!-- END SNIPPET: e4 -->
@@ -67,7 +77,7 @@
             <camel:from uri="direct:json"/>
             <!--  This route expects JSON as an input/output type -->
             <!--  Only scheme 'json' is specified for the type, which means it handles arbitrary JSON content -->
-            <camel:inputType urn="json"/>
+            <camel:inputType urn="json" validate="true"/>
             <camel:outputType urn="json"/>
             <camel:to uri="direct:java"/>
         </camel:route>
@@ -81,7 +91,7 @@
             <!--  If it comes from json route, the JSON-Java transformer is applied. -->
             <!--  If it's sent via ProducerTemplate directly without specifying input/output type, no transformer is applied. -->
             <camel:inputType urn="java:org.apache.camel.example.transformer.demo.Order"/>
-            <camel:outputType urn="java:org.apache.camel.example.transformer.demo.OrderResponse"/>
+            <camel:outputType urn="java:org.apache.camel.example.transformer.demo.OrderResponse" validate="true"/>
             <camel:wireTap uri="direct:csv"/>
             <camel:process ref="orderProcessor"/>
         </camel:route>

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/examples/camel-example-transformer-demo/src/main/resources/xsd/schema.xsd
----------------------------------------------------------------------
diff --git a/examples/camel-example-transformer-demo/src/main/resources/xsd/schema.xsd b/examples/camel-example-transformer-demo/src/main/resources/xsd/schema.xsd
new file mode 100644
index 0000000..cd1455e
--- /dev/null
+++ b/examples/camel-example-transformer-demo/src/main/resources/xsd/schema.xsd
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+  <xs:element name="order" type="order"/>
+
+  <xs:element name="orderResponse" type="orderResponse"/>
+
+  <xs:complexType name="order">
+    <xs:sequence/>
+    <xs:attribute name="orderId" type="xs:string"/>
+    <xs:attribute name="itemId" type="xs:string"/>
+    <xs:attribute name="quantity" type="xs:int" use="required"/>
+  </xs:complexType>
+
+  <xs:complexType name="orderResponse">
+    <xs:sequence/>
+    <xs:attribute name="orderId" type="xs:string"/>
+    <xs:attribute name="accepted" type="xs:boolean" use="required"/>
+    <xs:attribute name="description" type="xs:string"/>
+  </xs:complexType>
+</xs:schema>
+

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/examples/camel-example-validator-spring-boot/pom.xml
----------------------------------------------------------------------
diff --git a/examples/camel-example-validator-spring-boot/pom.xml b/examples/camel-example-validator-spring-boot/pom.xml
new file mode 100644
index 0000000..91ebba2
--- /dev/null
+++ b/examples/camel-example-validator-spring-boot/pom.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>examples</artifactId>
+    <version>2.19.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>camel-example-validator-spring-boot</artifactId>
+  <name>Camel :: Example :: Validator :: Spring Boot</name>
+  <description>An example showing how to work with declarative validation and Spring Boot</description>
+
+  <properties>
+    <category>Input/Output Type Contract</category>
+    <title>Validator Spring Boot</title>
+
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+    <spring.boot-version>${spring-boot-version}</spring.boot-version>
+  </properties>
+
+  <dependencyManagement>
+    <dependencies>
+      <!-- Spring Boot BOM -->
+      <dependency>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-dependencies</artifactId>
+        <version>${spring.boot-version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+      <!-- Camel BOM -->
+      <dependency>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>camel-spring-boot-dependencies</artifactId>
+        <version>${project.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
+  <dependencies>
+
+    <!-- Spring Boot -->
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-web</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-undertow</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-actuator</artifactId>
+    </dependency>
+
+    <!-- Camel -->
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-spring-boot-starter</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-stream-starter</artifactId>
+    </dependency>
+
+    <!-- test -->
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-test-spring</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+        <version>${spring-boot-version}</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>repackage</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/examples/camel-example-validator-spring-boot/readme.adoc
----------------------------------------------------------------------
diff --git a/examples/camel-example-validator-spring-boot/readme.adoc b/examples/camel-example-validator-spring-boot/readme.adoc
new file mode 100644
index 0000000..1bc83e4
--- /dev/null
+++ b/examples/camel-example-validator-spring-boot/readme.adoc
@@ -0,0 +1,28 @@
+# Camel Example Validator Spring Boot
+
+This example shows how to work with a simple Apache Camel application using Spring Boot with declarative content validation enabled.
+
+The example generates messages using timer trigger, writes them to standard output. The output type is declared as `greeting`, which has corresponding validator defined.
+
+## Camel routes
+
+The Camel route is located in the `SampleCamelRouter` class. In this class the route
+starts from a timer, that triggers every 2nd second and calls a Spring Bean `SampleBean`
+which returns a message, that is routed to a stream endpoint which writes to standard output.
+The output type is declared as `greeting`, and the validator `GreetingValidator` is registered
+to be triggered for `greeting` output message right after the routing. 
+
+## Using Camel components
+
+Apache Camel provides 200+ components which you can use to integrate and route messages between many systems
+and data formats. To use any of these Camel components, add the component as a dependency to your project.
+
+## How to run
+
+You can run this example using
+
+    mvn spring-boot:run
+
+## More information
+
+You can find more information about Apache Camel at the website: http://camel.apache.org/

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/examples/camel-example-validator-spring-boot/src/main/java/sample/camel/GreetingValidator.java
----------------------------------------------------------------------
diff --git a/examples/camel-example-validator-spring-boot/src/main/java/sample/camel/GreetingValidator.java b/examples/camel-example-validator-spring-boot/src/main/java/sample/camel/GreetingValidator.java
new file mode 100644
index 0000000..79129ff
--- /dev/null
+++ b/examples/camel-example-validator-spring-boot/src/main/java/sample/camel/GreetingValidator.java
@@ -0,0 +1,31 @@
+package sample.camel;
+
+import org.apache.camel.Message;
+import org.apache.camel.ValidationException;
+import org.apache.camel.spi.DataType;
+import org.apache.camel.spi.Validator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+@Component("greetingValidator")
+public class GreetingValidator extends Validator {
+
+    private static final Logger LOG = LoggerFactory.getLogger(GreetingValidator.class);
+
+    @Value("${greeting}")
+    private String greeting;
+
+    @Override
+    public void validate(Message message, DataType type) throws ValidationException {
+        Object body = message.getBody();
+        LOG.info("Validating : [{}]", body);
+        if (body instanceof String && body.equals(greeting)) {
+            LOG.info("OK");
+        } else {
+            throw new ValidationException(message.getExchange(), "Wrong content");
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/examples/camel-example-validator-spring-boot/src/main/java/sample/camel/SampleBean.java
----------------------------------------------------------------------
diff --git a/examples/camel-example-validator-spring-boot/src/main/java/sample/camel/SampleBean.java b/examples/camel-example-validator-spring-boot/src/main/java/sample/camel/SampleBean.java
new file mode 100644
index 0000000..b60ef69
--- /dev/null
+++ b/examples/camel-example-validator-spring-boot/src/main/java/sample/camel/SampleBean.java
@@ -0,0 +1,38 @@
+/**
+ * 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 sample.camel;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * A bean that returns a message when you call the {@link #saySomething()} method.
+ * <p/>
+ * Uses <tt>@Component("myBean")</tt> to register this bean with the name <tt>myBean</tt>
+ * that we use in the Camel route to lookup this bean.
+ */
+@Component("myBean")
+public class SampleBean {
+
+    @Value("${greeting}")
+    private String say;
+
+    public String saySomething() {
+        return say;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/examples/camel-example-validator-spring-boot/src/main/java/sample/camel/SampleCamelApplication.java
----------------------------------------------------------------------
diff --git a/examples/camel-example-validator-spring-boot/src/main/java/sample/camel/SampleCamelApplication.java b/examples/camel-example-validator-spring-boot/src/main/java/sample/camel/SampleCamelApplication.java
new file mode 100644
index 0000000..5d9304a
--- /dev/null
+++ b/examples/camel-example-validator-spring-boot/src/main/java/sample/camel/SampleCamelApplication.java
@@ -0,0 +1,37 @@
+/**
+ * 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 sample.camel;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+//CHECKSTYLE:OFF
+/**
+ * A sample Spring Boot application that starts the Camel routes.
+ */
+@SpringBootApplication
+public class SampleCamelApplication {
+
+    /**
+     * A main method to start this application.
+     */
+    public static void main(String[] args) {
+        SpringApplication.run(SampleCamelApplication.class, args);
+    }
+
+}
+//CHECKSTYLE:ON

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/examples/camel-example-validator-spring-boot/src/main/java/sample/camel/SampleCamelRouter.java
----------------------------------------------------------------------
diff --git a/examples/camel-example-validator-spring-boot/src/main/java/sample/camel/SampleCamelRouter.java b/examples/camel-example-validator-spring-boot/src/main/java/sample/camel/SampleCamelRouter.java
new file mode 100644
index 0000000..b7535ea
--- /dev/null
+++ b/examples/camel-example-validator-spring-boot/src/main/java/sample/camel/SampleCamelRouter.java
@@ -0,0 +1,42 @@
+/**
+ * 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 sample.camel;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.springframework.stereotype.Component;
+
+/**
+ * A simple Camel route that triggers from a timer and calls a bean and prints to system out.
+ * <p/>
+ * Use <tt>@Component</tt> to make Camel auto detect this route when starting.
+ */
+@Component
+public class SampleCamelRouter extends RouteBuilder {
+
+    @Override
+    public void configure() throws Exception {
+        validator()
+            .type("greeting")
+            .withBean("greetingValidator");
+        
+        from("timer:hello?period={{timer.period}}")
+            .outputType("greeting", true)
+            .transform(method("myBean", "saySomething"))
+            .to("stream:out");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/examples/camel-example-validator-spring-boot/src/main/resources/application.properties
----------------------------------------------------------------------
diff --git a/examples/camel-example-validator-spring-boot/src/main/resources/application.properties b/examples/camel-example-validator-spring-boot/src/main/resources/application.properties
new file mode 100644
index 0000000..1d32a64
--- /dev/null
+++ b/examples/camel-example-validator-spring-boot/src/main/resources/application.properties
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+
+# the name of Camel
+camel.springboot.name = SampleCamel
+
+# properties used in the Camel route and beans
+# --------------------------------------------
+
+# what to say
+greeting = Hello World
+
+# how often to trigger the timer
+timer.period = 2000

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/examples/camel-example-validator-spring-boot/src/test/java/sample/camel/SampleCamelApplicationTest.java
----------------------------------------------------------------------
diff --git a/examples/camel-example-validator-spring-boot/src/test/java/sample/camel/SampleCamelApplicationTest.java b/examples/camel-example-validator-spring-boot/src/test/java/sample/camel/SampleCamelApplicationTest.java
new file mode 100644
index 0000000..7d53276
--- /dev/null
+++ b/examples/camel-example-validator-spring-boot/src/test/java/sample/camel/SampleCamelApplicationTest.java
@@ -0,0 +1,47 @@
+/**
+ * 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 sample.camel;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.NotifyBuilder;
+import org.apache.camel.test.spring.CamelSpringBootRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import static org.junit.Assert.assertTrue;
+
+@RunWith(CamelSpringBootRunner.class)
+@SpringBootTest(classes = SampleCamelApplication.class)
+public class SampleCamelApplicationTest {
+
+    @Autowired
+    private CamelContext camelContext;
+
+    @Test
+    public void shouldProduceMessages() throws Exception {
+        // we expect that one or more messages is automatic done by the Camel
+        // route as it uses a timer to trigger
+        NotifyBuilder notify = new NotifyBuilder(camelContext).whenDone(1).create();
+
+        assertTrue(notify.matches(10, TimeUnit.SECONDS));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/examples/pom.xml
----------------------------------------------------------------------
diff --git a/examples/pom.xml b/examples/pom.xml
index a0c31a1..05a2e98 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -110,6 +110,7 @@
     <module>camel-example-twitter-salesforce</module>
     <module>camel-example-twitter-websocket</module>
     <module>camel-example-twitter-websocket-blueprint</module>
+    <module>camel-example-validator-spring-boot</module>
     <module>camel-example-widget-gadget-cdi</module>
     <module>camel-example-widget-gadget-java</module>
     <module>camel-example-widget-gadget-xml</module>

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractLocalCamelController.java
----------------------------------------------------------------------
diff --git a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractLocalCamelController.java b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractLocalCamelController.java
index a4d33d4..f37d85b 100644
--- a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractLocalCamelController.java
+++ b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/AbstractLocalCamelController.java
@@ -47,6 +47,7 @@ import org.apache.camel.spi.ManagementAgent;
 import org.apache.camel.spi.RestRegistry;
 import org.apache.camel.spi.RuntimeEndpointRegistry;
 import org.apache.camel.spi.Transformer;
+import org.apache.camel.spi.Validator;
 import org.apache.camel.util.JsonSchemaHelper;
 
 /**
@@ -646,6 +647,27 @@ public abstract class AbstractLocalCamelController extends AbstractCamelControll
         return answer;
     }
 
+    @Override
+    public List<Map<String, String>> getValidators(String camelContextName) throws Exception {
+        List<Map<String, String>> answer = new ArrayList<Map<String, String>>();
+
+        if (camelContextName != null) {
+            CamelContext context = this.getLocalCamelContext(camelContextName);
+            if (context != null) {
+                List<Validator> validators = new ArrayList<Validator>(context.getValidatorRegistry().values());
+                for (Validator validator : validators) {
+                    Map<String, String> row = new LinkedHashMap<String, String>();
+                    row.put("camelContextName", context.getName());
+                    row.put("type", validator.getType().toString());
+                    row.put("state", validator.getStatus().toString());
+                    row.put("description", validator.toString());
+                    answer.add(row);
+                }
+            }
+        }
+        return answer;
+    }
+
     private static String getEndpointState(Endpoint endpoint) {
         // must use String type to be sure remote JMX can read the attribute without requiring Camel classes.
         if (endpoint instanceof StatefulService) {

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CamelController.java
----------------------------------------------------------------------
diff --git a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CamelController.java b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CamelController.java
index 2cf70a4..67de587 100644
--- a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CamelController.java
+++ b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/CamelController.java
@@ -376,4 +376,13 @@ public interface CamelController {
      * @throws java.lang.Exception can be thrown
      */
     List<Map<String, String>> getTransformers(String camelContextName) throws Exception;
+
+    /**
+     * Return the validators
+     *
+     * @param camelContextName the Camel context.
+     * @return a list of key/value pairs with validator information
+     * @throws java.lang.Exception can be thrown
+     */
+    List<Map<String, String>> getValidators(String camelContextName) throws Exception;
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/ValidatorListCommand.java
----------------------------------------------------------------------
diff --git a/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/ValidatorListCommand.java b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/ValidatorListCommand.java
new file mode 100644
index 0000000..07608f0
--- /dev/null
+++ b/platforms/commands/commands-core/src/main/java/org/apache/camel/commands/ValidatorListCommand.java
@@ -0,0 +1,185 @@
+/**
+ * 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.commands;
+
+import java.io.PrintStream;
+import java.net.URLDecoder;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.util.JsonSchemaHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.URISupport;
+
+/**
+ * List the Camel validators available in the JVM.
+ */
+public class ValidatorListCommand extends AbstractCamelCommand {
+
+    private static final String CONTEXT_NAME_COLUMN_LABEL = "Context";
+    private static final String TYPE_COLUMN_LABEL = "Type";
+    private static final String STATE_COLUMN_LABEL = "State";
+    private static final String DESCRIPTION_COLUMN_LABEL = "Description";
+
+    private static final int DEFAULT_COLUMN_WIDTH_INCREMENT = 0;
+    private static final String DEFAULT_FIELD_PREAMBLE = " ";
+    private static final String DEFAULT_FIELD_POSTAMBLE = " ";
+    private static final String DEFAULT_HEADER_PREAMBLE = " ";
+    private static final String DEFAULT_HEADER_POSTAMBLE = " ";
+    private static final int DEFAULT_FORMAT_BUFFER_LENGTH = 24;
+    // endpoint uris can be very long so clip by default after 120 chars
+    private static final int MAX_COLUMN_WIDTH = 120;
+    private static final int MIN_COLUMN_WIDTH = 12;
+
+    boolean decode = true;
+    boolean verbose;
+    boolean explain;
+    private final String context;
+
+    public ValidatorListCommand(String context, boolean decode, boolean verbose, boolean explain) {
+        this.decode = decode;
+        this.verbose = verbose;
+        this.explain = explain;
+        this.context = context;
+    }
+
+    @Override
+    public Object execute(CamelController camelController, PrintStream out, PrintStream err) throws Exception {
+        final List<Map<String, String>> camelContextInfos = camelController.getCamelContexts(this.context);
+        final Map<String, List<Map<String, String>>> contextsToValidators = new HashMap<>();
+        
+        for (Map<String, String> camelContextInfo : camelContextInfos) {
+            String camelContextName = camelContextInfo.get("name");
+            final List<Map<String, String>> validators = camelController.getValidators(camelContextName);
+            if (validators.isEmpty()) {
+                continue;
+            }
+            contextsToValidators.put(camelContextName, validators);
+        }
+
+        final Map<String, Integer> columnWidths = computeColumnWidths(contextsToValidators);
+        final String headerFormat = buildFormatString(columnWidths, true);
+        final String rowFormat = buildFormatString(columnWidths, false);
+
+        for (Map.Entry<String, List<Map<String, String>>> stringListEntry : contextsToValidators.entrySet()) {
+            final String camelContextName = stringListEntry.getKey();
+            final List<Map<String, String>> validators = stringListEntry.getValue();
+
+            if (verbose) {
+                out.println(String.format(headerFormat, CONTEXT_NAME_COLUMN_LABEL, TYPE_COLUMN_LABEL, STATE_COLUMN_LABEL, DESCRIPTION_COLUMN_LABEL));
+                out.println(String.format(headerFormat, "-------", "----", "-----", "-----------"));
+            } else {
+                out.println(String.format(headerFormat, CONTEXT_NAME_COLUMN_LABEL, TYPE_COLUMN_LABEL, STATE_COLUMN_LABEL));
+                out.println(String.format(headerFormat, "-------", "----", "-----"));
+            }
+            for (Map<String, String> row : validators) {
+                String type = row.get("type");
+                String state = row.get("state");
+                if (verbose) {
+                    String desc = row.get("description");
+                    out.println(String.format(rowFormat, camelContextName, type, state, desc));
+                } else {
+                    out.println(String.format(rowFormat, camelContextName, type, state));
+                }
+            }
+        }
+        return null;
+    }
+
+    private Map<String, Integer> computeColumnWidths(final Map<String, List<Map<String, String>>> contextsToValidators) throws Exception {
+        int maxCamelContextLen = 0;
+        int maxTypeLen = 0;
+        int maxStatusLen = 0;
+        int maxDescLen = 0;
+
+        for (Map.Entry<String, List<Map<String, String>>> stringListEntry : contextsToValidators.entrySet()) {
+            final String camelContextName = stringListEntry.getKey();
+
+            maxCamelContextLen = java.lang.Math.max(maxCamelContextLen, camelContextName.length());
+            
+            final List<Map<String, String>> validators = stringListEntry.getValue();
+
+
+            for (Map<String, String> row : validators) {
+                String type = row.get("type");
+                maxTypeLen = java.lang.Math.max(maxTypeLen, type == null ? 0 : type.length());
+                String status = row.get("state");
+                maxStatusLen = java.lang.Math.max(maxStatusLen, status == null ? 0 : status.length());
+                if (verbose) {
+                    String desc = row.get("description");
+                    maxDescLen = java.lang.Math.max(maxDescLen, desc == null ? 0 : desc.length());
+                }
+            }
+        }
+    
+        final Map<String, Integer> retval = new Hashtable<>();
+        retval.put(CONTEXT_NAME_COLUMN_LABEL, maxCamelContextLen);
+        retval.put(TYPE_COLUMN_LABEL, maxTypeLen);
+        retval.put(STATE_COLUMN_LABEL, maxStatusLen);
+        if (verbose) {
+            retval.put(DESCRIPTION_COLUMN_LABEL, maxDescLen);
+        }
+
+        return retval;
+    }
+
+    private String buildFormatString(final Map<String, Integer> columnWidths, final boolean isHeader) {
+        final String fieldPreamble;
+        final String fieldPostamble;
+        final int columnWidthIncrement;
+
+        if (isHeader) {
+            fieldPreamble = DEFAULT_HEADER_PREAMBLE;
+            fieldPostamble = DEFAULT_HEADER_POSTAMBLE;
+        } else {
+            fieldPreamble = DEFAULT_FIELD_PREAMBLE;
+            fieldPostamble = DEFAULT_FIELD_POSTAMBLE;
+        }
+        columnWidthIncrement = DEFAULT_COLUMN_WIDTH_INCREMENT;
+
+        int ctxLen = java.lang.Math.min(columnWidths.get(CONTEXT_NAME_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth());
+        ctxLen = Math.max(MIN_COLUMN_WIDTH, ctxLen);
+        int typeLen = java.lang.Math.min(columnWidths.get(TYPE_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth());
+        typeLen = Math.max(MIN_COLUMN_WIDTH, typeLen);
+        int stateLen = -1;
+        if (verbose) {
+            stateLen = java.lang.Math.min(columnWidths.get(STATE_COLUMN_LABEL) + columnWidthIncrement, getMaxColumnWidth());
+            stateLen = Math.max(MIN_COLUMN_WIDTH, stateLen);
+        }
+        // last row does not have min width
+
+        final StringBuilder retval = new StringBuilder(DEFAULT_FORMAT_BUFFER_LENGTH);
+        retval.append(fieldPreamble).append("%-").append(ctxLen).append('.').append(ctxLen).append('s').append(fieldPostamble).append(' ');
+        retval.append(fieldPreamble).append("%-").append(typeLen).append('.').append(typeLen).append('s').append(fieldPostamble).append(' ');
+        if (verbose) {
+            retval.append(fieldPreamble).append("%-").append(stateLen).append('.').append(stateLen).append('s').append(fieldPostamble).append(' ');
+        }
+        retval.append(fieldPreamble).append("%s").append(fieldPostamble).append(' ');
+
+        return retval.toString();
+    }
+
+    private int getMaxColumnWidth() {
+        if (verbose) {
+            return Integer.MAX_VALUE;
+        } else {
+            return MAX_COLUMN_WIDTH;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/AbstractLocalCamelControllerTest.java
----------------------------------------------------------------------
diff --git a/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/AbstractLocalCamelControllerTest.java b/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/AbstractLocalCamelControllerTest.java
index 682ac0d..896dd46 100644
--- a/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/AbstractLocalCamelControllerTest.java
+++ b/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/AbstractLocalCamelControllerTest.java
@@ -21,11 +21,13 @@ import java.util.Map;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Message;
+import org.apache.camel.ValidationException;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.impl.ExplicitCamelContextNameStrategy;
 import org.apache.camel.spi.DataType;
 import org.apache.camel.spi.Transformer;
+import org.apache.camel.spi.Validator;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -50,6 +52,9 @@ public class AbstractLocalCamelControllerTest {
                     .fromType("xml:foo")
                     .toType("json:bar")
                     .withJava(DummyTransformer.class);
+                validator()
+                    .type("xml:foo")
+                    .withJava(DummyValidator.class);
                 from("direct:start1").id("route1").delay(100).to("mock:result1");
                 from("direct:start2").id("route2").delay(100).to("mock:result2");
                 from("direct:start3").id("route3").delay(100).to("mock:result3");
@@ -117,7 +122,6 @@ public class AbstractLocalCamelControllerTest {
 
     @Test
     public void testTransformer() throws Exception {
-        context.resolveTransformer(new DataType("xml:foo"), new DataType("json:bar"));
         List<Map<String, String>> transformers = localCamelController.getTransformers("context1");
         assertEquals(1, transformers.size());
         Map<String, String> dummyTransformer = transformers.get(0);
@@ -129,9 +133,26 @@ public class AbstractLocalCamelControllerTest {
         assertEquals("Started", dummyTransformer.get("state"));
     }
 
+    @Test
+    public void testValidator() throws Exception {
+        List<Map<String, String>> validators = localCamelController.getValidators("context1");
+        assertEquals(1, validators.size());
+        Map<String, String> dummyValidator = validators.get(0);
+        assertEquals("context1", dummyValidator.get("camelContextName"));
+        assertEquals("DummyValidator[type='xml:foo']", dummyValidator.get("description"));
+        assertEquals("xml:foo", dummyValidator.get("type"));
+        assertEquals("Started", dummyValidator.get("state"));
+    }
+
     public static class DummyTransformer extends Transformer {
         @Override
         public void transform(Message message, DataType from, DataType to) throws Exception {
         }
     }
+
+    public static class DummyValidator extends Validator {
+        @Override
+        public void validate(Message message, DataType type) throws ValidationException {
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/TransformerListCommandTest.java
----------------------------------------------------------------------
diff --git a/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/TransformerListCommandTest.java b/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/TransformerListCommandTest.java
index 5f71849..0acd9e5 100644
--- a/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/TransformerListCommandTest.java
+++ b/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/TransformerListCommandTest.java
@@ -78,18 +78,15 @@ public class TransformerListCommandTest {
         etd.setToType("json:bar");
         etd.setUri("direct:transformer");
         context.getTransformers().add(etd);
-        context.resolveTransformer(new DataType("xml:foo"), new DataType("json:bar"));
         DataFormatTransformerDefinition dftd = new DataFormatTransformerDefinition();
         dftd.setFromType(this.getClass());
         dftd.setToType("xml:test");
         dftd.setDataFormatType(new StringDataFormat());
         context.getTransformers().add(dftd);
-        context.resolveTransformer(new DataType(this.getClass()), new DataType("xml:test"));
         CustomTransformerDefinition ctd = new CustomTransformerDefinition();
         ctd.setScheme("custom");
-        ctd.setType(MyTransformer.class.getName());
+        ctd.setClassName(MyTransformer.class.getName());
         context.getTransformers().add(ctd);
-        context.resolveTransformer("custom");
         context.setNameStrategy(new ExplicitCamelContextNameStrategy("foobar"));
         context.start();
 

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/ValidatorListCommandTest.java
----------------------------------------------------------------------
diff --git a/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/ValidatorListCommandTest.java b/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/ValidatorListCommandTest.java
new file mode 100644
index 0000000..3457520
--- /dev/null
+++ b/platforms/commands/commands-core/src/test/java/org/apache/camel/commands/ValidatorListCommandTest.java
@@ -0,0 +1,121 @@
+/**
+ * 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.commands;
+
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Message;
+import org.apache.camel.ValidationException;
+import org.apache.camel.builder.ExpressionBuilder;
+import org.apache.camel.builder.PredicateBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.builder.SimpleBuilder;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.impl.ExplicitCamelContextNameStrategy;
+import org.apache.camel.model.dataformat.StringDataFormat;
+import org.apache.camel.model.language.ExpressionDefinition;
+import org.apache.camel.model.transformer.CustomTransformerDefinition;
+import org.apache.camel.model.transformer.DataFormatTransformerDefinition;
+import org.apache.camel.model.transformer.EndpointTransformerDefinition;
+import org.apache.camel.model.validator.CustomValidatorDefinition;
+import org.apache.camel.model.validator.EndpointValidatorDefinition;
+import org.apache.camel.model.validator.PredicateValidatorDefinition;
+import org.apache.camel.spi.DataType;
+import org.apache.camel.spi.Transformer;
+import org.apache.camel.spi.Validator;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class ValidatorListCommandTest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ValidatorListCommandTest.class);
+
+    @Test
+    public void testValidatorList() throws Exception {
+        String out = doTest(false);
+        assertTrue(out.contains("xml:foo"));
+        assertTrue(out.contains("java:" + this.getClass().getName()));
+        assertTrue(out.contains("custom"));
+        assertTrue(out.contains("Started"));
+        assertFalse(out.contains("ProcessorValidator["));
+        assertFalse(out.contains("processor='validate(body)'"));
+        assertFalse(out.contains("processor='sendTo(direct://validator)'"));
+        assertFalse(out.contains("MyValidator["));
+    }
+    
+    @Test
+    public void testValidatorListVerbose() throws Exception {
+        String out = doTest(true);
+        assertTrue(out.contains("xml:foo"));
+        assertTrue(out.contains("java:" + this.getClass().getName()));
+        assertTrue(out.contains("custom"));
+        assertTrue(out.contains("Started"));
+        assertTrue(out.contains("ProcessorValidator["));
+        assertTrue(out.contains("processor='validate(body)'"));
+        assertTrue(out.contains("processor='sendTo(direct://validator)'"));
+        assertTrue(out.contains("MyValidator["));
+    }
+    
+    private String doTest(boolean verbose) throws Exception {
+        CamelContext context = new DefaultCamelContext();
+        EndpointValidatorDefinition evd = new EndpointValidatorDefinition();
+        evd.setType("xml:foo");
+        evd.setUri("direct:validator");
+        context.getValidators().add(evd);
+        PredicateValidatorDefinition pvd = new PredicateValidatorDefinition();
+        pvd.setType(this.getClass());
+        pvd.setExpression(new ExpressionDefinition(ExpressionBuilder.bodyExpression()));
+        context.getValidators().add(pvd);
+        CustomValidatorDefinition cvd = new CustomValidatorDefinition();
+        cvd.setType("custom");
+        cvd.setClassName(MyValidator.class.getName());
+        context.getValidators().add(cvd);
+        context.setNameStrategy(new ExplicitCamelContextNameStrategy("foobar"));
+        context.start();
+
+        CamelController controller = new DummyCamelController(context);
+
+        OutputStream os = new ByteArrayOutputStream();
+        PrintStream ps = new PrintStream(os);
+
+        ValidatorListCommand command = new ValidatorListCommand(null, false, verbose, false);
+        command.execute(controller, ps, null);
+
+        String out = os.toString();
+        assertNotNull(out);
+        LOG.info("\n\n{}\n", out);
+
+        context.stop();
+        return out;
+    }
+
+    public static class MyValidator extends Validator {
+        @Override
+        public void validate(Message message, DataType type) throws ValidationException {
+            return;
+        }
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/camel/blob/f9946b2e/platforms/commands/commands-jolokia/src/main/java/org/apache/camel/commands/jolokia/DefaultJolokiaCamelController.java
----------------------------------------------------------------------
diff --git a/platforms/commands/commands-jolokia/src/main/java/org/apache/camel/commands/jolokia/DefaultJolokiaCamelController.java b/platforms/commands/commands-jolokia/src/main/java/org/apache/camel/commands/jolokia/DefaultJolokiaCamelController.java
index e342840..cf30c39 100644
--- a/platforms/commands/commands-jolokia/src/main/java/org/apache/camel/commands/jolokia/DefaultJolokiaCamelController.java
+++ b/platforms/commands/commands-jolokia/src/main/java/org/apache/camel/commands/jolokia/DefaultJolokiaCamelController.java
@@ -820,6 +820,50 @@ public class DefaultJolokiaCamelController extends AbstractCamelController imple
         return answer;
     }
 
+    @Override
+    public List<Map<String, String>> getValidators(String camelContextName) throws Exception {
+        if (jolokia == null) {
+            throw new IllegalStateException("Need to connect to remote jolokia first");
+        }
+
+        List<Map<String, String>> answer = new ArrayList<Map<String, String>>();
+
+        ObjectName found = lookupCamelContext(camelContextName);
+        if (found != null) {
+            String pattern = String.format("%s:context=%s,type=services,name=DefaultValidatorRegistry", found.getDomain(), found.getKeyProperty("context"));
+            ObjectName on = ObjectName.getInstance(pattern);
+
+            J4pExecResponse response = jolokia.execute(new J4pExecRequest(on, "listValidators()"));
+            if (response != null) {
+                JSONObject data = response.getValue();
+                if (data != null) {
+                    for (Object obj : data.values()) {
+                        JSONObject data2 = (JSONObject) obj;
+                        JSONObject service = (JSONObject) data2.values().iterator().next();
+
+                        Map<String, String> row = new LinkedHashMap<String, String>();
+                        row.put("type", asString(service.get("type")));
+                        row.put("static", asString(service.get("static")));
+                        row.put("dynamic", asString(service.get("dynamic")));
+                        row.put("description", asString(service.get("description")));
+                        answer.add(row);
+                    }
+                }
+            }
+
+            // sort the list
+            Collections.sort(answer, new Comparator<Map<String, String>>() {
+                @Override
+                public int compare(Map<String, String> service1, Map<String, String> service2) {
+                    String type1 = service1.get("type");
+                    String type2 = service2.get("type");
+                    return type1.compareTo(type2);
+                }
+            });
+        }
+        return answer;
+    }
+
     private static String asKey(String attributeKey) {
         char ch = Character.toLowerCase(attributeKey.charAt(0));
         return ch + attributeKey.substring(1);