-
Notifications
You must be signed in to change notification settings - Fork 48
/
JaxrsGrailsPlugin.groovy
250 lines (213 loc) · 8.7 KB
/
JaxrsGrailsPlugin.groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
import org.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet
import org.grails.jaxrs.ProviderArtefactHandler
import org.grails.jaxrs.ResourceArtefactHandler
import org.grails.jaxrs.generator.CodeGenerator
import org.grails.jaxrs.provider.*
import org.grails.jaxrs.web.JaxrsContext
import org.grails.jaxrs.web.JaxrsFilter
import org.grails.jaxrs.web.JaxrsListener
import static org.grails.jaxrs.web.JaxrsUtils.JAXRS_CONTEXT_NAME
class JaxrsGrailsPlugin {
def groupId = "org.grails.plugins"
def version = "0.11"
def grailsVersion = "2.4 > *"
def pluginExcludes = [
"grails-app/domain/*",
"grails-app/providers/*",
"grails-app/resources/*",
"src/groovy/org/grails/jaxrs/test/*",
"lib/*-sources.jar",
"web-app/**"
]
def loadAfter = ['controllers', 'services', 'spring-security-core']
def artefacts = [
new ResourceArtefactHandler(),
new ProviderArtefactHandler()
]
def watchedResources = [
"file:./grails-app/resources/**/*Resource.groovy",
"file:./grails-app/providers/**/*Reader.groovy",
"file:./grails-app/providers/**/*Writer.groovy",
"file:./plugins/*/grails-app/resources/**/*Resource.groovy",
"file:./plugins/*/grails-app/providers/**/*Reader.groovy",
"file:./plugins/*/grails-app/providers/**/*Writer.groovy"
]
def author = "Martin Krasser"
def authorEmail = "krasserm@googlemail.com"
def title = "JSR 311 plugin"
def description = """
A plugin that supports the development of RESTful web services based on the
Java API for RESTful Web Services (JSR 311: JAX-RS). It is targeted at
developers who want to structure the web service layer of an application in
a JSR 311 compatible way but still want to continue to use Grails' powerful
features such as GORM, automated XML and JSON marshalling, Grails services,
Grails filters and so on. This plugin is an alternative to Grails' built-in
mechanism for implementing RESTful web services.
At the moment, plugin users may choose between Jersey and Restlet as JAX-RS
implementation. Both implementations are packaged with the plugin. Support for
Restlet was added in version 0.2 of the plugin in order to support deployments
on the Google App Engine. Other JAX-RS implementations such as RestEasy or
Apache Wink are likely to be added in upcoming versions of the plugin.
"""
def developers = [
[name: 'Davide Cavestro', email: 'davide.cavestro@gmail.com'],
[name: 'Noam Y. Tenne', email: 'noam@10ne.org']
]
def documentation = 'https://github.com/krasserm/grails-jaxrs/wiki'
def issueManagement = [url: 'https://github.com/krasserm/grails-jaxrs/issues']
def scm = [url: 'https://github.com/krasserm/grails-jaxrs']
/**
* Adds the JaxrsFilter and JaxrsListener to the web application
* descriptor.
*/
def doWithWebDescriptor = { xml ->
def lastListener = xml.'listener'.iterator().toList().last()
lastListener + {
'listener' {
'listener-class'(JaxrsListener.name)
}
}
def firstFilter = xml.'filter'[0]
firstFilter + {
'filter' {
'filter-name'('jaxrsFilter')
'filter-class'(JaxrsFilter.name)
}
}
def firstFilterMapping = xml.'filter-mapping'[0]
firstFilterMapping + {
'filter-mapping' {
'filter-name'('jaxrsFilter')
'url-pattern'('/*')
'dispatcher'('FORWARD')
'dispatcher'('REQUEST')
}
}
def grailsServlet = xml.servlet.find { servlet ->
'grails'.equalsIgnoreCase(servlet.'servlet-name'.text())
}
// reload default GrailsDispatcherServlet adding 'dispatchOptionsRequest':'true'
grailsServlet.replaceNode { node ->
'servlet' {
'servlet-name'('grails')
'servlet-class'(GrailsDispatcherServlet.name)
'init-param' {
'param-name'('dispatchOptionsRequest')
'param-value'('true')
}
'load-on-startup'('1')
}
}
}
/**
* Adds the JaxrsContext and plugin- and application-specific JAX-RS
* resource and provider classes to the application context.
*/
def doWithSpring = {
// Configure the JAX-RS context
'jaxrsContext'(JaxrsContext)
// Configure default providers
"${XMLWriter.name}"(XMLWriter)
"${XMLReader.name}"(XMLReader)
"${JSONWriter.name}"(JSONWriter)
"${JSONReader.name}"(JSONReader)
"${DomainObjectReader.name}"(DomainObjectReader)
"${DomainObjectWriter.name}"(DomainObjectWriter)
// Configure application-provided resources
application.resourceClasses.each { rc ->
"${rc.propertyName}"(rc.clazz) { bean ->
bean.scope = owner.getResourceScope(application)
bean.autowire = true
}
}
// Configure application-provided providers
application.providerClasses.each { pc ->
"${pc.propertyName}"(pc.clazz) { bean ->
bean.scope = 'singleton'
bean.autowire = true
}
}
// Configure the resource code generator
"${CodeGenerator.name}"(CodeGenerator)
}
/**
* Updates application-specific JAX-RS resource and provider classes in
* the application context.
*/
def onChange = { event ->
if (!event.ctx) {
return
}
if (application.isArtefactOfType(ResourceArtefactHandler.TYPE, event.source)) {
def resourceClass = application.addArtefact(ResourceArtefactHandler.TYPE, event.source)
beans {
"${resourceClass.propertyName}"(resourceClass.clazz) { bean ->
bean.scope = owner.getResourceScope(application)
bean.autowire = true
}
}.registerBeans(event.ctx)
} else if (application.isArtefactOfType(ProviderArtefactHandler.TYPE, event.source)) {
def providerClass = application.addArtefact(ProviderArtefactHandler.TYPE, event.source)
beans {
"${providerClass.propertyName}"(providerClass.clazz) { bean ->
bean.scope = 'singleton'
bean.autowire = true
}
}.registerBeans(event.ctx)
} else {
return
}
// Setup the JaxrsConfig
doWithApplicationContext(event.ctx)
// Resfresh the JaxrsContext
event.ctx.getBean(JAXRS_CONTEXT_NAME).refresh()
}
/**
* Reconfigures the JaxrsConfig with plugin- and application-specific
* JAX-RS resource and provider classes. Configures the JaxrsContext
* with the JAX-RS implementation to use. The name of the JAX-RS
* implementation is obtained from the configuration property
* <code>org.grails.jaxrs.provider.name</code>. Default value is
* <code>jersey</code>.
*/
def doWithApplicationContext = { applicationContext ->
def context = applicationContext.getBean(JAXRS_CONTEXT_NAME)
def config = context.jaxrsConfig
context.jaxrsProviderName = getProviderName(application)
context.jaxrsProviderExtraPaths = getProviderExtraPaths(application)
context.jaxrsProviderInitParameters = getProviderInitParameters(application)
config.reset()
config.classes << XMLWriter
config.classes << XMLReader
config.classes << JSONWriter
config.classes << JSONReader
config.classes << DomainObjectReader
config.classes << DomainObjectWriter
application.getArtefactInfo('Resource').classesByName.values().each { clazz ->
config.classes << clazz
}
application.getArtefactInfo('Provider').classesByName.values().each { clazz ->
config.classes << clazz
}
}
private String getResourceScope(application) {
def scope = application.config.org.grails.jaxrs.resource.scope
if (!scope) {
scope = 'prototype'
}
scope
}
private String getProviderName(application) {
def name = application.config.org.grails.jaxrs.provider.name
if (!name) {
name = JaxrsContext.JAXRS_PROVIDER_NAME_JERSEY
}
name
}
private String getProviderExtraPaths(application) {
application.config.org.grails.jaxrs.provider.extra.paths
}
private Map<String, String> getProviderInitParameters(application) {
application.config.org.grails.jaxrs.provider.init.parameters
}
}