インポートした WSDL からの非同期コールアウトの実行
Salesforce で WSDL をインポートすると、Salesforce によって、インポートされた WSDL の各名前空間用に 2 つの Apex クラスが自動生成されます。一方のクラスは同期サービス用のサービスクラスです。もう一方のクラスは、非同期サービス用に変更されたバージョンです。自動生成された非同期クラス名は、Async プレフィックスで開始し、AsyncServiceName の形式になります。ServiceName は、変更前の元のサービスクラスの名前です。非同期クラスは、次のさまざまな点で標準クラスと異なります。
- 公開サービスメソッドには、追加の Continuation パラメータが第 1 パラメータとして含まれます。
- Web サービス処理は非同期に呼び出され、その応答はレスポンス要素の getValue メソッドで取得されます。
- WebServiceCallout.beginInvoke および WebServiceCallout.endInvoke は、それぞれサービスの呼び出しと応答の取得に使用されます。
Salesforce ユーザインターフェースで WSDL から Apex クラスを生成できます。[設定] から、[クイック検索] ボックスに「Apex クラス」と入力し、[Apex クラス] を選択します。
非同期 Web サービスコールアウトを実行するには、自動生成された非同期クラスのメソッドに Continuation インスタンスを渡してこれらのメソッドをコールします。次の例は、架空の��価情報サービスに基づいています。この例では、組織に WSDL インポートで自動生成された AsyncSOAPStockQuoteService というクラスがあることを想定しています。この例は、自動生成された AsyncSOAPStockQuoteService クラスを使用してサービスへの非同期コールアウトを実行する方法を示します。最初に、60 秒でタイムアウトする継続を作成し、コールバックメソッドを設定します。次に、beginStockQuote メソッドを継続インスタンスに渡して呼び出します。beginStockQuote メソッドコールは、非同期コールアウト実行に対応します。
1public Continuation startRequest() {
2 Integer TIMEOUT_INT_SECS = 60;
3 Continuation cont = new Continuation(TIMEOUT_INT_SECS);
4 cont.continuationMethod = 'processResponse';
5
6 AsyncSOAPStockQuoteService.AsyncStockQuoteServiceSoap
7 stockQuoteService =
8 new AsyncSOAPStockQuoteService.AsyncStockQuoteServiceSoap();
9 stockQuoteFuture = stockQuoteService.beginStockQuote(cont,'CRM');
10
11 return cont;
12}外部サービスが非同期コールアウト (beginStockQuote メソッド) の応答を返すと、このコールバックメソッドが実行されます。応答は、応答オブジェクトに対して getValue メソッドをコールすることで取得されます。
1public Object processResponse() {
2 result = stockQuoteFuture.getValue();
3 return null;
4}次に、アクションおよびコールバックメソッドを含むコントローラ全体を示します。
1public class ContinuationSOAPController {
2
3 AsyncSOAPStockQuoteService.GetStockQuoteResponse_elementFuture
4 stockQuoteFuture;
5 public String result {get;set;}
6
7 // Action method
8 public Continuation startRequest() {
9 Integer TIMEOUT_INT_SECS = 60;
10 Continuation cont = new Continuation(TIMEOUT_INT_SECS);
11 cont.continuationMethod = 'processResponse';
12
13 AsyncSOAPStockQuoteService.AsyncStockQuoteServiceSoap
14 stockQuoteService =
15 new AsyncSOAPStockQuoteService.AsyncStockQuoteServiceSoap();
16 stockQuoteFuture = stockQuoteService.beginGetStockQuote(cont,'CRM');
17 return cont;
18 }
19
20 // Callback method
21 public Object processResponse() {
22 result = stockQuoteFuture.getValue();
23 // Return null to re-render the original Visualforce page
24 return null;
25 }
26}次の例は、対応する Visualforce ページを示します。このページは startRequest メソッドを呼び出し、結果項目を表示します。
1<apex:page controller="ContinuationSOAPController" showChat="false" showHeader="false">
2 <apex:form >
3 <!-- Invokes the action method when the user clicks this button. -->
4 <apex:commandButton action="{!startRequest}"
5 value="Start Request" reRender="result"/>
6 </apex:form>
7
8 <!-- This output text component displays the callout response body. -->
9 <apex:outputText value="{!result}" />
10</apex:page>WSDL ベースの非同期コールアウトのテスト
WSDL から Apex クラスに基づく非同期コールアウトをテストするのは、HttpRequest クラスに基づくコールアウトで使用するプロセスと似ています。ContinuationSOAPController.cls をテストする前に、WebServiceMock を実装するクラスを作成します。このクラスにより ContinuationTestForWSDL.cls の安全なテストが可能になります。ContinuationTestForWSDL.cls についてはこの後、疑似継続を作成し、テストによる実質的な影響がないことを確認する方法で作成します。
1public class AsyncSOAPStockQuoteServiceMockImpl implements WebServiceMock {
2 public void doInvoke(
3 Object stub,
4 Object request,
5 Map<String, Object> response,
6 String endpoint,
7 String soapAction,
8 String requestName,
9 String responseNS,
10 String responseName,
11 String responseType) {
12 // do nothing
13 }
14}次の例は、ContinuationSOAPController コントローラに対応するテストクラスです。このクラスのテストメソッドは疑似応答を設定し、疑似継続を呼び出します。コールアウトは外部サービスには送信されません。疑似コールアウトを実行するには、テストで Test クラスの setContinuationResponse(requestLabel, mockResponse) および invokeContinuationMethod(controller, request) メソッドをコールします。
1@isTest
2public class ContinuationTestingForWSDL {
3 public static testmethod void testWebService() {
4
5 ContinuationSOAPController demoWSDLClass =
6 new ContinuationSOAPController();
7
8 // Invoke the continuation by calling the action method
9 Continuation conti = demoWSDLClass.startRequest();
10
11 // Verify that the continuation has the proper requests
12 Map<String, HttpRequest> requests = conti.getRequests();
13 System.assertEquals(requests.size(), 1);
14
15 // Perform mock callout
16 // (i.e. skip the callout and call the callback method)
17 HttpResponse response = new HttpResponse();
18 response.setBody('<SOAP:Envelope'
19 + ' xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">'
20 + '<SOAP:Body>'
21 + '<m:getStockQuoteResponse '
22 + 'xmlns:m="http://soap.sforce.com/schemas/class/StockQuoteServiceSoap">'
23 + '<m:result>Mock response body</m:result>'
24 + '</m:getStockQuoteResponse>'
25 + '</SOAP:Body>'
26 + '</SOAP:Envelope>');
27
28 // Set the fake response for the continuation
29 String requestLabel = requests.keyset().iterator().next();
30 Test.setContinuationResponse(requestLabel, response);
31
32 // Invoke callback method
33 Object result = Test.invokeContinuationMethod(demoWSDLClass, conti);
34 System.debug(demoWSDLClass);
35
36 // result is the return value of the callback
37 System.assertEquals(null, result);
38
39 // Verify that the controller's result variable
40 // is set to the mock response.
41 System.assertEquals('Mock response body', demoWSDLClass.result);
42 }
43}