Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ ext {
groovyVersion = System.getenv('CI_GROOVY_VERSION') ?: "2.5.6"
isBuildSnapshot = grailsVersion.endsWith(".BUILD-SNAPSHOT")
isTravisBuild = System.getenv().get("TRAVIS") == 'true'
springLoadedCommonOptions = "-Xverify:none -Dspringloaded.synchronize=true -Djdk.reflect.allowGetCallerClass=true"
dependencyVersions = [
'javax.annotation-api': [
version: javaxAnnotationApiVersion,
Expand Down Expand Up @@ -85,6 +86,12 @@ ext {
names : ['directory-watcher'],
modules: ['']
],
springLoaded: [
version: springLoadedVersion,
group : 'org.springframework',
names : ['springloaded'],
modules: ['']
],
async: [
version: asyncVersion,
group : 'org.grails.plugins',
Expand Down
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ springVersion=5.1.11.RELEASE
spockVersion=1.2-groovy-2.5
micronautVersion=1.1.4
micronautSpringVersion=1.0.2
springLoadedVersion=1.2.8.RELEASE
gradleSdkVendorVersion=1.1.1
jaxbVersion=2.3.1
javaxAnnotationApiVersion=1.3.2
Expand Down
20 changes: 19 additions & 1 deletion grails-bootstrap/src/main/groovy/grails/util/Environment.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import org.grails.io.support.Resource;
import org.grails.io.support.UrlResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -51,14 +53,16 @@ public enum Environment {
TEST,

/**
* For the application data source, primarly for backward compatability for those applications
* For the application data source, primarily for backward compatibility for those applications
* that use ApplicationDataSource.groovy.
*/
APPLICATION,

/** A custom environment */
CUSTOM;

private static final Logger LOG = LoggerFactory.getLogger(Environment.class);

/**
* Constant used to resolve the environment via System.getProperty(Environment.KEY)
*/
Expand Down Expand Up @@ -659,9 +663,23 @@ public static boolean isReloadingAgentEnabled() {
try {
Class.forName("org.springframework.boot.devtools.RemoteSpringApplication");
reloadingAgentEnabled = Environment.getCurrent().isReloadEnabled();
LOG.debug("Found spring-dev-tools on the class path");
}
catch (ClassNotFoundException e) {
reloadingAgentEnabled = false;
try {
String jvmVersion = System.getProperty("java.specification.version");
if(jvmVersion.equals("1.8")) {
Class.forName("org.springsource.loaded.TypeRegistry");
LOG.debug("Found spring-loaded on the class path");
reloadingAgentEnabled = Environment.getCurrent().isReloadEnabled();
} else {
LOG.warn("Found spring-loaded on classpath but JVM is not 1.8 - skipping");
}
}
catch (ClassNotFoundException e1) {
reloadingAgentEnabled = false;
}
}
return reloadingAgentEnabled;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public class DefaultStackTraceFilterer implements StackTraceFilterer {
"sun.",
"java.lang.reflect.",
"org.springframework.boot.devtools.",
"org.springsource.loaded.",
"com.opensymphony.",
"javax.servlet."
};
Expand Down
4 changes: 1 addition & 3 deletions grails-core/src/main/groovy/grails/boot/GrailsApp.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class GrailsApp extends SpringApplication {
log.debug("Current base directory is [{}]. Reloading base directory is [{}]", new File("."), BuildSettings.BASE_DIR)

if(environment.isReloadEnabled()) {
log.debug("Reloading status: ", environment.isReloadEnabled())
log.debug("Reloading status: {}", environment.isReloadEnabled())
enableDevelopmentModeWatch(environment, applicationContext)
}
printRunStatus(applicationContext)
Expand Down Expand Up @@ -326,8 +326,6 @@ class GrailsApp extends SpringApplication {
}
directoryWatcher.start()
}


}

static boolean isDevelopmentModeActive() {
Expand Down
4 changes: 3 additions & 1 deletion grails-core/src/main/groovy/grails/dev/Support.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ class Support {
}

def environment = Environment.current
if(environment.isReloadEnabled() && !ClassUtils.isPresent("org.springframework.boot.devtools.RemoteSpringApplication", System.classLoader)) {
if(environment.isReloadEnabled() &&
(!ClassUtils.isPresent("org.springsource.loaded.SpringLoaded", System.classLoader) ||
!ClassUtils.isPresent("org.springsource.loaded.TypeRegistry", System.classLoader))) {
def grailsHome = System.getenv(Environment.ENV_GRAILS_HOME)

if(grailsHome) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package org.grails.plugins.web.controllers
import grails.config.Settings
import grails.core.GrailsControllerClass
import grails.plugins.Plugin
import grails.util.Environment
import grails.util.GrailsUtil
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
Expand All @@ -33,7 +32,6 @@ import org.grails.web.servlet.view.CompositeViewResolver
import org.springframework.beans.factory.support.AbstractBeanDefinition
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean
import org.springframework.boot.web.servlet.FilterRegistrationBean
import org.springframework.boot.web.servlet.ServletRegistrationBean
import org.springframework.boot.web.servlet.filter.OrderedFilter
import org.springframework.context.ApplicationContext
import org.springframework.util.ClassUtils
Expand All @@ -57,6 +55,10 @@ import javax.servlet.MultipartConfigElement
@Slf4j
class ControllersGrailsPlugin extends Plugin {

def watchedResources = [
"file:./grails-app/controllers/**/*Controller.groovy",
"file:./plugins/*/grails-app/controllers/**/*Controller.groovy"]

def version = GrailsUtil.getGrailsVersion()
def observe = ['domainClass']
def dependsOn = [core: version, i18n: version, urlMappings: version]
Expand Down Expand Up @@ -200,7 +202,6 @@ class ControllersGrailsPlugin extends Plugin {
this.resourcesPattern = resourcesPattern
}

@Override
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!addMappings) {
Expand All @@ -220,4 +221,33 @@ class ControllersGrailsPlugin extends Plugin {
}
}

@Override
void onChange( Map<String, Object> event) {
if (!(event.source instanceof Class)) {
return
}
def application = grailsApplication
if (application.isArtefactOfType(ControllerArtefactHandler.TYPE, (Class)event.source)) {
ApplicationContext context = applicationContext
if (!context) {
if (log.isDebugEnabled()) {
log.debug("Application context not found. Can't reload")
}
return
}

GrailsControllerClass controllerClass = (GrailsControllerClass)application.addArtefact(ControllerArtefactHandler.TYPE, (Class)event.source)
beans {
"${controllerClass.fullName}"(controllerClass.clazz) { bean ->
def beanScope = controllerClass.getScope()
bean.scope = beanScope
bean.autowire = "byName"
if (beanScope == 'prototype') {
bean.beanDefinition.dependencyCheck = AbstractBeanDefinition.DEPENDENCY_CHECK_NONE
}
}
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import grails.util.GrailsUtil
import org.grails.core.artefact.ServiceArtefactHandler
import org.grails.core.exceptions.GrailsConfigurationException

import java.lang.reflect.Modifier


/**
* Configures services in the Spring context.
Expand Down Expand Up @@ -73,4 +75,29 @@ class ServicesGrailsPlugin extends Plugin {
serviceBeanAliasPostProcessor(ServiceBeanAliasPostProcessor)
}}

void onChange(Map<String,Object> event) {
if (!event.source || !applicationContext) {
return
}

if (event.source instanceof Class) {
def application = grailsApplication
Class javaClass = event.source
// do nothing for abstract classes
if (Modifier.isAbstract(javaClass.modifiers)) return
def serviceClass = (GrailsServiceClass) application.addArtefact(ServiceArtefactHandler.TYPE, (Class) event.source)
def serviceName = "${serviceClass.propertyName}"
def scope = serviceClass.getPropertyValue("scope")

beans {
"$serviceName"(serviceClass.getClazz()) { bean ->
bean.autowire = true
if (scope) {
bean.scope = scope
}
}
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,46 @@ class UrlMappingsGrailsPlugin extends Plugin {
urlMappingsErrorPageCustomizer(UrlMappingsErrorPageCustomizer)
grailsLinkGenerator(cacheUrls ? CachingLinkGenerator : DefaultLinkGenerator, serverURL)

grailsUrlMappingsHolder(UrlMappingsHolderFactoryBean) { bean ->
bean.lazyInit = true
if (isReloadEnabled) {
urlMappingsTargetSource(HotSwappableTargetSourceFactoryBean) {
it.lazyInit = true
target = bean(UrlMappingsHolderFactoryBean) {
it.lazyInit = true
}
}
grailsUrlMappingsHolder(ProxyFactoryBean) {
it.lazyInit = true
targetSource = urlMappingsTargetSource
proxyInterfaces = [UrlMappings]
}
} else {
grailsUrlMappingsHolder(UrlMappingsHolderFactoryBean) { bean ->
bean.lazyInit = true
}
}
}}

@Override
void onChange(Map<String, Object> event) {
def application = grailsApplication
if (!application.isArtefactOfType(UrlMappingsArtefactHandler.TYPE, event.source)) {
return
}

application.addArtefact(UrlMappingsArtefactHandler.TYPE, event.source)

ApplicationContext ctx = applicationContext
UrlMappingsHolder urlMappingsHolder = createUrlMappingsHolder(applicationContext)

HotSwappableTargetSource ts = ctx.getBean("urlMappingsTargetSource", HotSwappableTargetSource)
ts.swap urlMappingsHolder

LinkGenerator linkGenerator = ctx.getBean("grailsLinkGenerator", LinkGenerator)
if (linkGenerator instanceof CachingLinkGenerator) {
linkGenerator.clearCache()
}
}

@CompileStatic
private static UrlMappingsHolder createUrlMappingsHolder(ApplicationContext applicationContext) {
def factory = new UrlMappingsHolderFactoryBean(applicationContext: applicationContext)
Expand Down