如何在Grails中的控制器中调用服务?
我正在用Grails编写一个REST客户机,我需要使用OAUTH与第三方CRM集成,所以我使用的是HTTPBuilder。我想将OAUTH内容抽象为一个服务,并使令牌和实例url可用于控制器和视图 这是我的服务:如何在Grails中的控制器中调用服务?,grails,oauth,Grails,Oauth,我正在用Grails编写一个REST客户机,我需要使用OAUTH与第三方CRM集成,所以我使用的是HTTPBuilder。我想将OAUTH内容抽象为一个服务,并使令牌和实例url可用于控制器和视图 这是我的服务: import org.springframework.transaction.annotation.Transactional; import groovyx.net.http.HTTPBuilder import groovyx.net.http.HttpResponseExcep
import org.springframework.transaction.annotation.Transactional;
import groovyx.net.http.HTTPBuilder
import groovyx.net.http.HttpResponseException
import static groovyx.net.http.ContentType.URLENC
import static groovyx.net.http.Method.POST
import static groovyx.net.http.Method.GET
import static groovyx.net.http.ContentType.JSON
class APIConnectorService {
def sf_login_domain = 'STUFFTHATWORKS'
def instance_domain
def access_token = ''
def consumer_key = 'STUFFTHATWORKS'
def consumer_secret = 'STUFFTHATWORKS'
def auth_username = 'STUFFTHATWORKS'
def auth_password = 'STUFFTHATWORKS'
def serviceMethod() {
//Request Access_token and instance domain for work
def http = new HTTPBuilder(sf_login_domain)
def postBody = [
grant_type: 'password',
client_id: consumer_key,
client_secret: consumer_secret,
username: auth_username,
password: auth_password+auth_security_token
]
try{
http.post( path : 'services/oauth2/token',
body : postBody,
requestContentType: URLENC) { resp, json ->
access_token = json.access_token
instance_domain = json.instance_url +"/"
}
}catch(HttpResponseException e){
println "Error code: ${e.statusCode}"
println "Post form: $postBody"
}
println "Access Token $access_token"
println "Instance domain $instance_domain \n"
}
}
这是我的控制器
import groovyx.net.http.HTTPBuilder
import groovyx.net.http.HttpResponseException
import static groovyx.net.http.ContentType.URLENC
import static groovyx.net.http.Method.POST
import static groovyx.net.http.Method.GET
import static groovyx.net.http.ContentType.JSON
class APIConnectorController {
def APIConnectorService
def index(){
http = new HTTPBuilder(APIConnectorService.serviceMethod())
http.request(GET,JSON) { req ->
uri.path = 'services/data/v28.0/'
headers['Authorization'] = "Bearer $access_token"
response.success = { resp, json ->
assert resp.status == 200
json.each{ key,value ->
render(view:"index", model: [json: json])
}
}
response.failure = { resp, json ->
println resp.status
println json.errorCode
println json.message
}
}
}
}
因此,当我将所有服务代码直接包含在控制器中时,它会以我希望的方式运行,但正如我所说的,我希望将OAUTH令牌生成抽象为一个服务(至少,这对我来说最有意义)
我在尝试上述配置时遇到此错误
ERROR errors.GrailsExceptionResolver - MissingMethodException occurred when processing request: [GET] /SFAPITest/APIConnector
No signature of method: sfapitest.APIConnectorController.HTTPBuilder() is applicable for argument types: (null) values: [null]. Stacktrace follows:
Message: No signature of method: sfapitest.APIConnectorController.HTTPBuilder() is applicable for argument types: (null) values: [null]
更新
我正在获取从服务传递到控制器的访问令牌和实例域,但现在我得到了错误:
ERROR errors.GrailsExceptionResolver - MissingMethodException occurred when processing request: [GET] /SFAPITest/ApiConnector
No signature of method: sfapitest.ApiConnectorController.HTTPBuilder() is applicable for argument types: (java.lang.String) values: [https://scholastica--FullBox.cs16.my.salesforce.com/]. Stacktrace follows:
Message: No signature of method: sfapitest.ApiConnectorController.HTTPBuilder() is applicable for argument types: (java.lang.String) values: [https://ourschool--FullBox.cs16.my.forcefulCRM.com/]
这是我的最新服务
package sfapitest
import groovyx.net.http.HTTPBuilder
import groovyx.net.http.HttpResponseException
import static groovyx.net.http.ContentType.URLENC
import static groovyx.net.http.Method.POST
import static groovyx.net.http.Method.GET
import static groovyx.net.http.ContentType.JSON
class ApiConnectorService {
def transactional = false
def sf_login_domain = 'STUFFTHATWORKS'
def instance_domain
def access_token = ''
def consumer_key = 'STUFFTHATWORKS'
def consumer_secret = 'STUFFTHATWORKS'
def auth_username = 'STUFFTHATWORKS'
def auth_password = 'STUFFTHATWORKS'
def auth_security_token = 'STUFFTHATWORKS'
def api_token_path = 'services/oauth2/token'
def oauthObject
def serviceMethod() {
//Request Access_token and instance domain for work
def http = new HTTPBuilder(sf_login_domain)
def postBody = [
grant_type: 'password',
client_id: consumer_key,
client_secret: consumer_secret,
username: auth_username,
password: auth_password+auth_security_token
]
try{
http.post( path : api_token_path,
body : postBody,
requestContentType: URLENC) { resp, json ->
access_token = json.access_token
instance_domain = json.instance_url +"/"
}
oauthObject = [access_token, instance_domain]
}catch(HttpResponseException e){
println "Error code: ${e.statusCode}"
println "Post form: $postBody"
}
return oauthObject
}
}
因此,感谢下面的建议,我将把access_令牌和instance_域的数组返回给serviceMethod()
这是我的控制器:
package sfapitest
import groovyx.net.http.HTTPBuilder
import groovyx.net.http.HttpResponseException
import static groovyx.net.http.ContentType.URLENC
import static groovyx.net.http.Method.POST
import static groovyx.net.http.Method.GET
import static groovyx.net.http.ContentType.JSON
class ApiConnectorController {
def apiConnectorService
def index(){
def access_token = apiConnectorService.serviceMethod()[0]
def instance_domain = apiConnectorService.serviceMethod()[1]
http = HTTPBuilder(instance_domain)
http.request(GET,JSON) { req ->
uri.path = 'services/data/v28.0/'
headers['Authorization'] = "Bearer $access_token"
response.success = { resp, json ->
assert resp.status == 200
json.each{ key,value ->
render(view:"index", model: [json: json])
}
}
response.failure = { resp, json ->
println resp.status
println json.errorCode
println json.message
}
}
}
}
MissingMethodException可能意味着我没有正确数量的参数。我可以从cotroller呈现access_令牌和instance_域,它们显示正确的值。任何关于如何使这项工作更有效、更优雅的提示和建议都将不胜感激。我的目标是制作一个RESTful/OAUTH应用程序,可以用于各种第三方Web服务集成。我认为问题在于您声明您的服务的方式
APIConnectorService apiConnectorService
def aPIConnectorService
而不是
def APIConnectorService
最好将服务名称更改为ApiConnectorService,并在控制器中声明,如下所示
def apiConnectorService
您的serviceMethod的最后一个操作是导致返回null的println。
要访问http builder对象,您必须在post请求成功后返回它。您正在将
APIConnectorService.serviceMethod()
作为参数传递到中
http = new HTTPBuilder(APIConnectorService.serviceMethod())
您的方法serviceMethod()
不返回任何内容,因此我认为您会遇到此错误
serviceMethod()
应返回objectdefaultURI
创建具有空默认URI的新实例
HTTPBuilder(Object defaultURI)
为所有不显式接受URI参数的请求方法提供一个默认URI
HTTPBuilder(Object defaultURI, Object defaultContentType)
为所有未显式接受URI参数的请求方法提供一个默认URI,并为请求编码和响应解析提供一个默认内容类型。可能是由于没有遵循正确的命名约定造成的
第一个建议是通过遵循类命名约定来更改服务名称
ApiConnectorService
然后在控制器中为您的服务使用camel case声明
def apiConnectorService
def http = new HTTPBuilder(instance_domain)
http.request(GET,JSON) { req ->
uri.path = 'services/data/v28.0/'
headers['Authorization'] = "Bearer $access_token"
grails使用其约定查找名称及其类
也可以尝试使用
APIConnectorService apiConnectorService
好的,经过多次尝试、出错和解析HTTPBuilder文档之后,最后一步是在我的控制器中正确定义新的HTTPBuilder()实例
def apiConnectorService
def http = new HTTPBuilder(instance_domain)
http.request(GET,JSON) { req ->
uri.path = 'services/data/v28.0/'
headers['Authorization'] = "Bearer $access_token"
这现在允许我将OAUTH组件从控制器中抽象出来。我绝对相信,对于我想要实现的目标,有一个更优雅的解决方案。我很想听到一些关于如何清理的建议
- 我是否需要在服务和控制器中导入李>
- OAUTH可以放在config.groovy中吗
在省略了println之后,我从服务中获得了一些信息,而不是我想要的对象元素。我怎样才能干净利落地归还物品?Stacktrace如下所示:消息:没有方法的签名:sfapitest.ApiConnectorController.HTTPBuilder()适用于参数类型:(java.lang.String)值:['@Lorenzo,我现在将访问令牌和实例域从服务返回给控制器。谢谢!但我得到错误“没有方法签名:ApiConnectorController.HTTPBuilder()适用于参数类型:(java.lang.String)值:[”