This is an automated email from the ASF dual-hosted git repository. acosentino pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel-spring-boot.git
The following commit(s) were added to refs/heads/master by this push: new 368c769 "CAMEL-15274:camel-spring-boot - Add back http endpoint for route information" 368c769 is described below commit 368c76981c3b189a6ef8a9959a8e2136898f6b39 Author: Kodanda Ramu Kakarla <kkaka...@kkakarla.pnq.csb> AuthorDate: Sun Jul 19 14:54:04 2020 +0530 "CAMEL-15274:camel-spring-boot - Add back http endpoint for route information" --- .../src/main/docs/spring-boot.adoc | 10 +- .../endpoint/CamelRouteControllerEndpoint.java | 54 +++ ...elRouteControllerEndpointAutoConfiguration.java | 42 ++ .../boot/actuate/endpoint/CamelRoutesEndpoint.java | 517 +++++++++++++++++++++ .../CamelRoutesEndpointAutoConfiguration.java | 52 +++ .../endpoint/CamelRoutesEndpointProperties.java | 45 ++ .../additional-spring-configuration-metadata.json | 28 ++ .../boot/actuate/endpoint/ActuatorTestRoute.java | 30 ++ .../CamelEndpointsGloballyEnabledTest.java | 48 ++ .../CamelRouteControllerEndpointEnabledTest.java | 55 +++ ...erEndpointGloballyDisabledAndReenabledTest.java | 62 +++ .../endpoint/CamelRouteControllerEndpointTest.java | 62 +++ .../endpoint/CamelRoutesEndpointEnabledTest.java | 56 +++ .../actuate/endpoint/CamelRoutesEndpointTest.java | 85 ++++ .../CamelRoutesEndpointWriteOperationTest.java | 65 +++ 15 files changed, 1210 insertions(+), 1 deletion(-) diff --git a/core/camel-spring-boot/src/main/docs/spring-boot.adoc b/core/camel-spring-boot/src/main/docs/spring-boot.adoc index 93d00c7..86fb065 100644 --- a/core/camel-spring-boot/src/main/docs/spring-boot.adoc +++ b/core/camel-spring-boot/src/main/docs/spring-boot.adoc @@ -92,7 +92,7 @@ When using spring-boot with Spring Boot make sure to use the following Maven dep ---- -The component supports 149 options, which are listed below. +The component supports 157 options, which are listed below. @@ -248,6 +248,14 @@ The component supports 149 options, which are listed below. | *camel.threadpool.pool-size* | Sets the default core pool size (threads to keep minimum in pool) | | Integer | *camel.threadpool.rejected-policy* | Sets the default handler for tasks which cannot be executed by the thread pool. | | ThreadPoolRejectedPolicy | *camel.threadpool.time-unit* | Sets the default time unit used for keep alive time | | TimeUnit +| *management.endpoint.camelroutecontroller.cache.time-to-live* | Maximum time that a response can be cached. | 0ms | Duration +| *management.endpoint.camelroutecontroller.enabled* | To turn on or off information about Camel Route Controller via actuator endpoint. | true | Boolean +| *management.endpoint.camelroutes.cache.time-to-live* | Maximum time that a response can be cached. | 0ms | Duration +| *management.endpoint.camelroutes.enabled* | | false | Boolean +| *management.endpoint.camelroutes.enabled* | Whether to enable the camelroutes endpoint. | true | Boolean +| *management.endpoint.camelroutes.enabled* | To turn on or off information about Camel Routes via actuator endpoint. | true | Boolean +| *management.endpoint.camelroutes.read-only* | Whether Camel Routes actuator is in read-only mode. If not in read-only mode then operations to start/stop routes would be enabled. | true | Boolean +| *management.info.camel.enabled* | Whether to enable Camel info. | true | Boolean |=== // spring-boot-auto-configure options: END diff --git a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRouteControllerEndpoint.java b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRouteControllerEndpoint.java new file mode 100644 index 0000000..c6d3f00 --- /dev/null +++ b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRouteControllerEndpoint.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.spring.boot.actuate.endpoint; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.camel.CamelContext; +import org.apache.camel.Route; +import org.apache.camel.spi.RouteController; +import org.springframework.boot.actuate.endpoint.annotation.Endpoint; +import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; + +/* + * {@link Endpoint} to expose {@link RouteController} information. + */ +@Endpoint(id = "camelroutecontroller", enableByDefault = true) +public class CamelRouteControllerEndpoint { + + private CamelContext camelContext; + + public CamelRouteControllerEndpoint(CamelContext camelContext) { + this.camelContext = camelContext; + } + + @ReadOperation + public List<String> getControlledRoutes() { + RouteController controller = camelContext.getRouteController(); + + if (controller != null) { + return controller.getControlledRoutes().stream() + .map(Route::getId) + .collect(Collectors.toList()); + } + + return Collections.emptyList(); + } + +} diff --git a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRouteControllerEndpointAutoConfiguration.java b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRouteControllerEndpointAutoConfiguration.java new file mode 100644 index 0000000..0b2cccd --- /dev/null +++ b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRouteControllerEndpointAutoConfiguration.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.spring.boot.actuate.endpoint; + +import org.apache.camel.CamelContext; +import org.apache.camel.spring.boot.CamelAutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/* + * Auto configuration for the {@link CamelRouteControllerEndpoint}. + */ +@Configuration +@ConditionalOnClass({CamelRouteControllerEndpoint.class}) +@ConditionalOnBean(CamelAutoConfiguration.class) +@AutoConfigureAfter(CamelAutoConfiguration.class) +public class CamelRouteControllerEndpointAutoConfiguration { + @Bean + @ConditionalOnClass(CamelContext.class) + @ConditionalOnMissingBean + public CamelRouteControllerEndpoint routeControllerEndpoint(CamelContext camelContext) { + return new CamelRouteControllerEndpoint(camelContext); + } +} diff --git a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpoint.java b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpoint.java new file mode 100644 index 0000000..1b2c34c --- /dev/null +++ b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpoint.java @@ -0,0 +1,517 @@ +/* + * 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.actuate.endpoint; + +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import org.apache.camel.CamelContext; +import org.apache.camel.ExtendedCamelContext; +import org.apache.camel.Route; +import org.apache.camel.RuntimeCamelException; +import org.apache.camel.StatefulService; +import org.apache.camel.api.management.ManagedCamelContext; +import org.apache.camel.api.management.mbean.ManagedRouteMBean; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.spi.RouteError; +import org.springframework.boot.actuate.endpoint.annotation.Endpoint; +import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; +import org.springframework.boot.actuate.endpoint.annotation.Selector; +import org.springframework.boot.actuate.endpoint.annotation.WriteOperation; +import org.springframework.lang.Nullable; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/* + * {@link Endpoint} to expose {@link org.apache.camel.Route} information. + */ +@Endpoint(id = "camelroutes", enableByDefault = true) +public class CamelRoutesEndpoint { + + private CamelContext camelContext; + private static ExtendedCamelContext extendedContext; + private static ManagedCamelContext mcontext; + private static DefaultCamelContext dcontext; + private CamelRoutesEndpointProperties properties; + + public CamelRoutesEndpoint(CamelContext camelContext, CamelRoutesEndpointProperties properties) { + this.camelContext = camelContext; + this.extendedContext = camelContext.getExtension(ExtendedCamelContext.class); + this.mcontext = camelContext.getExtension(ManagedCamelContext.class);; + this.dcontext = camelContext.getExtension(DefaultCamelContext.class); + this.properties = properties; + } + + @ReadOperation + public List<RouteEndpointInfo> readRoutes() { + return getRoutesInfo(); + } + + @ReadOperation + public Object doReadAction(@Selector String id, @Selector ReadAction action) { + switch (action) { + case DETAIL: + return getRouteDetailsInfo(id); + case INFO: + return getRouteInfo(id); + default: + throw new IllegalArgumentException("Unsupported read action " + action); + } + } + + @WriteOperation + public void doWriteAction(@Selector String id, @Selector WriteAction action, @Nullable TimeInfo timeInfo) { + if (this.properties.isReadOnly()) { + throw new IllegalArgumentException(String.format("Read only: write action %s is not allowed", action)); + } + + switch (action) { + case STOP: + stopRoute( + id, + Optional.ofNullable(timeInfo).flatMap(ti -> Optional.ofNullable(ti.getTimeout())), + Optional.of(TimeUnit.SECONDS), + Optional.ofNullable(timeInfo).flatMap(ti -> Optional.ofNullable(ti.getAbortAfterTimeout()))); + break; + case START: + startRoute(id); + break; + case RESET: + resetRoute(id); + break; + case SUSPEND: + suspendRoute(id, + Optional.ofNullable(timeInfo).flatMap(ti -> Optional.ofNullable(ti.getTimeout())), + Optional.of(TimeUnit.SECONDS)); + break; + case RESUME: + resumeRoute(id); + break; + default: + throw new IllegalArgumentException("Unsupported write action " + action); + } + } + + private RouteEndpointInfo getRouteInfo(String id) { + Route route = camelContext.getRoute(id); + if (route != null) { + return new RouteEndpointInfo(route); + } + + return null; + } + + private List<RouteEndpointInfo> getRoutesInfo() { + return camelContext.getRoutes().stream() + .map(RouteEndpointInfo::new) + .collect(Collectors.toList()); + } + + private RouteDetailsEndpointInfo getRouteDetailsInfo(String id) { + Route route = camelContext.getRoute(id); + if (route != null) { + return new RouteDetailsEndpointInfo(camelContext, route); + } + + return null; + } + + private void startRoute(String id) { + try { + camelContext.getRouteController().startRoute(id); + } catch (Exception e) { + throw new RuntimeCamelException(e); + } + } + + private void resetRoute(String id) { + try { + ManagedRouteMBean managedRouteMBean = mcontext.getManagedRoute(id, ManagedRouteMBean.class); + if (managedRouteMBean != null) { + managedRouteMBean.reset(true); + } + } catch (Exception e) { + throw new RuntimeCamelException(e); + } + } + + private void stopRoute(String id, Optional<Long> timeout, Optional<TimeUnit> timeUnit, Optional<Boolean> abortAfterTimeout) { + try { + if (timeout.isPresent()) { + camelContext.getRouteController().stopRoute(id, timeout.get(), timeUnit.orElse(TimeUnit.SECONDS), abortAfterTimeout.orElse(Boolean.TRUE)); + } else { + camelContext.getRouteController().stopRoute(id); + } + } catch (Exception e) { + throw new RuntimeCamelException(e); + } + } + + private void suspendRoute(String id, Optional<Long> timeout, Optional<TimeUnit> timeUnit) { + try { + if (timeout.isPresent()) { + camelContext.getRouteController().suspendRoute(id, timeout.get(), timeUnit.orElse(TimeUnit.SECONDS)); + } else { + camelContext.getRouteController().suspendRoute(id); + } + } catch (Exception e) { + throw new RuntimeCamelException(e); + } + } + + private void resumeRoute(String id) { + try { + camelContext.getRouteController().resumeRoute(id); + } catch (Exception e) { + throw new RuntimeCamelException(e); + } + } + + /* + * Container for exposing {@link org.apache.camel.Route} information as JSON. + */ + @JsonPropertyOrder({"id", "group", "description", "uptime", "uptimeMillis"}) + @JsonInclude(JsonInclude.Include.NON_EMPTY) + public static class RouteEndpointInfo { + + private final String id; + + private final String group; + + private final Map<String, Object> properties; + + private final String description; + + private final String uptime; + + private final long uptimeMillis; + + private final String status; + + public RouteEndpointInfo(Route route) { + this.id = route.getId(); + this.group = route.getGroup(); + this.description = route.getDescription(); + this.uptime = route.getUptime(); + this.uptimeMillis = route.getUptimeMillis(); + + if (route.getProperties() != null) { + this.properties = new HashMap<>(route.getProperties()); + } else { + this.properties = Collections.emptyMap(); + } + + if (route instanceof StatefulService) { + this.status = ((StatefulService) route).getStatus().name(); + } else { + this.status = null; + } + } + + public String getId() { + return id; + } + + public String getGroup() { + return group; + } + + public Map<String, Object> getProperties() { + return properties; + } + + public String getDescription() { + return description; + } + + public String getUptime() { + return uptime; + } + + public long getUptimeMillis() { + return uptimeMillis; + } + + public String getStatus() { + return status; + } + } + + /* + * Container for exposing {@link org.apache.camel.Route} information + * with route details as JSON. Route details are retrieved from JMX. + */ + public static class RouteDetailsEndpointInfo extends RouteEndpointInfo { + + @JsonProperty("details") + private RouteDetails routeDetails; + + public RouteDetailsEndpointInfo(final CamelContext camelContext, final Route route) { + super(route); + + if (camelContext.getManagementStrategy().getManagementAgent() != null) { + this.routeDetails = new RouteDetails(mcontext.getManagedRoute(route.getId(), ManagedRouteMBean.class)); + } + } + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + static class RouteDetails { + + private long deltaProcessingTime; + + private long exchangesInflight; + + private long exchangesTotal; + + private long externalRedeliveries; + + private long failuresHandled; + + private String firstExchangeCompletedExchangeId; + + private Date firstExchangeCompletedTimestamp; + + private String firstExchangeFailureExchangeId; + + private Date firstExchangeFailureTimestamp; + + private String lastExchangeCompletedExchangeId; + + private Date lastExchangeCompletedTimestamp; + + private String lastExchangeFailureExchangeId; + + private Date lastExchangeFailureTimestamp; + + private long lastProcessingTime; + + private String load01; + + private String load05; + + private String load15; + + private long maxProcessingTime; + + private long meanProcessingTime; + + private long minProcessingTime; + + private Long oldestInflightDuration; + + private String oldestInflightExchangeId; + + private long redeliveries; + + private long totalProcessingTime; + + private RouteError lastError; + + private boolean hasRouteController; + + RouteDetails(ManagedRouteMBean managedRoute) { + try { + this.deltaProcessingTime = managedRoute.getDeltaProcessingTime(); + this.exchangesInflight = managedRoute.getExchangesInflight(); + this.exchangesTotal = managedRoute.getExchangesTotal(); + this.externalRedeliveries = managedRoute.getExternalRedeliveries(); + this.failuresHandled = managedRoute.getFailuresHandled(); + this.firstExchangeCompletedExchangeId = managedRoute.getFirstExchangeCompletedExchangeId(); + this.firstExchangeCompletedTimestamp = managedRoute.getFirstExchangeCompletedTimestamp(); + this.firstExchangeFailureExchangeId = managedRoute.getFirstExchangeFailureExchangeId(); + this.firstExchangeFailureTimestamp = managedRoute.getFirstExchangeFailureTimestamp(); + this.lastExchangeCompletedExchangeId = managedRoute.getLastExchangeCompletedExchangeId(); + this.lastExchangeCompletedTimestamp = managedRoute.getLastExchangeCompletedTimestamp(); + this.lastExchangeFailureExchangeId = managedRoute.getLastExchangeFailureExchangeId(); + this.lastExchangeFailureTimestamp = managedRoute.getLastExchangeFailureTimestamp(); + this.lastProcessingTime = managedRoute.getLastProcessingTime(); + this.load01 = managedRoute.getLoad01(); + this.load05 = managedRoute.getLoad05(); + this.load15 = managedRoute.getLoad15(); + this.maxProcessingTime = managedRoute.getMaxProcessingTime(); + this.meanProcessingTime = managedRoute.getMeanProcessingTime(); + this.minProcessingTime = managedRoute.getMinProcessingTime(); + this.oldestInflightDuration = managedRoute.getOldestInflightDuration(); + this.oldestInflightExchangeId = managedRoute.getOldestInflightExchangeId(); + this.redeliveries = managedRoute.getRedeliveries(); + this.totalProcessingTime = managedRoute.getTotalProcessingTime(); + //this.lastError = managedRoute.getLastError(); + this.hasRouteController = managedRoute.getHasRouteController(); + } catch (Exception e) { + // Ignore + } + } + + public long getDeltaProcessingTime() { + return deltaProcessingTime; + } + + public long getExchangesInflight() { + return exchangesInflight; + } + + public long getExchangesTotal() { + return exchangesTotal; + } + + public long getExternalRedeliveries() { + return externalRedeliveries; + } + + public long getFailuresHandled() { + return failuresHandled; + } + + public String getFirstExchangeCompletedExchangeId() { + return firstExchangeCompletedExchangeId; + } + + public Date getFirstExchangeCompletedTimestamp() { + return firstExchangeCompletedTimestamp; + } + + public String getFirstExchangeFailureExchangeId() { + return firstExchangeFailureExchangeId; + } + + public Date getFirstExchangeFailureTimestamp() { + return firstExchangeFailureTimestamp; + } + + public String getLastExchangeCompletedExchangeId() { + return lastExchangeCompletedExchangeId; + } + + public Date getLastExchangeCompletedTimestamp() { + return lastExchangeCompletedTimestamp; + } + + public String getLastExchangeFailureExchangeId() { + return lastExchangeFailureExchangeId; + } + + public Date getLastExchangeFailureTimestamp() { + return lastExchangeFailureTimestamp; + } + + public long getLastProcessingTime() { + return lastProcessingTime; + } + + public String getLoad01() { + return load01; + } + + public String getLoad05() { + return load05; + } + + public String getLoad15() { + return load15; + } + + public long getMaxProcessingTime() { + return maxProcessingTime; + } + + public long getMeanProcessingTime() { + return meanProcessingTime; + } + + public long getMinProcessingTime() { + return minProcessingTime; + } + + public Long getOldestInflightDuration() { + return oldestInflightDuration; + } + + public String getOldestInflightExchangeId() { + return oldestInflightExchangeId; + } + + public long getRedeliveries() { + return redeliveries; + } + + public long getTotalProcessingTime() { + return totalProcessingTime; + } + + public RouteError getLastError() { + return lastError; + } + + public boolean getHasRouteController() { + return hasRouteController; + } + } + } + + /* + * List of write actions available for the endpoint + */ + public enum WriteAction { + STOP, + START, + RESET, + SUSPEND, + RESUME + } + + /* + * List of read actions available for the endpoint + */ + public enum ReadAction { + DETAIL, + INFO + } + + /* + * Optional time information for the actions + */ + public static class TimeInfo { + private Long timeout; + private Boolean abortAfterTimeout; + + public Long getTimeout() { + return timeout; + } + + public void setTimeout(Long timeout) { + this.timeout = timeout; + } + + public Boolean getAbortAfterTimeout() { + return abortAfterTimeout; + } + + public void setAbortAfterTimeout(Boolean abortAfterTimeout) { + this.abortAfterTimeout = abortAfterTimeout; + } + } + +} diff --git a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointAutoConfiguration.java b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointAutoConfiguration.java new file mode 100644 index 0000000..24c9131 --- /dev/null +++ b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointAutoConfiguration.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.spring.boot.actuate.endpoint; + +import org.apache.camel.CamelContext; +import org.apache.camel.spring.boot.CamelAutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/* + * Auto configuration for the {@link CamelRoutesEndpoint}. + */ +@Configuration +@EnableConfigurationProperties({ CamelRoutesEndpointProperties.class }) +@ConditionalOnClass({CamelRoutesEndpoint.class}) +@ConditionalOnBean(CamelAutoConfiguration.class) +@AutoConfigureAfter(CamelAutoConfiguration.class) +public class CamelRoutesEndpointAutoConfiguration { + + private CamelRoutesEndpointProperties properties; + + public CamelRoutesEndpointAutoConfiguration(CamelRoutesEndpointProperties properties) { + this.properties = properties; + } + + @Bean + @ConditionalOnClass(CamelContext.class) + @ConditionalOnMissingBean + public CamelRoutesEndpoint camelEndpoint(CamelContext camelContext) { + return new CamelRoutesEndpoint(camelContext, properties); + } + +} diff --git a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointProperties.java b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointProperties.java new file mode 100644 index 0000000..21d447b --- /dev/null +++ b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointProperties.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.spring.boot.actuate.endpoint; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties("management.endpoint.camelroutes") +public class CamelRoutesEndpointProperties { + + private boolean readOnly = true; + private boolean enabled = false; + + public boolean isReadOnly() { + return readOnly; + } + + public void setReadOnly(boolean readOnly) { + this.readOnly = readOnly; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + + +} diff --git a/core/camel-spring-boot/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/core/camel-spring-boot/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 0000000..cf56bd1 --- /dev/null +++ b/core/camel-spring-boot/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -0,0 +1,28 @@ +{ + "properties": [ + { + "name": "management.endpoint.camelroutes.read-only", + "type": "java.lang.Boolean", + "description": "Whether Camel Routes actuator is in read-only mode. If not in read-only mode then operations to start/stop routes would be enabled.", + "defaultValue": true + }, + { + "name": "management.endpoint.camelroutes.enabled", + "type": "java.lang.Boolean", + "description": "To turn on or off information about Camel Routes via actuator endpoint.", + "defaultValue": true + }, + { + "name": "management.endpoint.camelroutecontroller.enabled", + "type": "java.lang.Boolean", + "description": "To turn on or off information about Camel Route Controller via actuator endpoint.", + "defaultValue": true + }, + { + "name": "management.info.camel.enabled", + "type": "java.lang.Boolean", + "description": "Whether to enable Camel info.", + "defaultValue": true + } + ] +} diff --git a/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/ActuatorTestRoute.java b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/ActuatorTestRoute.java new file mode 100644 index 0000000..b56f1bc --- /dev/null +++ b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/ActuatorTestRoute.java @@ -0,0 +1,30 @@ +/* + * 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.actuate.endpoint; + +import org.apache.camel.builder.RouteBuilder; +import org.springframework.stereotype.Component; + +@Component +public class ActuatorTestRoute extends RouteBuilder { + + @Override + public void configure() throws Exception { + from("timer:foo").routeId("foo-route").routeGroup("foo-route-group").to("log:foo"); + } + +} diff --git a/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelEndpointsGloballyEnabledTest.java b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelEndpointsGloballyEnabledTest.java new file mode 100644 index 0000000..729714a --- /dev/null +++ b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelEndpointsGloballyEnabledTest.java @@ -0,0 +1,48 @@ +/* + * 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.actuate.endpoint; + +import org.apache.camel.spring.boot.CamelAutoConfiguration; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; + +@DirtiesContext +@RunWith(SpringRunner.class) +@SpringBootTest( + classes = {CamelAutoConfiguration.class, CamelRouteControllerEndpointAutoConfiguration.class, + CamelRoutesEndpointAutoConfiguration.class}, + properties = {"management.endpoints.web.exposure.include=*"}) + +public class CamelEndpointsGloballyEnabledTest { + @Autowired + private CamelRouteControllerEndpoint routeControllerEndpoint; + + @Autowired + private CamelRoutesEndpoint routesEndpoint; + + @Test + public void testHealthCheckEndpointPresent() throws Exception { + Assert.assertNotNull(routeControllerEndpoint); + Assert.assertNotNull(routesEndpoint); + } +} diff --git a/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRouteControllerEndpointEnabledTest.java b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRouteControllerEndpointEnabledTest.java new file mode 100644 index 0000000..2a643e1 --- /dev/null +++ b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRouteControllerEndpointEnabledTest.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.spring.boot.actuate.endpoint; + +import org.apache.camel.CamelContext; +import org.apache.camel.spring.boot.CamelAutoConfiguration; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; + +/* + * Test for the {@link CamelRoutesEndpoint} actuator endpoint. + */ +@DirtiesContext +@RunWith(SpringRunner.class) +@EnableAutoConfiguration +@SpringBootApplication +@SpringBootTest( + classes = {CamelAutoConfiguration.class, CamelRouteControllerEndpointAutoConfiguration.class, ActuatorTestRoute.class}, + properties = {"management.endpoint.camelroutecontroller.enabled=true"} +) +public class CamelRouteControllerEndpointEnabledTest extends Assert { + + @Autowired(required = true) + CamelRouteControllerEndpoint routeControllerEndpoint; + + @Autowired + CamelContext camelContext; + + @Test + public void testRoutesEndpointPresent() throws Exception { + Assert.assertNotNull(routeControllerEndpoint); + } + +} diff --git a/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRouteControllerEndpointGloballyDisabledAndReenabledTest.java b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRouteControllerEndpointGloballyDisabledAndReenabledTest.java new file mode 100644 index 0000000..03e1e46 --- /dev/null +++ b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRouteControllerEndpointGloballyDisabledAndReenabledTest.java @@ -0,0 +1,62 @@ +/* + * 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.actuate.endpoint; + +import org.apache.camel.CamelContext; +import org.apache.camel.spring.boot.CamelAutoConfiguration; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; + +/* + * Test for the {@link CamelRoutesEndpoint} actuator endpoint. + */ +@DirtiesContext +@RunWith(SpringRunner.class) +@EnableAutoConfiguration +@SpringBootApplication +@SpringBootTest( + classes = {CamelAutoConfiguration.class, CamelRoutesEndpointAutoConfiguration.class, + CamelRouteControllerEndpointAutoConfiguration.class, ActuatorTestRoute.class}, + properties = {"management.endpoints.enabled-by-default = true", + "management.endpoint.camelroutecontroller.enabled = true"} +) +public class CamelRouteControllerEndpointGloballyDisabledAndReenabledTest extends Assert { + + @Autowired + CamelRouteControllerEndpoint routeControllerEndpoint; + + @Autowired + CamelRoutesEndpoint routesEndpoint; + + @Autowired + CamelContext camelContext; + + @Test + public void testRoutesEndpointPresent() throws Exception { + + Assert.assertNotNull(routesEndpoint); + Assert.assertNotNull(routeControllerEndpoint); + } + +} diff --git a/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRouteControllerEndpointTest.java b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRouteControllerEndpointTest.java new file mode 100644 index 0000000..74cc589 --- /dev/null +++ b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRouteControllerEndpointTest.java @@ -0,0 +1,62 @@ +/* + * 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.actuate.endpoint; + +import java.util.List; + +import org.apache.camel.CamelContext; +import org.apache.camel.spring.boot.CamelAutoConfiguration; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; + + +/* + * Test for the {@link CamelRouteControllerEndpoint} actuator endpoint. + */ +@DirtiesContext +@RunWith(SpringRunner.class) +@EnableAutoConfiguration +@SpringBootApplication +@SpringBootTest(classes = {CamelAutoConfiguration.class, CamelRouteControllerEndpointAutoConfiguration.class, ActuatorTestRoute.class}) +public class CamelRouteControllerEndpointTest extends Assert { + + @Autowired + CamelRouteControllerEndpoint endpoint; + + @Autowired + CamelContext camelContext; + + @Test + public void testRouteControllerEndpoint() throws Exception { + List<String> routesId = endpoint.getControlledRoutes(); + + assertNotNull(routesId); + /* FIXME DefaultRouteController returns empty list while it does control any route... + assertFalse(routesId.isEmpty()); + assertEquals(routesId.size(), camelContext.getRoutes().size()); + assertTrue(routesId.stream().anyMatch(r -> "foo-route".equals(r))); + */ + } + +} diff --git a/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointEnabledTest.java b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointEnabledTest.java new file mode 100644 index 0000000..65a5f58 --- /dev/null +++ b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointEnabledTest.java @@ -0,0 +1,56 @@ +/* + * 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.actuate.endpoint; + +import org.apache.camel.CamelContext; +import org.apache.camel.spring.boot.CamelAutoConfiguration; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; + + +/* + * Test for the {@link CamelRoutesEndpoint} actuator endpoint. + */ +@DirtiesContext +@RunWith(SpringRunner.class) +@EnableAutoConfiguration +@SpringBootApplication +@SpringBootTest( + classes = {CamelAutoConfiguration.class, CamelRoutesEndpointAutoConfiguration.class, ActuatorTestRoute.class}, + properties = {"management.endpoint.camelroutes.enabled = true"} +) +public class CamelRoutesEndpointEnabledTest extends Assert { + + @Autowired + CamelRoutesEndpoint routesEndpoint; + + @Autowired + CamelContext camelContext; + + @Test + public void testRoutesEndpointNotPresent() throws Exception { + Assert.assertNotNull(routesEndpoint); + } + +} diff --git a/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointTest.java b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointTest.java new file mode 100644 index 0000000..8b8aeca --- /dev/null +++ b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointTest.java @@ -0,0 +1,85 @@ +/* + * 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.actuate.endpoint; + +import java.util.List; + +import org.apache.camel.CamelContext; +import org.apache.camel.spring.boot.CamelAutoConfiguration; +import org.apache.camel.spring.boot.actuate.endpoint.CamelRoutesEndpoint.ReadAction; +import org.apache.camel.spring.boot.actuate.endpoint.CamelRoutesEndpoint.RouteDetailsEndpointInfo; +import org.apache.camel.spring.boot.actuate.endpoint.CamelRoutesEndpoint.RouteEndpointInfo; +import org.apache.camel.spring.boot.actuate.endpoint.CamelRoutesEndpoint.TimeInfo; +import org.apache.camel.spring.boot.actuate.endpoint.CamelRoutesEndpoint.WriteAction; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; + +/* + * Test for the {@link CamelRoutesEndpoint} actuator endpoint. + */ +@DirtiesContext +@RunWith(SpringRunner.class) +@EnableAutoConfiguration +@SpringBootApplication +@SpringBootTest(classes = {CamelAutoConfiguration.class, CamelRoutesEndpointAutoConfiguration.class, ActuatorTestRoute.class}, + properties = {"management.endpoints.web.exposure.include=*"}) + +public class CamelRoutesEndpointTest extends Assert { + + @Autowired + CamelRoutesEndpoint endpoint; + + @Autowired + CamelContext camelContext; + + @Test + public void testRoutesEndpoint() throws Exception { + List<RouteEndpointInfo> routes = endpoint.readRoutes(); + + assertFalse(routes.isEmpty()); + assertEquals(routes.size(), camelContext.getRoutes().size()); + assertTrue(routes.stream().anyMatch(r -> "foo-route".equals(r.getId()))); + assertTrue(routes.stream().anyMatch(r -> "foo-route-group".equals(r.getGroup()))); + assertTrue(routes.stream().anyMatch(r -> r.getProperties().containsKey("key1") && "val1".equals(r.getProperties().get("key1")))); + assertTrue(routes.stream().anyMatch(r -> r.getProperties().containsKey("key2") && "val2".equals(r.getProperties().get("key2")))); + } + + @Test + public void testReadOperation() throws Exception { + Object answer = endpoint.doReadAction("foo-route", ReadAction.INFO); + Assert.assertEquals(RouteEndpointInfo.class, answer.getClass()); + Assert.assertEquals("foo-route", RouteEndpointInfo.class.cast(answer).getId()); + answer = endpoint.doReadAction("foo-route", ReadAction.DETAIL); + Assert.assertEquals(RouteDetailsEndpointInfo.class, answer.getClass()); + } + + @Test(expected = IllegalArgumentException.class) + public void testWriteOperationReadOnly() throws Exception { + TimeInfo timeInfo = new TimeInfo(); + timeInfo.setAbortAfterTimeout(true); + timeInfo.setTimeout(5L); + endpoint.doWriteAction("foo-route", WriteAction.STOP, timeInfo); + } + +} diff --git a/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointWriteOperationTest.java b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointWriteOperationTest.java new file mode 100644 index 0000000..e50df8c --- /dev/null +++ b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointWriteOperationTest.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.spring.boot.actuate.endpoint; + +import org.apache.camel.CamelContext; +import org.apache.camel.ServiceStatus; +import org.apache.camel.impl.engine.AbstractCamelContext; +import org.apache.camel.spring.boot.CamelAutoConfiguration; +import org.apache.camel.spring.boot.actuate.endpoint.CamelRoutesEndpoint.TimeInfo; +import org.apache.camel.spring.boot.actuate.endpoint.CamelRoutesEndpoint.WriteAction; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; + +/* + * Test for the {@link CamelRoutesEndpoint} actuator endpoint. + */ +@DirtiesContext +@RunWith(SpringRunner.class) +@EnableAutoConfiguration +@SpringBootApplication +@SpringBootTest( + classes = {CamelAutoConfiguration.class, CamelRoutesEndpointAutoConfiguration.class, ActuatorTestRoute.class}, + properties = {"management.endpoint.camelroutes.read-only = false"}) +public class CamelRoutesEndpointWriteOperationTest extends Assert { + + @Autowired + CamelRoutesEndpoint endpoint; + + @Autowired + CamelContext camelContext; + + @Test + public void testWriteOperation() throws Exception { + AbstractCamelContext acontext = camelContext.getExtension(AbstractCamelContext.class); + ServiceStatus status = acontext.getRouteStatus("foo-route"); + Assert.assertTrue(status.isStarted()); + TimeInfo timeInfo = new TimeInfo(); + timeInfo.setAbortAfterTimeout(true); + timeInfo.setTimeout(10L); + endpoint.doWriteAction("foo-route", WriteAction.STOP, timeInfo); + status = acontext.getRouteStatus("foo-route"); + Assert.assertTrue(status.isStopped()); + } +}