Commit 2e94fd44 authored by Stephane Nicoll's avatar Stephane Nicoll

Remove support for Spring Loaded

Closes gh-7978
parent 1a84d41f
...@@ -160,7 +160,6 @@ ...@@ -160,7 +160,6 @@
<spring-integration.version>5.0.0.M4</spring-integration.version> <spring-integration.version>5.0.0.M4</spring-integration.version>
<spring-kafka.version>2.0.0.M2</spring-kafka.version> <spring-kafka.version>2.0.0.M2</spring-kafka.version>
<spring-ldap.version>2.3.1.RELEASE</spring-ldap.version> <spring-ldap.version>2.3.1.RELEASE</spring-ldap.version>
<spring-loaded.version>1.2.7.RELEASE</spring-loaded.version>
<spring-mobile.version>2.0.0.M1</spring-mobile.version> <spring-mobile.version>2.0.0.M1</spring-mobile.version>
<spring-plugin.version>1.2.0.RELEASE</spring-plugin.version> <spring-plugin.version>1.2.0.RELEASE</spring-plugin.version>
<spring-restdocs.version>1.2.1.RELEASE</spring-restdocs.version> <spring-restdocs.version>1.2.1.RELEASE</spring-restdocs.version>
...@@ -2080,11 +2079,6 @@ ...@@ -2080,11 +2079,6 @@
<scope>import</scope> <scope>import</scope>
<type>pom</type> <type>pom</type>
</dependency> </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>${spring-loaded.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.amqp</groupId> <groupId>org.springframework.amqp</groupId>
<artifactId>spring-amqp</artifactId> <artifactId>spring-amqp</artifactId>
......
...@@ -2310,9 +2310,8 @@ for other Groovy customization options. ...@@ -2310,9 +2310,8 @@ for other Groovy customization options.
=== Fast application restarts === Fast application restarts
The `spring-boot-devtools` module includes support for automatic application restarts. The `spring-boot-devtools` module includes support for automatic application restarts.
Whilst not as fast a technologies such as http://zeroturnaround.com/software/jrebel/[JRebel] Whilst not as fast a technologies such as http://zeroturnaround.com/software/jrebel/[JRebel]
or https://github.com/spring-projects/spring-loaded[Spring Loaded] it's usually it's usually significantly faster than a "`cold start`". You should probably give it a try
significantly faster than a "`cold start`". You should probably give it a try before before investigating some of the more complex reload options discussed below.
investigating some of the more complex reload options discussed below.
For more details see the <<using-spring-boot.adoc#using-boot-devtools>> section. For more details see the <<using-spring-boot.adoc#using-boot-devtools>> section.
...@@ -2323,78 +2322,6 @@ Modern IDEs (Eclipse, IDEA, etc.) all support hot swapping of bytecode, so if yo ...@@ -2323,78 +2322,6 @@ Modern IDEs (Eclipse, IDEA, etc.) all support hot swapping of bytecode, so if yo
change that doesn't affect class or method signatures it should reload cleanly with no change that doesn't affect class or method signatures it should reload cleanly with no
side effects. side effects.
https://github.com/spring-projects/spring-loaded[Spring Loaded] goes a little further in
that it can reload class definitions with changes in the method signatures. With some
customization it can force an `ApplicationContext` to refresh itself (but there is no
general mechanism to ensure that would be safe for a running application anyway, so it
would only ever be a development time trick probably).
[[howto-reload-springloaded-maven]]
==== Configuring Spring Loaded for use with Maven
To use Spring Loaded with the Maven command line, just add it as a dependency in the
Spring Boot plugin declaration, e.g.
[source,xml,indent=0]
----
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.6.RELEASE</version>
</dependency>
</dependencies>
</plugin>
----
This normally works pretty well with Eclipse and IntelliJ IDEA as long as they have their
build configuration aligned with the Maven defaults (Eclipse m2e does this out of the
box).
[[howto-reload-springloaded-gradle-and-intellij-idea]]
==== Configuring Spring Loaded for use with Gradle and IntelliJ IDEA
You need to jump through a few hoops if you want to use Spring Loaded in combination with
Gradle and IntelliJ IDEA. By default, IntelliJ IDEA will compile classes into a different
location than Gradle, causing Spring Loaded monitoring to fail.
To configure IntelliJ IDEA correctly you can use the `idea` Gradle plugin:
[source,groovy,indent=0,subs="verbatim,attributes"]
----
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.springframework.boot:spring-boot-gradle-plugin:{spring-boot-version}'
classpath 'org.springframework:springloaded:1.2.6.RELEASE'
}
}
apply plugin: 'idea'
idea {
module {
inheritOutputDirs = false
outputDir = file("$buildDir/classes/main/")
}
}
// ...
----
NOTE: IntelliJ IDEA must be configured to use the same Java version as the command line
Gradle task and `springloaded` *must* be included as a `buildscript` dependency.
You can also additionally enable '`Make Project Automatically`' inside IntelliJ IDEA to
automatically compile your code whenever a file is saved.
[[howto-build]] [[howto-build]]
......
...@@ -664,8 +664,7 @@ You might also want to use this useful operating system environment variable: ...@@ -664,8 +664,7 @@ You might also want to use this useful operating system environment variable:
Since Spring Boot applications are just plain Java applications, JVM hot-swapping should Since Spring Boot applications are just plain Java applications, JVM hot-swapping should
work out of the box. JVM hot swapping is somewhat limited with the bytecode that it can work out of the box. JVM hot swapping is somewhat limited with the bytecode that it can
replace, for a more complete solution replace, for a more complete solution
http://zeroturnaround.com/software/jrebel/[JRebel] or the http://zeroturnaround.com/software/jrebel/[JRebel] can be used. The
https://github.com/spring-projects/spring-loaded[Spring Loaded] project can be used. The
`spring-boot-devtools` module also includes support for quick application restarts. `spring-boot-devtools` module also includes support for quick application restarts.
See the <<using-boot-devtools>> section below and the See the <<using-boot-devtools>> section below and the
...@@ -791,8 +790,6 @@ If you find that restarts aren't quick enough for your applications, or you enco ...@@ -791,8 +790,6 @@ If you find that restarts aren't quick enough for your applications, or you enco
classloading issues, you could consider reloading technologies such as classloading issues, you could consider reloading technologies such as
http://zeroturnaround.com/software/jrebel/[JRebel] from ZeroTurnaround. These work by http://zeroturnaround.com/software/jrebel/[JRebel] from ZeroTurnaround. These work by
rewriting classes as they are loaded to make them more amenable to reloading. rewriting classes as they are loaded to make them more amenable to reloading.
https://github.com/spring-projects/spring-loaded[Spring Loaded] provides another option,
however it doesn't support as many frameworks and it isn't commercially supported.
**** ****
......
buildscript { buildscript {
ext { ext {
springBootVersion = '2.0.0.BUILD-SNAPSHOT' springBootVersion = '2.0.0.BUILD-SNAPSHOT'
springLoadedVersion = '1.2.4.RELEASE'
} }
repositories { repositories {
// NOTE: You should declare only repositories that you need here // NOTE: You should declare only repositories that you need here
...@@ -13,7 +12,6 @@ buildscript { ...@@ -13,7 +12,6 @@ buildscript {
} }
dependencies { dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath("org.springframework:springloaded:${springLoadedVersion}")
} }
} }
...@@ -35,6 +33,5 @@ repositories { ...@@ -35,6 +33,5 @@ repositories {
dependencies { dependencies {
compile("org.springframework.boot:spring-boot-starter-web") compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-thymeleaf") compile("org.springframework.boot:spring-boot-starter-thymeleaf")
compile("org.hibernate:hibernate-validator")
testCompile("org.springframework.boot:spring-boot-starter-test") testCompile("org.springframework.boot:spring-boot-starter-test")
} }
...@@ -40,11 +40,6 @@ ...@@ -40,11 +40,6 @@
<artifactId>zt-zip</artifactId> <artifactId>zt-zip</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
......
/*
* Copyright 2012-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.boot.loader.tools;
import java.io.File;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.util.List;
/**
* Utility class to attach an instrumentation agent to the running JVM.
*
* @author Dave Syer
*/
public abstract class AgentAttacher {
private static final String VIRTUAL_MACHINE_CLASS_NAME = "com.sun.tools.attach.VirtualMachine";
public static void attach(File agent) {
try {
String name = ManagementFactory.getRuntimeMXBean().getName();
String pid = name.substring(0, name.indexOf('@'));
ClassLoader classLoader = JvmUtils.getToolsClassLoader();
Class<?> vmClass = classLoader.loadClass(VIRTUAL_MACHINE_CLASS_NAME);
Method attachMethod = vmClass.getDeclaredMethod("attach", String.class);
Object vm = attachMethod.invoke(null, pid);
Method loadAgentMethod = vmClass.getDeclaredMethod("loadAgent", String.class);
loadAgentMethod.invoke(vm, agent.getAbsolutePath());
vmClass.getDeclaredMethod("detach").invoke(vm);
}
catch (Exception ex) {
throw new RuntimeException("Unable to attach agent to the JVM", ex);
}
}
public static List<String> commandLineArguments() {
return ManagementFactory.getRuntimeMXBean().getInputArguments();
}
public static boolean hasNoVerify() {
return commandLineArguments().contains("-Xverify:none");
}
}
/*
* Copyright 2012-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.boot.loader.tools;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
/**
* Java Virtual Machine Utils.
*
* @author Phillip Webb
*/
abstract class JvmUtils {
/**
* Various search locations for tools, including the odd Java 6 OSX jar.
*/
private static final String[] TOOLS_LOCATIONS = { "lib/tools.jar", "../lib/tools.jar",
"../Classes/classes.jar" };
public static ClassLoader getToolsClassLoader() {
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
return new URLClassLoader(new URL[] { getToolsJarUrl() }, systemClassLoader);
}
public static URL getToolsJarUrl() {
String javaHome = getJavaHome();
for (String location : TOOLS_LOCATIONS) {
try {
URL url = new URL(javaHome + "/" + location);
if (new File(url.toURI()).exists()) {
return url;
}
}
catch (Exception ex) {
// Ignore and try the next location
}
}
throw new IllegalStateException("Unable to locate tools.jar");
}
private static String getJavaHome() {
try {
return new File(System.getProperty("java.home")).toURI().toURL()
.toExternalForm();
}
catch (MalformedURLException e) {
throw new IllegalStateException("Cannot locate java.home", e);
}
}
}
/*
* 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.loader.tools;
import java.io.File;
import java.net.URL;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link JvmUtils}.
*
* @author Phillip Webb
*/
public class JvmUtilsTests {
@Test
public void getToolsJar() throws Exception {
URL jarUrl = JvmUtils.getToolsJarUrl();
assertThat(jarUrl.toString()).endsWith(".jar");
assertThat(new File(jarUrl.toURI()).exists()).isTrue();
}
}
...@@ -21,7 +21,6 @@ import java.io.IOException; ...@@ -21,7 +21,6 @@ import java.io.IOException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.security.CodeSource;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
...@@ -54,8 +53,6 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo { ...@@ -54,8 +53,6 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
private static final String SPRING_BOOT_APPLICATION_CLASS_NAME = "org.springframework.boot.autoconfigure.SpringBootApplication"; private static final String SPRING_BOOT_APPLICATION_CLASS_NAME = "org.springframework.boot.autoconfigure.SpringBootApplication";
private static final String SPRING_LOADED_AGENT_CLASS_NAME = "org.springsource.loaded.agent.SpringLoadedAgent";
/** /**
* The Maven project. * The Maven project.
* @since 1.0 * @since 1.0
...@@ -87,7 +84,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo { ...@@ -87,7 +84,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
* @since 1.0 * @since 1.0
*/ */
@Parameter(property = "run.noverify") @Parameter(property = "run.noverify")
private Boolean noverify; private boolean noverify = false;
/** /**
* Current working directory to use for the application. If not specified, basedir * Current working directory to use for the application. If not specified, basedir
...@@ -211,33 +208,8 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo { ...@@ -211,33 +208,8 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
return this.workingDirectory != null; return this.workingDirectory != null;
} }
private void findAgent() {
try {
if (this.agent == null || this.agent.length == 0) {
Class<?> loaded = Class.forName(SPRING_LOADED_AGENT_CLASS_NAME);
if (loaded != null) {
if (this.noverify == null) {
this.noverify = true;
}
CodeSource source = loaded.getProtectionDomain().getCodeSource();
if (source != null) {
this.agent = new File[] {
new File(source.getLocation().getFile()) };
}
}
}
}
catch (ClassNotFoundException ex) {
// ignore;
}
if (this.noverify == null) {
this.noverify = false;
}
}
private void run(String startClassName) private void run(String startClassName)
throws MojoExecutionException, MojoFailureException { throws MojoExecutionException, MojoFailureException {
findAgent();
boolean fork = isFork(); boolean fork = isFork();
this.project.getProperties().setProperty("_spring.boot.fork.enabled", this.project.getProperties().setProperty("_spring.boot.fork.enabled",
Boolean.toString(fork)); Boolean.toString(fork));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment