From 64145a2519dbf824eebe7c1189b7c8310cb6733e Mon Sep 17 00:00:00 2001 From: "g.sartori" Date: Wed, 5 Feb 2025 18:36:27 +0100 Subject: [PATCH 1/4] BootStrap init servletContext cleanup --- src/en/guide/REST/domainResources.adoc | 2 +- src/en/guide/conf/environments.adoc | 10 ++++++---- src/en/ref/Database Mapping/column.adoc | 6 ++++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/en/guide/REST/domainResources.adoc b/src/en/guide/REST/domainResources.adoc index ff0cb4296a0..19ba6e1a9db 100644 --- a/src/en/guide/REST/domainResources.adoc +++ b/src/en/guide/REST/domainResources.adoc @@ -21,7 +21,7 @@ You can try it out by adding some test data to `BootStrap.groovy`: [source,groovy] ---- -def init = { servletContext -> +def init = { new Book(title:"The Stand").save() new Book(title:"The Shining").save() } diff --git a/src/en/guide/conf/environments.adoc b/src/en/guide/conf/environments.adoc index 441407fd200..e52001f8cb2 100644 --- a/src/en/guide/conf/environments.adoc +++ b/src/en/guide/conf/environments.adoc @@ -123,16 +123,18 @@ It's often desirable to run code when your application starts up on a per-enviro [source,groovy] ---- -def init = { ServletContext ctx -> +ServletContext servletContext + +def init = { environments { production { - ctx.setAttribute("env", "prod") + servletContext.setAttribute("env", "prod") } development { - ctx.setAttribute("env", "dev") + servletContext.setAttribute("env", "dev") } } - ctx.setAttribute("foo", "bar") + servletContext.setAttribute("foo", "bar") } ---- diff --git a/src/en/ref/Database Mapping/column.adoc b/src/en/ref/Database Mapping/column.adoc index 36b7b82767d..e11b4355821 100644 --- a/src/en/ref/Database Mapping/column.adoc +++ b/src/en/ref/Database Mapping/column.adoc @@ -84,7 +84,7 @@ import groovy.transform.CompileStatic @CompileStatic class BootStrap { - def init = { servletContext -> + def init = { Book.saveAll( new Book(name: 'Grails 3 - Step by Step', status: Status.NOT_SET), @@ -94,7 +94,9 @@ class BootStrap { status: Status.SOLD), ) } - def destroy = { } + + def destroy = { + } } ---- From 5f4fed68a2a964c118e3a77614b1cc574bf331d3 Mon Sep 17 00:00:00 2001 From: "g.sartori" Date: Wed, 5 Feb 2025 19:01:44 +0100 Subject: [PATCH 2/4] Prefer typed fields instead of untyped "def" fields when injecting a service --- .../transactionsRollbackAndTheSession.adoc | 6 ++-- .../services/dependencyInjectionServices.adoc | 31 +++++++------------ src/en/guide/spring/springdslAdditional.adoc | 2 +- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/en/guide/services/declarativeTransactions/transactionsRollbackAndTheSession.adoc b/src/en/guide/services/declarativeTransactions/transactionsRollbackAndTheSession.adoc index e8a87969b72..612fba08e4c 100644 --- a/src/en/guide/services/declarativeTransactions/transactionsRollbackAndTheSession.adoc +++ b/src/en/guide/services/declarativeTransactions/transactionsRollbackAndTheSession.adoc @@ -54,7 +54,7 @@ class AuthorService { ---- class AuthorController { - def authorService + AuthorService authorService def updateAge() { try { @@ -110,7 +110,7 @@ In this case a new request will deal with retrieving the `Author` again. And, fi ---- class AuthorController { - def authorService + AuthorService authorService def updateAge() { try { @@ -154,7 +154,7 @@ import grails.validation.ValidationException class AuthorController { - def authorService + AuthorService authorService def updateAge() { try { diff --git a/src/en/guide/services/dependencyInjectionServices.adoc b/src/en/guide/services/dependencyInjectionServices.adoc index c7eddd7a99a..e8028865699 100644 --- a/src/en/guide/services/dependencyInjectionServices.adoc +++ b/src/en/guide/services/dependencyInjectionServices.adoc @@ -1,20 +1,19 @@ ==== Dependency Injection Basics - A key aspect of Grails services is the ability to use http://www.springframework.org/[Spring Framework]'s dependency injection features. Grails supports "dependency injection by convention". In other words, you can use the property name representation of the class name of a service to automatically inject them into controllers, tag libraries, and so on. -As an example, given a service called `BookService`, if you define a property called `bookService` in a controller as follows: +As an example, given a service called `BookService`, you can define a property called `bookService` in a controller as follows: [source,groovy] ---- class BookController { - def bookService + BookService bookService ... } ---- -In this case, the Spring container will automatically inject an instance of that service based on its configured scope. All dependency injection is done by name. You can also specify the type as follows: +In this case, the Spring container will automatically inject an instance of that service based on its configured scope. Since all dependency injection is done by name you can also specify the type as follows: [source,groovy] ---- @@ -33,56 +32,51 @@ NOTE: Only the top level object is subjected to injection as traversing all nest Be careful when injecting the non-default datasources. For example, using this config: -[source,groovy] +[source,yaml] ---- dataSources: dataSource: pooled: true jmxExport: true - ..... + ... secondary: pooled: true jmxExport: true - ..... + ... ---- You can inject the primary `dataSource` like you would expect: -[source,java] +[source,groovy] ---- class BookSqlService { - - def dataSource + DataSource dataSource } ---- But to inject the `secondary` datasource, you have to use Spring's `Autowired` injection or `resources.groovy`. -[source,java] +[source,groovy] ---- class BookSqlSecondaryService { @Autowired @Qualifier('dataSource_secondary') - def dataSource2 + DataSource dataSource2 } ---- - - ==== Dependency Injection and Services - You can inject services in other services with the same technique. If you had an `AuthorService` that needed to use the `BookService`, declaring the `AuthorService` as follows would allow that: [source,groovy] ---- class AuthorService { - def bookService + BookService bookService } ---- - ==== Dependency Injection and Domain Classes / Tag Libraries You can even inject services into domain classes and tag libraries, which can aid in the development of rich domain models and views: @@ -91,7 +85,7 @@ You can even inject services into domain classes and tag libraries, which can ai ---- class Book { ... - def bookService + BookService bookService def buyBook() { bookService.buyBook(this) @@ -103,7 +97,6 @@ WARNING: Since Grails 3.2.8 this is not enabled by default. If you want to enabl ==== Service Bean Names - The default bean name which is associated with a service can be problematic if there are multiple services with the same name defined in different packages. For example consider the situation where an application defines a service class named `com.demo.ReportingService` and the application uses a plugin named `ReportingUtilities` and that plugin provides a service class named `com.reporting.util.ReportingService`. The default bean name for each of those would be `reportingService` so they would conflict with each other. Grails manages this by changing the default bean name for services provided by plugins by prefixing the bean name with the plugin name. diff --git a/src/en/guide/spring/springdslAdditional.adoc b/src/en/guide/spring/springdslAdditional.adoc index 5d6f7c84bde..2be122f5849 100644 --- a/src/en/guide/spring/springdslAdditional.adoc +++ b/src/en/guide/spring/springdslAdditional.adoc @@ -153,7 +153,7 @@ package my.company class MyBeanImpl { Integer someProperty String otherProperty - BookService bookService // or just "def bookService" + BookService bookService } ---- From 2f3eb5534622fcc6048c7c6a2908c0b985793d70 Mon Sep 17 00:00:00 2001 From: James Fredley Date: Wed, 5 Feb 2025 13:52:45 -0500 Subject: [PATCH 3/4] Update to actions/upload-artifact@v4 --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index ba83b803ebd..170ee74702c 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -37,7 +37,7 @@ jobs: -PgithubBranch=${{ steps.extract_branch.outputs.value }} - name: Upload Docs Artifacts if: success() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: grails-docs-${{ env.NOW }}.zip path: ./build/distributions/*.zip From 08ecd01f1b7fea3f4fc37ba4c480e69adf58bcf7 Mon Sep 17 00:00:00 2001 From: "g.sartori" Date: Sun, 9 Feb 2025 18:47:13 +0100 Subject: [PATCH 4/4] Removed @CompileStatic to make the example code compile --- src/en/ref/Database Mapping/column.adoc | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/en/ref/Database Mapping/column.adoc b/src/en/ref/Database Mapping/column.adoc index e11b4355821..f53e6ff7431 100644 --- a/src/en/ref/Database Mapping/column.adoc +++ b/src/en/ref/Database Mapping/column.adoc @@ -79,9 +79,6 @@ Given the next code: ---- package demo -import groovy.transform.CompileStatic - -@CompileStatic class BootStrap { def init = {