CAMEL-11659: Create a ClusteredRouteController
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/d043c7d0 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/d043c7d0 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/d043c7d0 Branch: refs/heads/master Commit: d043c7d0a7315c6c6a7971894f4574361c93289d Parents: f8ddd23 Author: lburgazzoli <lburgazz...@gmail.com> Authored: Thu Aug 10 17:27:49 2017 +0200 Committer: lburgazzoli <lburgazz...@gmail.com> Committed: Fri Aug 11 14:54:43 2017 +0200 ---------------------------------------------------------------------- .../impl/ha/ClusteredRouteConfiguration.java | 54 ++++ .../camel/impl/ha/ClusteredRouteController.java | 314 +++++++++++++++++++ .../camel/impl/ha/ClusteredRouteFilter.java | 32 ++ .../camel/impl/ha/ClusteredRouteFilters.java | 59 ++++ .../camel/impl/ha/ClusteredRoutePolicy.java | 76 ++++- .../atomix/ha/AtomixClusterClientService.java | 10 + .../atomix/ha/AtomixClusterService.java | 10 + .../component/atomix/ha/AtomixClusterView.java | 18 +- ...usteredRouteControllerAutoConfiguration.java | 101 ++++++ .../ClusteredRouteControllerConfiguration.java | 147 +++++++++ .../main/resources/META-INF/spring.factories | 1 + examples/README.adoc | 6 +- .../cluster-bootstrap/pom.xml | 77 +++++ .../examples/cluster/ClusterBootstrap.java | 41 +++ .../src/main/resources/log4j2.xml | 18 ++ .../cluster-node/pom.xml | 100 ++++++ .../camel/examples/cluster/ClusterNode.java | 36 +++ .../cluster/ClusterNodeConfiguration.java | 68 ++++ .../src/main/resources/application.properties | 31 ++ .../pom.xml | 68 ++++ .../readme.adoc | 25 ++ .../pom.xml | 154 --------- .../readme.adoc | 51 --- .../src/main/java/sample/camel/Application.java | 37 --- .../java/sample/camel/ApplicationRoutes.java | 52 --- .../src/main/resources/application.properties | 46 --- .../pom.xml | 154 +++++++++ .../readme.adoc | 51 +++ .../src/main/java/sample/camel/Application.java | 37 +++ .../java/sample/camel/ApplicationRoutes.java | 52 +++ .../src/main/resources/application.properties | 46 +++ examples/pom.xml | 3 +- .../AtomixClusterServiceAutoConfiguration.java | 96 ++++++ .../AtomixClusterServiceConfiguration.java | 151 +++++++++ .../springboot/StringToAddressConverter.java | 29 ++ .../main/resources/META-INF/spring.factories | 15 +- 36 files changed, 1903 insertions(+), 363 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRouteConfiguration.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRouteConfiguration.java b/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRouteConfiguration.java new file mode 100644 index 0000000..9cdfaeb --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRouteConfiguration.java @@ -0,0 +1,54 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.impl.ha; + +import java.time.Duration; + +import org.apache.camel.util.ObjectHelper; + +public class ClusteredRouteConfiguration implements Cloneable { + private String namespace; + private Duration initialDelay; + + public String getNamespace() { + return namespace; + } + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + public Duration getInitialDelay() { + return initialDelay; + } + + public void setInitialDelay(Duration initialDelay) { + this.initialDelay = initialDelay; + } + + // **************************************** + // Copy + // **************************************** + + public ClusteredRouteConfiguration copy() { + try { + return (ClusteredRouteConfiguration) super.clone(); + } catch (CloneNotSupportedException e) { + throw ObjectHelper.wrapRuntimeCamelException(e); + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRouteController.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRouteController.java b/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRouteController.java new file mode 100644 index 0000000..2a1849e --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRouteController.java @@ -0,0 +1,314 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.impl.ha; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import org.apache.camel.CamelContext; +import org.apache.camel.Route; +import org.apache.camel.ha.CamelClusterService; +import org.apache.camel.impl.DefaultRouteController; +import org.apache.camel.model.RouteDefinition; +import org.apache.camel.spi.RoutePolicy; +import org.apache.camel.spi.RoutePolicyFactory; +import org.apache.camel.util.ObjectHelper; +import org.apache.camel.util.ServiceHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ClusteredRouteController extends DefaultRouteController { + private static final Logger LOGGER = LoggerFactory.getLogger(ClusteredRouteController.class); + + private final Set<String> routes; + private final ConcurrentMap<String, ClusteredRouteConfiguration> configurations; + private final List<ClusteredRouteFilter> filters; + private final PolicyFactory policyFactory; + private final ClusteredRouteConfiguration defaultConfiguration; + private CamelClusterService clusterService; + + public ClusteredRouteController() { + this.routes = new CopyOnWriteArraySet<>(); + this.configurations = new ConcurrentHashMap<>(); + this.filters = new ArrayList<>(); + this.policyFactory = new PolicyFactory(); + + this.defaultConfiguration = new ClusteredRouteConfiguration(); + this.defaultConfiguration.setInitialDelay(Duration.ofMillis(0)); + } + + // ******************************* + // Properties. + // ******************************* + + /** + * Add a filter used to to filter cluster aware routes. + */ + public void addFilter(ClusteredRouteFilter filter) { + this.filters.add(filter); + } + + /** + * Sets the filters used to filter cluster aware routes. + */ + public void setFilters(Collection<ClusteredRouteFilter> filters) { + this.filters.clear(); + this.filters.addAll(filters); + } + + public Collection<ClusteredRouteFilter> getFilters() { + return Collections.unmodifiableList(filters); + } + + /** + * Add a configuration for the given route. + */ + public void addRouteConfiguration(String routeId, ClusteredRouteConfiguration configuration) { + configurations.put(routeId, configuration); + } + + /** + * Sets the configurations for the routes. + */ + public void setRoutesConfiguration(Map<String, ClusteredRouteConfiguration> configurations) { + this.configurations.clear(); + this.configurations.putAll(configurations); + } + + public Map<String, ClusteredRouteConfiguration> getRoutesConfiguration() { + return Collections.unmodifiableMap(this.configurations); + } + + public Duration getInitialDelay() { + return this.defaultConfiguration.getInitialDelay(); + } + + /** + * Set the amount of time the route controller should wait before to start + * the routes after the camel context is started. + * + * @param initialDelay the initial delay. + */ + public void setInitialDelay(Duration initialDelay) { + this.defaultConfiguration.setInitialDelay(initialDelay); + } + + public String getNamespace() { + return this.defaultConfiguration.getNamespace(); + } + + /** + * Set the default namespace. + */ + public void setNamespace(String namespace) { + this.defaultConfiguration.setNamespace(namespace); + } + + public CamelClusterService getClusterService() { + return clusterService; + } + + public void setClusterService(CamelClusterService clusterService) { + // prevent replacing the service + if (this.clusterService != null && this.clusterService != clusterService) { + throw new IllegalArgumentException("CamelClusterService is already set"); + } + + this.clusterService = clusterService; + } + + // ******************************* + // + // ******************************* + + @Override + public Collection<Route> getControlledRoutes() { + return this.routes.stream() + .map(getCamelContext()::getRoute) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + + @Override + public void doStart() throws Exception { + final CamelContext context = getCamelContext(); + + // Parameters validation + ObjectHelper.notNull(defaultConfiguration.getNamespace(), "Namespace"); + ObjectHelper.notNull(defaultConfiguration.getInitialDelay(), "initialDelay"); + ObjectHelper.notNull(context, "camelContext"); + + if (clusterService == null) { + // Finally try to grab it from the camel context. + clusterService = context.hasService(CamelClusterService.class); + } + + ObjectHelper.notNull(clusterService, "clusterService"); + + if (!ServiceHelper.isStarted(clusterService)) { + // Start the cluster service if not yet started. + clusterService.start(); + } + + super.doStart(); + } + + @Override + public void doStop() throws Exception { + if (ServiceHelper.isStarted(clusterService)) { + // Stop the cluster service. + clusterService.stop(); + } + } + + @Override + public void setCamelContext(CamelContext camelContext) { + if (!camelContext.getRoutePolicyFactories().contains(this.policyFactory)) { + camelContext.addRoutePolicyFactory(this.policyFactory); + } + + super.setCamelContext(camelContext); + } + + // ******************************* + // Route operations are disabled + // ******************************* + + @Override + public void startRoute(String routeId) throws Exception { + failIfClustered(routeId); + + // Delegate to default impl. + super.startRoute(routeId); + } + + @Override + public void stopRoute(String routeId) throws Exception { + failIfClustered(routeId); + + // Delegate to default impl. + super.stopRoute(routeId); + } + + @Override + public void stopRoute(String routeId, long timeout, TimeUnit timeUnit) throws Exception { + failIfClustered(routeId); + + // Delegate to default impl. + super.stopRoute(routeId, timeout, timeUnit); + } + + @Override + public boolean stopRoute(String routeId, long timeout, TimeUnit timeUnit, boolean abortAfterTimeout) throws Exception { + failIfClustered(routeId); + + // Delegate to default impl. + return super.stopRoute(routeId, timeout, timeUnit, abortAfterTimeout); + } + + @Override + public void suspendRoute(String routeId) throws Exception { + failIfClustered(routeId); + + // Delegate to default impl. + super.suspendRoute(routeId); + } + + @Override + public void suspendRoute(String routeId, long timeout, TimeUnit timeUnit) throws Exception { + failIfClustered(routeId); + + // Delegate to default impl. + super.suspendRoute(routeId, timeout, timeUnit); + } + + @Override + public void resumeRoute(String routeId) throws Exception { + failIfClustered(routeId); + + // Delegate to default impl. + super.resumeRoute(routeId); + } + + // ******************************* + // Helpers + // ******************************* + + private void failIfClustered(String routeId) { + // Can't perform action on routes managed by this controller as they + // are clustered and they may be part of the same view. + if (routes.contains(routeId)) { + throw new UnsupportedOperationException( + "Operation not supported as route " + routeId + " is clustered" + ); + } + } + + // ******************************* + // Factories + // ******************************* + + private final class PolicyFactory implements RoutePolicyFactory { + @Override + public RoutePolicy createRoutePolicy(CamelContext camelContext, String routeId, RouteDefinition route) { + // All the filter have to be match to include the route in the + // clustering set-up + if (filters.stream().allMatch(filter -> filter.test(camelContext, routeId, route))) { + + if (ObjectHelper.isNotEmpty(route.getRoutePolicies())) { + // Check if the route is already configured with a clustered + // route policy, in that case exclude it. + if (route.getRoutePolicies().stream().anyMatch(ClusteredRoutePolicy.class::isInstance)) { + LOGGER.debug("Route '{}' has a ClusteredRoutePolicy already set-up", routeId); + return null; + } + } + + try { + final ClusteredRouteConfiguration configuration = configurations.getOrDefault(routeId, defaultConfiguration); + final String namespace = ObjectHelper.supplyIfEmpty(configuration.getNamespace(), defaultConfiguration::getNamespace); + final Duration initialDelay = ObjectHelper.supplyIfEmpty(configuration.getInitialDelay(), defaultConfiguration::getInitialDelay); + + ClusteredRoutePolicy policy = new ClusteredRoutePolicy(clusterService.getView(namespace)); + policy.setCamelContext(getCamelContext()); + policy.setInitialDelay(initialDelay); + + LOGGER.debug("Attaching route '{}' to namespace '{}'", routeId, namespace); + + routes.add(routeId); + + return policy; + } catch (Exception e) { + throw ObjectHelper.wrapRuntimeCamelException(e); + } + } + + return null; + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRouteFilter.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRouteFilter.java b/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRouteFilter.java new file mode 100644 index 0000000..a6d3c01 --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRouteFilter.java @@ -0,0 +1,32 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.impl.ha; + +import org.apache.camel.CamelContext; +import org.apache.camel.model.RouteDefinition; + +public interface ClusteredRouteFilter { + /** + * Test if the route should be clustered or not. + * + * @param camelContext the camel context + * @param routeId the route id + * @param route the route definition + * @return true if the route should be included + */ + boolean test(CamelContext camelContext, String routeId, RouteDefinition route); +} http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRouteFilters.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRouteFilters.java b/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRouteFilters.java new file mode 100644 index 0000000..ccda0e1 --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRouteFilters.java @@ -0,0 +1,59 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.impl.ha; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.apache.camel.CamelContext; +import org.apache.camel.model.RouteDefinition; +import org.apache.camel.util.ObjectHelper; + +public final class ClusteredRouteFilters { + private ClusteredRouteFilters() { + } + + public static final class IsAutoStartup implements ClusteredRouteFilter { + @Override + public boolean test(CamelContext camelContext, String routeId, RouteDefinition route) { + try { + return route.isAutoStartup(camelContext); + } catch (Exception e) { + throw ObjectHelper.wrapRuntimeCamelException(e); + } + } + } + + public static final class BlackList implements ClusteredRouteFilter { + private final Set<String> names; + + public BlackList(String name) { + this(Collections.singletonList(name)); + } + + public BlackList(Collection<String> names) { + this.names = new HashSet<>(names); + } + + @Override + public boolean test(CamelContext camelContext, String routeId, RouteDefinition route) { + return !names.contains(routeId); + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRoutePolicy.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRoutePolicy.java b/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRoutePolicy.java index 542b15b..e85b3bf 100644 --- a/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRoutePolicy.java +++ b/camel-core/src/main/java/org/apache/camel/impl/ha/ClusteredRoutePolicy.java @@ -16,14 +16,19 @@ */ package org.apache.camel.impl.ha; +import java.time.Duration; import java.util.EventObject; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; import org.apache.camel.Route; +import org.apache.camel.ServiceStatus; import org.apache.camel.StartupListener; import org.apache.camel.api.management.ManagedAttribute; import org.apache.camel.api.management.ManagedResource; @@ -39,7 +44,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; @ManagedResource(description = "Clustered Route policy using") -public final class ClusteredRoutePolicy extends RoutePolicySupport implements CamelContextAware { +public class ClusteredRoutePolicy extends RoutePolicySupport implements CamelContextAware { private static final Logger LOGGER = LoggerFactory.getLogger(ClusteredRoutePolicy.class); private final AtomicBoolean leader; @@ -50,6 +55,8 @@ public final class ClusteredRoutePolicy extends RoutePolicySupport implements Ca private final CamelClusterEventListener.Leadership leadershipEventListener; private final CamelContextStartupListener listener; private final AtomicBoolean contextStarted; + private Duration initialDelay; + private ScheduledExecutorService executorService; private CamelContext camelContext; @@ -61,6 +68,7 @@ public final class ClusteredRoutePolicy extends RoutePolicySupport implements Ca this.startedRoutes = new HashSet<>(); this.leader = new AtomicBoolean(false); this.contextStarted = new AtomicBoolean(false); + this.initialDelay = Duration.ofMillis(0); try { this.listener = new CamelContextStartupListener(); @@ -74,6 +82,9 @@ public final class ClusteredRoutePolicy extends RoutePolicySupport implements Ca this.refCount = ReferenceCount.onRelease(() -> { if (camelContext != null) { camelContext.getManagementStrategy().removeEventNotifier(listener); + if (executorService != null) { + camelContext.getExecutorServiceManager().shutdownNow(executorService); + } } clusterView.removeEventListener(leadershipEventListener); @@ -102,11 +113,24 @@ public final class ClusteredRoutePolicy extends RoutePolicySupport implements Ca this.camelContext = camelContext; this.camelContext.addStartupListener(this.listener); this.camelContext.getManagementStrategy().addEventNotifier(this.listener); + this.executorService = camelContext.getExecutorServiceManager().newSingleThreadScheduledExecutor(this, "ClusteredRoutePolicy"); } catch (Exception e) { throw new RuntimeException(e); } } + public Duration getInitialDelay() { + return initialDelay; + } + + public void setInitialDelay(Duration initialDelay) { + this.initialDelay = initialDelay; + } + + // **************************************************** + // life-cycle + // **************************************************** + @Override public void onInit(Route route) { super.onInit(route); @@ -121,7 +145,7 @@ public final class ClusteredRoutePolicy extends RoutePolicySupport implements Ca } @Override - public void doShutdown() { + public void doShutdown() throws Exception { this.refCount.release(); } @@ -159,11 +183,19 @@ public final class ClusteredRoutePolicy extends RoutePolicySupport implements Ca } private void doStartManagedRoutes() { + if (!isRunAllowed()) { + return; + } + try { for (Route route : stoppedRoutes) { - LOGGER.debug("Starting route {}", route.getId()); - camelContext.startRoute(route.getId()); - startedRoutes.add(route); + ServiceStatus status = route.getRouteContext().getRoute().getStatus(getCamelContext()); + if (status.isStartable()) { + LOGGER.debug("Starting route '{}'", route.getId()); + camelContext.startRoute(route.getId()); + + startedRoutes.add(route); + } } stoppedRoutes.removeAll(startedRoutes); @@ -183,11 +215,19 @@ public final class ClusteredRoutePolicy extends RoutePolicySupport implements Ca } private void doStopManagedRoutes() { + if (!isRunAllowed()) { + return; + } + try { for (Route route : startedRoutes) { - LOGGER.debug("Stopping route {}", route.getId()); - stopRoute(route); - stoppedRoutes.add(route); + ServiceStatus status = route.getRouteContext().getRoute().getStatus(getCamelContext()); + if (status.isStoppable()) { + LOGGER.debug("Stopping route '{}'", route.getId()); + stopRoute(route); + + stoppedRoutes.add(route); + } } startedRoutes.removeAll(stoppedRoutes); @@ -196,6 +236,16 @@ public final class ClusteredRoutePolicy extends RoutePolicySupport implements Ca } } + private void onCamelContextStarted() { + LOGGER.debug("Apply cluster policy (stopped-routes='{}', started-routes='{}')", + stoppedRoutes.stream().map(Route::getId).collect(Collectors.joining(",")), + startedRoutes.stream().map(Route::getId).collect(Collectors.joining(",")) + ); + + clusterView.addEventListener(leadershipEventListener); + setLeader(clusterView.getLocalMember().isMaster()); + } + // **************************************************** // Event handling // **************************************************** @@ -240,8 +290,14 @@ public final class ClusteredRoutePolicy extends RoutePolicySupport implements Ca // so start/stop of managed routes do not clash with CamelContext // startup if (contextStarted.compareAndSet(false, true)) { - clusterView.addEventListener(leadershipEventListener); - setLeader(clusterView.getLocalMember().isMaster()); + + // Eventually delay the startup of the routes a later time + if (initialDelay.toMillis() > 0) { + LOGGER.debug("Policy will be effective in {}", initialDelay); + executorService.schedule(ClusteredRoutePolicy.this::onCamelContextStarted, initialDelay.toMillis(), TimeUnit.MILLISECONDS); + } else { + ClusteredRoutePolicy.this.onCamelContextStarted(); + } } } } http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/components/camel-atomix/src/main/java/org/apache/camel/component/atomix/ha/AtomixClusterClientService.java ---------------------------------------------------------------------- diff --git a/components/camel-atomix/src/main/java/org/apache/camel/component/atomix/ha/AtomixClusterClientService.java b/components/camel-atomix/src/main/java/org/apache/camel/component/atomix/ha/AtomixClusterClientService.java index 6194f81..6df320f 100644 --- a/components/camel-atomix/src/main/java/org/apache/camel/component/atomix/ha/AtomixClusterClientService.java +++ b/components/camel-atomix/src/main/java/org/apache/camel/component/atomix/ha/AtomixClusterClientService.java @@ -113,6 +113,16 @@ public final class AtomixClusterClientService extends AbstractCamelClusterServic } @Override + protected void doStop() throws Exception { + super.doStop(); + + if (atomix != null) { + LOGGER.debug("Shutdown atomix client {}", atomix); + atomix.close().join(); + } + } + + @Override protected AtomixClusterView createView(String namespace) throws Exception { return new AtomixClusterView(this, namespace, getOrCreateClient(), configuration); } http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/components/camel-atomix/src/main/java/org/apache/camel/component/atomix/ha/AtomixClusterService.java ---------------------------------------------------------------------- diff --git a/components/camel-atomix/src/main/java/org/apache/camel/component/atomix/ha/AtomixClusterService.java b/components/camel-atomix/src/main/java/org/apache/camel/component/atomix/ha/AtomixClusterService.java index 3faf79e..b2315ae 100644 --- a/components/camel-atomix/src/main/java/org/apache/camel/component/atomix/ha/AtomixClusterService.java +++ b/components/camel-atomix/src/main/java/org/apache/camel/component/atomix/ha/AtomixClusterService.java @@ -143,6 +143,16 @@ public final class AtomixClusterService extends AbstractCamelClusterService<Atom } @Override + protected void doStop() throws Exception { + super.doStop(); + + if (atomix != null) { + LOGGER.debug("Shutdown atomix replica {}", atomix); + atomix.shutdown().join(); + } + } + + @Override protected AtomixClusterView createView(String namespace) throws Exception { return new AtomixClusterView(this, namespace, getOrCreateReplica(), configuration); } http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/components/camel-atomix/src/main/java/org/apache/camel/component/atomix/ha/AtomixClusterView.java ---------------------------------------------------------------------- diff --git a/components/camel-atomix/src/main/java/org/apache/camel/component/atomix/ha/AtomixClusterView.java b/components/camel-atomix/src/main/java/org/apache/camel/component/atomix/ha/AtomixClusterView.java index 4f02a85..4be80a1 100644 --- a/components/camel-atomix/src/main/java/org/apache/camel/component/atomix/ha/AtomixClusterView.java +++ b/components/camel-atomix/src/main/java/org/apache/camel/component/atomix/ha/AtomixClusterView.java @@ -93,13 +93,25 @@ final class AtomixClusterView extends AbstractCamelClusterView { ).get(); LOGGER.debug("Listen election events"); - group.election().onElection(term -> fireLeadershipChangedEvent(new AtomixClusterMember(term.leader()))); + group.election().onElection(term -> { + if (isRunAllowed()) { + fireLeadershipChangedEvent(new AtomixClusterMember(term.leader())); + } + }); LOGGER.debug("Listen join events"); - group.onJoin(member -> fireMemberAddedEvent(new AtomixClusterMember(member))); + group.onJoin(member -> { + if (isRunAllowed()) { + fireMemberAddedEvent(new AtomixClusterMember(member)); + } + }); LOGGER.debug("Listen leave events"); - group.onLeave(member -> fireMemberRemovedEvent(new AtomixClusterMember(member))); + group.onLeave(member -> { + if (isRunAllowed()) { + fireMemberRemovedEvent(new AtomixClusterMember(member)); + } + }); LOGGER.debug("Join group {}", getNamespace()); localMember.join(); http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/ha/ClusteredRouteControllerAutoConfiguration.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/ha/ClusteredRouteControllerAutoConfiguration.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/ha/ClusteredRouteControllerAutoConfiguration.java new file mode 100644 index 0000000..29be993 --- /dev/null +++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/ha/ClusteredRouteControllerAutoConfiguration.java @@ -0,0 +1,101 @@ +/** + * 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.spring.boot.ha; + +import java.time.Duration; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.apache.camel.converter.TimePatternConverter; +import org.apache.camel.ha.CamelClusterService; +import org.apache.camel.impl.ha.ClusteredRouteConfiguration; +import org.apache.camel.impl.ha.ClusteredRouteController; +import org.apache.camel.impl.ha.ClusteredRouteFilter; +import org.apache.camel.impl.ha.ClusteredRouteFilters; +import org.apache.camel.spi.RouteController; +import org.apache.camel.spring.boot.CamelAutoConfiguration; +import org.apache.camel.util.ObjectHelper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; + +@Configuration +@AutoConfigureBefore(CamelAutoConfiguration.class) +@ConditionalOnProperty(prefix = "camel.clustered.controller", name = "enabled") +@EnableConfigurationProperties(ClusteredRouteControllerConfiguration.class) +public class ClusteredRouteControllerAutoConfiguration { + @Autowired + private ClusteredRouteControllerConfiguration configuration; + @Autowired(required = false) + private List<ClusteredRouteFilter> filters = Collections.emptyList(); + + @Bean + @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON) + @ConditionalOnMissingBean + @ConditionalOnBean(CamelClusterService.class) + public RouteController routeController() { + ClusteredRouteController controller = new ClusteredRouteController(); + controller.setNamespace(configuration.getNamespace()); + + Optional.ofNullable(configuration.getInitialDelay()) + .map(TimePatternConverter::toMilliSeconds) + .map(Duration::ofMillis) + .ifPresent(controller::setInitialDelay); + + controller.setFilters(filters); + controller.addFilter(new ClusteredRouteFilters.IsAutoStartup()); + + if (ObjectHelper.isEmpty(configuration.getClusterService())) { + controller.setClusterService(configuration.getClusterService()); + } + + for (Map.Entry<String, ClusteredRouteControllerConfiguration.RouteConfiguration> entry: configuration.getRoutes().entrySet()) { + final String routeId = entry.getKey(); + final ClusteredRouteControllerConfiguration.RouteConfiguration conf = entry.getValue(); + + if (conf.isClustered()) { + ClusteredRouteConfiguration routeConfiguration = new ClusteredRouteConfiguration(); + + routeConfiguration.setNamespace( + Optional.ofNullable(conf.getNamespace()) + .orElseGet(controller::getNamespace) + ); + routeConfiguration.setInitialDelay( + Optional.ofNullable(conf.getInitialDelay()) + .map(TimePatternConverter::toMilliSeconds) + .map(Duration::ofMillis) + .orElseGet(controller::getInitialDelay) + ); + + controller.addRouteConfiguration(routeId, routeConfiguration); + } else { + controller.addFilter(new ClusteredRouteFilters.BlackList(routeId)); + } + } + + return controller; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/ha/ClusteredRouteControllerConfiguration.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/ha/ClusteredRouteControllerConfiguration.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/ha/ClusteredRouteControllerConfiguration.java new file mode 100644 index 0000000..946c20d --- /dev/null +++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/ha/ClusteredRouteControllerConfiguration.java @@ -0,0 +1,147 @@ +/** + * 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.spring.boot.ha; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.camel.ha.CamelClusterService; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "camel.clustered.controller") +public class ClusteredRouteControllerConfiguration { + /** + * Global option to enable/disable this ${@link org.apache.camel.spi.RouteController}, default is false. + */ + private boolean enabled; + + /** + * Set the amount of time the route controller should wait before to start + * the routes after the camel context is started or after the route is + * initialized if the route is created after the camel context is started. + */ + private String initialDelay; + + /** + * The default namespace. + */ + private String namespace; + + /** + * The reference to a cluster service. + */ + private String clusterServiceRef; + + /** + * The cluster service. + */ + private CamelClusterService clusterService; + + /** + * Routes configuration. + */ + private Map<String, RouteConfiguration> routes = new HashMap<>(); + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public String getInitialDelay() { + return initialDelay; + } + + public void setInitialDelay(String initialDelay) { + this.initialDelay = initialDelay; + } + + public String getNamespace() { + return namespace; + } + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + public Map<String, RouteConfiguration> getRoutes() { + return routes; + } + + public void setRoutes(Map<String, RouteConfiguration> routes) { + this.routes = routes; + } + + public CamelClusterService getClusterService() { + return clusterService; + } + + public void setClusterService(CamelClusterService clusterService) { + this.clusterService = clusterService; + } + + // ***************************************** + // Configuration Classes + // ***************************************** + + public static class RouteConfiguration { + /** + * Control if the route should be clustered or not, default is true. + */ + private boolean clustered = true; + + /** + * Set the amount of time the route controller should wait before to start + * the routes after the camel context is started or after the route is + * initialized if the route is created after the camel context is started. + */ + private String initialDelay; + + /** + * The default namespace. + */ + private String namespace; + + + public boolean isClustered() { + return clustered; + } + + public void setClustered(boolean clustered) { + this.clustered = clustered; + } + + public String getInitialDelay() { + return initialDelay; + } + + public void setInitialDelay(String initialDelay) { + this.initialDelay = initialDelay; + } + + public String getNamespace() { + return namespace; + } + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/components/camel-spring-boot/src/main/resources/META-INF/spring.factories ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/main/resources/META-INF/spring.factories b/components/camel-spring-boot/src/main/resources/META-INF/spring.factories index ac8c58e..9686cc3 100644 --- a/components/camel-spring-boot/src/main/resources/META-INF/spring.factories +++ b/components/camel-spring-boot/src/main/resources/META-INF/spring.factories @@ -26,4 +26,5 @@ org.apache.camel.spring.boot.cloud.CamelCloudServiceCallConfigurationAutoConfigu org.apache.camel.spring.boot.cloud.CamelCloudServiceDiscoveryAutoConfiguration,\ org.apache.camel.spring.boot.cloud.CamelCloudServiceFilterAutoConfiguration,\ org.apache.camel.spring.boot.cloud.CamelCloudServiceChooserAutoConfiguration,\ +org.apache.camel.spring.boot.ha.ClusteredRouteControllerAutoConfiguration,\ org.apache.camel.spring.boot.security.CamelSSLAutoConfiguration http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/examples/README.adoc ---------------------------------------------------------------------- diff --git a/examples/README.adoc b/examples/README.adoc index bb2568c..1f10378 100644 --- a/examples/README.adoc +++ b/examples/README.adoc @@ -11,7 +11,7 @@ View the individual example READMEs for details. ### Examples // examples: START -Number of Examples: 96 (8 deprecated) +Number of Examples: 97 (8 deprecated) [width="100%",cols="4,2,4",options="header"] |======================================================================= @@ -44,11 +44,13 @@ Number of Examples: 96 (8 deprecated) | link:camel-example-spring-boot/readme.adoc[Spring Boot] (camel-example-spring-boot) | Beginner | An example showing how to work with Camel and Spring Boot +| link:camel-example-spring-boot-clustered-route-controller/readme.adoc[Spring Boot Clustered Route Controller] (camel-example-spring-boot-clustered-route-controller) | Beginner | An example showing how to work with Camel's Clustered Route Controller and Spring Boot + | link:camel-example-spring-boot-live-reload/readme.adoc[Spring Boot Live Reload] (camel-example-spring-boot-live-reload) | Beginner | An example showing how to use the live reload feature of Spring Boot with Camel | link:camel-example-spring-boot-pojo/README.adoc[Spring Boot Pojo] (camel-example-spring-boot-pojo) | Beginner | An example showing how to work with Camel POJO routing with Spring Boot -| link:camel-example-spring-boot-routecontroller/readme.adoc[Spring Boot Routecontroller] (camel-example-spring-boot-routecontroller) | Beginner | An example showing how to work with Camel Route Controller and Spring Boot +| link:camel-example-spring-boot-supervising-route-controller/readme.adoc[Spring Boot Supervising Route Controller] (camel-example-spring-boot-supervising-route-controller) | Beginner | An example showing how to work with Camel's Supervising Route Controller and Spring Boot | link:camel-example-spring-javaconfig/README.md[Spring Java Config] (camel-example-spring-javaconfig) | Beginner | An example showing how to work with Camel and Spring Java Config http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/examples/camel-example-spring-boot-clustered-route-controller/cluster-bootstrap/pom.xml ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-clustered-route-controller/cluster-bootstrap/pom.xml b/examples/camel-example-spring-boot-clustered-route-controller/cluster-bootstrap/pom.xml new file mode 100644 index 0000000..f86fb3b --- /dev/null +++ b/examples/camel-example-spring-boot-clustered-route-controller/cluster-bootstrap/pom.xml @@ -0,0 +1,77 @@ +<?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>camel-example-spring-boot-clustered-route-controller</artifactId> + <version>2.20.0-SNAPSHOT</version> + </parent> + + <artifactId>camel-example-spring-boot-clustered-route-controller-cluster-bootstrap</artifactId> + <name>Camel :: Example :: Spring Boot :: Clustered Route Controller :: Cluster Bootstrap</name> + <description>Bootstrap an Atomix Cluster (single node)</description> + + <dependencies> + <dependency> + <groupId>io.atomix</groupId> + <artifactId>atomix-all</artifactId> + <version>${atomix-version}</version> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-api</artifactId> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-core</artifactId> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-slf4j-impl</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>1.6.0</version> + <executions> + <execution> + <goals> + <goal>java</goal> + </goals> + </execution> + </executions> + <configuration> + <includeProjectDependencies>true</includeProjectDependencies> + <mainClass>org.apache.camel.examples.cluster.ClusterBootstrap</mainClass> + </configuration> + </plugin> + </plugins> + </build> + +</project> http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/examples/camel-example-spring-boot-clustered-route-controller/cluster-bootstrap/src/main/java/org/apache/camel/examples/cluster/ClusterBootstrap.java ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-clustered-route-controller/cluster-bootstrap/src/main/java/org/apache/camel/examples/cluster/ClusterBootstrap.java b/examples/camel-example-spring-boot-clustered-route-controller/cluster-bootstrap/src/main/java/org/apache/camel/examples/cluster/ClusterBootstrap.java new file mode 100644 index 0000000..1115524 --- /dev/null +++ b/examples/camel-example-spring-boot-clustered-route-controller/cluster-bootstrap/src/main/java/org/apache/camel/examples/cluster/ClusterBootstrap.java @@ -0,0 +1,41 @@ +/** + * 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.examples.cluster; + +import io.atomix.AtomixReplica; +import io.atomix.catalyst.transport.Address; +import io.atomix.catalyst.transport.netty.NettyTransport; +import io.atomix.copycat.server.storage.Storage; +import io.atomix.copycat.server.storage.StorageLevel; + +public final class ClusterBootstrap { + private ClusterBootstrap() { + } + + public static void main(String[] args) { + String address = System.getProperty("cluster.address", "127.0.0.1:8700"); + + AtomixReplica.builder(new Address(address)) + .withTransport(new NettyTransport()) + .withStorage(Storage.builder() + .withStorageLevel(StorageLevel.MEMORY) + .build()) + .build() + .bootstrap() + .join(); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/examples/camel-example-spring-boot-clustered-route-controller/cluster-bootstrap/src/main/resources/log4j2.xml ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-clustered-route-controller/cluster-bootstrap/src/main/resources/log4j2.xml b/examples/camel-example-spring-boot-clustered-route-controller/cluster-bootstrap/src/main/resources/log4j2.xml new file mode 100644 index 0000000..06e8664 --- /dev/null +++ b/examples/camel-example-spring-boot-clustered-route-controller/cluster-bootstrap/src/main/resources/log4j2.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration status="INFO"> + <Appenders> + <Console name="Console" target="SYSTEM_OUT"> + <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /> + </Console> + <File name="File" fileName="target/cluster-bootstrap.log" immediateFlush="false" append="false"> + <PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> + </File> + </Appenders> + <Loggers> + <Logger name="io.atomix" level="DEBUG"/> + + <Root level="INFO"> + <AppenderRef ref="Console" /> + </Root> + </Loggers> +</Configuration> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/examples/camel-example-spring-boot-clustered-route-controller/cluster-node/pom.xml ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-clustered-route-controller/cluster-node/pom.xml b/examples/camel-example-spring-boot-clustered-route-controller/cluster-node/pom.xml new file mode 100644 index 0000000..c137031 --- /dev/null +++ b/examples/camel-example-spring-boot-clustered-route-controller/cluster-node/pom.xml @@ -0,0 +1,100 @@ +<?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>camel-example-spring-boot-clustered-route-controller</artifactId> + <version>2.20.0-SNAPSHOT</version> + </parent> + + <artifactId>camel-example-spring-boot-clustered-route-controller-cluster-node</artifactId> + <name>Camel :: Example :: Spring Boot :: Clustered Route Controller :: Cluster Node</name> + <description>Bootstrap an Camel Cluster Node</description> + + <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> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter</artifactId> + </dependency> + <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-starter-actuator</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-spring-boot-starter</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-atomix-starter</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <version>${spring-boot-version}</version> + <executions> + <execution> + <goals> + <goal>repackage</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/examples/camel-example-spring-boot-clustered-route-controller/cluster-node/src/main/java/org/apache/camel/examples/cluster/ClusterNode.java ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-clustered-route-controller/cluster-node/src/main/java/org/apache/camel/examples/cluster/ClusterNode.java b/examples/camel-example-spring-boot-clustered-route-controller/cluster-node/src/main/java/org/apache/camel/examples/cluster/ClusterNode.java new file mode 100644 index 0000000..7228dc3 --- /dev/null +++ b/examples/camel-example-spring-boot-clustered-route-controller/cluster-node/src/main/java/org/apache/camel/examples/cluster/ClusterNode.java @@ -0,0 +1,36 @@ +/** + * 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.examples.cluster; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +//CHECKSTYLE:OFF +/** + * A sample Spring Boot application that starts the Camel routes. + */ +@SpringBootApplication +public class ClusterNode { + + /** + * A main method to start this application. + */ + public static void main(String[] args) { + SpringApplication.run(ClusterNode.class, args); + } +} +//CHECKSTYLE:ON http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/examples/camel-example-spring-boot-clustered-route-controller/cluster-node/src/main/java/org/apache/camel/examples/cluster/ClusterNodeConfiguration.java ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-clustered-route-controller/cluster-node/src/main/java/org/apache/camel/examples/cluster/ClusterNodeConfiguration.java b/examples/camel-example-spring-boot-clustered-route-controller/cluster-node/src/main/java/org/apache/camel/examples/cluster/ClusterNodeConfiguration.java new file mode 100644 index 0000000..e7df7be --- /dev/null +++ b/examples/camel-example-spring-boot-clustered-route-controller/cluster-node/src/main/java/org/apache/camel/examples/cluster/ClusterNodeConfiguration.java @@ -0,0 +1,68 @@ +/** + * 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.examples.cluster; + +import java.io.IOException; +import java.net.ServerSocket; + +import org.apache.camel.builder.RouteBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ClusterNodeConfiguration { + private static final Logger LOGGER = LoggerFactory.getLogger(ClusterNodeConfiguration.class); + + @Bean + public RouteBuilder routeBuilder() { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + // This route is configured to be local (see application.properties) + // so it will be started regardless of the leadership status if + // this node. + from("timer:heartbeat?period=10s") + .routeId("heartbeat") + .log("HeartBeat route (timer) {{node.id}} ..."); + + // This route is configured to be clustered so it will be started + // by the controller only when this node is leader + from("timer:clustered?period=5s") + .routeId("clustered") + .log("Clustered route (timer) {{node.id}} ..."); + } + }; + } + + /** + * A small hack to find out the a free port so you can run multiple instances + * of the example without having to manually set the property: server.port + */ + @Bean + public EmbeddedServletContainerCustomizer containerCustomizer() { + return container -> { + try (ServerSocket socket = new ServerSocket(0)) { + LOGGER.debug("server.port: {}", socket.getLocalPort()); + container.setPort(socket.getLocalPort()); + } catch (IOException ignored) { + } + }; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/examples/camel-example-spring-boot-clustered-route-controller/cluster-node/src/main/resources/application.properties ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-clustered-route-controller/cluster-node/src/main/resources/application.properties b/examples/camel-example-spring-boot-clustered-route-controller/cluster-node/src/main/resources/application.properties new file mode 100644 index 0000000..e364efa --- /dev/null +++ b/examples/camel-example-spring-boot-clustered-route-controller/cluster-node/src/main/resources/application.properties @@ -0,0 +1,31 @@ + +debug = false + +logging.level.org.springframework = INFO +logging.level.io.atomix = DEBUG +logging.level.org.apache.camel.ha = DEBUG +logging.level.org.apache.camel.impl.ha = DEBUG +logging.level.org.apache.camel.component.atomix = DEBUG +logging.level.org.apache.camel.examples.cluster = DEBUG + +endpoints.enabled = false +endpoints.jmx.enabled = false +endpoints.health.enabled = true + +management.port = -1 + +node.id = ${random.uuid} + +camel.springboot.name = SampleClusteredRouteController +camel.springboot.jmx-enabled = false + +camel.clustered.controller.enabled = true +camel.clustered.controller.namespace = camel +camel.clustered.controller.initial-delay = 5s + +camel.clustered.controller.routes.heartbeat.clustered = false + +camel.clustered.service.atomix.enabled = true +camel.clustered.service.atomix.mode = client +camel.clustered.service.atomix.nodes = localhost:8700 +camel.clustered.service.atomix.id = ${node.id} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/examples/camel-example-spring-boot-clustered-route-controller/pom.xml ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-clustered-route-controller/pom.xml b/examples/camel-example-spring-boot-clustered-route-controller/pom.xml new file mode 100644 index 0000000..c27d554 --- /dev/null +++ b/examples/camel-example-spring-boot-clustered-route-controller/pom.xml @@ -0,0 +1,68 @@ +<?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-clustered-route-controller</artifactId> + <name>Camel :: Example :: Spring Boot :: Clustered Route Controller</name> + <description>An example showing how to work with Camel's Clustered Route Controller and Spring Boot</description> + <packaging>pom</packaging> + + <modules> + <module>cluster-bootstrap</module> + <module>cluster-node</module> + </modules> + <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> + + + + <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/d043c7d0/examples/camel-example-spring-boot-clustered-route-controller/readme.adoc ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-clustered-route-controller/readme.adoc b/examples/camel-example-spring-boot-clustered-route-controller/readme.adoc new file mode 100644 index 0000000..38cc96f --- /dev/null +++ b/examples/camel-example-spring-boot-clustered-route-controller/readme.adoc @@ -0,0 +1,25 @@ +# Camel Clustered Route Controller Example Spring Boot + +This example shows how to work with a simple Apache Camel application using Spring Boot and a Clustered Route Controller. + +## How to run + +1. build the project: ++ + mvn clean package + +2. in a shell, run the cluster node ++ + mvn -pl cluster-bootstrap exec:java + +3. in a separate shell, run the first camel node ++ + mvn -pl cluster-node spring-boot:run + +4. in a separate shell, run the second camel node ++ + mvn -pl cluster-node spring-boot:run + +## More information + +You can find more information about Apache Camel at the website: http://camel.apache.org/ http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/examples/camel-example-spring-boot-routecontroller/pom.xml ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-routecontroller/pom.xml b/examples/camel-example-spring-boot-routecontroller/pom.xml deleted file mode 100644 index b30b67e..0000000 --- a/examples/camel-example-spring-boot-routecontroller/pom.xml +++ /dev/null @@ -1,154 +0,0 @@ -<?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-routecontroller</artifactId> - <name>Camel :: Example :: Spring Boot :: Route Controller</name> - <description>An example showing how to work with Camel Route Controller 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> - - <dependency> - <groupId>org.jolokia</groupId> - <artifactId>jolokia-core</artifactId> - </dependency> - - <!-- 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> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-configuration-processor</artifactId> - <optional>true</optional> - <version>${spring-boot-version}</version> - </dependency> - - <!-- Camel --> - <dependency> - <groupId>org.apache.camel</groupId> - <artifactId>camel-spring-boot-starter</artifactId> - </dependency> - <dependency> - <groupId>org.apache.camel</groupId> - <artifactId>camel-undertow-starter</artifactId> - </dependency> - <dependency> - <groupId>org.apache.camel</groupId> - <artifactId>camel-stream-starter</artifactId> - </dependency> - - <!-- test --> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-test</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.apache.camel</groupId> - <artifactId>camel-test-spring</artifactId> - <scope>test</scope> - </dependency> - - </dependencies> - - <build> - <plugins> - <plugin> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-maven-plugin</artifactId> - <version>${spring-boot-version}</version> - <executions> - <execution> - <goals> - <goal>repackage</goal> - </goals> - </execution> - </executions> - </plugin> - </plugins> - </build> - - <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/d043c7d0/examples/camel-example-spring-boot-routecontroller/readme.adoc ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-routecontroller/readme.adoc b/examples/camel-example-spring-boot-routecontroller/readme.adoc deleted file mode 100644 index f94221d..0000000 --- a/examples/camel-example-spring-boot-routecontroller/readme.adoc +++ /dev/null @@ -1,51 +0,0 @@ -# Camel Route Controller Example Spring Boot - -This example shows how to work with a simple Apache Camel application using Spring Boot and a Route Controller. - -## How to run - -You can run this example using - - mvn spring-boot:run - -Beside JMX you can use Spring Boot Endpoints to interact with the routes: - -* To get info about the routes -+ -[source] ----- -curl -XGET -s http://localhost:8080/camel/routes ----- -+ -+* To get details about a route -++ -+[source] -+---- -+curl -XGET -s http://localhost:8080/camel/routes/{id}/detail -+---- - -* To get info about a route -+ -[source] ----- -curl -XGET -s http://localhost:8080/camel/routes/{id}/info ----- - -* To stop a route -+ -[source] ----- -curl -XPOST -s http://localhost:8080/camel/routes/{id}/stop ----- - -* To start a route -+ -[source] ----- -curl -XPOST -s http://localhost:8080/camel/routes/{id}/stop ----- - - -## 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/d043c7d0/examples/camel-example-spring-boot-routecontroller/src/main/java/sample/camel/Application.java ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-routecontroller/src/main/java/sample/camel/Application.java b/examples/camel-example-spring-boot-routecontroller/src/main/java/sample/camel/Application.java deleted file mode 100644 index 2a97fed..0000000 --- a/examples/camel-example-spring-boot-routecontroller/src/main/java/sample/camel/Application.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package sample.camel; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -//CHECKSTYLE:OFF -/** - * A sample Spring Boot application that starts the Camel routes. - */ -@SpringBootApplication -public class Application { - - /** - * A main method to start this application. - */ - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } - -} -//CHECKSTYLE:ON http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/examples/camel-example-spring-boot-routecontroller/src/main/java/sample/camel/ApplicationRoutes.java ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-routecontroller/src/main/java/sample/camel/ApplicationRoutes.java b/examples/camel-example-spring-boot-routecontroller/src/main/java/sample/camel/ApplicationRoutes.java deleted file mode 100644 index fb6e2f5..0000000 --- a/examples/camel-example-spring-boot-routecontroller/src/main/java/sample/camel/ApplicationRoutes.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package sample.camel; - -import org.apache.camel.builder.RouteBuilder; -import org.springframework.stereotype.Component; - -/** - * - */ -@Component -public class ApplicationRoutes extends RouteBuilder { - @Override - public void configure() throws Exception { - from("timer:foo?period=5s") - .id("foo") - .startupOrder(2) - .log("From timer (foo) ..."); - - from("timer:bar?period=5s") - .id("bar") - .startupOrder(1) - .log("From timer (bar) ..."); - - from("undertow:http://localhost:9011") - .id("undertow") - .log("From undertow ..."); - - from("undertow:http://localhost:9012") - .id("undertow2") - .autoStartup(false) - .log("From undertow 2..."); - - from("undertow:http://localhost:9013") - .id("undertow3") - .log("From undertow 3..."); - } -} http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/examples/camel-example-spring-boot-routecontroller/src/main/resources/application.properties ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-routecontroller/src/main/resources/application.properties b/examples/camel-example-spring-boot-routecontroller/src/main/resources/application.properties deleted file mode 100644 index 8533f6b..0000000 --- a/examples/camel-example-spring-boot-routecontroller/src/main/resources/application.properties +++ /dev/null @@ -1,46 +0,0 @@ -## --------------------------------------------------------------------------- -## Licensed to the Apache Software Foundation (ASF) under one or more -## contributor license agreements. See the NOTICE file distributed with -## this work for additional information regarding copyright ownership. -## The ASF licenses this file to You under the Apache License, Version 2.0 -## (the "License"); you may not use this file except in compliance with -## the License. You may obtain a copy of the License at -## -## http://www.apache.org/licenses/LICENSE-2.0 -## -## Unless required by applicable law or agreed to in writing, software -## distributed under the License is distributed on an "AS IS" BASIS, -## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -## See the License for the specific language governing permissions and -## limitations under the License. -## --------------------------------------------------------------------------- - -debug = false - -logging.level.org.springframework = INFO -logging.level.org.apache.camel.spring.boot = INFO -logging.level.org.apache.camel.impl = INFO -logging.level.org.apache.camel.impl.SupervisingRouteController = DEBUG -logging.level.org.apache.camel.util.backoff = DEBUG -logging.level.sample.camel = DEBUG - -endpoints.enabled = false -endpoints.jmx.enabled = false -endpoints.health.enabled = true - -# camel routes is by default enabled -# so you do not have to configure below -# endpoints.camelroutes.path = /camel/routes -# endpoints.camelroutes.enabled = true - -management.security.enabled = false - -camel.springboot.name = SampleSupervisingRouteController - -camel.supervising.controller.enabled = true -camel.supervising.controller.initial-delay = 5s -camel.supervising.controller.default-back-off.delay = 5s -camel.supervising.controller.default-back-off.max-attempts = 10 -camel.supervising.controller.routes.undertow.back-off.delay = 10s -camel.supervising.controller.routes.undertow.back-off.max-attempts = 3 -camel.supervising.controller.routes.undertow3.supervise = false http://git-wip-us.apache.org/repos/asf/camel/blob/d043c7d0/examples/camel-example-spring-boot-supervising-route-controller/pom.xml ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-supervising-route-controller/pom.xml b/examples/camel-example-spring-boot-supervising-route-controller/pom.xml new file mode 100644 index 0000000..6b231fe --- /dev/null +++ b/examples/camel-example-spring-boot-supervising-route-controller/pom.xml @@ -0,0 +1,154 @@ +<?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-supervising-route-controller</artifactId> + <name>Camel :: Example :: Spring Boot :: Supervising Route Controller</name> + <description>An example showing how to work with Camel's Supervising Route Controller 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> + + <dependency> + <groupId>org.jolokia</groupId> + <artifactId>jolokia-core</artifactId> + </dependency> + + <!-- 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> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-configuration-processor</artifactId> + <optional>true</optional> + <version>${spring-boot-version}</version> + </dependency> + + <!-- Camel --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-spring-boot-starter</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-undertow-starter</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-stream-starter</artifactId> + </dependency> + + <!-- test --> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-test-spring</artifactId> + <scope>test</scope> + </dependency> + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <version>${spring-boot-version}</version> + <executions> + <execution> + <goals> + <goal>repackage</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <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>