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 2016/06/15 13:44:17 UTC
[2/9] camel git commit: CAMEL-10052: Spring-boot integration tests
http://git-wip-us.apache.org/repos/asf/camel/blob/c39b9558/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/arquillian/SpringBootZipExporterDelegate.java
----------------------------------------------------------------------
diff --git a/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/arquillian/SpringBootZipExporterDelegate.java b/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/arquillian/SpringBootZipExporterDelegate.java
new file mode 100644
index 0000000..7c5a9b8
--- /dev/null
+++ b/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/arquillian/SpringBootZipExporterDelegate.java
@@ -0,0 +1,51 @@
+/**
+ * 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.itest.springboot.arquillian;
+
+import java.io.InputStream;
+
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ArchivePath;
+import org.jboss.shrinkwrap.api.Node;
+import org.jboss.shrinkwrap.impl.base.exporter.AbstractExporterDelegate;
+
+/**
+ * A spring-boot compatible zip exporter delegate.
+ * Uses {@link SpringBootZipOnDemandInputStream} not to compress entries for spring-boot
+ * nested jar structure compatibility.
+ */
+public class SpringBootZipExporterDelegate extends AbstractExporterDelegate<InputStream> {
+
+ protected SpringBootZipExporterDelegate(final Archive<?> archive) {
+ super(archive);
+
+ if (archive.getContent().isEmpty()) {
+ throw new IllegalArgumentException("Cannot export a ZIP archive with no content: " + archive.toString());
+ }
+ }
+
+ @Override
+ protected void processNode(final ArchivePath path, final Node node) {
+ // do nothing
+ }
+
+ @Override
+ protected InputStream getResult() {
+ return new SpringBootZipOnDemandInputStream(getArchive());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c39b9558/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/arquillian/SpringBootZipExporterImpl.java
----------------------------------------------------------------------
diff --git a/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/arquillian/SpringBootZipExporterImpl.java b/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/arquillian/SpringBootZipExporterImpl.java
new file mode 100644
index 0000000..920fbe5
--- /dev/null
+++ b/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/arquillian/SpringBootZipExporterImpl.java
@@ -0,0 +1,45 @@
+/**
+ * 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.itest.springboot.arquillian;
+
+import java.io.InputStream;
+
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+import org.jboss.shrinkwrap.impl.base.exporter.AbstractExporterDelegate;
+import org.jboss.shrinkwrap.impl.base.exporter.AbstractStreamExporterImpl;
+
+/**
+ * An implementation of the zip exporter that does not compress entries,
+ * for compatibility with spring-boot nested jar structure.
+ */
+public class SpringBootZipExporterImpl extends AbstractStreamExporterImpl implements ZipExporter {
+
+ public SpringBootZipExporterImpl(Archive<?> archive) {
+ super(archive);
+ }
+
+ @Override
+ public InputStream exportAsInputStream() {
+ // Create export delegate
+ final AbstractExporterDelegate<InputStream> exportDelegate = new SpringBootZipExporterDelegate(this.getArchive());
+
+ // Export and get result
+ return exportDelegate.export();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c39b9558/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/arquillian/SpringBootZipOnDemandInputStream.java
----------------------------------------------------------------------
diff --git a/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/arquillian/SpringBootZipOnDemandInputStream.java b/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/arquillian/SpringBootZipOnDemandInputStream.java
new file mode 100644
index 0000000..70aa374
--- /dev/null
+++ b/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/arquillian/SpringBootZipOnDemandInputStream.java
@@ -0,0 +1,224 @@
+/**
+ * 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.itest.springboot.arquillian;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.zip.CRC32;
+import java.util.zip.Deflater;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ArchivePath;
+import org.jboss.shrinkwrap.api.Node;
+import org.jboss.shrinkwrap.api.exporter.ArchiveExportException;
+import org.jboss.shrinkwrap.impl.base.io.IOUtil;
+import org.jboss.shrinkwrap.impl.base.path.PathUtil;
+
+/**
+ * A spring-boot compatible on-demand input stream.
+ * It does not compress jar entries for spring-boot nested jar structure compatibility.
+ */
+public class SpringBootZipOnDemandInputStream extends InputStream {
+
+ /**
+ * Created by abstract method.
+ */
+ protected ZipOutputStream outputStream;
+
+ /**
+ * Iterator over nodes contained in base archive.
+ */
+ private final Iterator<Node> nodesIterator;
+
+ /**
+ * Base for outputStream.
+ */
+ private final ByteArrayOutputStream bufferedOutputStream = new ByteArrayOutputStream();
+
+ /**
+ * Stream of currently processed Node.
+ */
+ private InputStream currentNodeStream;
+
+ /**
+ * Stream to the buffer.
+ */
+ private ByteArrayInputStream bufferInputStream;
+
+ /**
+ * If output stream was closed - we should finish.
+ */
+ private boolean outputStreamClosed;
+
+ /**
+ * Currently processed archive path - for displaying exception.
+ */
+ private ArchivePath currentPath;
+
+ /**
+ * Creates stream directly from archive.
+ *
+ * @param archive
+ */
+ public SpringBootZipOnDemandInputStream(final Archive<?> archive) {
+ final Collection<Node> nodes = archive.getContent().values();
+ this.nodesIterator = nodes.iterator();
+ }
+
+ @Override
+ public int read() throws IOException {
+
+ if (outputStream == null && !outputStreamClosed) {
+ // first run
+ outputStream = createOutputStream(bufferedOutputStream);
+ }
+
+ int value = bufferInputStream != null ? bufferInputStream.read() : -1;
+ if (value == -1) {
+ if (currentNodeStream != null) {
+ // current node was not processed completely
+ try {
+ doCopy();
+ bufferInputStream = new ByteArrayInputStream(bufferedOutputStream.toByteArray());
+ bufferedOutputStream.reset();
+ return this.read();
+ } catch (final Throwable t) {
+ throw new ArchiveExportException("Failed to write asset to output: " + currentPath.get(), t);
+ }
+ } else if (nodesIterator.hasNext()) {
+ // current node was processed completely, process next one
+ final Node currentNode = nodesIterator.next();
+
+ currentPath = currentNode.getPath();
+ final String pathName = PathUtil.optionallyRemovePrecedingSlash(currentPath.get());
+
+ final boolean isDirectory = currentNode.getAsset() == null;
+ String resolvedPath = pathName;
+
+ if (isDirectory) {
+ resolvedPath = PathUtil.optionallyAppendSlash(resolvedPath);
+ startAsset(resolvedPath, 0L, 0L);
+ endAsset();
+ } else {
+
+ try {
+ byte[] content = IOUtil.asByteArray(currentNode.getAsset().openStream());
+ long size = content.length;
+ CRC32 crc = new CRC32();
+ crc.update(content);
+ long crc32Value = crc.getValue();
+ startAsset(resolvedPath, size, crc32Value);
+
+ currentNodeStream = new ByteArrayInputStream(content);
+ doCopy();
+ } catch (final Throwable t) {
+ throw new ArchiveExportException("Failed to write asset to output: " + currentPath.get(), t);
+ }
+ bufferInputStream = new ByteArrayInputStream(bufferedOutputStream.toByteArray());
+ bufferedOutputStream.reset();
+ }
+
+ } else {
+ // each node was processed
+ if (!outputStreamClosed) {
+ outputStream.close();
+ outputStreamClosed = true;
+
+ // output closed, now process what was saved on close
+ bufferInputStream = new ByteArrayInputStream(bufferedOutputStream.toByteArray());
+ bufferedOutputStream.close();
+
+ currentNodeStream = null;
+ outputStream = null;
+ return this.read();
+ }
+
+ // everything was read, end
+ return -1;
+ }
+
+ // chosen new node or new data in buffer - read again
+ return this.read();
+ }
+
+ return value;
+ }
+
+ /**
+ * Performs copy operation between currentNodeStream and outputStream using buffer length.
+ *
+ * @throws IOException
+ */
+ private void doCopy() throws IOException {
+ IOUtil.copy(currentNodeStream, outputStream);
+ currentNodeStream.close();
+ currentNodeStream = null;
+ endAsset();
+ }
+
+ /**
+ * Start entry in stream.
+ *
+ * @param path
+ * @throws IOException
+ */
+ private void startAsset(final String path, long size, long crc32) throws IOException {
+ putNextEntry(outputStream, path, size, crc32);
+ }
+
+ /**
+ * Close entry in stream.
+ *
+ * @throws IOException
+ */
+ private void endAsset() throws IOException {
+ closeEntry(outputStream);
+ }
+
+
+ protected ZipOutputStream createOutputStream(final OutputStream outputStream) {
+ ZipOutputStream stream = new ZipOutputStream(outputStream);
+ stream.setMethod(ZipEntry.STORED);
+ stream.setLevel(Deflater.NO_COMPRESSION);
+ return stream;
+ }
+
+
+ protected void closeEntry(final ZipOutputStream outputStream) throws IOException {
+ outputStream.closeEntry();
+ }
+
+
+ protected void putNextEntry(final ZipOutputStream outputStream, final String context, long size, long crc32) throws IOException {
+
+ ZipEntry entry = new ZipEntry(context);
+ entry.setMethod(ZipEntry.STORED);
+ entry.setSize(size);
+ entry.setCrc(crc32);
+
+ outputStream.putNextEntry(entry);
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c39b9558/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/util/ArquillianPackager.java
----------------------------------------------------------------------
diff --git a/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/util/ArquillianPackager.java b/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/util/ArquillianPackager.java
new file mode 100644
index 0000000..c9d9e9f
--- /dev/null
+++ b/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/util/ArquillianPackager.java
@@ -0,0 +1,237 @@
+/**
+ * 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.itest.springboot.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import org.apache.camel.itest.springboot.ITestConfig;
+import org.apache.camel.itest.springboot.arquillian.SpringBootZipExporterImpl;
+import org.apache.commons.io.FileUtils;
+import org.jboss.arquillian.container.se.api.ClassPath;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.Configuration;
+import org.jboss.shrinkwrap.api.ConfigurationBuilder;
+import org.jboss.shrinkwrap.api.Domain;
+import org.jboss.shrinkwrap.api.ExtensionLoader;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.FileAsset;
+import org.jboss.shrinkwrap.api.exporter.ZipExporter;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.jboss.shrinkwrap.impl.base.ServiceExtensionLoader;
+import org.jboss.shrinkwrap.resolver.api.maven.Maven;
+import org.jboss.shrinkwrap.resolver.api.maven.MavenResolvedArtifact;
+import org.jboss.shrinkwrap.resolver.api.maven.PackagingType;
+import org.jboss.shrinkwrap.resolver.api.maven.ScopeType;
+import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenCoordinate;
+import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenCoordinates;
+import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenDependencies;
+import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenDependency;
+import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenDependencyExclusion;
+import org.junit.Assert;
+
+/**
+ * Packages a module in a spring-boot compatible nested-jar structure.
+ */
+public final class ArquillianPackager {
+
+ /**
+ * A flag to enable system-out logging.
+ * Cannot use logging libraries here.
+ */
+ private static final boolean DEBUG_ENABLED = false;
+
+ private ArquillianPackager() {
+ }
+
+ public static Archive<?> springBootPackage(ITestConfig config) throws Exception {
+
+ ExtensionLoader extensionLoader = new ServiceExtensionLoader(Collections.singleton(getExtensionClassloader()));
+ extensionLoader.addOverride(ZipExporter.class, SpringBootZipExporterImpl.class);
+ ConfigurationBuilder builder = new ConfigurationBuilder().extensionLoader(extensionLoader);
+ Configuration conf = builder.build();
+
+ Domain domain = ShrinkWrap.createDomain(conf);
+
+ JavaArchive ark = domain.getArchiveFactory().create(JavaArchive.class, "test.jar");
+
+ ark = ark.addAsManifestResource("BOOT-MANIFEST.MF", "MANIFEST.MF");
+ ark = ark.addAsResource("spring-boot-itest.properties");
+
+ ark = ark.addAsDirectories("/lib");
+
+ String version = config.getMavenVersion();
+ if (version == null) {
+ // It is missing when launching from IDE
+ List<MavenResolvedArtifact> resolved = Arrays.asList(Maven.resolver().loadPomFromFile("pom.xml").importRuntimeDependencies().resolve().withTransitivity().asResolvedArtifact());
+ Optional<MavenResolvedArtifact> camelDep = resolved.stream().filter(dep -> dep.getCoordinate().getGroupId().equals("org.apache.camel")).findAny();
+ version = camelDep.map(art -> art.getCoordinate().getVersion()).orElse(null);
+ debug("Resolved version: " + version);
+ if (version == null) {
+ throw new IllegalStateException("Cannot determine the current version of the camel component");
+ }
+ }
+
+ // Test dependencies
+ List<MavenDependency> testDependencies = new LinkedList<>();
+ if (config.getIncludeTestDependencies() || config.getUnitTestEnabled()) {
+
+ List<MavenResolvedArtifact> testArtifacts = Arrays.asList(Maven.resolver()
+ .loadPomFromFile(config.getModulesPath() + config.getModuleName() + "/pom.xml")
+ .importTestDependencies()
+ .resolve().withoutTransitivity().asResolvedArtifact());
+
+ MavenDependencyExclusion[] excl = new MavenDependencyExclusion[]{MavenDependencies.createExclusion("org.slf4j", "slf4j-log4j12"), MavenDependencies.createExclusion("log4j", "log4j")};
+
+ testDependencies = testArtifacts.stream()
+ .map(MavenResolvedArtifact::getCoordinate)
+ .filter(ArquillianPackager::validTestDependency) // remove direct logging dependencies from test libs
+ .map(c -> MavenDependencies.createDependency(c, ScopeType.RUNTIME, false, excl)) // remove transitive logging dependencies from test libs
+ .collect(Collectors.toList());
+ }
+
+
+ MavenCoordinate jar = MavenCoordinates.createCoordinate(config.getMavenGroup(), config.getModuleName(), version, PackagingType.JAR, null);
+ MavenDependency dep = MavenDependencies.createDependency(jar, ScopeType.COMPILE, false);
+
+ List<File> dependencies = new LinkedList<>();
+ dependencies.addAll(Arrays.asList(Maven.resolver()
+ .loadPomFromFile("pom.xml")
+ .importRuntimeDependencies()
+ .addDependencies(dep)
+ .addDependencies(testDependencies)
+ .resolve()
+ .withTransitivity()
+ .asFile()));
+
+
+ // The spring boot-loader dependency will be added to the main jar, so it should be excluded from the embedded ones
+ excludeDependencyRegex(dependencies, "^spring-boot-loader-[0-9].*");
+
+ // Add all dependencies as spring-boot nested jars
+ ark = addDependencies(ark, dependencies);
+
+ if (config.getUnitTestEnabled()) {
+ // Add unit test classes of the module under test
+ ark = addTestResources(ark, config);
+ }
+
+ // Add common packages to main jar
+ ark = ark.addPackages(true, "org.apache.camel.itest.springboot");
+ ark = ark.addPackages(true, "org.springframework.boot.loader");
+ ark = ark.addPackages(true, "org.jboss.shrinkwrap");
+
+ return ClassPath.builder().add(ark).build();
+ }
+
+ public static void copyResource(String folder, String fileNameRegex, String targetFolder) throws IOException {
+
+ Pattern pattern = Pattern.compile(fileNameRegex);
+
+ File sourceFolder = new File(folder);
+ File[] candidates = sourceFolder.listFiles((dir, name) -> pattern.matcher(name).matches());
+ if (candidates.length == 0) {
+ Assert.fail("No file matching regex " + fileNameRegex + " has been found");
+ }
+
+ File f = candidates[0];
+ FileUtils.copyFileToDirectory(f, new File(targetFolder));
+ }
+
+ private static ClassLoader getExtensionClassloader() {
+ ClassLoader cl = AccessController.doPrivileged((PrivilegedAction<ClassLoader>) () -> Thread.currentThread().getContextClassLoader());
+ if (cl == null) {
+ cl = ClassLoader.getSystemClassLoader();
+ }
+
+ return cl;
+ }
+
+ private static boolean validTestDependency(MavenCoordinate coordinate) {
+
+ Pattern log4j = Pattern.compile("^log4j$");
+ Pattern slf4jLog4j = Pattern.compile("^slf4j-log4j12$");
+
+ boolean valid = !log4j.matcher(coordinate.getArtifactId()).matches() && !slf4jLog4j.matcher(coordinate.getArtifactId()).matches();
+
+ if (!valid) {
+ debug("Discarded test dependency " + coordinate.toCanonicalForm());
+ }
+
+ return valid;
+ }
+
+ private static void excludeDependencyRegex(List<File> dependencies, String regex) {
+ Pattern pattern = Pattern.compile(regex);
+ for (Iterator<File> it = dependencies.iterator(); it.hasNext();) {
+ File f = it.next();
+ if (pattern.matcher(f.getName()).matches()) {
+ it.remove();
+ break;
+ }
+ }
+ }
+
+ private static JavaArchive addDependencies(JavaArchive ark, Collection<File> deps) {
+ Set<File> dependencySet = new HashSet<>(deps);
+ for (File d : dependencySet) {
+ debug("Adding spring-boot dependency: " + d.getName());
+ ark = ark.add(new FileAsset(d), "/lib/" + d.getName());
+ }
+
+ return ark;
+ }
+
+ private static JavaArchive addTestResources(JavaArchive ark, ITestConfig config) throws IOException {
+ File test = new File(config.getModulesPath() + config.getModuleName() + "/target/test-classes/");
+ File[] fs = Optional.ofNullable(test.listFiles()).orElse(new File[]{});
+ LinkedList<File> testFiles = new LinkedList<>(Arrays.asList(fs));
+ while (!testFiles.isEmpty()) {
+ File f = testFiles.pop();
+ String relative = test.getCanonicalFile().toURI().relativize(f.getCanonicalFile().toURI()).getPath();
+ if (f.isFile()) {
+ ark = ark.addAsResource(f, relative);
+ } else {
+ ark = ark.addAsDirectory(relative);
+ File[] files = Optional.ofNullable(f.listFiles()).orElse(new File[]{});
+ testFiles.addAll(Arrays.asList(files));
+ }
+ }
+
+ return ark;
+ }
+
+ private static void debug(String str) {
+ if (DEBUG_ENABLED) {
+ System.out.println("DEBUG>>> " + str);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c39b9558/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/util/JarExporter.java
----------------------------------------------------------------------
diff --git a/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/util/JarExporter.java b/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/util/JarExporter.java
new file mode 100644
index 0000000..4157559
--- /dev/null
+++ b/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/util/JarExporter.java
@@ -0,0 +1,44 @@
+/**
+ * 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.itest.springboot.util;
+
+import java.io.File;
+
+import org.apache.camel.itest.springboot.ITestConfigBuilder;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.impl.base.exporter.zip.ZipExporterImpl;
+import org.junit.Test;
+
+/**
+ * Utililty to export a spring-boot jar and check the content.
+ */
+public class JarExporter {
+
+ @Test
+ public void exportJar() throws Exception {
+
+ Archive<?> archive = ArquillianPackager.springBootPackage(new ITestConfigBuilder()
+ .module("camel-jetty9")
+ .build());
+
+
+ new ZipExporterImpl(archive).exportTo(new File("target/export.zip"), true);
+
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c39b9558/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/util/SpringBootContainerFacade.java
----------------------------------------------------------------------
diff --git a/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/util/SpringBootContainerFacade.java b/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/util/SpringBootContainerFacade.java
new file mode 100644
index 0000000..190c6cb
--- /dev/null
+++ b/tests/camel-itest-spring-boot/src/test/java/org/apache/camel/itest/springboot/util/SpringBootContainerFacade.java
@@ -0,0 +1,65 @@
+/**
+ * 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.itest.springboot.util;
+
+import java.lang.reflect.Method;
+
+import org.apache.camel.itest.springboot.ITestConfig;
+
+/**
+ * Provide access to testing methods defined in the Spring-Boot context (that uses a different classloader).
+ */
+public class SpringBootContainerFacade {
+
+ private Class<?> delegateClass;
+
+ public SpringBootContainerFacade(ClassLoader springClassloader) {
+ try {
+ this.delegateClass = springClassloader.loadClass("org.apache.camel.itest.springboot.CommandRouter");
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException("Exception while loading target class", e);
+ }
+ }
+
+ public Object executeTest(String test, ITestConfig config, String component) throws Exception {
+ Object resObj = execute(test, config, component);
+ return resObj;
+ }
+
+ private Object execute(String command, Object... args) throws Exception {
+ Method method = delegateClass.getMethod("execute", String.class, byte[].class);
+ byte[] argsSer = null;
+ if (args != null) {
+ argsSer = SerializationUtils.marshal(args);
+ }
+
+ byte[] resByte = (byte[]) method.invoke(null, command, argsSer);
+ if (resByte != null) {
+ Object res = SerializationUtils.unmarshal(resByte);
+ if (res instanceof Exception) {
+ throw (Exception) res;
+ } else if (res instanceof Throwable) {
+ throw new RuntimeException((Throwable) res);
+ } else {
+ return res;
+ }
+ }
+
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/c39b9558/tests/camel-itest-spring-boot/src/test/resources/BOOT-MANIFEST.MF
----------------------------------------------------------------------
diff --git a/tests/camel-itest-spring-boot/src/test/resources/BOOT-MANIFEST.MF b/tests/camel-itest-spring-boot/src/test/resources/BOOT-MANIFEST.MF
new file mode 100644
index 0000000..b8f139f
--- /dev/null
+++ b/tests/camel-itest-spring-boot/src/test/resources/BOOT-MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: org.springframework.boot.loader.JarLauncher
+Start-Class: org.apache.camel.itest.springboot.ITestApplication
http://git-wip-us.apache.org/repos/asf/camel/blob/c39b9558/tests/camel-itest-spring-boot/src/test/resources/spring-boot-itest.properties
----------------------------------------------------------------------
diff --git a/tests/camel-itest-spring-boot/src/test/resources/spring-boot-itest.properties b/tests/camel-itest-spring-boot/src/test/resources/spring-boot-itest.properties
new file mode 100644
index 0000000..a1e2702
--- /dev/null
+++ b/tests/camel-itest-spring-boot/src/test/resources/spring-boot-itest.properties
@@ -0,0 +1,9 @@
+# Test configuration can be overriden here.
+# This file is included in the spring-boot jar built by Arquillian.
+
+# It is better disabling unit testing for all-modules-verification,
+# as many of them fail for various reasons (unrelated to spring-boot)
+# when running in the arquillian jar.
+unitTestEnabled=false
+
+includeTestDependencies=false
http://git-wip-us.apache.org/repos/asf/camel/blob/c39b9558/tests/pom.xml
----------------------------------------------------------------------
diff --git a/tests/pom.xml b/tests/pom.xml
index b21d46d..d9c6e12 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -66,6 +66,14 @@
</modules>
</profile>
+ <!-- spring-boot tests -->
+ <profile>
+ <id>spring-boot.test</id>
+ <modules>
+ <module>camel-itest-spring-boot</module>
+ </modules>
+ </profile>
+
<!-- performance tests -->
<profile>
<id>performance.test</id>