Skip to content

Commit e9e015c

Browse files
authored
Merge pull request #15245 from codeconsole/7.1.x-scaffold-service-controller
7.1.x @scaffold Services and Controllers
2 parents 1b67ebd + 3c29ede commit e9e015c

File tree

18 files changed

+976
-47
lines changed

18 files changed

+976
-47
lines changed

grails-doc/src/en/guide/scaffolding.adoc

Lines changed: 151 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,14 @@ dependencies {
3636

3737
==== Dynamic Scaffolding
3838

39-
40-
The simplest way to get started with scaffolding is to enable it by setting the `scaffold` property in the controller to a specific domain class:
39+
The simplest way to get started with scaffolding is to use the `@Scaffold` annotation on a controller:
4140

4241
[source,groovy]
4342
----
43+
import grails.plugin.scaffolding.annotation.Scaffold
44+
45+
@Scaffold(Book)
4446
class BookController {
45-
static scaffold = Book // Or any other domain class such as "Author", "Publisher"
4647
}
4748
----
4849

@@ -58,45 +59,115 @@ With this configured, when you start your application the actions and views will
5859

5960
A CRUD interface will also be generated. To access this open `http://localhost:8080/book` in a browser.
6061

61-
Note: The old alternative of defining `scaffold` property:
62+
If you prefer to keep your domain model in Java and https://hibernate.org/[mapped with Hibernate] you can still use scaffolding, simply import the domain class and use it in the `@Scaffold` annotation.
63+
64+
===== Legacy Static Scaffold Property
65+
66+
The older `static scaffold = Book` syntax is still supported but the `@Scaffold` annotation is preferred:
67+
68+
[source,groovy]
69+
----
70+
class BookController {
71+
static scaffold = Book // Legacy syntax - @Scaffold annotation is preferred
72+
}
73+
----
74+
75+
NOTE: The `static scaffold = true` form is not supported in Grails 3.0 and above.
76+
77+
===== Scaffolded Services
78+
79+
In addition to controllers, you can also scaffold services using the `@Scaffold` annotation:
80+
81+
[source,groovy]
82+
----
83+
import grails.plugin.scaffolding.annotation.Scaffold
84+
85+
@Scaffold(Book)
86+
class BookService {
87+
}
88+
----
89+
90+
This generates a service that extends `grails.plugin.scaffolding.GormService` and provides standard CRUD operations:
91+
92+
* `get(id)` - Retrieve by ID
93+
* `list(Map args)` - List with pagination/sorting
94+
* `count(Map args)` - Count entities
95+
* `save(instance)` - Create or update
96+
* `delete(id)` - Delete by ID
97+
98+
===== Service-Backed Controllers
99+
100+
For better separation of concerns, you can create controllers that delegate to a scaffolded service using `RestfulServiceController`:
62101

63102
[source,groovy]
64103
----
104+
import grails.plugin.scaffolding.annotation.Scaffold
105+
import grails.plugin.scaffolding.RestfulServiceController
106+
107+
@Scaffold(RestfulServiceController<Book>)
65108
class BookController {
66-
static scaffold = true
67109
}
68110
----
69111

70-
is no longer supported above Grails 3.0.
112+
This controller will automatically locate and use the corresponding `BookService` for all data operations.
71113

72-
If you prefer to keep your domain model in Java and https://hibernate.org/[mapped with Hibernate] you can still use scaffolding, simply import the domain class and set its name as the `scaffold` argument.
114+
===== Extending Custom Classes
73115

74-
You can add new actions to a scaffolded controller, for example:
116+
You can specify a custom class to extend for your scaffolded controllers or services:
75117

76118
[source,groovy]
77119
----
120+
import grails.plugin.scaffolding.annotation.Scaffold
121+
import com.example.MyCustomService
122+
123+
@Scaffold(MyCustomService<Book>)
124+
class BookService {
125+
}
126+
----
127+
128+
===== Read-Only Mode
129+
130+
You can create read-only scaffolded controllers or services:
131+
132+
[source,groovy]
133+
----
134+
import grails.plugin.scaffolding.annotation.Scaffold
135+
136+
@Scaffold(domain = Book, readOnly = true)
78137
class BookController {
138+
}
139+
----
140+
141+
===== Adding Custom Actions
79142

80-
static scaffold = Book
143+
You can add new actions to a scaffolded controller:
144+
145+
[source,groovy]
146+
----
147+
import grails.plugin.scaffolding.annotation.Scaffold
148+
149+
@Scaffold(Book)
150+
class BookController {
81151
82152
def changeAuthor() {
83153
def b = Book.get(params.id)
84154
b.author = Author.get(params["author.id"])
85155
b.save()
86156
87157
// redirect to a scaffolded action
88-
redirect(action:show)
89-
}
158+
redirect(action: 'show')
159+
}
90160
}
91161
----
92162

