http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/model/RouteDetails.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/model/RouteDetails.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/model/RouteDetails.java new file mode 100644 index 0000000..f41fcb5 --- /dev/null +++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/model/RouteDetails.java @@ -0,0 +1,216 @@ +/** + * 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.model; + +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonInclude; +import org.apache.camel.api.management.mbean.ManagedRouteMBean; +import org.apache.camel.spi.RouteError; + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public 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; + + public 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; + } +}
http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/model/RouteDetailsInfo.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/model/RouteDetailsInfo.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/model/RouteDetailsInfo.java new file mode 100644 index 0000000..4bff3e3 --- /dev/null +++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/model/RouteDetailsInfo.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.spring.boot.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.camel.CamelContext; +import org.apache.camel.Route; +import org.apache.camel.api.management.mbean.ManagedRouteMBean; + +/** + * Container for exposing {@link org.apache.camel.Route} information + * with route details as JSON. Route details are retrieved from JMX. + */ +public class RouteDetailsInfo extends RouteInfo { + + @JsonProperty("details") + private RouteDetails routeDetails; + + public RouteDetailsInfo(final CamelContext camelContext, final Route route) { + super(route); + + if (camelContext.getManagementStrategy().getManagementAgent() != null) { + this.routeDetails = new RouteDetails(camelContext.getManagedRoute(route.getId(), ManagedRouteMBean.class)); + } + } + +} http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/model/RouteInfo.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/model/RouteInfo.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/model/RouteInfo.java new file mode 100644 index 0000000..93bc6a4 --- /dev/null +++ b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/model/RouteInfo.java @@ -0,0 +1,73 @@ +/** + * 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.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import org.apache.camel.Route; +import org.apache.camel.StatefulService; + +/** + * Container for exposing {@link org.apache.camel.Route} information as JSON. + */ +@JsonPropertyOrder({"id", "description", "uptime", "uptimeMillis"}) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class RouteInfo { + + private final String id; + + private final String description; + + private final String uptime; + + private final long uptimeMillis; + + private final String status; + + public RouteInfo(Route route) { + this.id = route.getId(); + this.description = route.getDescription(); + this.uptime = route.getUptime(); + this.uptimeMillis = route.getUptimeMillis(); + + if (route instanceof StatefulService) { + this.status = ((StatefulService) route).getStatus().name(); + } else { + this.status = null; + } + } + + public String getId() { + return id; + } + + public String getDescription() { + return description; + } + + public String getUptime() { + return uptime; + } + + public long getUptimeMillis() { + return uptimeMillis; + } + + public String getStatus() { + return status; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/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 9686cc3..1642563 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 @@ -20,11 +20,15 @@ org.apache.camel.spring.boot.CamelAutoConfiguration,\ org.apache.camel.spring.boot.SupervisingRouteControllerAutoConfiguration,\ org.apache.camel.spring.boot.actuate.endpoint.CamelRoutesEndpointAutoConfiguration,\ org.apache.camel.spring.boot.actuate.endpoint.CamelRouteControllerEndpointAutoConfiguration,\ +org.apache.camel.spring.boot.actuate.endpoint.CamelHealthCheckEndpointAutoConfiguration,\ org.apache.camel.spring.boot.actuate.health.CamelHealthAutoConfiguration,\ +org.apache.camel.spring.boot.actuate.health.CamelHealthCheckIndicatorAutoConfiguration,\ org.apache.camel.spring.boot.cloud.CamelCloudAutoConfiguration,\ org.apache.camel.spring.boot.cloud.CamelCloudServiceCallConfigurationAutoConfiguration,\ 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.health.HealthCheckRoutesAutoConfiguration,\ +org.apache.camel.spring.boot.health.HealthCheckServiceAutoConfiguration,\ org.apache.camel.spring.boot.security.CamelSSLAutoConfiguration http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelHealthCheckEndpointTest.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelHealthCheckEndpointTest.java b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelHealthCheckEndpointTest.java new file mode 100644 index 0000000..8b591e0 --- /dev/null +++ b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelHealthCheckEndpointTest.java @@ -0,0 +1,121 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.camel.spring.boot.actuate.endpoint; + +import java.util.Collection; +import java.util.Map; +import java.util.Optional; + +import org.apache.camel.health.HealthCheck; +import org.apache.camel.health.HealthCheckResultBuilder; +import org.apache.camel.impl.health.AbstractHealthCheck; +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.context.annotation.Bean; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; + +@DirtiesContext +@RunWith(SpringRunner.class) +@SpringBootTest( + classes = { + CamelAutoConfiguration.class, + CamelHealthCheckEndpointAutoConfiguration.class, + CamelHealthCheckEndpointTest.TestConfiguration.class + }, + properties = { + + } +) +public class CamelHealthCheckEndpointTest { + @Autowired + private CamelHealthCheckEndpoint endpoint; + + @Test + public void testHealthCheckEndpoint() throws Exception { + Collection<CamelHealthCheckEndpoint.HealthCheckResult> results = endpoint.invoke(); + + Assert.assertNotNull(results); + Assert.assertEquals(2, results.size()); + Assert.assertEquals(1, results.stream().filter(r -> r.getCheck().getId().equals("check-1") && r.getStatus().equals(HealthCheck.State.UP.name())).count()); + Assert.assertEquals(1, results.stream().filter(r -> r.getCheck().getId().equals("check-2") && r.getStatus().equals(HealthCheck.State.DOWN.name())).count()); + } + + @Test + public void testInvokeHealthCheckEndpoint() throws Exception { + Optional<CamelHealthCheckEndpoint.HealthCheckResult> result1 = endpoint.invoke("check-1", null); + Optional<CamelHealthCheckEndpoint.HealthCheckResult> result2 = endpoint.invoke("check-2", null); + Optional<CamelHealthCheckEndpoint.HealthCheckResult> result3 = endpoint.invoke("check-3", null); + + Assert.assertTrue(result1.isPresent()); + Assert.assertEquals("check-1", result1.get().getCheck().getId()); + Assert.assertEquals(HealthCheck.State.UP.name(), result1.get().getStatus()); + + Assert.assertTrue(result2.isPresent()); + Assert.assertEquals("check-2", result2.get().getCheck().getId()); + Assert.assertEquals(HealthCheck.State.DOWN.name(), result2.get().getStatus()); + + Assert.assertFalse(result3.isPresent()); + } + + public static class TestConfiguration { + @Bean + public HealthCheck check1() { + MyCheck check = new MyCheck("test", "check-1"); + check.getConfiguration().setEnabled(true); + check.setState(HealthCheck.State.UP); + + return check; + } + + @Bean + public HealthCheck check2() { + MyCheck check = new MyCheck("test", "check-2"); + check.getConfiguration().setEnabled(true); + check.setState(HealthCheck.State.DOWN); + + return check; + } + } + + public static class MyCheck extends AbstractHealthCheck { + private State state; + + public MyCheck(String group, String id) { + super(group, id); + } + + + public State getState() { + return state; + } + + public void setState(State state) { + this.state = state; + } + + @Override + protected void doCall(HealthCheckResultBuilder builder, Map<String, Object> options) { + builder.state(state); + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointTest.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointTest.java b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointTest.java index ea6e8cb..8f58ca3 100644 --- a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointTest.java +++ b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesEndpointTest.java @@ -20,7 +20,7 @@ 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.RouteEndpointInfo; +import org.apache.camel.spring.boot.model.RouteInfo; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -49,7 +49,7 @@ public class CamelRoutesEndpointTest extends Assert { @Test public void testRoutesEndpoint() throws Exception { - List<RouteEndpointInfo> routes = endpoint.invoke(); + List<RouteInfo> routes = endpoint.invoke(); assertFalse(routes.isEmpty()); assertEquals(routes.size(), camelContext.getRoutes().size()); http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesMvcEndpointTest.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesMvcEndpointTest.java b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesMvcEndpointTest.java index c0b1e45..dcb0eda 100644 --- a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesMvcEndpointTest.java +++ b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/actuate/endpoint/CamelRoutesMvcEndpointTest.java @@ -20,8 +20,8 @@ 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.RouteDetailsEndpointInfo; -import org.apache.camel.spring.boot.actuate.endpoint.CamelRoutesEndpoint.RouteEndpointInfo; +import org.apache.camel.spring.boot.model.RouteDetailsInfo; +import org.apache.camel.spring.boot.model.RouteInfo; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -50,7 +50,7 @@ public class CamelRoutesMvcEndpointTest extends Assert { @Test public void testRoutesEndpoint() throws Exception { - List<RouteEndpointInfo> routes = (List<RouteEndpointInfo>)endpoint.invoke(); + List<RouteInfo> routes = (List<RouteInfo>)endpoint.invoke(); assertFalse(routes.isEmpty()); assertEquals(routes.size(), camelContext.getRoutes().size()); @@ -61,8 +61,8 @@ public class CamelRoutesMvcEndpointTest extends Assert { public void testMvcRoutesEndpoint() throws Exception { Object result = endpoint.detail("foo-route"); - assertTrue(result instanceof RouteDetailsEndpointInfo); - assertEquals("foo-route", ((RouteDetailsEndpointInfo)result).getId()); + assertTrue(result instanceof RouteDetailsInfo); + assertEquals("foo-route", ((RouteDetailsInfo)result).getId()); } } http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/health/HealthCheckRegistryTest.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/health/HealthCheckRegistryTest.java b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/health/HealthCheckRegistryTest.java new file mode 100644 index 0000000..485bd3c --- /dev/null +++ b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/health/HealthCheckRegistryTest.java @@ -0,0 +1,89 @@ +/** + * 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.health; + +import java.util.Collection; +import java.util.Optional; + +import org.apache.camel.CamelContext; +import org.apache.camel.health.HealthCheckRepository; +import org.apache.camel.impl.health.RegistryRepository; +import org.apache.camel.impl.health.RoutePerformanceCounterEvaluators; +import org.apache.camel.impl.health.RoutesHealthCheckRepository; +import org.apache.camel.spring.boot.CamelAutoConfiguration; +import org.apache.camel.spring.boot.actuate.health.CamelHealthAutoConfiguration; +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.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest( + classes = { + CamelAutoConfiguration.class, + CamelHealthAutoConfiguration.class, + HealthCheckRoutesAutoConfiguration.class + }, + properties = { + "camel.health.check.routes.enabled = true", + "camel.health.check.routes.thresholds.exchanges-failed = 1", + "camel.health.check.routes.thresholds.last-processing-time.threshold = 1", + "camel.health.check.routes.thresholds.last-processing-time.failures = 2", + "camel.health.check.routes.threshold[route-1].inherit = false", + "camel.health.check.routes.threshold[route-1].exchanges-inflight = 1", + "camel.health.check.routes.threshold[route-2].inherit = true", + "camel.health.check.routes.threshold[route-2].exchanges-inflight = 1", + } +) +public class HealthCheckRegistryTest extends Assert { + @Autowired + private CamelContext context; + + @Test + public void testRepositories() { + Collection<HealthCheckRepository> repos = context.getHealthCheckRegistry().getRepositories(); + + Assert.assertNotNull(repos); + Assert.assertEquals(2, repos.size()); + Assert.assertTrue(repos.stream().anyMatch(RegistryRepository.class::isInstance)); + Assert.assertTrue(repos.stream().anyMatch(RoutesHealthCheckRepository.class::isInstance)); + + Optional<RoutesHealthCheckRepository> repo = repos.stream() + .filter(RoutesHealthCheckRepository.class::isInstance) + .map(RoutesHealthCheckRepository.class::cast) + .findFirst(); + + Assert.assertTrue(repo.isPresent()); + + // default thresholds configuration + Assert.assertEquals(2, repo.get().evaluators().count()); + Assert.assertEquals(1, repo.get().evaluators().filter(RoutePerformanceCounterEvaluators.ExchangesFailed.class::isInstance).count()); + Assert.assertEquals(1, repo.get().evaluators().filter(RoutePerformanceCounterEvaluators.LastProcessingTime.class::isInstance).count()); + + // route-1 does not inherit from default thresholds configuration + Assert.assertEquals(1, repo.get().evaluators("route-1").count()); + Assert.assertEquals(1, repo.get().evaluators("route-1").filter(RoutePerformanceCounterEvaluators.ExchangesInflight.class::isInstance).count()); + + // route-2 inherits from default thresholds configuration + Assert.assertEquals(3, repo.get().evaluators("route-2").count()); + Assert.assertEquals(1, repo.get().evaluators("route-2").filter(RoutePerformanceCounterEvaluators.ExchangesFailed.class::isInstance).count()); + Assert.assertEquals(1, repo.get().evaluators("route-2").filter(RoutePerformanceCounterEvaluators.LastProcessingTime.class::isInstance).count()); + Assert.assertEquals(1, repo.get().evaluators("route-2").filter(RoutePerformanceCounterEvaluators.ExchangesInflight.class::isInstance).count()); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-spring/src/test/java/org/apache/camel/spring/health/HealthCheckRegistryTest.java ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/test/java/org/apache/camel/spring/health/HealthCheckRegistryTest.java b/components/camel-spring/src/test/java/org/apache/camel/spring/health/HealthCheckRegistryTest.java new file mode 100644 index 0000000..dd483bb --- /dev/null +++ b/components/camel-spring/src/test/java/org/apache/camel/spring/health/HealthCheckRegistryTest.java @@ -0,0 +1,67 @@ +/** + * 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.health; + +import java.util.Collection; +import java.util.Optional; + +import org.apache.camel.CamelContext; +import org.apache.camel.health.HealthCheckRepository; +import org.apache.camel.impl.health.RegistryRepository; +import org.apache.camel.impl.health.RoutePerformanceCounterEvaluators; +import org.apache.camel.impl.health.RoutesHealthCheckRepository; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import static org.junit.Assert.assertNotNull; + +public class HealthCheckRegistryTest { + + @Test + public void testRepositories() { + CamelContext context = createContext("org/apache/camel/spring/health/HealthCheckRegistryTest.xml"); + Collection<HealthCheckRepository> repos = context.getHealthCheckRegistry().getRepositories(); + + Assert.assertNotNull(repos); + Assert.assertEquals(2, repos.size()); + Assert.assertTrue(repos.stream().anyMatch(RegistryRepository.class::isInstance)); + Assert.assertTrue(repos.stream().anyMatch(RoutesHealthCheckRepository.class::isInstance)); + + Optional<RoutesHealthCheckRepository> repo = repos.stream() + .filter(RoutesHealthCheckRepository.class::isInstance) + .map(RoutesHealthCheckRepository.class::cast) + .findFirst(); + + Assert.assertTrue(repo.isPresent()); + Assert.assertEquals(2, repo.get().evaluators().count()); + Assert.assertEquals(1, repo.get().evaluators().filter(RoutePerformanceCounterEvaluators.ExchangesFailed.class::isInstance).count()); + Assert.assertEquals(1, repo.get().evaluators().filter(RoutePerformanceCounterEvaluators.LastProcessingTime.class::isInstance).count()); + Assert.assertEquals(1, repo.get().evaluators("route-1").count()); + Assert.assertEquals(1, repo.get().evaluators("route-1").filter(RoutePerformanceCounterEvaluators.ExchangesInflight.class::isInstance).count()); + } + + + protected CamelContext createContext(String classpathConfigFile) { + ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(classpathConfigFile); + + CamelContext camelContext = appContext.getBean(CamelContext.class); + assertNotNull("No Camel Context in file: " + classpathConfigFile, camelContext); + + return camelContext; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-spring/src/test/resources/org/apache/camel/spring/health/HealthCheckRegistryTest.xml ---------------------------------------------------------------------- diff --git a/components/camel-spring/src/test/resources/org/apache/camel/spring/health/HealthCheckRegistryTest.xml b/components/camel-spring/src/test/resources/org/apache/camel/spring/health/HealthCheckRegistryTest.xml new file mode 100644 index 0000000..879a9df --- /dev/null +++ b/components/camel-spring/src/test/resources/org/apache/camel/spring/health/HealthCheckRegistryTest.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://camel.apache.org/schema/spring + http://camel.apache.org/schema/spring/camel-spring.xsd"> + + <bean id="hc-repo-routes" class="org.apache.camel.impl.health.RoutesHealthCheckRepository"> + <property name="evaluators"> + <list> + <bean class="org.apache.camel.impl.health.RoutePerformanceCounterEvaluators.ExchangesFailed"> + <constructor-arg value="10"/> + </bean> + <bean class="org.apache.camel.impl.health.RoutePerformanceCounterEvaluators.LastProcessingTime"> + <constructor-arg value="1000"/> + <constructor-arg value="1"/> + </bean> + </list> + </property> + <property name="routesEvaluators"> + <map> + <entry key="route-1"> + <list> + <bean class="org.apache.camel.impl.health.RoutePerformanceCounterEvaluators.ExchangesInflight"> + <constructor-arg value="10"/> + </bean> + </list> + </entry> + </map> + </property> + </bean> + + <camelContext xmlns="http://camel.apache.org/schema/spring"> + </camelContext> + +</beans> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/health/HealthCheckRegistryTest.java ---------------------------------------------------------------------- diff --git a/components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/health/HealthCheckRegistryTest.java b/components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/health/HealthCheckRegistryTest.java new file mode 100644 index 0000000..706574b --- /dev/null +++ b/components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/health/HealthCheckRegistryTest.java @@ -0,0 +1,57 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.test.blueprint.health; + +import java.util.Collection; +import java.util.Optional; + +import org.apache.camel.health.HealthCheckRepository; +import org.apache.camel.impl.health.RegistryRepository; +import org.apache.camel.impl.health.RoutePerformanceCounterEvaluators; +import org.apache.camel.impl.health.RoutesHealthCheckRepository; +import org.apache.camel.test.blueprint.CamelBlueprintTestSupport; +import org.junit.Assert; +import org.junit.Test; + +public class HealthCheckRegistryTest extends CamelBlueprintTestSupport { + @Override + protected String getBlueprintDescriptor() { + return "org/apache/camel/test/blueprint/health/HealthCheckRegistryTest.xml"; + } + + @Test + public void testRepositories() { + Collection<HealthCheckRepository> repos = context.getHealthCheckRegistry().getRepositories(); + + Assert.assertNotNull(repos); + Assert.assertEquals(2, repos.size()); + Assert.assertTrue(repos.stream().anyMatch(RegistryRepository.class::isInstance)); + Assert.assertTrue(repos.stream().anyMatch(RoutesHealthCheckRepository.class::isInstance)); + + Optional<RoutesHealthCheckRepository> repo = repos.stream() + .filter(RoutesHealthCheckRepository.class::isInstance) + .map(RoutesHealthCheckRepository.class::cast) + .findFirst(); + + Assert.assertTrue(repo.isPresent()); + Assert.assertEquals(2, repo.get().evaluators().count()); + Assert.assertEquals(1, repo.get().evaluators().filter(RoutePerformanceCounterEvaluators.ExchangesFailed.class::isInstance).count()); + Assert.assertEquals(1, repo.get().evaluators().filter(RoutePerformanceCounterEvaluators.LastProcessingTime.class::isInstance).count()); + Assert.assertEquals(1, repo.get().evaluators("route-1").count()); + Assert.assertEquals(1, repo.get().evaluators("route-1").filter(RoutePerformanceCounterEvaluators.ExchangesInflight.class::isInstance).count()); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/health/HealthCheckRegistryTest.xml ---------------------------------------------------------------------- diff --git a/components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/health/HealthCheckRegistryTest.xml b/components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/health/HealthCheckRegistryTest.xml new file mode 100644 index 0000000..453582b --- /dev/null +++ b/components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/health/HealthCheckRegistryTest.xml @@ -0,0 +1,54 @@ +<?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. + +--> +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation=" + http://www.osgi.org/xmlns/blueprint/v1.0.0 + https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> + + <bean id="hc-repo-routes" class="org.apache.camel.impl.health.RoutesHealthCheckRepository"> + <property name="evaluators"> + <list> + <bean class="org.apache.camel.impl.health.RoutePerformanceCounterEvaluators.ExchangesFailed"> + <argument value="10"/> + </bean> + <bean class="org.apache.camel.impl.health.RoutePerformanceCounterEvaluators.LastProcessingTime"> + <argument value="1000"/> + <argument value="1"/> + </bean> + </list> + </property> + <property name="routesEvaluators"> + <map> + <entry key="route-1"> + <list> + <bean class="org.apache.camel.impl.health.RoutePerformanceCounterEvaluators.ExchangesInflight"> + <argument value="10"/> + </bean> + </list> + </entry> + </map> + </property> + </bean> + + <camelContext xmlns="http://camel.apache.org/schema/blueprint"> + </camelContext> + +</blueprint> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java ---------------------------------------------------------------------- diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java index b3623d4..052c300 100644 --- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java +++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponent.java @@ -79,6 +79,9 @@ public class UndertowComponent extends DefaultComponent implements RestConsumerF @Override protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception { + // Sa ve a copy of the parameters. + Map<String, Object> healthCheckOptions = new HashMap<>(parameters); + URI uriHttpUriAddress = new URI(UnsafeUriCharactersEncoder.encodeHttpURI(remaining)); URI endpointUri = URISupport.createRemainingURI(uriHttpUriAddress, parameters); @@ -369,5 +372,4 @@ public class UndertowComponent extends DefaultComponent implements RestConsumerF public ComponentVerifier getVerifier() { return (scope, parameters) -> getExtension(ComponentVerifierExtension.class).orElseThrow(UnsupportedOperationException::new).verify(scope, parameters); } - } http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtension.java ---------------------------------------------------------------------- diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtension.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtension.java index 7be54be..9d51ba5 100644 --- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtension.java +++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowComponentVerifierExtension.java @@ -17,6 +17,7 @@ package org.apache.camel.component.undertow; import java.io.IOException; +import java.lang.ref.WeakReference; import java.net.URI; import java.net.URISyntaxException; import java.util.HashMap; @@ -48,9 +49,12 @@ import org.xnio.Xnio; import org.xnio.XnioWorker; public final class UndertowComponentVerifierExtension extends DefaultComponentVerifierExtension { + private ThreadLocal<WeakReference<UndertowClientWrapper>> clientCache; UndertowComponentVerifierExtension() { super("undertow"); + + clientCache = new ThreadLocal<>(); } // ********************************* @@ -99,15 +103,15 @@ public final class UndertowComponentVerifierExtension extends DefaultComponentVe // Check if validation is rest-related final boolean isRest = verifyParams.entrySet().stream().anyMatch(e -> e.getKey().startsWith("rest.")); - String httpUri; - Optional<String> httpMethod; + String httpUri = null; + String httpMethod = null; if (isRest) { // We are doing rest endpoint validation but as today the endpoint // can't do any param substitution so the validation is performed // against the http uri httpUri = getOption(verifyParams, "rest.host", String.class).orElse(null); - httpMethod = getOption(verifyParams, "rest.method", String.class); + httpMethod = getOption(verifyParams, "rest.method", String.class).orElse(null); String path = getOption(verifyParams, "rest.path", String.class).map(FileUtil::stripLeadingSeparator).orElse(null); if (ObjectHelper.isNotEmpty(httpUri) && ObjectHelper.isNotEmpty(path)) { @@ -120,11 +124,10 @@ public final class UndertowComponentVerifierExtension extends DefaultComponentVe verifyParams.entrySet().removeIf(e -> e.getKey().startsWith("rest.")); } - httpUri = getOption(verifyParams, "httpURI", String.class).orElse(null); - httpMethod = Optional.empty(); + final URI uri = getHttpUri(verifyParams); // Check whether the http uri is null or empty - if (ObjectHelper.isEmpty(httpUri)) { + if (ObjectHelper.isEmpty(uri)) { builder.error( ResultErrorBuilder.withMissingOption("httpURI") .detail("rest", isRest) @@ -137,8 +140,8 @@ public final class UndertowComponentVerifierExtension extends DefaultComponentVe } try { - final UndertowClientWrapper wrapper = new UndertowClientWrapper(); - final ClientResponse response = wrapper.send(httpUri, httpMethod); + final UndertowClientWrapper wrapper = getUndertowClientWrapper(); + final ClientResponse response = wrapper.send(uri, Optional.ofNullable(httpMethod)); if (response != null) { int code = response.getResponseCode(); @@ -184,6 +187,44 @@ public final class UndertowComponentVerifierExtension extends DefaultComponentVe // Helpers // ********************************* + private URI getHttpUri(Map<String, Object> parameters) { + URI uri = null; + + // check if a client has been supplied to the parameters map + for (Object value : parameters.values()) { + if (value instanceof URI) { + uri = URI.class.cast(value); + break; + } + } + + if (ObjectHelper.isEmpty(uri)) { + String httpUri = (String)parameters.get("httpURI"); + + if (!ObjectHelper.isEmpty(httpUri)) { + uri = URI.create(UnsafeUriCharactersEncoder.encodeHttpURI(httpUri)); + } + } + + return uri; + } + + private UndertowClientWrapper getUndertowClientWrapper() throws Exception { + WeakReference<UndertowClientWrapper> ref = clientCache.get(); + UndertowClientWrapper wrapper = null; + + if (ref != null) { + wrapper = ref.get(); + } + + if (wrapper == null) { + wrapper = new UndertowClientWrapper(); + clientCache.set(new WeakReference<>(wrapper)); + } + + return wrapper; + } + private final class UndertowClientWrapper { private final XnioWorker worker; private final ByteBufferPool pool; @@ -195,9 +236,8 @@ public final class UndertowComponentVerifierExtension extends DefaultComponentVe this.client = UndertowClient.getInstance(); } - public ClientResponse send(String httpUri, Optional<String> httpMethod) throws Exception { - URI uri = new URI(UnsafeUriCharactersEncoder.encodeHttpURI(httpUri)); - HttpString method = httpMethod.map(Methods::fromString).orElse(Methods.GET); + public ClientResponse send(URI uri, Optional<String> httpMethod) throws Exception { + HttpString method = httpMethod.map(String::toUpperCase).map(Methods::fromString).orElse(Methods.GET); ClientRequest request = new ClientRequest(); request.setMethod(method); @@ -213,7 +253,7 @@ public final class UndertowComponentVerifierExtension extends DefaultComponentVe } } - private static final class UndertowClientResponseFuture extends AbstractIoFuture<ClientExchange> implements ClientCallback<ClientExchange> { + private final class UndertowClientResponseFuture extends AbstractIoFuture<ClientExchange> implements ClientCallback<ClientExchange> { @Override public void completed(ClientExchange result) { result.setResponseListener(new ClientCallback<ClientExchange>() { http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowEndpoint.java ---------------------------------------------------------------------- diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowEndpoint.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowEndpoint.java index ec9986a..35ba81a 100644 --- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowEndpoint.java +++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowEndpoint.java @@ -39,7 +39,6 @@ import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.spi.UriPath; -import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.jsse.SSLContextParameters; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -150,16 +149,7 @@ public class UndertowEndpoint extends DefaultEndpoint implements AsyncEndpoint, * The url of the HTTP endpoint to use. */ public void setHttpURI(URI httpURI) { - if (ObjectHelper.isEmpty(httpURI.getPath())) { - try { - this.httpURI = new URI(httpURI.getScheme(), httpURI.getUserInfo(), httpURI.getHost(), httpURI.getPort(), - "/", httpURI.getQuery(), httpURI.getFragment()); - } catch (URISyntaxException e) { - throw new IllegalArgumentException(e); - } - } else { - this.httpURI = httpURI; - } + this.httpURI = UndertowHelper.makeHttpURI(httpURI); } public String getHttpMethodRestrict() { http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowHelper.java ---------------------------------------------------------------------- diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowHelper.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowHelper.java index cd8ff73..ab134a7 100644 --- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowHelper.java +++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowHelper.java @@ -26,6 +26,7 @@ import io.undertow.util.HttpString; import io.undertow.util.Methods; import org.apache.camel.Exchange; import org.apache.camel.RuntimeExchangeException; +import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.URISupport; import org.apache.camel.util.UnsafeUriCharactersEncoder; @@ -171,4 +172,30 @@ public final class UndertowHelper { return answer; } + public static URI makeHttpURI(String httpURI) { + return makeHttpURI( + URI.create(UnsafeUriCharactersEncoder.encodeHttpURI(httpURI)) + ); + } + + public static URI makeHttpURI(URI httpURI) { + if (ObjectHelper.isEmpty(httpURI.getPath())) { + try { + return new URI( + httpURI.getScheme(), + httpURI.getUserInfo(), + httpURI.getHost(), + httpURI.getPort(), + "/", + httpURI.getQuery(), + httpURI.getFragment() + ); + } catch (URISyntaxException e) { + throw new IllegalArgumentException(e); + } + } else { + return httpURI; + } + } + } http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowProducer.java ---------------------------------------------------------------------- diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowProducer.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowProducer.java index 02acfdf..dfa986f 100644 --- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowProducer.java +++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/UndertowProducer.java @@ -24,7 +24,6 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; - import javax.net.ssl.SSLContext; import io.undertow.client.ClientRequest; @@ -34,9 +33,7 @@ import io.undertow.server.DefaultByteBufferPool; import io.undertow.util.HeaderMap; import io.undertow.util.Headers; import io.undertow.util.HttpString; - import org.apache.camel.AsyncCallback; -import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.camel.TypeConverter; http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowComponentVerifierTest.java ---------------------------------------------------------------------- diff --git a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowComponentVerifierTest.java b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowComponentVerifierTest.java index 8108134..25a7c4f 100644 --- a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowComponentVerifierTest.java +++ b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowComponentVerifierTest.java @@ -36,7 +36,7 @@ public class RestUndertowComponentVerifierTest extends BaseUndertowTest { parameters.put("componentName", "undertow"); parameters.put("host", "http://localhost:" + getPort()); parameters.put("path", "verify"); - parameters.put("method", "get"); + parameters.put("method", "GET"); ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.PARAMETERS, parameters); @@ -75,7 +75,7 @@ public class RestUndertowComponentVerifierTest extends BaseUndertowTest { parameters.put("componentName", "undertow"); parameters.put("host", "http://localhost:" + getPort()); parameters.put("path", "verify"); - parameters.put("method", "get"); + parameters.put("method", "GET"); // This parameter does not belong to the rest component and validation // is delegated to the transport component @@ -99,7 +99,7 @@ public class RestUndertowComponentVerifierTest extends BaseUndertowTest { parameters.put("componentName", "undertow"); parameters.put("host", "http://localhost:" + getPort()); parameters.put("path", "verify"); - parameters.put("method", "get"); + parameters.put("method", "GET"); ComponentVerifier.Result result = verifier.verify(ComponentVerifier.Scope.CONNECTIVITY, parameters); http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/examples/camel-example-spring-boot-health-checks/application/pom.xml ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-health-checks/application/pom.xml b/examples/camel-example-spring-boot-health-checks/application/pom.xml new file mode 100644 index 0000000..00f4abf --- /dev/null +++ b/examples/camel-example-spring-boot-health-checks/application/pom.xml @@ -0,0 +1,106 @@ +<?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-health-checks</artifactId> + <version>2.20.0-SNAPSHOT</version> + </parent> + + <artifactId>camel-example-spring-boot-health-checks-application</artifactId> + <name>Camel :: Example :: Spring Boot :: Health Checks :: Application</name> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + <spring.boot-version>${spring-boot-version}</spring.boot-version> + </properties> + + <dependencyManagement> + <dependencies> + <!-- Spring Boot BOM --> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-dependencies</artifactId> + <version>${spring.boot-version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + <!-- Camel BOM --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-spring-boot-dependencies</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> + + <dependencies> + <!-- Spring Boot --> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-undertow</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-actuator</artifactId> + </dependency> + <!-- Camel --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-spring-boot-starter</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-stream-starter</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-consul-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/00d1d70b/examples/camel-example-spring-boot-health-checks/application/src/main/java/sample/camel/Application.java ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-health-checks/application/src/main/java/sample/camel/Application.java b/examples/camel-example-spring-boot-health-checks/application/src/main/java/sample/camel/Application.java new file mode 100644 index 0000000..c387ca4 --- /dev/null +++ b/examples/camel-example-spring-boot-health-checks/application/src/main/java/sample/camel/Application.java @@ -0,0 +1,35 @@ +/** + * 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/00d1d70b/examples/camel-example-spring-boot-health-checks/application/src/main/java/sample/camel/ApplicationCheck.java ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-health-checks/application/src/main/java/sample/camel/ApplicationCheck.java b/examples/camel-example-spring-boot-health-checks/application/src/main/java/sample/camel/ApplicationCheck.java new file mode 100644 index 0000000..af5dca5 --- /dev/null +++ b/examples/camel-example-spring-boot-health-checks/application/src/main/java/sample/camel/ApplicationCheck.java @@ -0,0 +1,49 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package sample.camel; + +import java.util.Map; +import java.util.UUID; + +import org.apache.camel.health.HealthCheckResultBuilder; +import org.apache.camel.impl.health.AbstractHealthCheck; + +public class ApplicationCheck extends AbstractHealthCheck { + private State state; + + public ApplicationCheck(String group, String id) { + super(group, id); + + this.state = State.UP; + + getConfiguration().setEnabled(true); + } + + + public State getState() { + return state; + } + + public void setState(State state) { + this.state = state; + } + + @Override + protected void doCall(HealthCheckResultBuilder builder, Map<String, Object> options) { + builder.state(state).detail("random.value", UUID.randomUUID().toString()); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/examples/camel-example-spring-boot-health-checks/application/src/main/java/sample/camel/ApplicationConfiguration.java ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-health-checks/application/src/main/java/sample/camel/ApplicationConfiguration.java b/examples/camel-example-spring-boot-health-checks/application/src/main/java/sample/camel/ApplicationConfiguration.java new file mode 100644 index 0000000..45bfafd --- /dev/null +++ b/examples/camel-example-spring-boot-health-checks/application/src/main/java/sample/camel/ApplicationConfiguration.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 sample.camel; + +import org.apache.camel.RuntimeCamelException; +import org.apache.camel.builder.RouteBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ApplicationConfiguration { + @Bean + public RouteBuilder routesBuilder() { + return new RouteBuilder() { + public void configure() throws Exception { + from("timer:foo?period=1s") + .routeId("foo") + .process(e -> { + throw new RuntimeCamelException("fail (foo)"); + }); + from("timer:bar?period=1s") + .routeId("bar") + .process(e -> { + throw new RuntimeCamelException("fail (bar)"); + }); + from("timer:slow?period=1s") + .routeId("slow") + .process(e -> { + Thread.sleep(1200); + }); + } + }; + } + + @Bean(name = "my-check-1") + public ApplicationCheck applicationHealth1() { + return new ApplicationCheck("global", "my-check-1"); + } + + @Bean(name = "my-check-2") + public ApplicationCheck applicationHealth2() { + return new ApplicationCheck("local", "my-check-2"); + } +} + http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/examples/camel-example-spring-boot-health-checks/application/src/main/resources/application.properties ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-health-checks/application/src/main/resources/application.properties b/examples/camel-example-spring-boot-health-checks/application/src/main/resources/application.properties new file mode 100644 index 0000000..f10fe56 --- /dev/null +++ b/examples/camel-example-spring-boot-health-checks/application/src/main/resources/application.properties @@ -0,0 +1,82 @@ +## --------------------------------------------------------------------------- +## 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.health = DEBUG +logging.level.org.apache.camel.impl.health = DEBUG +logging.level.sample.camel = DEBUG + +endpoints.enabled = false +endpoints.mappings.enabled = true +endpoints.health.enabled = true +endpoints.camelhealthchecks.enabled = true + +management.security.enabled = false + +camel.springboot.name = SampleHealthChecks + +################################################################################ +# +# health checks +# +################################################################################ + +# Enable camel health indicator +camel.health.indicator.enabled = true + +# Enable camel HealthCheck integration with spring's health indicator. +camel.health.check.indicator.enabled = true + +# Enable camel HealthCheck for routes. +camel.health.check.routes.enabled = true +camel.health.check.routes.thresholds.exchanges-failed = 10 +camel.health.check.routes.threshold[bar].exchanges-failed = 20 +camel.health.check.routes.threshold[slow].inherit = false +camel.health.check.routes.threshold[slow].last-processing-time.threshold = 1s +camel.health.check.routes.threshold[slow].last-processing-time.failures = 5 + +# HealthChecks can be pulled out from SpringBoot's health endpoint using either +# the literal id or a regexp. Exclusion list can be applied to both the ID or the +# Group as shown below: +# +#camel.health.check.indicator.exclusion.ids[0] = my-.*-2 +#camel.health.check.indicator.exclusion.groups[0] = global + +# Without the HealthCheckService running each invocation to either the Camel's +# health check endpoint or SpringBoot's one results in an invocation of the check +# whereas when enables, all the responses are cached until the check timeout is +# reached or the invocation is forced. +# +#camel.health.check.service.enabled = true +#camel.health.check.service.check-interval = 10s + +################################################################################ +# +# Consul repository +# +# Make consul checks identified by http and file available to camel +# +################################################################################ + +camel.component.consul.health.check.repository.enabled = true +camel.component.consul.health.check.repository.url = http://localhost:8500 +camel.component.consul.health.check.repository.checks[0] = http +camel.component.consul.health.check.repository.checks[1] = file + http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/examples/camel-example-spring-boot-health-checks/pom.xml ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-health-checks/pom.xml b/examples/camel-example-spring-boot-health-checks/pom.xml new file mode 100644 index 0000000..7fa4a7e --- /dev/null +++ b/examples/camel-example-spring-boot-health-checks/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-health-checks</artifactId> + <name>Camel :: Example :: Spring Boot :: Health Checks</name> + <description>An example showing how to work with Camel's Health Checks and Spring Boot</description> + <packaging>pom</packaging> + + <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> + + + <modules> + <module>service</module> + <module>application</module> + </modules> + + <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/00d1d70b/examples/camel-example-spring-boot-health-checks/readme.adoc ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-health-checks/readme.adoc b/examples/camel-example-spring-boot-health-checks/readme.adoc new file mode 100644 index 0000000..e6651f2 --- /dev/null +++ b/examples/camel-example-spring-boot-health-checks/readme.adoc @@ -0,0 +1,213 @@ +# Camel Health Checks and Spring Boot + +This example shows how to work with a simple Apache Camel application using Spring Boot. + +## How to run + +* mvn clean package +* service/src/main/bash/consul-run-linux.sh +* mvn -pl service spring-boot:run +* mvn -pl application spring-boot:run + +### How to play with the example + +You can interact with the example using curl or httpie + +* Trigger the checks an gather the results: ++ +[source,console] +---- +$ http -b GET localhost:8080/camel/health/check +---- ++ +[source,json] +---- +[ + { + "check": { + "id": "consul-file" + }, + "status": "UP" + }, + { + "check": { + "id": "consul-http" + }, + "status": "UP" + }, + { + "check": { + "group": "global", + "id": "my-check-1" + }, + "status": "UP" + }, + { + "check": { + "group": "local", + "id": "my-check-2" + }, + "status": "UP" + } +] +---- + +* Query the status of a named check ++ +[source,console] +---- +$ http -b GET localhost:8080/camel/health/check/consul-http +---- ++ +[source,json] +---- +{ + "check": { + "configuration": { + "enabled": true, + "failureThreshold": 0, + "interval": "PT0S" + }, + "id": "consul-http", + "metaData": { + "check.id": "consul-http", + "failure.count": 0, + "invocation.attempt.time": "2017-08-29T10:03:10.292+02:00[Europe/Rome]", + "invocation.count": 3, + "invocation.time": "2017-08-29T10:03:10.292+02:00[Europe/Rome]" + } + }, + "details": { + "consul.check.id": "http", + "consul.check.status": "passing", + "consul.service.id": "", + "consul.service.name": "", + "failure.count": 0, + "invocation.count": 3, + "invocation.time": "2017-08-29T10:03:10.292+02:00[Europe/Rome]" + }, + "status": "UP" +} +---- ++ +IMPORTANT: This call may result in a direct invocation of the check, the behavior is implementation dependant. + + +* Trigger a named check ++ +[source,console] +---- +$ http -b GET localhost:8080/camel/health/check/consul-http/invoke +---- ++ +[source,json] +---- +{ + "check": { + "configuration": { + "enabled": true, + "failureThreshold": 0, + "interval": "PT0S" + }, + "id": "consul-http", + "metaData": { + "check.id": "consul-http", + "failure.count": 0, + "invocation.attempt.time": "2017-08-29T10:05:02.729+02:00[Europe/Rome]", + "invocation.count": 14, + "invocation.time": "2017-08-29T10:05:02.729+02:00[Europe/Rome]" + } + }, + "details": { + "consul.check.id": "http", + "consul.check.status": "passing", + "consul.service.id": "", + "consul.service.name": "", + "failure.count": 0, + "invocation.count": 14, + "invocation.time": "2017-08-29T10:05:02.729+02:00[Europe/Rome]" + }, + "status": "UP" +} +---- + +* Check the application status using Spring-Boot's health endpoint: ++ +[source,console] +---- +$ http -b GET localhost:8080/health +---- ++ +[source,json] +---- +{ + "camel": { + "contextStatus": "Started", + "name": "SampleHealthChecks", + "status": "UP", + "version": "2.20.0-SNAPSHOT" + }, + "camel-health-checks": { + "consul-file": "UP", + "consul-http": "UP", + "my-check-1": "UP", + "my-check-2": "UP", + "status": "UP" + }, + "diskSpace": { + "free": 120546111488, + "status": "UP", + "threshold": 10485760, + "total": 192459673600 + }, + "status": "UP" +} +---- + +If you stop the `service` application, the Spring-Boot's health endpoint will report the `application` as un-healthy: + +[source,console] +---- +$ http -b GET localhost:8080/health +---- + +[source,json] +---- +{ + "camel": { + "contextStatus": "Started", + "name": "SampleHealthChecks", + "status": "UP", + "version": "2.20.0-SNAPSHOT" + }, + "camel-health-checks": { + "consul-file": "UP", + "consul-http": "UP", + "my-check-1": "UP", + "my-check-2": "UP", + "status": "DOWN" + }, + "diskSpace": { + "free": 120546017280, + "status": "UP", + "threshold": 10485760, + "total": 192459673600 + }, + "status": "DOWN" +} +---- + +### Using the HealthCheckService + +The HealthCheckService can be enabled by setting the property `camel.health.check.service.enabled` to `true`. Once done every call to the Camel health check endpoint as well as the SpringBoot one will return the last known response or an error if the requested check has not yet been invoked. + +To force the service to refresh a check, you can use: + +[source,console] +---- +$ http -b GET localhost:8080/camel/health/check/{id}/invoke +---- + +## 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/00d1d70b/examples/camel-example-spring-boot-health-checks/service/pom.xml ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-health-checks/service/pom.xml b/examples/camel-example-spring-boot-health-checks/service/pom.xml new file mode 100644 index 0000000..74eca03 --- /dev/null +++ b/examples/camel-example-spring-boot-health-checks/service/pom.xml @@ -0,0 +1,84 @@ +<?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-health-checks</artifactId> + <version>2.20.0-SNAPSHOT</version> + </parent> + + <artifactId>camel-example-spring-boot-health-checks-service</artifactId> + <name>Camel :: Example :: Spring Boot :: Health Checks :: Service</name> + + <properties> + <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> + </dependencies> + </dependencyManagement> + + <dependencies> + <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> + </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/00d1d70b/examples/camel-example-spring-boot-health-checks/service/src/main/bash/consul-run-linux.sh ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-health-checks/service/src/main/bash/consul-run-linux.sh b/examples/camel-example-spring-boot-health-checks/service/src/main/bash/consul-run-linux.sh new file mode 100755 index 0000000..b1aa954 --- /dev/null +++ b/examples/camel-example-spring-boot-health-checks/service/src/main/bash/consul-run-linux.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +CONSUL_VER="0.9.2" +CONSUL_ZIP="consul_${CONSUL_VER}_linux_amd64.zip" + +# cleanup +rm -rf "target/consul-data" +rm -rf "target/consul-config" +rm -rf "target/consul" + +mkdir -p target/ +mkdir -p target/consul-data +mkdir -p target/consul-config + +if [ ! -f target/${CONSUL_ZIP} ]; then + wget "https://releases.hashicorp.com/consul/${CONSUL_VER}/${CONSUL_ZIP}" -O target/${CONSUL_ZIP} +fi + +cat > target/consul-config/checks.json <<EOF +{ + "checks": [{ + "id": "http", "script": "curl www.google.com >/dev/null 2>&1", "interval": "10s" + }, { + "id": "file", "script": "ls /tmp/camel-check >/dev/null 2>&1", "interval": "10s" + }] +} +EOF + +unzip -d target target/${CONSUL_ZIP} + +target/consul \ + agent \ + -server \ + -bootstrap \ + -datacenter camel \ + -advertise 127.0.0.1 \ + -bind 0.0.0.0 \ + -log-level trace \ + -data-dir target/consul-data \ + -config-dir target/consul-config \ + -enable-script-checks \ + -ui \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/examples/camel-example-spring-boot-health-checks/service/src/main/bash/consul-run-osx.sh ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-health-checks/service/src/main/bash/consul-run-osx.sh b/examples/camel-example-spring-boot-health-checks/service/src/main/bash/consul-run-osx.sh new file mode 100755 index 0000000..b52f810 --- /dev/null +++ b/examples/camel-example-spring-boot-health-checks/service/src/main/bash/consul-run-osx.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +CONSUL_VER="0.9.2" +CONSUL_ZIP="consul_${CONSUL_VER}_darwin_amd64.zip" + +# cleanup +rm -rf "target/consul-data" +rm -rf "target/consul-config" +rm -rf "target/consul" + +mkdir -p target/ +mkdir -p target/consul-data +mkdir -p target/consul-config + + +if [ ! -f target/$CONSUL_ZIP ]; then + echo Downloading: https://releases.hashicorp.com/consul/$CONSUL_VER/$CONSUL_ZIP + curl -o target/$CONSUL_ZIP "https://releases.hashicorp.com/consul/$CONSUL_VER/$CONSUL_ZIP" +fi + +cat > target/consul-config/checks.json <<EOF +{ + "checks": [{ + "id": "http", "script": "curl www.google.com >/dev/null 2>&1", "interval": "10s" + }, { + "id": "file", "script": "ls /tmp/camel-check >/dev/null 2>&1", "interval": "10s" + }] +} +EOF + +unzip -d target target/$CONSUL_ZIP +chmod +x target/consul + +target/consul \ + agent \ + -server \ + -bootstrap \ + -datacenter camel \ + -advertise 127.0.0.1 \ + -bind 0.0.0.0 \ + -log-level trace \ + -data-dir target/consul-data \ + -config-dir target/consul-config \ + -enable-script-checks \ + -ui \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/00d1d70b/examples/camel-example-spring-boot-health-checks/service/src/main/java/sample/service/Application.java ---------------------------------------------------------------------- diff --git a/examples/camel-example-spring-boot-health-checks/service/src/main/java/sample/service/Application.java b/examples/camel-example-spring-boot-health-checks/service/src/main/java/sample/service/Application.java new file mode 100644 index 0000000..776fc82 --- /dev/null +++ b/examples/camel-example-spring-boot-health-checks/service/src/main/java/sample/service/Application.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 sample.service; + +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 +