Skip to content

Commit

Permalink
Merge branch '7.0.x' into renovate/jackson.version
Browse files Browse the repository at this point in the history
  • Loading branch information
codeconsole authored Nov 24, 2024
2 parents 1c3a970 + e2c12e5 commit 90b786b
Show file tree
Hide file tree
Showing 32 changed files with 651 additions and 365 deletions.
245 changes: 245 additions & 0 deletions CONTRIBUTING.md

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions UPGRADE7.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Common 7.0 Upgrade Gotchas - DRAFT -

Experienced while upgrading modules for Grails 7

- h2 2.x is stricter about reserved words
- https://github.com/grails/gorm-hibernate5/pull/910/commits/c8de45df204966ccc228b46b94beeb2142ae0f59
- [GROOVY-10621](https://issues.apache.org/jira/browse/GROOVY-10621)
- Primitive booleans will no longer generate the form of isProperty & getProperty. They will only generate isProperty()
- Jar artifacts produced by Grails Plugins will no longer have the suffix `-plain`
- https://github.com/grails/grails-gradle-plugin/pull/347
- [GROOVY-5169](https://issues.apache.org/jira/browse/GROOVY-5169) [GROOVY-10449](https://issues.apache.org/jira/browse/GROOVY-10449)
- Fields with a public modifier were not returned with MetaClassImpl#getProperties() in groovy 3, but are now.

## NOTE: This document is a draft and the explanations are only highlights and will be expanded further prior to release of 7.0.

### Cool New Features
- You can now @Scaffold Controllers and Services and virtually eliminate any boiler plate code.
- Hello Exterminator, Good by bugs! Lot's of things started working... and working well! For instance, use of controller namespaces now work seemlessly.
- Bootstrap 5.3.3 support. Saffolding and Fields tags now optionally support boostrap classes.
- Priortization of AutoConfiguration over bean overriding.
- Lightweight, Removal of numerous dependencies.
- grails-bom overhaul for keeping depedencies up to date and in sync.
- g:form now automatically provides csrf protection when Spring Security CSRF is enabled.
- Massive decoupling of dependencies and cleanup between modules. SiteMesh dependencies are no longer compiled into controllers fused between numerous modules. SiteMesh isn't even required to use Grails!
- SiteMesh ahs been upgrade to SiteMesh 3!
- Completely up to date modern stack that has been optimized for easier future transitions.
- GSP can now be used OUTSIDE of Grails! see grails-boot
- Works with Spring Security 6 out of the box. No plugin needed!
- Tested and works with Java [17-23](https://github.com/grails/grails-core/blob/0549617f27aeb5b90b64797fa4147dde40fc9c86/.github/workflows/gradle.yml#L18)
4 changes: 3 additions & 1 deletion dependabot/build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Generated on Mon Oct 21 14:36:55 PDT 2024 by: ./gradlew :grails-bom:dependabotBuild
// Generated on Fri Nov 22 09:58:56 CET 2024 by: ./gradlew :grails-bom:dependabotBuild
plugins {
id 'java-library'
}
Expand All @@ -7,6 +7,7 @@ dependencies {
api "org.apache.ant:ant:${project['ant.version']}"
api "org.apache.ant:ant-junit:${project['ant.version']}"
api "org.asciidoctor:asciidoctorj:${project['asciidoctorj.version']}"
api "com.bertramlabs.plugins:asset-pipeline-gradle:${project['asset-pipeline-gradle.version']}"
api "com.bertramlabs.plugins:asset-pipeline-grails:${project['asset-pipeline-grails.version']}"
api "net.bytebuddy:byte-buddy:${project['byte-buddy.version']}"
api "commons-codec:commons-codec:${project['commons-codec.version']}"
Expand All @@ -24,6 +25,7 @@ dependencies {
api "org.grails:grails-events-rxjava:${project['grails-async.version']}"
api "org.grails:grails-events-rxjava2:${project['grails-async.version']}"
api "org.grails:grails-datastore-gorm-hibernate5:${project['grails-datastore-gorm-hibernate5.version']}"
api "org.grails:grails-datastore-gorm-mongodb:${project['grails-datastore-gorm-mongodb.version']}"
api "org.grails:grails-datastore-async:${project['grails-datastore.version']}"
api "org.grails:grails-datastore-core:${project['grails-datastore.version']}"
api "org.grails:grails-datastore-gorm:${project['grails-datastore.version']}"
Expand Down
12 changes: 7 additions & 5 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ gradleNexusPluginVersion=2.3.1
gradleNexusPublishPluginVersion=2.0.0
gradleExtraConfigurationsPluginVersion=10.0.1
gradleLicensePluginVersion=0.16.1
gradleToolingApiVersion=8.10.2
groovyVersion=4.0.23
gradleToolingApiVersion=8.11.1
groovyVersion=4.0.24
joptSimpleVersion=5.0.4
plexusComponentApiVersion=1.0-alpha-33
plexusSecDispatcherVersion=1.4
Expand All @@ -21,10 +21,11 @@ org.gradle.parallel=true
org.gradle.daemon=true
org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Xmx1536M -XX:MaxMetaspaceSize=1024M

# Generated on Tue Oct 22 16:16:30 EDT 2024 by: ./gradlew :grails-bom:syncProps
# Generated on Fri Nov 22 09:58:56 CET 2024 by: ./gradlew :grails-bom:syncProps
# Only version value modifications allowed after this point. Do not insert or change version names.
ant.version=1.10.15
asciidoctorj.version=3.0.0
asset-pipeline-gradle.version=5.0.1
asset-pipeline-grails.version=5.0.1
byte-buddy.version=1.15.5
commons-codec.version=1.17.1
Expand All @@ -36,10 +37,11 @@ geb-spock.version=7.0
grails-async.version=6.0.0-SNAPSHOT
grails-datastore.version=9.0.0-SNAPSHOT
grails-datastore-gorm-hibernate5.version=9.0.0-SNAPSHOT
grails-datastore-gorm-mongodb.version=9.0.0-SNAPSHOT
grails-gdoc-engine.version=1.0.1
grails-gradle-plugin.version=7.0.0-SNAPSHOT
grails-testing-support.version=4.0.0-SNAPSHOT
groovy.version=4.0.23
groovy.version=4.0.24
gsp.version=7.0.0-SNAPSHOT
h2.version=2.3.232
jackson.version=2.18.1
Expand Down Expand Up @@ -75,6 +77,6 @@ profiles-web.version=7.0.1-SNAPSHOT
profiles-web-plugin.version=7.0.1-SNAPSHOT
spock.version=2.3-groovy-4.0
spotbugs-annotations.version=4.8.6
spring-boot.version=3.4.0-RC1
spring-boot.version=3.4.0
springloaded.version=1.2.8.RELEASE
views-json-testing-support.version=4.0.0-SNAPSHOT
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
2 changes: 2 additions & 0 deletions grails-bom/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ ext {
// version name = versionNameOverride ?: artifactId-prefixes[0]
dependenciesOverview = """\
com.bertramlabs.plugins:asset-pipeline-grails::
com.bertramlabs.plugins:asset-pipeline-gradle::
com.fasterxml.jackson:jackson-bom:::jackson
com.github.javaparser:javaparser-core::
com.h2database:h2::
Expand All @@ -45,6 +46,7 @@ ext {
org.grails.plugins:gsp::
org.grails:grails-async,grails-events:gpars,rxjava,rxjava2::grails-async
org.grails:grails-datastore-gorm-hibernate5::
org.grails:grails-datastore-gorm-mongodb::
org.grails:grails-datastore:async,core,gorm,gorm-async,gorm-support,gorm-rx,gorm-test,gorm-validation,web:
org.grails:grails-gdoc-engine::
org.grails:grails-gradle-plugin::
Expand Down
1 change: 1 addition & 0 deletions grails-bom/plugins.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ neo4j=8.1.0
rxjava=1.1.1
rxjava2=2.0.0
scaffolding=6.0.0-SNAPSHOT
views-gradle=4.0.0-SNAPSHOT
views-json=4.0.0-SNAPSHOT
views-json-templates=4.0.0-SNAPSHOT
views-markup=4.0.0-SNAPSHOT
8 changes: 1 addition & 7 deletions grails-core/build.gradle
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
configurations.all {
resolutionStrategy {
force "org.hamcrest:hamcrest-core:1.3"
}
}

dependencies {
compileOnly "org.aspectj:aspectjrt", "org.aspectj:aspectjweaver"
api "jakarta.inject:jakarta.inject-api"
Expand All @@ -27,7 +21,7 @@ dependencies {

testImplementation "org.springframework:spring-jdbc"

testImplementation "org.hamcrest:hamcrest-core:1.3"
testImplementation "org.hamcrest:hamcrest"

testRuntimeOnly "com.h2database:h2"
testRuntimeOnly "com.fasterxml.jackson.core:jackson-databind"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -541,12 +541,9 @@ public void doWithRuntimeConfiguration(RuntimeSpringConfiguration springConfig)
BeanBuilder bb = new BeanBuilder(getParentCtx(),springConfig, grailsApplication.getClassLoader());
bb.setBinding(b);
c.setDelegate(bb);
c.setResolveStrategy(Closure.OWNER_FIRST);
bb.invokeMethod("beans", new Object[]{c});
}
}
else {

} else {
if (!pluginBean.isReadableProperty(DO_WITH_SPRING)) {
return;
}
Expand All @@ -559,7 +556,6 @@ public void doWithRuntimeConfiguration(RuntimeSpringConfiguration springConfig)
BeanBuilder bb = new BeanBuilder(getParentCtx(),springConfig, grailsApplication.getClassLoader());
bb.setBinding(b);
c.setDelegate(bb);
c.setResolveStrategy(Closure.DELEGATE_FIRST);
bb.invokeMethod("beans", new Object[]{c});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package org.grails.transaction;

import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.junit.jupiter.api.Test;
import org.springframework.transaction.*;
import org.springframework.transaction.support.DefaultTransactionDefinition;
Expand Down Expand Up @@ -176,7 +175,6 @@ public TestPlatformTransactionManager(String name) {
this.name = name;
}

@Factory
static PlatformTransactionManager createFailingTransactionManager(String name) {
return new TestPlatformTransactionManager(name + "-failing") {
@Override
Expand All @@ -191,7 +189,6 @@ public void rollback(TransactionStatus status) throws TransactionException {
};
}

@Factory
static PlatformTransactionManager createNonFailingTransactionManager(String name) {
return new TestPlatformTransactionManager(name + "-non-failing");
}
Expand Down Expand Up @@ -296,12 +293,10 @@ public void describeTo(Description description) {
description.appendText("that a " + (commitCheck ? "committed" : "rolled-back") + " TransactionManager");
}

@Factory
public static TransactionManagerMatcher isCommitted() {
return new TransactionManagerMatcher(true);
}

@Factory
public static TransactionManagerMatcher wasRolledback() {
return new TransactionManagerMatcher(false);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
package org.grails.plugins.web.controllers;

import grails.config.Settings;
import grails.core.GrailsApplication;
import jakarta.servlet.DispatcherType;
import jakarta.servlet.Filter;
import jakarta.servlet.MultipartConfigElement;
import org.grails.web.config.http.GrailsFilters;
import org.grails.web.filters.HiddenHttpMethodFilter;
import org.grails.web.servlet.mvc.GrailsDispatcherServlet;
import org.grails.web.servlet.mvc.GrailsWebRequestFilter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
import org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.util.ClassUtils;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.EnumSet;

@AutoConfiguration(before = { HttpEncodingAutoConfiguration.class, WebMvcAutoConfiguration.class })
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class ControllersAutoConfiguration {

@Value("${" + Settings.FILTER_ENCODING + ":utf-8}")
private String filtersEncoding;

@Value("${" + Settings.FILTER_FORCE_ENCODING + ":false}")
private boolean filtersForceEncoding;

@Value("${" + Settings.RESOURCES_CACHE_PERIOD + ":0}")
private int resourcesCachePeriod;

@Value("${" + Settings.RESOURCES_ENABLED + ":true}")
private boolean resourcesEnabled;

@Value("${" + Settings.RESOURCES_PATTERN + ":" + Settings.DEFAULT_RESOURCE_PATTERN + "}")
private String resourcesPattern;

@Value("${" + Settings.CONTROLLERS_UPLOAD_LOCATION + ":#{null}}")
private String uploadTmpDir;

@Value("${" + Settings.CONTROLLERS_UPLOAD_MAX_FILE_SIZE + ":128000}")
private long maxFileSize;

@Value("${" + Settings.CONTROLLERS_UPLOAD_MAX_REQUEST_SIZE + ":128000}")
private long maxRequestSize;

@Value("${" + Settings.CONTROLLERS_UPLOAD_FILE_SIZE_THRESHOLD + ":0}")
private int fileSizeThreshold;

@Value("${" + Settings.WEB_SERVLET_PATH + ":#{null}}")
String grailsServletPath;

@Bean
@ConditionalOnMissingBean(CharacterEncodingFilter.class)
public CharacterEncodingFilter characterEncodingFilter() {
FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>();
OrderedCharacterEncodingFilter characterEncodingFilter = new OrderedCharacterEncodingFilter();
characterEncodingFilter.setEncoding(filtersEncoding);
characterEncodingFilter.setForceEncoding(filtersForceEncoding);
characterEncodingFilter.setOrder(GrailsFilters.CHARACTER_ENCODING_FILTER.getOrder());
return characterEncodingFilter;
}

@Bean
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
public FilterRegistrationBean<Filter> hiddenHttpMethodFilter() {
FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new HiddenHttpMethodFilter());
registrationBean.addUrlPatterns(Settings.DEFAULT_WEB_SERVLET_PATH);
registrationBean.setOrder(GrailsFilters.HIDDEN_HTTP_METHOD_FILTER.getOrder());
return registrationBean;
}

@Bean
@ConditionalOnMissingBean(GrailsWebRequestFilter.class)
public FilterRegistrationBean<Filter> grailsWebRequestFilter(ApplicationContext applicationContext) {
FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>();
GrailsWebRequestFilter grailsWebRequestFilter = new GrailsWebRequestFilter();
grailsWebRequestFilter.setApplicationContext(applicationContext);
registrationBean.setFilter(grailsWebRequestFilter);
registrationBean.setDispatcherTypes(EnumSet.of(
DispatcherType.FORWARD,
DispatcherType.INCLUDE,
DispatcherType.REQUEST)
);
registrationBean.addUrlPatterns(Settings.DEFAULT_WEB_SERVLET_PATH);
registrationBean.setOrder(GrailsFilters.GRAILS_WEB_REQUEST_FILTER.getOrder());
return registrationBean;
}

@Bean
public MultipartConfigElement multipartConfigElement() {
if (uploadTmpDir == null) {
uploadTmpDir = System.getProperty("java.io.tmpdir");
}
return new MultipartConfigElement(uploadTmpDir, maxFileSize, maxRequestSize, fileSizeThreshold);
}

@Bean
public DispatcherServlet dispatcherServlet() {
return new GrailsDispatcherServlet();
}

@Bean
public DispatcherServletRegistrationBean dispatcherServletRegistration(GrailsApplication application, DispatcherServlet dispatcherServlet, MultipartConfigElement multipartConfigElement) {
if (grailsServletPath == null) {
boolean isTomcat = ClassUtils.isPresent("org.apache.catalina.startup.Tomcat", application.getClassLoader());
grailsServletPath = isTomcat ? Settings.DEFAULT_TOMCAT_SERVLET_PATH : Settings.DEFAULT_WEB_SERVLET_PATH;
}
DispatcherServletRegistrationBean dispatcherServletRegistration = new DispatcherServletRegistrationBean(dispatcherServlet, grailsServletPath);
dispatcherServletRegistration.setLoadOnStartup(2);
dispatcherServletRegistration.setAsyncSupported(true);
dispatcherServletRegistration.setMultipartConfig(multipartConfigElement);
return dispatcherServletRegistration;
}

@Bean
public GrailsWebMvcConfigurer webMvcConfig() {
return new GrailsWebMvcConfigurer(resourcesCachePeriod, resourcesEnabled, resourcesPattern);
}

static class GrailsWebMvcConfigurer implements WebMvcConfigurer {

private static final String[] SERVLET_RESOURCE_LOCATIONS = new String[] { "/" };

private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[] {
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/", "classpath:/public/"
};

private static final String[] RESOURCE_LOCATIONS;

static {
RESOURCE_LOCATIONS = new String[CLASSPATH_RESOURCE_LOCATIONS.length
+ SERVLET_RESOURCE_LOCATIONS.length];
System.arraycopy(SERVLET_RESOURCE_LOCATIONS, 0, RESOURCE_LOCATIONS, 0,
SERVLET_RESOURCE_LOCATIONS.length);
System.arraycopy(CLASSPATH_RESOURCE_LOCATIONS, 0, RESOURCE_LOCATIONS,
SERVLET_RESOURCE_LOCATIONS.length, CLASSPATH_RESOURCE_LOCATIONS.length);
}

boolean addMappings;
Integer cachePeriod;
String resourcesPattern;

GrailsWebMvcConfigurer(Integer cachePeriod, Boolean addMappings, String resourcesPattern) {
this.addMappings = addMappings;
this.cachePeriod = cachePeriod;
this.resourcesPattern = resourcesPattern;
}

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!addMappings) {
return;
}

if (!registry.hasMappingForPattern("/webjars/**")) {
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(cachePeriod);
}
if (!registry.hasMappingForPattern(resourcesPattern)) {
registry.addResourceHandler(resourcesPattern)
.addResourceLocations(RESOURCE_LOCATIONS)
.setCachePeriod(cachePeriod);
}
}
}
}
Loading

0 comments on commit 90b786b

Please sign in to comment.