diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/RemoteSpringApplication.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/RemoteSpringApplication.java index 036075cd137..8bdf496f695 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/RemoteSpringApplication.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/RemoteSpringApplication.java @@ -38,10 +38,9 @@ import org.springframework.core.io.ClassPathResource; /** * Application that can be used to establish a link to remotely running Spring Boot code. - * Allows remote debugging and remote updates (if enabled). This class should be launched - * from within your IDE and should have the same classpath configuration as the locally - * developed application. The remote URL of the application should be provided as a - * non-option argument. + * Allows remote updates (if enabled). This class should be launched from within your IDE + * and should have the same classpath configuration as the locally developed application. + * The remote URL of the application should be provided as a non-option argument. * * @author Phillip Webb * @since 1.3.0 diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/RemoteDevToolsAutoConfiguration.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/RemoteDevToolsAutoConfiguration.java index c6d8823a334..5d49545e284 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/RemoteDevToolsAutoConfiguration.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/RemoteDevToolsAutoConfiguration.java @@ -24,7 +24,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -45,10 +44,6 @@ import org.springframework.boot.devtools.restart.server.DefaultSourceFolderUrlFi import org.springframework.boot.devtools.restart.server.HttpRestartServer; import org.springframework.boot.devtools.restart.server.HttpRestartServerHandler; import org.springframework.boot.devtools.restart.server.SourceFolderUrlFilter; -import org.springframework.boot.devtools.tunnel.server.HttpTunnelServer; -import org.springframework.boot.devtools.tunnel.server.HttpTunnelServerHandler; -import org.springframework.boot.devtools.tunnel.server.RemoteDebugPortProvider; -import org.springframework.boot.devtools.tunnel.server.SocketTargetServerConnection; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; @@ -148,39 +143,6 @@ public class RemoteDevToolsAutoConfiguration { } - /** - * Configuration for remote debug HTTP tunneling. - */ - @ConditionalOnProperty(prefix = "spring.devtools.remote.debug", name = "enabled", matchIfMissing = true) - static class RemoteDebugTunnelConfiguration { - - @Autowired - private DevToolsProperties properties; - - @Autowired - private ServerProperties serverProperties; - - @Bean - @ConditionalOnMissingBean(name = "remoteDebugHandlerMapper") - public UrlHandlerMapper remoteDebugHandlerMapper( - @Qualifier("remoteDebugHttpTunnelServer") HttpTunnelServer server) { - String url = (this.serverProperties.getServlet().getContextPath() == null ? "" - : this.serverProperties.getServlet().getContextPath()) - + this.properties.getRemote().getContextPath() + "/debug"; - logger.warn("Listening for remote debug traffic on " + url); - Handler handler = new HttpTunnelServerHandler(server); - return new UrlHandlerMapper(url, handler); - } - - @Bean - @ConditionalOnMissingBean(name = "remoteDebugHttpTunnelServer") - public HttpTunnelServer remoteDebugHttpTunnelServer() { - return new HttpTunnelServer( - new SocketTargetServerConnection(new RemoteDebugPortProvider())); - } - - } - @Configuration @ConditionalOnClass(WebSecurityConfigurerAdapter.class) @ConditionalOnBean(ObjectPostProcessor.class) diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/RemoteDevToolsProperties.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/RemoteDevToolsProperties.java index ac17bea9a32..39f4505cd59 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/RemoteDevToolsProperties.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/RemoteDevToolsProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2017 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. @@ -48,8 +48,6 @@ public class RemoteDevToolsProperties { private Restart restart = new Restart(); - private Debug debug = new Debug(); - private Proxy proxy = new Proxy(); public String getContextPath() { @@ -80,10 +78,6 @@ public class RemoteDevToolsProperties { return this.restart; } - public Debug getDebug() { - return this.debug; - } - public Proxy getProxy() { return this.proxy; } @@ -105,38 +99,6 @@ public class RemoteDevToolsProperties { } - public static class Debug { - - public static final Integer DEFAULT_LOCAL_PORT = 8000; - - /** - * Enable remote debug support. - */ - private boolean enabled = true; - - /** - * Local remote debug server port. - */ - private int localPort = DEFAULT_LOCAL_PORT; - - public boolean isEnabled() { - return this.enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public int getLocalPort() { - return this.localPort; - } - - public void setLocalPort(int localPort) { - this.localPort = localPort; - } - - } - public static class Proxy { /** diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/LocalDebugPortAvailableCondition.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/LocalDebugPortAvailableCondition.java deleted file mode 100644 index d8f1e3051ab..00000000000 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/LocalDebugPortAvailableCondition.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2012-2017 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.boot.devtools.remote.client; - -import javax.net.ServerSocketFactory; - -import org.springframework.boot.autoconfigure.condition.ConditionMessage; -import org.springframework.boot.autoconfigure.condition.ConditionOutcome; -import org.springframework.boot.autoconfigure.condition.SpringBootCondition; -import org.springframework.boot.devtools.autoconfigure.RemoteDevToolsProperties; -import org.springframework.context.annotation.ConditionContext; -import org.springframework.core.type.AnnotatedTypeMetadata; - -/** - * Condition used to check that the actual local port is available. - * - * @author Phillip Webb - * @author Madhura Bhave - */ -class LocalDebugPortAvailableCondition extends SpringBootCondition { - - @Override - public ConditionOutcome getMatchOutcome(ConditionContext context, - AnnotatedTypeMetadata metadata) { - ConditionMessage.Builder message = ConditionMessage - .forCondition("Local Debug Port Condition"); - Integer port = context.getEnvironment().getProperty( - "spring.devtools.remote.debug.local-port", Integer.class, - RemoteDevToolsProperties.Debug.DEFAULT_LOCAL_PORT); - if (isPortAvailable(port)) { - return ConditionOutcome.match(message.foundExactly("local debug port")); - } - return ConditionOutcome.noMatch(message.didNotFind("local debug port").atAll()); - } - - private boolean isPortAvailable(int port) { - try { - ServerSocketFactory.getDefault().createServerSocket(port).close(); - return true; - } - catch (Exception ex) { - return false; - } - } - -} diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/LoggingTunnelClientListener.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/LoggingTunnelClientListener.java deleted file mode 100644 index 1951692deeb..00000000000 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/LoggingTunnelClientListener.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2012-2015 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.boot.devtools.remote.client; - -import java.nio.channels.SocketChannel; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.devtools.tunnel.client.TunnelClientListener; - -/** - * {@link TunnelClientListener} to log open/close events. - * - * @author Phillip Webb - */ -class LoggingTunnelClientListener implements TunnelClientListener { - - private static final Log logger = LogFactory - .getLog(LoggingTunnelClientListener.class); - - @Override - public void onOpen(SocketChannel socket) { - logger.info("Remote debug connection opened"); - } - - @Override - public void onClose(SocketChannel socket) { - logger.info("Remote debug connection closed"); - } - -} diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/RemoteClientConfiguration.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/RemoteClientConfiguration.java index ad7ae524bdc..e914e47b368 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/RemoteClientConfiguration.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/RemoteClientConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * Copyright 2012-2017 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. @@ -25,14 +25,12 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.annotation.PostConstruct; -import javax.servlet.Filter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -52,11 +50,7 @@ import org.springframework.boot.devtools.livereload.LiveReloadServer; import org.springframework.boot.devtools.restart.DefaultRestartInitializer; import org.springframework.boot.devtools.restart.RestartScope; import org.springframework.boot.devtools.restart.Restarter; -import org.springframework.boot.devtools.tunnel.client.HttpTunnelConnection; -import org.springframework.boot.devtools.tunnel.client.TunnelClient; -import org.springframework.boot.devtools.tunnel.client.TunnelConnection; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.event.EventListener; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; @@ -120,9 +114,8 @@ public class RemoteClientConfiguration { @PostConstruct private void logWarnings() { RemoteDevToolsProperties remoteProperties = this.properties.getRemote(); - if (!remoteProperties.getDebug().isEnabled() - && !remoteProperties.getRestart().isEnabled()) { - logger.warn("Remote restart and debug are both disabled."); + if (!remoteProperties.getRestart().isEnabled()) { + logger.warn("Remote restart is disabled."); } if (!this.remoteUrl.startsWith("https://")) { logger.warn("The connection to " + this.remoteUrl @@ -239,32 +232,4 @@ public class RemoteClientConfiguration { } - /** - * Client configuration for remote debug HTTP tunneling. - */ - @ConditionalOnProperty(prefix = "spring.devtools.remote.debug", name = "enabled", matchIfMissing = true) - @ConditionalOnClass(Filter.class) - @Conditional(LocalDebugPortAvailableCondition.class) - static class RemoteDebugTunnelClientConfiguration { - - @Autowired - private DevToolsProperties properties; - - @Value("${remoteUrl}") - private String remoteUrl; - - @Bean - public TunnelClient remoteDebugTunnelClient( - ClientHttpRequestFactory requestFactory) { - RemoteDevToolsProperties remoteProperties = this.properties.getRemote(); - String url = this.remoteUrl + remoteProperties.getContextPath() + "/debug"; - TunnelConnection connection = new HttpTunnelConnection(url, requestFactory); - int localPort = remoteProperties.getDebug().getLocalPort(); - TunnelClient client = new TunnelClient(localPort, connection); - client.addListener(new LoggingTunnelClientListener()); - return client; - } - - } - } diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/tunnel/client/HttpTunnelConnection.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/tunnel/client/HttpTunnelConnection.java index 9014fb757ce..086530f232d 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/tunnel/client/HttpTunnelConnection.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/tunnel/client/HttpTunnelConnection.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * Copyright 2012-2017 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. @@ -196,12 +196,6 @@ public class HttpTunnelConnection implements TunnelConnection { close(); return; } - if (response.getStatusCode() == HttpStatus.SERVICE_UNAVAILABLE) { - logger.warn("Remote application responded with service unavailable. Did " - + "you forget to start it with remote debugging enabled?"); - close(); - return; - } if (response.getStatusCode() == HttpStatus.OK) { HttpTunnelPayload payload = HttpTunnelPayload.get(response); if (payload != null) { diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/tunnel/server/HttpTunnelServer.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/tunnel/server/HttpTunnelServer.java index 7afb2ceb9ee..e626ad3677c 100644 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/tunnel/server/HttpTunnelServer.java +++ b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/tunnel/server/HttpTunnelServer.java @@ -158,9 +158,6 @@ public class HttpTunnelServer { catch (ConnectException ex) { httpConnection.respond(HttpStatus.GONE); } - catch (RemoteDebugNotRunningException ex) { - httpConnection.respond(HttpStatus.SERVICE_UNAVAILABLE); - } } /** diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/tunnel/server/RemoteDebugNotRunningException.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/tunnel/server/RemoteDebugNotRunningException.java deleted file mode 100644 index 2c2af1d0308..00000000000 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/tunnel/server/RemoteDebugNotRunningException.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2012-2016 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.boot.devtools.tunnel.server; - -/** - * Exception thrown to indicate that remote debug is not running. - * - * @author Andy Wilkinson - */ -class RemoteDebugNotRunningException extends RuntimeException { - -} diff --git a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/tunnel/server/RemoteDebugPortProvider.java b/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/tunnel/server/RemoteDebugPortProvider.java deleted file mode 100644 index 9223da08d4f..00000000000 --- a/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/tunnel/server/RemoteDebugPortProvider.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2012-2016 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.boot.devtools.tunnel.server; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.boot.lang.UsesUnsafeJava; - -/** - * {@link PortProvider} that provides the port being used by the Java remote debugging. - * - * @author Phillip Webb - * @author Andy Wilkinson - */ -public class RemoteDebugPortProvider implements PortProvider { - - private static final String JDWP_ADDRESS_PROPERTY = "sun.jdwp.listenerAddress"; - - private static final Log logger = LogFactory.getLog(RemoteDebugPortProvider.class); - - @Override - public int getPort() { - if (!isRemoteDebugRunning()) { - throw new RemoteDebugNotRunningException(); - } - return getRemoteDebugPort(); - } - - public static boolean isRemoteDebugRunning() { - return getRemoteDebugPort() != -1; - } - - @UsesUnsafeJava - @SuppressWarnings("restriction") - private static int getRemoteDebugPort() { - String property = sun.misc.VMSupport.getAgentProperties() - .getProperty(JDWP_ADDRESS_PROPERTY); - try { - if (property != null && property.contains(":")) { - return Integer.valueOf(property.split(":")[1]); - } - } - catch (Exception ex) { - logger.trace( - "Unable to get JDWP port from property value '" + property + "'"); - } - return -1; - } - -} diff --git a/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/RemoteDevToolsAutoConfigurationTests.java b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/RemoteDevToolsAutoConfigurationTests.java index 082e75f7f42..4f70785657f 100644 --- a/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/RemoteDevToolsAutoConfigurationTests.java +++ b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/RemoteDevToolsAutoConfigurationTests.java @@ -31,8 +31,6 @@ import org.springframework.boot.devtools.restart.MockRestarter; import org.springframework.boot.devtools.restart.server.HttpRestartServer; import org.springframework.boot.devtools.restart.server.SourceFolderUrlFilter; import org.springframework.boot.devtools.tunnel.server.HttpTunnelServer; -import org.springframework.boot.devtools.tunnel.server.RemoteDebugPortProvider; -import org.springframework.boot.devtools.tunnel.server.SocketTargetServerConnection; import org.springframework.boot.devtools.tunnel.server.TargetServerConnection; import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.context.annotation.Bean; @@ -154,46 +152,6 @@ public class RemoteDevToolsAutoConfigurationTests { this.context.getBean("remoteRestartHandlerMapper"); } - @Test - public void invokeTunnelWithDefaultSetup() throws Exception { - loadContext("spring.devtools.remote.secret:supersecret"); - DispatcherFilter filter = this.context.getBean(DispatcherFilter.class); - this.request.setRequestURI(DEFAULT_CONTEXT_PATH + "/debug"); - this.request.addHeader(DEFAULT_SECRET_HEADER_NAME, "supersecret"); - filter.doFilter(this.request, this.response, this.chain); - assertTunnelInvoked(true); - } - - @Test - public void invokeTunnelWithCustomServerContextPath() throws Exception { - loadContext("spring.devtools.remote.secret:supersecret", - "server.servlet.context-path:/test"); - DispatcherFilter filter = this.context.getBean(DispatcherFilter.class); - this.request.setRequestURI("/test" + DEFAULT_CONTEXT_PATH + "/debug"); - this.request.addHeader(DEFAULT_SECRET_HEADER_NAME, "supersecret"); - filter.doFilter(this.request, this.response, this.chain); - assertTunnelInvoked(true); - } - - @Test - public void invokeTunnelWithCustomHeaderName() throws Exception { - loadContext("spring.devtools.remote.secret:supersecret", - "spring.devtools.remote.secretHeaderName:customheader"); - DispatcherFilter filter = this.context.getBean(DispatcherFilter.class); - this.request.setRequestURI(DEFAULT_CONTEXT_PATH + "/debug"); - this.request.addHeader("customheader", "supersecret"); - filter.doFilter(this.request, this.response, this.chain); - assertTunnelInvoked(true); - } - - @Test - public void disableRemoteDebug() throws Exception { - loadContext("spring.devtools.remote.secret:supersecret", - "spring.devtools.remote.debug.enabled:false"); - this.thrown.expect(NoSuchBeanDefinitionException.class); - this.context.getBean("remoteDebugHandlerMapper"); - } - @Test public void devToolsHealthReturns200() throws Exception { loadContext("spring.devtools.remote.secret:supersecret"); @@ -239,12 +197,6 @@ public class RemoteDevToolsAutoConfigurationTests { @Import(RemoteDevToolsAutoConfiguration.class) static class Config { - @Bean - public HttpTunnelServer remoteDebugHttpTunnelServer() { - return new MockHttpTunnelServer( - new SocketTargetServerConnection(new RemoteDebugPortProvider())); - } - @Bean public HttpRestartServer remoteRestartHttpRestartServer() { SourceFolderUrlFilter sourceFolderUrlFilter = mock( diff --git a/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/remote/client/LocalDebugPortAvailableConditionTests.java b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/remote/client/LocalDebugPortAvailableConditionTests.java deleted file mode 100644 index 0542fdf93e1..00000000000 --- a/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/remote/client/LocalDebugPortAvailableConditionTests.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2012-2017 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.boot.devtools.remote.client; - -import java.net.ServerSocket; - -import javax.net.ServerSocketFactory; - -import org.junit.Test; - -import org.springframework.boot.autoconfigure.condition.ConditionOutcome; -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.context.annotation.ConditionContext; -import org.springframework.mock.env.MockEnvironment; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link LocalDebugPortAvailableCondition}. - * - * @author Phillip Webb - */ -public class LocalDebugPortAvailableConditionTests { - - private LocalDebugPortAvailableCondition condition = new LocalDebugPortAvailableCondition(); - - @Test - public void portAvailable() throws Exception { - ConditionOutcome outcome = getOutcome(0); - assertThat(outcome.isMatch()).isTrue(); - assertThat(outcome.getMessage()) - .isEqualTo("Local Debug Port Condition found local debug port"); - } - - @Test - public void portInUse() throws Exception { - ServerSocket serverSocket = ServerSocketFactory.getDefault() - .createServerSocket(0); - ConditionOutcome outcome = getOutcome(serverSocket.getLocalPort()); - serverSocket.close(); - assertThat(outcome.isMatch()).isFalse(); - assertThat(outcome.getMessage()) - .isEqualTo("Local Debug Port Condition did not find local debug port"); - } - - private ConditionOutcome getOutcome(int port) { - MockEnvironment environment = new MockEnvironment(); - TestPropertyValues.of("spring.devtools.remote.debug.local-port:" + port) - .applyTo(environment); - ConditionContext context = mock(ConditionContext.class); - given(context.getEnvironment()).willReturn(environment); - ConditionOutcome outcome = this.condition.getMatchOutcome(context, null); - return outcome; - } - -} diff --git a/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/remote/client/RemoteClientConfigurationTests.java b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/remote/client/RemoteClientConfigurationTests.java index c087907f45e..2f37ba51d5d 100644 --- a/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/remote/client/RemoteClientConfigurationTests.java +++ b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/remote/client/RemoteClientConfigurationTests.java @@ -38,7 +38,6 @@ import org.springframework.boot.devtools.remote.server.Dispatcher; import org.springframework.boot.devtools.remote.server.DispatcherFilter; import org.springframework.boot.devtools.restart.MockRestarter; import org.springframework.boot.devtools.restart.RestartScopeInitializer; -import org.springframework.boot.devtools.tunnel.client.TunnelClient; import org.springframework.boot.test.rule.OutputCapture; import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; @@ -86,11 +85,10 @@ public class RemoteClientConfigurationTests { } @Test - public void warnIfDebugAndRestartDisabled() throws Exception { - configure("spring.devtools.remote.debug.enabled:false", - "spring.devtools.remote.restart.enabled:false"); + public void warnIfRestartDisabled() throws Exception { + configure("spring.devtools.remote.restart.enabled:false"); assertThat(this.output.toString()) - .contains("Remote restart and debug are both disabled"); + .contains("Remote restart is disabled"); } @Test @@ -140,13 +138,6 @@ public class RemoteClientConfigurationTests { this.context.getBean(ClassPathFileSystemWatcher.class); } - @Test - public void remoteDebugDisabled() throws Exception { - configure("spring.devtools.remote.debug.enabled:false"); - this.thrown.expect(NoSuchBeanDefinitionException.class); - this.context.getBean(TunnelClient.class); - } - private void configure(String... pairs) { configure("http://localhost", true, pairs); } diff --git a/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/tunnel/client/HttpTunnelConnectionTests.java b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/tunnel/client/HttpTunnelConnectionTests.java index 0ae74020817..98517169692 100644 --- a/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/tunnel/client/HttpTunnelConnectionTests.java +++ b/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/tunnel/client/HttpTunnelConnectionTests.java @@ -146,15 +146,6 @@ public class HttpTunnelConnectionTests { assertThat(this.requestFactory.getExecutedRequests().size()).isGreaterThan(10); } - @Test - public void serviceUnavailableResponseLogsWarningAndClosesTunnel() throws Exception { - this.requestFactory.willRespond(HttpStatus.SERVICE_UNAVAILABLE); - TunnelChannel tunnel = openTunnel(true); - assertThat(tunnel.isOpen()).isFalse(); - this.outputCapture.expect(containsString( - "Did you forget to start it with remote debugging enabled?")); - } - @Test public void connectFailureLogsWarning() throws Exception { this.requestFactory.willRespond(new ConnectException()); diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index fbbb3ffa337..1ff477da189 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -1265,8 +1265,6 @@ content into your application; rather pick only the properties that you need. # REMOTE DEVTOOLS ({sc-spring-boot-devtools}/autoconfigure/RemoteDevToolsProperties.{sc-ext}[RemoteDevToolsProperties]) spring.devtools.remote.context-path=/.~~spring-boot!~ # Context path used to handle the remote connection. - spring.devtools.remote.debug.enabled=true # Enable remote debug support. - spring.devtools.remote.debug.local-port=8000 # Local remote debug server port. spring.devtools.remote.proxy.host= # The host of the proxy to use to connect to the remote application. spring.devtools.remote.proxy.port= # The port of the proxy to use to connect to the remote application. spring.devtools.remote.restart.enabled=true # Enable remote restart. diff --git a/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc b/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc index 3c8cb39cad2..8438db7fc49 100644 --- a/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc +++ b/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc @@ -1047,49 +1047,6 @@ before starting the remote client, it won't be pushed to the remote server. -[[using-boot-devtools-remote-debugtunnel]] -==== Remote debug tunnel -Java remote debugging is useful when diagnosing issues on a remote application. -Unfortunately, it's not always possible to enable remote debugging when your application -is deployed outside of your data center. Remote debugging can also be tricky to setup if -you are using a container based technology such as Docker. - -To help work around these limitations, devtools supports tunneling of remote debug traffic -over HTTP. The remote client provides a local server on port `8000` that you can attach -a remote debugger to. Once a connection is established, debug traffic is sent over HTTP -to the remote application. You can use the `spring.devtools.remote.debug.local-port` -property if you want to use a different port. - -You'll need to ensure that your remote application is started with remote debugging -enabled. Often this can be achieved by configuring `JAVA_OPTS`. For example, with -Cloud Foundry you can add the following to your `manifest.yml`: - -[source,yaml,indent=0] ----- - --- - env: - JAVA_OPTS: "-Xdebug -Xrunjdwp:server=y,transport=dt_socket,suspend=n" ----- - -TIP: Notice that you don't need to pass an `address=NNNN` option to `-Xrunjdwp`. If -omitted Java will simply pick a random free port. - -NOTE: Debugging a remote service over the Internet can be slow and you might need to -increase timeouts in your IDE. For example, in Eclipse you can select `Java` -> `Debug` -from `Preferences...` and change the `Debugger timeout (ms)` to a more suitable value -(`60000` works well in most situations). - -WARNING: When using the remote debug tunnel with IntelliJ IDEA, all breakpoints must be -configured to suspend the thread rather than the VM. By default, breakpoints in IntelliJ -IDEA suspend the entire VM rather than only suspending the thread that hit the -breakpoint. This has the unwanted side-effect of suspending the thread that manages the -remote debug tunnel, causing your debugging session to freeze. When using the remote -debug tunnel with IntelliJ IDEA, all breakpoints should be configured to suspend the -thread rather than the VM. Please see -https://youtrack.jetbrains.com/issue/IDEA-165769[IDEA-165769] for further details. - - - [[using-boot-packaging-for-production]] == Packaging your application for production Executable jars can be used for production deployment. As they are self-contained, they