2014-05-12 46 views
1

我在Grails中編寫了一個REST客戶端,我需要使用OAUTH與第三方CRM進行集成,所以我使用的是HTTP-Builder。我想抽象OAUTH的東西到一個服務,並使令牌和instance_url控制器和視圖可用。如何在Grails中的控制器中調用服務?

這裏是我的服務:

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_token和instance _domain的數組返回給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_token和instance_domain,並顯示正確的值。任何有關如何使這項工作和更優雅的提示和指針將不勝感激。我的目標是製作可用於各種第三方Web服務集成的RESTful/OAuth應用程序。

+0

@Lorenzo,我現在將access_token和instance_domain從服務返回到控制器。謝謝!但是我得到錯誤'沒有方法的簽名:ApiConnectorController.HTTPBuilder()適用於參數類型:(java.lang.String)values:[https://ourschool--FullBox.cs16.my.forcefulCRM.com /]' – Baci

回答

0

我覺得問題是你已經宣佈使用

def APIConnectorService

最佳

def aPIConnectorService

,而不是將更改服務名稱爲您服務靠緊ApiConnectorService方式並在控制器中聲明如下

def apiConnectorService

0

您的serviceMethod的最後一個操作是println,它導致返回null。 要訪問http-builder對象,必須在成功發送後請求後將其返回。

+0

在省略printlns之後,我從服務中獲取_something_,而不是我想要的對象元素。我該如何清理_return_對象? Stacktrace如下: 消息:沒有方法的簽名:sfapitest.ApiConnectorController.HTTPBuilder()適用於參數類型:(java.lang.String)values:[https:// ourschool - FullBox。cs16.my.forcefulCRM.com/]」 – Baci

1

你傳入APIConnectorService.serviceMethod()爲參數

http = new HTTPBuilder(APIConnectorService.serviceMethod()) 

你的方法serviceMethod()returns沒什麼所以這就是爲什麼我認爲你得到這個錯誤。

serviceMethod()應該返回Object defaultURI

HttpBuilder API

HTTPBuilder() 

創建一個新的實例與空默認URI。

HTTPBuilder(Object defaultURI) 

給出一個默認的URI,用於所有不明確使用URI參數的請求方法。

HTTPBuilder(Object defaultURI, Object defaultContentType) 

給一個默認URI用於不明確地採取URI參數的所有請求的方法,以及用於請求編碼和響應解析默認的內容類型。

0

可能是由於未遵循適當的命名約定而導致的。

第一個建議是按照類命名約定更改服務名稱。

ApiConnectorService 

然後在控制器中爲您的服務使用駱駝大小寫聲明。

def apiConnectorService 

grails使用其約定來查找名稱及其類。

同時嘗試使用

APIConnectorService apiConnectorService 
1

好,很多試驗,故障後和解析HTTPBuilder文檔,最後一塊是在我的控制器正確定義新HTTPBuilder()實例。

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中嗎?
相關問題