diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/archaius/ArchaiusAutoConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/archaius/ArchaiusAutoConfiguration.java
index da7c1ec7..5c83b2fa 100644
--- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/archaius/ArchaiusAutoConfiguration.java
+++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/archaius/ArchaiusAutoConfiguration.java
@@ -10,11 +10,13 @@ import static com.netflix.config.ConfigurationManager.URL_CONFIG_NAME;
import java.util.concurrent.atomic.AtomicBoolean;
+import org.apache.commons.configuration.ConfigurationBuilder;
import org.apache.commons.configuration.EnvironmentConfiguration;
import org.apache.commons.configuration.SystemConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
@@ -27,6 +29,7 @@ import com.netflix.config.DynamicURLConfiguration;
* @author Spencer Gibb
*/
@Configuration
+@ConditionalOnClass({ConcurrentCompositeConfiguration.class, ConfigurationBuilder.class})
public class ArchaiusAutoConfiguration {
private static final Logger logger = LoggerFactory.getLogger(ArchaiusAutoConfiguration.class);
diff --git a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientConfiguration.java b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientConfiguration.java
index 85acb3dd..2f0f850a 100644
--- a/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientConfiguration.java
+++ b/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/eureka/EurekaClientConfiguration.java
@@ -26,7 +26,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.discovery.DiscoveryClient;
-import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.SmartLifecycle;
import org.springframework.context.annotation.Bean;
diff --git a/spring-cloud-netflix-hystrix-dashboard/pom.xml b/spring-cloud-netflix-hystrix-dashboard/pom.xml
index 33284543..fa990f66 100644
--- a/spring-cloud-netflix-hystrix-dashboard/pom.xml
+++ b/spring-cloud-netflix-hystrix-dashboard/pom.xml
@@ -20,6 +20,10 @@
org.springframework.boot
spring-boot-starter-web
+
+ org.springframework.boot
+ spring-boot-starter-freemarker
+
org.springframework.cloud
spring-cloud-netflix-core
@@ -28,10 +32,6 @@
org.apache.httpcomponents
httpclient
-
- com.netflix.eureka
- eureka-client
-
com.netflix.hystrix
hystrix-core
@@ -48,5 +48,10 @@
org.webjars
d3js
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
diff --git a/spring-cloud-netflix-hystrix-dashboard/src/main/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardConfiguration.java b/spring-cloud-netflix-hystrix-dashboard/src/main/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardConfiguration.java
index a584dc14..3da958e3 100644
--- a/spring-cloud-netflix-hystrix-dashboard/src/main/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardConfiguration.java
+++ b/spring-cloud-netflix-hystrix-dashboard/src/main/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardConfiguration.java
@@ -37,6 +37,11 @@ public class HystrixDashboardConfiguration {
return new ServletRegistrationBean(new ProxyStreamServlet(), "/proxy.stream");
}
+ @Bean
+ public HystrixDashboardController hsytrixDashboardController() {
+ return new HystrixDashboardController();
+ }
+
/**
* Proxy an EventStream request (data.stream via proxy.stream) since EventStream does not yet support CORS (https://bugs.webkit.org/show_bug.cgi?id=61862)
* so that a UI can request a stream from a different server.
diff --git a/spring-cloud-netflix-hystrix-dashboard/src/main/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardController.java b/spring-cloud-netflix-hystrix-dashboard/src/main/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardController.java
new file mode 100644
index 00000000..a562c35e
--- /dev/null
+++ b/spring-cloud-netflix-hystrix-dashboard/src/main/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardController.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013-2014 the original author or authors.
+ *
+ * Licensed 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.springframework.cloud.netflix.hystrix.dashboard;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.context.request.WebRequest;
+
+/**
+ * @author Dave Syer
+ *
+ */
+@Controller
+public class HystrixDashboardController {
+
+ @RequestMapping("/hystrix")
+ public String home(Model model, WebRequest request) {
+ model.addAttribute("basePath", extractPath(request));
+ return "index";
+ }
+
+ @RequestMapping("/hystrix/monitor")
+ public String monitor(Model model, WebRequest request) {
+ model.addAttribute("basePath", extractPath(request));
+ model.addAttribute("contextPath", request.getContextPath());
+ return "monitor";
+ }
+
+ private String extractPath(WebRequest request) {
+ String path = request.getContextPath()
+ + (String) request
+ .getAttribute(
+ "org.springframework.web.servlet.HandlerMapping.pathWithinHandlerMapping",
+ WebRequest.SCOPE_REQUEST);
+ return path;
+ }
+
+}
diff --git a/spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/components/hystrixCommand/hystrixCommand.js b/spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/components/hystrixCommand/hystrixCommand.js
index dc375759..01fa98f0 100644
--- a/spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/components/hystrixCommand/hystrixCommand.js
+++ b/spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/components/hystrixCommand/hystrixCommand.js
@@ -2,10 +2,10 @@
(function(window) {
// cache the templates we use on this page as global variables (asynchronously)
- jQuery.get(getRelativePath("../components/hystrixCommand/templates/hystrixCircuit.html"), function(data) {
+ jQuery.get(getRelativePath("components/hystrixCommand/templates/hystrixCircuit.html"), function(data) {
hystrixTemplateCircuit = data;
});
- jQuery.get(getRelativePath("../components/hystrixCommand/templates/hystrixCircuitContainer.html"), function(data) {
+ jQuery.get(getRelativePath("components/hystrixCommand/templates/hystrixCircuitContainer.html"), function(data) {
hystrixTemplateCircuitContainer = data;
});
diff --git a/spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/components/hystrixThreadPool/hystrixThreadPool.js b/spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/components/hystrixThreadPool/hystrixThreadPool.js
index a5003bc4..9f6a3326 100644
--- a/spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/components/hystrixThreadPool/hystrixThreadPool.js
+++ b/spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/components/hystrixThreadPool/hystrixThreadPool.js
@@ -2,10 +2,10 @@
(function(window) {
// cache the templates we use on this page as global variables (asynchronously)
- jQuery.get(getRelativePath("../components/hystrixThreadPool/templates/hystrixThreadPool.html"), function(data) {
+ jQuery.get(getRelativePath("components/hystrixThreadPool/templates/hystrixThreadPool.html"), function(data) {
htmlTemplate = data;
});
- jQuery.get(getRelativePath("../components/hystrixThreadPool/templates/hystrixThreadPoolContainer.html"), function(data) {
+ jQuery.get(getRelativePath("components/hystrixThreadPool/templates/hystrixThreadPoolContainer.html"), function(data) {
htmlTemplateContainer = data;
});
diff --git a/spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/monitor/monitor.css b/spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/css/monitor.css
similarity index 100%
rename from spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/monitor/monitor.css
rename to spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/css/monitor.css
diff --git a/spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/index.html b/spring-cloud-netflix-hystrix-dashboard/src/main/resources/templates/index.ftl
similarity index 89%
rename from spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/index.html
rename to spring-cloud-netflix-hystrix-dashboard/src/main/resources/templates/index.ftl
index 1c0bc56b..9a20d202 100644
--- a/spring-cloud-netflix-hystrix-dashboard/src/main/resources/static/hystrix/index.html
+++ b/spring-cloud-netflix-hystrix-dashboard/src/main/resources/templates/index.ftl
@@ -1,17 +1,18 @@
+
Hystrix Dashboard
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
+
+
@@ -96,8 +97,8 @@
stream = stream + "&delay=" + getUrlVars()["delay"];
}
- var commandStream = "/proxy.stream?origin=" + stream;
- var poolStream = "/proxy.stream?origin=" + stream;
+ var commandStream = "${contextPath}/proxy.stream?origin=" + stream;
+ var poolStream = "${contextPath}/proxy.stream?origin=" + stream;
if(getUrlVars()["title"] != undefined) {
$('#title_name').html("Hystrix Stream: " + decodeURIComponent(getUrlVars()["title"]))
diff --git a/spring-cloud-netflix-hystrix-dashboard/src/test/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardContextTests.java b/spring-cloud-netflix-hystrix-dashboard/src/test/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardContextTests.java
new file mode 100644
index 00000000..fe7c529b
--- /dev/null
+++ b/spring-cloud-netflix-hystrix-dashboard/src/test/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardContextTests.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2013-2014 the original author or authors.
+ *
+ * Licensed 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.springframework.cloud.netflix.hystrix.dashboard;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.test.IntegrationTest;
+import org.springframework.boot.test.SpringApplicationConfiguration;
+import org.springframework.boot.test.TestRestTemplate;
+import org.springframework.cloud.netflix.hystrix.dashboard.HystrixDashboardContextTests.Application;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+
+/**
+ * @author Dave Syer
+ *
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringApplicationConfiguration(classes = Application.class)
+@WebAppConfiguration
+@IntegrationTest({ "server.port=0", "spring.application.name=hystrix-dashboard", "server.contextPath=/context" })
+public class HystrixDashboardContextTests {
+
+ @Value("${local.server.port}")
+ private int port = 0;
+
+ @Test
+ public void homePage() {
+ ResponseEntity entity = new TestRestTemplate().getForEntity(
+ "http://localhost:" + port + "/context/hystrix", String.class);
+ assertEquals(HttpStatus.OK, entity.getStatusCode());
+ }
+
+ @Test
+ public void cssAvailable() {
+ ResponseEntity entity = new TestRestTemplate().getForEntity(
+ "http://localhost:" + port + "/context/hystrix/css/global.css", String.class);
+ assertEquals(HttpStatus.OK, entity.getStatusCode());
+ }
+
+ @Test
+ public void webjarsAvailable() {
+ ResponseEntity entity = new TestRestTemplate().getForEntity(
+ "http://localhost:" + port + "/context/webjars/jquery/2.1.1/jquery.min.js", String.class);
+ assertEquals(HttpStatus.OK, entity.getStatusCode());
+ }
+
+ @Test
+ public void monitorPage() {
+ ResponseEntity entity = new TestRestTemplate().getForEntity(
+ "http://localhost:" + port + "/context/hystrix/monitor", String.class);
+ assertEquals(HttpStatus.OK, entity.getStatusCode());
+ }
+
+ @Configuration
+ @EnableAutoConfiguration
+ @EnableHystrixDashboard
+ protected static class Application {
+ public static void main(String[] args) {
+ new SpringApplicationBuilder(Application.class).properties(
+ "spring.application.name=hystrix-dashboard", "server.contextPath=/context").run();
+ }
+ }
+
+}
diff --git a/spring-cloud-netflix-hystrix-dashboard/src/test/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardTests.java b/spring-cloud-netflix-hystrix-dashboard/src/test/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardTests.java
new file mode 100644
index 00000000..40721457
--- /dev/null
+++ b/spring-cloud-netflix-hystrix-dashboard/src/test/java/org/springframework/cloud/netflix/hystrix/dashboard/HystrixDashboardTests.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2013-2014 the original author or authors.
+ *
+ * Licensed 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.springframework.cloud.netflix.hystrix.dashboard;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.test.IntegrationTest;
+import org.springframework.boot.test.SpringApplicationConfiguration;
+import org.springframework.boot.test.TestRestTemplate;
+import org.springframework.cloud.netflix.hystrix.dashboard.HystrixDashboardTests.Application;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+
+/**
+ * @author Dave Syer
+ *
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringApplicationConfiguration(classes = Application.class)
+@WebAppConfiguration
+@IntegrationTest({ "server.port=0", "spring.application.name=hystrix-dashboard" })
+public class HystrixDashboardTests {
+
+ @Value("${local.server.port}")
+ private int port = 0;
+
+ @Test
+ public void homePage() {
+ ResponseEntity entity = new TestRestTemplate().getForEntity(
+ "http://localhost:" + port + "/hystrix", String.class);
+ assertEquals(HttpStatus.OK, entity.getStatusCode());
+ }
+
+ @Test
+ public void cssAvailable() {
+ ResponseEntity entity = new TestRestTemplate().getForEntity(
+ "http://localhost:" + port + "/hystrix/css/global.css", String.class);
+ assertEquals(HttpStatus.OK, entity.getStatusCode());
+ }
+
+ @Test
+ public void monitorPage() {
+ ResponseEntity entity = new TestRestTemplate().getForEntity(
+ "http://localhost:" + port + "/hystrix/monitor", String.class);
+ assertEquals(HttpStatus.OK, entity.getStatusCode());
+ }
+
+ @Configuration
+ @EnableAutoConfiguration
+ @EnableHystrixDashboard
+ protected static class Application {
+ public static void main(String[] args) {
+ new SpringApplicationBuilder(Application.class).properties(
+ "spring.application.name=hystrix-dashboard").run();
+ }
+ }
+
+}