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/10/12 18:03:37 UTC
[2/6] camel git commit: Moved over camel route coverage maven plugin
to master branch.
Moved over camel route coverage maven plugin to master branch.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/f015f7b0
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/f015f7b0
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/f015f7b0
Branch: refs/heads/master
Commit: f015f7b0d3a33712454637f2d9d8f24a3743adca
Parents: 9ffb254
Author: Claus Ibsen <da...@apache.org>
Authored: Thu Oct 12 19:20:05 2017 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Thu Oct 12 19:21:23 2017 +0200
----------------------------------------------------------------------
.../mbean/RouteCoverageXmlParser.java | 17 +-
.../test/spring/CamelAnnotationsHandler.java | 25 +
.../CamelSpringBootExecutionListener.java | 11 +-
.../CamelSpringDelegatingTestContextLoader.java | 13 +
.../spring/CamelSpringTestContextLoader.java | 45 +-
...gTestContextLoaderTestExecutionListener.java | 3 +-
.../test/spring/CamelSpringTestHelper.java | 14 +-
.../camel/test/spring/EnableRouteCoverage.java | 39 ++
.../test/spring/RouteCoverageEventNotifier.java | 98 ++++
...ringRouteProcessorDumpRouteCoverageTest.java | 55 +++
.../test/spring/CamelSpringRunnerPlainTest.java | 5 +
.../camel/test/junit4/CamelTestSupport.java | 4 +-
examples/camel-example-spring-boot-xml/pom.xml | 151 ++++++
.../camel-example-spring-boot-xml/readme.adoc | 41 ++
.../src/main/java/sample/camel/SampleBean.java | 38 ++
.../sample/camel/SampleCamelApplication.java | 40 ++
.../src/main/resources/application.properties | 46 ++
.../src/main/resources/my-camel.xml | 40 ++
.../java/sample/camel/FooApplicationTest.java | 52 ++
.../camel/SampleCamelApplicationTest.java | 49 ++
examples/camel-example-spring-boot/pom.xml | 12 +
.../java/sample/camel/SampleCamelRouter.java | 7 +-
.../java/sample/camel/FooApplicationTest.java | 52 ++
.../camel/SampleCamelApplicationTest.java | 2 +
examples/pom.xml | 1 +
tooling/camel-route-parser/pom.xml | 7 +
.../apache/camel/parser/RouteBuilderParser.java | 39 ++
.../org/apache/camel/parser/XmlRouteParser.java | 57 +++
.../apache/camel/parser/graph/RenderRoute.java | 70 +++
.../helper/CamelJavaTreeParserHelper.java | 478 +++++++++++++++++++
.../parser/helper/CamelXmlTreeParserHelper.java | 134 ++++++
.../parser/helper/RouteCoverageHelper.java | 115 +++++
.../camel/parser/model/CamelNodeDetails.java | 165 +++++++
.../parser/model/CamelNodeDetailsFactory.java | 37 ++
.../apache/camel/parser/model/CoverageData.java | 39 ++
.../parser/java/MyJavaDslRouteBuilder.java | 39 ++
.../camel/parser/java/RoasterJavaDslTest.java | 77 +++
.../java/RoasterJavaDslTwoRoutesTest.java | 86 ++++
.../parser/java/TwoRoutesRouteBuilder.java | 33 ++
.../camel/parser/xml/XmlParseTreeTest.java | 58 +++
.../org/apache/camel/parser/xml/mycamel.xml | 2 +-
.../apache/camel/maven/RouteCoverageMojo.java | 408 ++++++++++++++++
.../camel/maven/model/RouteCoverageNode.java | 77 +++
43 files changed, 2764 insertions(+), 17 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/camel-core/src/main/java/org/apache/camel/management/mbean/RouteCoverageXmlParser.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/management/mbean/RouteCoverageXmlParser.java b/camel-core/src/main/java/org/apache/camel/management/mbean/RouteCoverageXmlParser.java
index 4633ece..a28ff71 100644
--- a/camel-core/src/main/java/org/apache/camel/management/mbean/RouteCoverageXmlParser.java
+++ b/camel-core/src/main/java/org/apache/camel/management/mbean/RouteCoverageXmlParser.java
@@ -96,7 +96,20 @@ public final class RouteCoverageXmlParser {
el.setAttribute("totalProcessingTime", "" + totalTime);
}
} else if ("from".equals(qName)) {
- // TODO: include the stats from the route mbean as that would be the same
+ // grab statistics from the parent route as from would be the same
+ Element parent = elementStack.peek();
+ if (parent != null) {
+ String routeId = parent.getAttribute("id");
+ ManagedRouteMBean route = camelContext.getManagedRoute(routeId, ManagedRouteMBean.class);
+ if (route != null) {
+ long total = route.getExchangesTotal();
+ el.setAttribute("exchangesTotal", "" + total);
+ long totalTime = route.getTotalProcessingTime();
+ el.setAttribute("totalProcessingTime", "" + totalTime);
+ // from is index-0
+ el.setAttribute("index", "0");
+ }
+ }
} else {
ManagedProcessorMBean processor = camelContext.getManagedProcessor(id, ManagedProcessorMBean.class);
if (processor != null) {
@@ -104,6 +117,8 @@ public final class RouteCoverageXmlParser {
el.setAttribute("exchangesTotal", "" + total);
long totalTime = processor.getTotalProcessingTime();
el.setAttribute("totalProcessingTime", "" + totalTime);
+ int index = processor.getIndex();
+ el.setAttribute("index", "" + index);
}
}
} catch (Exception e) {
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelAnnotationsHandler.java
----------------------------------------------------------------------
diff --git a/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelAnnotationsHandler.java b/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelAnnotationsHandler.java
index 8902f4f..071891f 100644
--- a/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelAnnotationsHandler.java
+++ b/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelAnnotationsHandler.java
@@ -23,6 +23,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
import org.apache.camel.component.properties.PropertiesComponent;
import org.apache.camel.impl.DefaultDebugger;
@@ -30,6 +31,7 @@ import org.apache.camel.impl.InterceptSendToMockEndpointStrategy;
import org.apache.camel.management.JmxSystemPropertyKeys;
import org.apache.camel.spi.Breakpoint;
import org.apache.camel.spi.Debugger;
+import org.apache.camel.spi.EventNotifier;
import org.apache.camel.spring.SpringCamelContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -69,6 +71,29 @@ public final class CamelAnnotationsHandler {
}
}
+ /**
+ * Handles disabling of JMX on Camel contexts based on {@link DisableJmx}.
+ *
+ * @param context the initialized Spring context
+ * @param testClass the test class being executed
+ */
+ public static void handleRouteCoverage(ConfigurableApplicationContext context, Class<?> testClass, Function testMethod) throws Exception {
+ if (testClass.isAnnotationPresent(EnableRouteCoverage.class)) {
+ System.setProperty("CamelTestRouteCoverage", "true");
+
+ CamelSpringTestHelper.doToSpringCamelContexts(context, new CamelSpringTestHelper.DoToSpringCamelContextsStrategy() {
+
+ @Override
+ public void execute(String contextName, SpringCamelContext camelContext) throws Exception {
+ LOGGER.info("Enabling RouteCoverage");
+ EventNotifier notifier = new RouteCoverageEventNotifier(testClass.getName(), testMethod);
+ camelContext.addService(notifier, true);
+ camelContext.getManagementStrategy().addEventNotifier(notifier);
+ }
+ });
+ }
+ }
+
public static void handleProvidesBreakpoint(ConfigurableApplicationContext context, Class<?> testClass) throws Exception {
Collection<Method> methods = getAllMethods(testClass);
final List<Breakpoint> breakpoints = new LinkedList<Breakpoint>();
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringBootExecutionListener.java
----------------------------------------------------------------------
diff --git a/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringBootExecutionListener.java b/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringBootExecutionListener.java
index 546462d..195f57d 100644
--- a/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringBootExecutionListener.java
+++ b/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringBootExecutionListener.java
@@ -30,7 +30,7 @@ public class CamelSpringBootExecutionListener extends AbstractTestExecutionListe
@Override
public void prepareTestInstance(TestContext testContext) throws Exception {
- LOG.info("@RunWith(CamelSpringBootJUnit4ClassRunner.class) preparing: {}", testContext.getTestClass());
+ LOG.info("@RunWith(CamelSpringBootRunner.class) preparing: {}", testContext.getTestClass());
Class<?> testClass = testContext.getTestClass();
// we are customizing the Camel context with
@@ -56,15 +56,20 @@ public class CamelSpringBootExecutionListener extends AbstractTestExecutionListe
@Override
public void beforeTestMethod(TestContext testContext) throws Exception {
- LOG.info("@RunWith(CamelSpringBootJUnit4ClassRunner.class) before: {}.{}", testContext.getTestClass(), testContext.getTestMethod().getName());
+ LOG.info("@RunWith(CamelSpringBootRunner.class) before: {}.{}", testContext.getTestClass(), testContext.getTestMethod().getName());
Class<?> testClass = testContext.getTestClass();
+ String testName = testContext.getTestMethod().getName();
+
ConfigurableApplicationContext context = (ConfigurableApplicationContext) testContext.getApplicationContext();
// mark Camel to be startable again and start Camel
System.clearProperty("skipStartingCamelContext");
- LOG.info("Initialized CamelSpringBootJUnit4ClassRunner now ready to start CamelContext");
+ // route coverage need to know the test method
+ CamelAnnotationsHandler.handleRouteCoverage(context, testClass, (String) -> testName);
+
+ LOG.info("Initialized CamelSpringBootRunner now ready to start CamelContext");
CamelAnnotationsHandler.handleCamelContextStartup(context, testClass);
}
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringDelegatingTestContextLoader.java
----------------------------------------------------------------------
diff --git a/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringDelegatingTestContextLoader.java b/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringDelegatingTestContextLoader.java
index 380fac0..aa76c15 100644
--- a/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringDelegatingTestContextLoader.java
+++ b/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringDelegatingTestContextLoader.java
@@ -16,6 +16,8 @@
*/
package org.apache.camel.test.spring;
+import java.lang.reflect.Method;
+
import org.apache.camel.management.JmxSystemPropertyKeys;
import org.apache.camel.spring.SpringCamelContext;
import org.slf4j.Logger;
@@ -77,6 +79,7 @@ public class CamelSpringDelegatingTestContextLoader extends DelegatingSmartConte
AnnotationConfigUtils.registerAnnotationConfigProcessors((BeanDefinitionRegistry) context);
// Post CamelContext(s) instantiation but pre CamelContext(s) start setup
+ CamelAnnotationsHandler.handleRouteCoverage(context, testClass, (String) -> getTestMethod().getName());
CamelAnnotationsHandler.handleProvidesBreakpoint(context, testClass);
CamelAnnotationsHandler.handleShutdownTimeout(context, testClass);
CamelAnnotationsHandler.handleMockEndpoints(context, testClass);
@@ -119,4 +122,14 @@ public class CamelSpringDelegatingTestContextLoader extends DelegatingSmartConte
return CamelSpringTestHelper.getTestClass();
}
+ /**
+ * Returns the test method under test.
+ *
+ * @return the method that is being executed
+ * @see CamelSpringTestHelper
+ */
+ protected Method getTestMethod() {
+ return CamelSpringTestHelper.getTestMethod();
+ }
+
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringTestContextLoader.java
----------------------------------------------------------------------
diff --git a/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringTestContextLoader.java b/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringTestContextLoader.java
index b595ce3..434f188 100644
--- a/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringTestContextLoader.java
+++ b/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringTestContextLoader.java
@@ -32,6 +32,7 @@ import org.apache.camel.impl.InterceptSendToMockEndpointStrategy;
import org.apache.camel.management.JmxSystemPropertyKeys;
import org.apache.camel.spi.Breakpoint;
import org.apache.camel.spi.Debugger;
+import org.apache.camel.spi.EventNotifier;
import org.apache.camel.spring.SpringCamelContext;
import org.apache.camel.test.ExcludingPackageScanClassResolver;
import org.apache.camel.test.spring.CamelSpringTestHelper.DoToSpringCamelContextsStrategy;
@@ -107,7 +108,7 @@ public class CamelSpringTestContextLoader extends AbstractContextLoader {
public ApplicationContext loadContext(String... locations) throws Exception {
Class<?> testClass = getTestClass();
-
+
if (LOG.isDebugEnabled()) {
LOG.debug("Loading ApplicationContext for locations [" + StringUtils.arrayToCommaDelimitedString(locations) + "].");
}
@@ -153,6 +154,7 @@ public class CamelSpringTestContextLoader extends AbstractContextLoader {
SpringCamelContext.setNoStart(false);
// Post CamelContext(s) instantiation but pre CamelContext(s) start setup
+ handleRouteCoverage(context, testClass);
handleProvidesBreakpoint(context, testClass);
handleShutdownTimeout(context, testClass);
handleMockEndpoints(context, testClass);
@@ -204,7 +206,6 @@ public class CamelSpringTestContextLoader extends AbstractContextLoader {
if (mergedConfig != null) {
parentContext = mergedConfig.getParentApplicationContext();
-
}
if (testClass.isAnnotationPresent(ExcludeRoutes.class)) {
@@ -258,7 +259,7 @@ public class CamelSpringTestContextLoader extends AbstractContextLoader {
*/
protected void handleDisableJmx(GenericApplicationContext context, Class<?> testClass) {
CamelSpringTestHelper.setOriginalJmxDisabledValue(System.getProperty(JmxSystemPropertyKeys.DISABLED));
-
+
if (testClass.isAnnotationPresent(DisableJmx.class)) {
if (testClass.getAnnotation(DisableJmx.class).value()) {
LOG.info("Disabling Camel JMX globally as DisableJmx annotation was found and disableJmx is set to true.");
@@ -267,12 +268,36 @@ public class CamelSpringTestContextLoader extends AbstractContextLoader {
LOG.info("Enabling Camel JMX as DisableJmx annotation was found and disableJmx is set to false.");
System.clearProperty(JmxSystemPropertyKeys.DISABLED);
}
- } else {
+ } else if (!testClass.isAnnotationPresent(EnableRouteCoverage.class)) {
+ // route coverage need JMX so do not disable it by default
LOG.info("Disabling Camel JMX globally for tests by default. Use the DisableJMX annotation to override the default setting.");
System.setProperty(JmxSystemPropertyKeys.DISABLED, "true");
}
}
-
+
+ /**
+ * Handles disabling of JMX on Camel contexts based on {@link DisableJmx}.
+ *
+ * @param context the initialized Spring context
+ * @param testClass the test class being executed
+ */
+ private void handleRouteCoverage(GenericApplicationContext context, Class<?> testClass) throws Exception {
+ if (testClass.isAnnotationPresent(EnableRouteCoverage.class)) {
+ System.setProperty("CamelTestRouteCoverage", "true");
+
+ CamelSpringTestHelper.doToSpringCamelContexts(context, new DoToSpringCamelContextsStrategy() {
+
+ @Override
+ public void execute(String contextName, SpringCamelContext camelContext) throws Exception {
+ LOG.info("Enabling RouteCoverage");
+ EventNotifier notifier = new RouteCoverageEventNotifier(testClass.getName(), (String) -> getTestMethod().getName());
+ camelContext.addService(notifier, true);
+ camelContext.getManagementStrategy().addEventNotifier(notifier);
+ }
+ });
+ }
+ }
+
/**
* Handles the processing of the {@link ProvidesBreakpoint} annotation on a test class. Exists here
* as it is needed in
@@ -504,4 +529,14 @@ public class CamelSpringTestContextLoader extends AbstractContextLoader {
protected Class<?> getTestClass() {
return CamelSpringTestHelper.getTestClass();
}
+
+ /**
+ * Returns the test method under test.
+ *
+ * @return the method that is being executed
+ * @see CamelSpringTestHelper
+ */
+ protected Method getTestMethod() {
+ return CamelSpringTestHelper.getTestMethod();
+ }
}
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringTestContextLoaderTestExecutionListener.java
----------------------------------------------------------------------
diff --git a/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringTestContextLoaderTestExecutionListener.java b/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringTestContextLoaderTestExecutionListener.java
index d8533d1..100b998 100644
--- a/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringTestContextLoaderTestExecutionListener.java
+++ b/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringTestContextLoaderTestExecutionListener.java
@@ -45,5 +45,6 @@ public class CamelSpringTestContextLoaderTestExecutionListener extends AbstractT
@Override
public void prepareTestInstance(TestContext testContext) throws Exception {
CamelSpringTestHelper.setTestClass(testContext.getTestClass());
- }
+ CamelSpringTestHelper.setTestContext(testContext);
+ }
}
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringTestHelper.java
----------------------------------------------------------------------
diff --git a/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringTestHelper.java b/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringTestHelper.java
index aa75c0e..1c426b4 100644
--- a/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringTestHelper.java
+++ b/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringTestHelper.java
@@ -27,6 +27,7 @@ import java.util.Set;
import org.apache.camel.spring.SpringCamelContext;
import org.springframework.context.ApplicationContext;
+import org.springframework.test.context.TestContext;
/**
* Helper that provides state information across the levels of Spring Test that do not expose the
@@ -41,7 +42,8 @@ public final class CamelSpringTestHelper {
private static ThreadLocal<String> originalJmxDisabledValue = new ThreadLocal<String>();
private static ThreadLocal<Class<?>> testClazz = new ThreadLocal<Class<?>>();
-
+ private static ThreadLocal<TestContext> testContext = new ThreadLocal<TestContext>();
+
private CamelSpringTestHelper() {
}
@@ -60,7 +62,15 @@ public final class CamelSpringTestHelper {
public static void setTestClass(Class<?> testClass) {
testClazz.set(testClass);
}
-
+
+ public static Method getTestMethod() {
+ return testContext.get().getTestMethod();
+ }
+
+ public static void setTestContext(TestContext context) {
+ testContext.set(context);
+ }
+
/**
* Returns all methods defined in {@code clazz} and its superclasses/interfaces.
*/
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/EnableRouteCoverage.java
----------------------------------------------------------------------
diff --git a/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/EnableRouteCoverage.java b/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/EnableRouteCoverage.java
new file mode 100644
index 0000000..13c8514
--- /dev/null
+++ b/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/EnableRouteCoverage.java
@@ -0,0 +1,39 @@
+/**
+ * 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.test.spring;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Enables dumping route coverage statistic.
+ * The route coverage status is written as xml files in the <tt>target/camel-route-coverage</tt> directory after the test has finished.
+ * <p/>
+ * This allows tooling or manual inspection of the stats, so you can generate a route trace diagram of which EIPs
+ * have been in use and which have not. Similar concepts as a code coverage report.
+ */
+@Documented
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface EnableRouteCoverage {
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/RouteCoverageEventNotifier.java
----------------------------------------------------------------------
diff --git a/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/RouteCoverageEventNotifier.java b/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/RouteCoverageEventNotifier.java
new file mode 100644
index 0000000..17b7064
--- /dev/null
+++ b/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/RouteCoverageEventNotifier.java
@@ -0,0 +1,98 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.test.spring;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.EventObject;
+import java.util.function.Function;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.api.management.mbean.ManagedCamelContextMBean;
+import org.apache.camel.management.event.CamelContextStoppingEvent;
+import org.apache.camel.support.EventNotifierSupport;
+import org.apache.camel.util.IOHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RouteCoverageEventNotifier extends EventNotifierSupport {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RouteCoverageEventNotifier.class);
+
+ private final String testClassName;
+ private final Function testMethodName;
+
+ public RouteCoverageEventNotifier(String testClassName, Function testMethodName) {
+ this.testClassName = testClassName;
+ this.testMethodName = testMethodName;
+ setIgnoreCamelContextEvents(false);
+ setIgnoreExchangeEvents(true);
+ }
+
+ @Override
+ public boolean isEnabled(EventObject event) {
+ return event instanceof CamelContextStoppingEvent;
+ }
+
+ @Override
+ public void notify(EventObject event) throws Exception {
+ CamelContext context = ((CamelContextStoppingEvent) event).getContext();
+ try {
+ String className = this.getClass().getSimpleName();
+ String dir = "target/camel-route-coverage";
+ String testName = (String) testMethodName.apply(this);
+ String name = className + "-" + testName + ".xml";
+
+ ManagedCamelContextMBean managedCamelContext = context.getManagedCamelContext();
+ if (managedCamelContext == null) {
+ LOG.warn("Cannot dump route coverage to file as JMX is not enabled. Override useJmx() method to enable JMX in the unit test classes.");
+ } else {
+ String xml = managedCamelContext.dumpRoutesCoverageAsXml();
+ String combined = "<camelRouteCoverage>\n" + gatherTestDetailsAsXml(testName) + xml + "\n</camelRouteCoverage>";
+
+ File file = new File(dir);
+ // ensure dir exists
+ file.mkdirs();
+ file = new File(dir, name);
+
+ LOG.info("Dumping route coverage to file: " + file);
+ InputStream is = new ByteArrayInputStream(combined.getBytes());
+ OutputStream os = new FileOutputStream(file, false);
+ IOHelper.copyAndCloseInput(is, os);
+ IOHelper.close(os);
+ }
+ } catch (Exception e) {
+ LOG.warn("Error during dumping route coverage statistic. This exception is ignored.", e);
+ }
+ }
+
+ /**
+ * Gathers test details as xml
+ */
+ private String gatherTestDetailsAsXml(String testName) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("<test>\n");
+ sb.append(" <class>").append(testClassName).append("</class>\n");
+ sb.append(" <method>").append(testName).append("</method>\n");
+ sb.append("</test>\n");
+ return sb.toString();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/components/camel-test-spring/src/test/java/org/apache/camel/test/spring/CamelSpringRouteProcessorDumpRouteCoverageTest.java
----------------------------------------------------------------------
diff --git a/components/camel-test-spring/src/test/java/org/apache/camel/test/spring/CamelSpringRouteProcessorDumpRouteCoverageTest.java b/components/camel-test-spring/src/test/java/org/apache/camel/test/spring/CamelSpringRouteProcessorDumpRouteCoverageTest.java
new file mode 100644
index 0000000..9374d2f
--- /dev/null
+++ b/components/camel-test-spring/src/test/java/org/apache/camel/test/spring/CamelSpringRouteProcessorDumpRouteCoverageTest.java
@@ -0,0 +1,55 @@
+/**
+ * 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.test.spring;
+
+import java.io.File;
+
+import org.apache.camel.management.ManagedManagementStrategy;
+import org.apache.camel.test.junit4.TestSupport;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+@EnableRouteCoverage
+public class CamelSpringRouteProcessorDumpRouteCoverageTest extends CamelSpringRunnerPlainTest {
+
+ @BeforeClass
+ public static void prepareFiles() throws Exception {
+ TestSupport.deleteDirectory("target/camel-route-coverage");
+ }
+
+ @Test
+ public void testJmx() throws Exception {
+ // JMX is enabled with route coverage
+ assertEquals(ManagedManagementStrategy.class, camelContext.getManagementStrategy().getClass());
+ }
+
+ @Override
+ public void testRouteCoverage() throws Exception{
+ camelContext.stop();
+ camelContext2.stop();
+
+ // there should be files
+ String[] names = new File("target/camel-route-coverage").list();
+ assertNotNull(names);
+ assertTrue(names.length > 0);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/components/camel-test-spring/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerPlainTest.java
----------------------------------------------------------------------
diff --git a/components/camel-test-spring/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerPlainTest.java b/components/camel-test-spring/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerPlainTest.java
index 17fa2d6..39b2d88 100644
--- a/components/camel-test-spring/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerPlainTest.java
+++ b/components/camel-test-spring/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerPlainTest.java
@@ -118,6 +118,11 @@ public class CamelSpringRunnerPlainTest {
assertNull(camelContext2.getDebugger());
}
+ @Test
+ public void testRouteCoverage() throws Exception {
+ // noop
+ }
+
}
// end::example[]
// END SNIPPET: e1
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/components/camel-test/src/main/java/org/apache/camel/test/junit4/CamelTestSupport.java
----------------------------------------------------------------------
diff --git a/components/camel-test/src/main/java/org/apache/camel/test/junit4/CamelTestSupport.java b/components/camel-test/src/main/java/org/apache/camel/test/junit4/CamelTestSupport.java
index 632b8b0..2206822 100644
--- a/components/camel-test/src/main/java/org/apache/camel/test/junit4/CamelTestSupport.java
+++ b/components/camel-test/src/main/java/org/apache/camel/test/junit4/CamelTestSupport.java
@@ -391,7 +391,8 @@ public abstract class CamelTestSupport extends TestSupport {
log.info("Took: " + TimeUtils.printDuration(time) + " (" + time + " millis)");
// if we should dump route stats, then write that to a file
- if (isDumpRouteCoverage()) {
+ boolean coverage = System.getProperty("CamelTestRouteCoverage", "false").equalsIgnoreCase("true") || isDumpRouteCoverage();
+ if (coverage) {
String className = this.getClass().getSimpleName();
String dir = "target/camel-route-coverage";
String name = className + "-" + getTestMethodName() + ".xml";
@@ -485,7 +486,6 @@ public abstract class CamelTestSupport extends TestSupport {
builder.append(routesSummary);
log.info(builder.toString());
-
}
/**
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/examples/camel-example-spring-boot-xml/pom.xml
----------------------------------------------------------------------
diff --git a/examples/camel-example-spring-boot-xml/pom.xml b/examples/camel-example-spring-boot-xml/pom.xml
new file mode 100644
index 0000000..3501809
--- /dev/null
+++ b/examples/camel-example-spring-boot-xml/pom.xml
@@ -0,0 +1,151 @@
+<?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.example</groupId>
+ <artifactId>examples</artifactId>
+ <version>2.20.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>camel-example-spring-boot-xml</artifactId>
+ <name>Camel :: Example :: Spring Boot XML</name>
+ <description>An example showing how to work with Camel routes in XML files and Spring Boot</description>
+
+ <properties>
+ <category>Beginner</category>
+
+ <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>
+
+ <plugin>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <!-- allows to fail if not all routes are fully covered during testing -->
+<!--
+ <configuration>
+ <failOnError>true</failOnError>
+ </configuration>
+-->
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>jdk9-build</id>
+ <activation>
+ <jdk>9</jdk>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <argLine>--add-modules java.xml.bind --add-opens java.base/java.lang=ALL-UNNAMED</argLine>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/examples/camel-example-spring-boot-xml/readme.adoc
----------------------------------------------------------------------
diff --git a/examples/camel-example-spring-boot-xml/readme.adoc b/examples/camel-example-spring-boot-xml/readme.adoc
new file mode 100644
index 0000000..72475b2
--- /dev/null
+++ b/examples/camel-example-spring-boot-xml/readme.adoc
@@ -0,0 +1,41 @@
+# Camel Example Spring Boot
+
+This example shows how to work with a simple Apache Camel application using Spring Boot.
+
+The example generates messages using timer trigger, writes them to standard output.
+
+## 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.
+
+## 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
+
+## To get info about the routes
+
+To show a summary of all the routes
+
+----
+curl -XGET -s http://localhost:8080/camel/routes
+----
+
+To show detailed information for a specific route
+
+----
+curl -XGET -s http://localhost:8080/camel/routes/{id}/info
+----
+
+
+## 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/f015f7b0/examples/camel-example-spring-boot-xml/src/main/java/sample/camel/SampleBean.java
----------------------------------------------------------------------
diff --git a/examples/camel-example-spring-boot-xml/src/main/java/sample/camel/SampleBean.java b/examples/camel-example-spring-boot-xml/src/main/java/sample/camel/SampleBean.java
new file mode 100644
index 0000000..b60ef69
--- /dev/null
+++ b/examples/camel-example-spring-boot-xml/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/f015f7b0/examples/camel-example-spring-boot-xml/src/main/java/sample/camel/SampleCamelApplication.java
----------------------------------------------------------------------
diff --git a/examples/camel-example-spring-boot-xml/src/main/java/sample/camel/SampleCamelApplication.java b/examples/camel-example-spring-boot-xml/src/main/java/sample/camel/SampleCamelApplication.java
new file mode 100644
index 0000000..a678dae
--- /dev/null
+++ b/examples/camel-example-spring-boot-xml/src/main/java/sample/camel/SampleCamelApplication.java
@@ -0,0 +1,40 @@
+/**
+ * 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;
+import org.springframework.context.annotation.ImportResource;
+
+//CHECKSTYLE:OFF
+/**
+ * A sample Spring Boot application that starts the Camel routes.
+ */
+@SpringBootApplication
+// load the spring xml file from classpath
+@ImportResource("classpath:my-camel.xml")
+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/f015f7b0/examples/camel-example-spring-boot-xml/src/main/resources/application.properties
----------------------------------------------------------------------
diff --git a/examples/camel-example-spring-boot-xml/src/main/resources/application.properties b/examples/camel-example-spring-boot-xml/src/main/resources/application.properties
new file mode 100644
index 0000000..75a10de
--- /dev/null
+++ b/examples/camel-example-spring-boot-xml/src/main/resources/application.properties
@@ -0,0 +1,46 @@
+## ---------------------------------------------------------------------------
+## 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
+
+# to automatic shutdown the JVM after a period of time
+#camel.springboot.duration-max-seconds=60
+#camel.springboot.duration-max-messages=100
+
+# add for example: &repeatCount=5 to the timer endpoint to make Camel idle
+#camel.springboot.duration-max-idle-seconds=15
+
+# properties used in the Camel route and beans
+# --------------------------------------------
+
+# what to say
+greeting = Hello World
+
+# how often to trigger the timer
+timer.period = 2000
+
+# all access to actuator endpoints without security
+management.security.enabled = false
+# turn on actuator health check
+endpoints.health.enabled = true
+
+# to configure logging levels
+#logging.level.org.springframework = INFO
+#logging.level.org.apache.camel.spring.boot = INFO
+#logging.level.org.apache.camel.impl = DEBUG
+#logging.level.sample.camel = DEBUG
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/examples/camel-example-spring-boot-xml/src/main/resources/my-camel.xml
----------------------------------------------------------------------
diff --git a/examples/camel-example-spring-boot-xml/src/main/resources/my-camel.xml b/examples/camel-example-spring-boot-xml/src/main/resources/my-camel.xml
new file mode 100644
index 0000000..3fc6e0f
--- /dev/null
+++ b/examples/camel-example-spring-boot-xml/src/main/resources/my-camel.xml
@@ -0,0 +1,40 @@
+<?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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
+
+ <camelContext id="SampleCamel" xmlns="http://camel.apache.org/schema/spring">
+ <route id="hello">
+ <from uri="timer:hello?period={{timer.period}}"/>
+ <transform>
+ <method ref="myBean" method="saySomething"/>
+ </transform>
+ <filter>
+ <simple>${body} contains 'foo'</simple>
+ <to uri="log:foo"/>
+ </filter>
+ <to uri="stream:out"/>
+ </route>
+ </camelContext>
+
+</beans>
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/examples/camel-example-spring-boot-xml/src/test/java/sample/camel/FooApplicationTest.java
----------------------------------------------------------------------
diff --git a/examples/camel-example-spring-boot-xml/src/test/java/sample/camel/FooApplicationTest.java b/examples/camel-example-spring-boot-xml/src/test/java/sample/camel/FooApplicationTest.java
new file mode 100644
index 0000000..5a71fc9
--- /dev/null
+++ b/examples/camel-example-spring-boot-xml/src/test/java/sample/camel/FooApplicationTest.java
@@ -0,0 +1,52 @@
+/**
+ * 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.apache.camel.test.spring.EnableRouteCoverage;
+import org.junit.Ignore;
+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,
+ properties = "greeting = Hello foo")
+@EnableRouteCoverage
+@Ignore // enable me to run this test as well so we can cover testing the route completely
+public class FooApplicationTest {
+
+ @Autowired
+ private CamelContext camelContext;
+
+ @Test
+ public void shouldSayFoo() 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/f015f7b0/examples/camel-example-spring-boot-xml/src/test/java/sample/camel/SampleCamelApplicationTest.java
----------------------------------------------------------------------
diff --git a/examples/camel-example-spring-boot-xml/src/test/java/sample/camel/SampleCamelApplicationTest.java b/examples/camel-example-spring-boot-xml/src/test/java/sample/camel/SampleCamelApplicationTest.java
new file mode 100644
index 0000000..f4c2fc5
--- /dev/null
+++ b/examples/camel-example-spring-boot-xml/src/test/java/sample/camel/SampleCamelApplicationTest.java
@@ -0,0 +1,49 @@
+/**
+ * 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.apache.camel.test.spring.EnableRouteCoverage;
+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)
+@EnableRouteCoverage
+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/f015f7b0/examples/camel-example-spring-boot/pom.xml
----------------------------------------------------------------------
diff --git a/examples/camel-example-spring-boot/pom.xml b/examples/camel-example-spring-boot/pom.xml
index dbf3333..3467c2a 100644
--- a/examples/camel-example-spring-boot/pom.xml
+++ b/examples/camel-example-spring-boot/pom.xml
@@ -115,6 +115,18 @@
</execution>
</executions>
</plugin>
+
+ <plugin>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <!-- allows to fail if not all routes are fully covered during testing -->
+<!--
+ <configuration>
+ <failOnError>true</failOnError>
+ </configuration>
+-->
+ </plugin>
</plugins>
</build>
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/examples/camel-example-spring-boot/src/main/java/sample/camel/SampleCamelRouter.java
----------------------------------------------------------------------
diff --git a/examples/camel-example-spring-boot/src/main/java/sample/camel/SampleCamelRouter.java b/examples/camel-example-spring-boot/src/main/java/sample/camel/SampleCamelRouter.java
index 4e0422e..4b11938 100644
--- a/examples/camel-example-spring-boot/src/main/java/sample/camel/SampleCamelRouter.java
+++ b/examples/camel-example-spring-boot/src/main/java/sample/camel/SampleCamelRouter.java
@@ -29,8 +29,11 @@ public class SampleCamelRouter extends RouteBuilder {
@Override
public void configure() throws Exception {
- from("timer:hello?period={{timer.period}}")
- .transform(method("myBean", "saySomething"))
+ from("timer:hello?period={{timer.period}}").routeId("hello")
+ .transform().method("myBean", "saySomething")
+ .filter(simple("${body} contains 'foo'"))
+ .to("log:foo")
+ .end()
.to("stream:out");
}
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/examples/camel-example-spring-boot/src/test/java/sample/camel/FooApplicationTest.java
----------------------------------------------------------------------
diff --git a/examples/camel-example-spring-boot/src/test/java/sample/camel/FooApplicationTest.java b/examples/camel-example-spring-boot/src/test/java/sample/camel/FooApplicationTest.java
new file mode 100644
index 0000000..45f2076
--- /dev/null
+++ b/examples/camel-example-spring-boot/src/test/java/sample/camel/FooApplicationTest.java
@@ -0,0 +1,52 @@
+/**
+ * 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.apache.camel.test.spring.EnableRouteCoverage;
+import org.junit.Ignore;
+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,
+ properties = "greeting = Hello foo")
+@EnableRouteCoverage
+//@Ignore // enable me to run this test as well so we can cover testing the route completely
+public class FooApplicationTest {
+
+ @Autowired
+ private CamelContext camelContext;
+
+ @Test
+ public void shouldSayFoo() 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/f015f7b0/examples/camel-example-spring-boot/src/test/java/sample/camel/SampleCamelApplicationTest.java
----------------------------------------------------------------------
diff --git a/examples/camel-example-spring-boot/src/test/java/sample/camel/SampleCamelApplicationTest.java b/examples/camel-example-spring-boot/src/test/java/sample/camel/SampleCamelApplicationTest.java
index 7d53276..f4c2fc5 100644
--- a/examples/camel-example-spring-boot/src/test/java/sample/camel/SampleCamelApplicationTest.java
+++ b/examples/camel-example-spring-boot/src/test/java/sample/camel/SampleCamelApplicationTest.java
@@ -21,6 +21,7 @@ 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.apache.camel.test.spring.EnableRouteCoverage;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -30,6 +31,7 @@ import static org.junit.Assert.assertTrue;
@RunWith(CamelSpringBootRunner.class)
@SpringBootTest(classes = SampleCamelApplication.class)
+@EnableRouteCoverage
public class SampleCamelApplicationTest {
@Autowired
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/examples/pom.xml
----------------------------------------------------------------------
diff --git a/examples/pom.xml b/examples/pom.xml
index f8cdc10..717f593 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -108,6 +108,7 @@
<module>camel-example-spring-boot-rest-swagger</module>
<module>camel-example-spring-boot-servicecall</module>
<module>camel-example-spring-boot-supervising-route-controller</module>
+ <module>camel-example-spring-boot-xml</module>
<module>camel-example-spring-cloud-servicecall</module>
<module>camel-example-spring-javaconfig</module>
<module>camel-example-spring-jms</module>
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/tooling/camel-route-parser/pom.xml
----------------------------------------------------------------------
diff --git a/tooling/camel-route-parser/pom.xml b/tooling/camel-route-parser/pom.xml
index 0f65e3e..4cfc2bd 100644
--- a/tooling/camel-route-parser/pom.xml
+++ b/tooling/camel-route-parser/pom.xml
@@ -42,6 +42,13 @@
<scope>provided</scope>
</dependency>
+ <!-- the catalog has details the parser needs to parse the Camel Java DSL -->
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-catalog</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
<!-- only test scopes for camel as we have no runtime dependency on camel -->
<dependency>
<groupId>org.apache.camel</groupId>
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/RouteBuilderParser.java
----------------------------------------------------------------------
diff --git a/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/RouteBuilderParser.java b/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/RouteBuilderParser.java
index d38e1d6..96e54b2 100644
--- a/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/RouteBuilderParser.java
+++ b/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/RouteBuilderParser.java
@@ -20,10 +20,13 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+import org.apache.camel.parser.helper.CamelJavaTreeParserHelper;
import org.apache.camel.parser.helper.CamelJavaParserHelper;
import org.apache.camel.parser.model.CamelEndpointDetails;
+import org.apache.camel.parser.model.CamelNodeDetails;
import org.apache.camel.parser.model.CamelRouteDetails;
import org.apache.camel.parser.model.CamelSimpleExpressionDetails;
import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.ASTNode;
@@ -48,6 +51,42 @@ public final class RouteBuilderParser {
}
/**
+ * Parses the java source class and build a route model (tree) of the discovered routes in the java source class.
+ *
+ * @param clazz the java source class
+ * @param baseDir the base of the source code
+ * @param fullyQualifiedFileName the fully qualified source code file name
+ * @return a list of route model (tree) of each discovered route
+ */
+ public static List<CamelNodeDetails> parseRouteBuilderTree(JavaClassSource clazz, String baseDir, String fullyQualifiedFileName,
+ boolean includeInlinedRouteBuilders) {
+
+ List<MethodSource<JavaClassSource>> methods = new ArrayList<>();
+ MethodSource<JavaClassSource> method = CamelJavaParserHelper.findConfigureMethod(clazz);
+ if (method != null) {
+ methods.add(method);
+ }
+ if (includeInlinedRouteBuilders) {
+ List<MethodSource<JavaClassSource>> inlinedMethods = CamelJavaParserHelper.findInlinedConfigureMethods(clazz);
+ if (!inlinedMethods.isEmpty()) {
+ methods.addAll(inlinedMethods);
+ }
+ }
+
+ CamelJavaTreeParserHelper parser = new CamelJavaTreeParserHelper();
+ List<CamelNodeDetails> list = new ArrayList<>();
+ for (MethodSource<JavaClassSource> configureMethod : methods) {
+ // there may be multiple route builder configure methods
+ List<CamelNodeDetails> details = parser.parseCamelRouteTree(clazz, baseDir, fullyQualifiedFileName, configureMethod);
+ list.addAll(details);
+ }
+ // we end up parsing bottom->up so reverse list
+ Collections.reverse(list);
+
+ return list;
+ }
+
+ /**
* Parses the java source class to discover Camel endpoints.
*
* @param clazz the java source class
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/XmlRouteParser.java
----------------------------------------------------------------------
diff --git a/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/XmlRouteParser.java b/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/XmlRouteParser.java
index 364cf9a..5512837 100644
--- a/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/XmlRouteParser.java
+++ b/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/XmlRouteParser.java
@@ -17,8 +17,12 @@
package org.apache.camel.parser;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.List;
+import org.apache.camel.parser.helper.CamelXmlTreeParserHelper;
+import org.apache.camel.parser.model.CamelNodeDetails;
+import org.apache.camel.parser.model.CamelNodeDetailsFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
@@ -44,6 +48,59 @@ public final class XmlRouteParser {
}
/**
+ * Parses the XML file and build a route model (tree) of the discovered routes in the XML source file.
+ *
+ * @param xml the xml file as input stream
+ * @param baseDir the base of the source code
+ * @param fullyQualifiedFileName the fully qualified source code file name
+ * @return a list of route model (tree) of each discovered route
+ */
+ public static List<CamelNodeDetails> parseXmlRouteTree(InputStream xml, String baseDir, String fullyQualifiedFileName) {
+ List<CamelNodeDetails> answer = new ArrayList<>();
+
+ // try parse it as dom
+ Document dom = null;
+ try {
+ dom = XmlLineNumberParser.parseXml(xml);
+ } catch (Exception e) {
+ // ignore as the xml file may not be valid at this point
+ }
+ if (dom != null) {
+
+ // find any from which is the start of the route
+ CamelNodeDetailsFactory nodeFactory = CamelNodeDetailsFactory.newInstance();
+
+ CamelXmlTreeParserHelper parser = new CamelXmlTreeParserHelper();
+
+ List<Node> routes = CamelXmlHelper.findAllRoutes(dom);
+ for (Node route : routes) {
+ // parse each route and build
+ String routeId = getSafeAttribute(route, "id");
+ String lineNumber = (String) route.getUserData(XmlLineNumberParser.LINE_NUMBER);
+ String lineNumberEnd = (String) route.getUserData(XmlLineNumberParser.LINE_NUMBER_END);
+
+ // we only want the relative dir name from the resource directory, eg META-INF/spring/foo.xml
+ String fileName = fullyQualifiedFileName;
+ if (fileName.startsWith(baseDir)) {
+ fileName = fileName.substring(baseDir.length() + 1);
+ }
+
+ CamelNodeDetails node = nodeFactory.newNode(null, "route");
+ node.setRouteId(routeId);
+ node.setFileName(fileName);
+ node.setLineNumber(lineNumber);
+ node.setLineNumberEnd(lineNumberEnd);
+
+ // parse the route and gather all its EIPs
+ List<CamelNodeDetails> tree = parser.parseCamelRouteTree(route, routeId, node, baseDir, fullyQualifiedFileName);
+ answer.addAll(tree);
+ }
+ }
+
+ return answer;
+ }
+
+ /**
* Parses the XML source to discover Camel endpoints.
*
* @param xml the xml file as input stream
http://git-wip-us.apache.org/repos/asf/camel/blob/f015f7b0/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/graph/RenderRoute.java
----------------------------------------------------------------------
diff --git a/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/graph/RenderRoute.java b/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/graph/RenderRoute.java
new file mode 100644
index 0000000..a1f4807
--- /dev/null
+++ b/tooling/camel-route-parser/src/main/java/org/apache/camel/parser/graph/RenderRoute.java
@@ -0,0 +1,70 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.parser.graph;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import javax.imageio.ImageIO;
+
+import org.apache.camel.parser.model.CamelNodeDetails;
+
+/**
+ * @deprecated experiment to render a route via Java image
+ */
+@Deprecated
+public class RenderRoute {
+
+ public static void main(String[] args) {
+ RenderRoute render = new RenderRoute();
+ render(null);
+ }
+
+ public static void render(CamelNodeDetails root) {
+ // TODO:
+ try {
+ int width = 200, height = 200;
+
+ // TYPE_INT_ARGB specifies the image format: 8-bit RGBA packed
+ // into integer pixels
+// BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+
+ Graphics2D ig2 = bi.createGraphics();
+
+ ig2.drawRect(10, 10, 80, 40);
+ ig2.drawLine(45, 50, 45, 80);
+ ig2.drawRect(10, 80, 80, 40);
+
+ Font font = new Font("Arial", Font.BOLD, 20);
+ ig2.setFont(font);
+ String message = "Apache Camel";
+ FontMetrics fontMetrics = ig2.getFontMetrics();
+ int stringWidth = fontMetrics.stringWidth(message);
+ int stringHeight = fontMetrics.getAscent();
+ ig2.setPaint(Color.black);
+ ig2.drawString(message, (width - stringWidth) / 2, height / 2 + stringHeight / 4);
+
+ ImageIO.write(bi, "PNG", new File("target/route.png"));
+
+ } catch (IOException ie) {
+ ie.printStackTrace();
+ }
+
+ }
+}