93163
You can also override the scaffolded actions:
94164

95165
[source,groovy]
96166
----
97-
class BookController {
167+
import grails.plugin.scaffolding.annotation.Scaffold
98168
99-
static scaffold = Book
169+
@Scaffold(Book)
170+
class BookController {
100171
101172
// overrides scaffolded action to return both authors and books
102173
def index() {
@@ -108,7 +179,7 @@ class BookController {
108179
def show() {
109180
def book = Book.get(params.id)
110181
log.error("{}", book)
111-
[bookInstance : book]
182+
[bookInstance: book]
112183
}
113184
}
114185
----
@@ -122,35 +193,96 @@ Also, the standard scaffold views expect model variables of the form `<propertyN
122193

123194
==== Static Scaffolding
124195

196+
Grails lets you generate a controller and the views used to create the above interface from the command line.
125197

126-
Grails lets you generate a controller and the views used to create the above interface from the command line. To generate a controller type:
198+
===== Generating Controllers and Views
127199

128-
[source,groovy]
200+
To generate a controller type:
201+
202+
[source,bash]
129203
----
130204
grails generate-controller Book
131205
----
132206

133207
or to generate the views:
134208

135-
[source,groovy]
209+
[source,bash]
136210
----
137211
grails generate-views Book
138212
----
139213

140214
or to generate everything:
141215

142-
[source,groovy]
216+
[source,bash]
143217
----
144218
grails generate-all Book
145219
----
146220

147221
If you have a domain class in a package or are generating from a https://hibernate.org[Hibernate mapped class] remember to include the fully qualified package name:
148222

149-
[source,groovy]
223+
[source,bash]
150224
----
151225
grails generate-all com.bookstore.Book
152226
----
153227

228+
===== Generating Scaffolded Controllers and Services
229+
230+
To generate a scaffolded controller (using `@Scaffold` annotation):
231+
232+
[source,bash]
233+
----
234+
grails create-scaffold-controller Book
235+
----
236+
237+
To generate a scaffolded service:
238+
239+
[source,bash]
240+
----
241+
grails create-scaffold-service Book
242+
----
243+
244+
To generate both a scaffolded service and controller together:
245+
246+
[source,bash]
247+
----
248+
grails generate-scaffold-all Book
249+
----
250+
251+
===== Command Options
252+
253+
The `create-scaffold-controller` command supports the following options:
254+
255+
* `--force` - Overwrite existing files
256+
* `--namespace` - Set the controller namespace
257+
* `--service` - Use `grails.plugin.scaffolding.RestfulServiceController` instead of `grails.rest.RestfulController`
258+
* `--extends` - Specify a custom class to extend (default: `grails.rest.RestfulController`)
259+
260+
The `create-scaffold-service` command supports:
261+
262+
* `--force` - Overwrite existing files
263+
* `--extends` - Specify a custom class to extend (default: `grails.plugin.scaffolding.GormService`)
264+
265+
The `generate-scaffold-all` command supports:
266+
267+
* `--force` - Overwrite existing files
268+
* `--namespace` - Set the controller namespace
269+
* `--serviceExtends` - Specify a custom class to extend for the service (default: `grails.plugin.scaffolding.GormService`)
270+
* `--controllerExtends` - Specify a custom class to extend for the controller (default: `grails.plugin.scaffolding.RestfulServiceController`)
271+
272+
Examples:
273+
274+
[source,bash]
275+
----
276+
# Generate a scaffolded controller that uses a service
277+
grails create-scaffold-controller Book --service
278+
279+
# Generate with a custom class to extend
280+
grails create-scaffold-service Book --extends=com.example.MyCustomService
281+
282+
# Generate both with namespace
283+
grails generate-scaffold-all Book --namespace=api
284+
----
285+
154286

155287
==== Customizing the Generated Views
156288

0 commit comments

Comments
 (0)