この文章は Salesforce 機械翻訳システムを使用して翻訳されました。詳細はこちらをご参照ください。
英語に切り替える

ステップ 3: Java サンプルコードの説明

WSDL ファイルをインポートすると、メタデータ API を使用するクライアントアプリケーションの構築を開始できます。このサンプルは、独自のコードを記述するための出発点として適しています。

サンプルを実行する前に、プロジェクトとコードを次のように変更します。

  1. WSC JAR、その連動関係、および WSDL から生成した JAR ファイルを含めます。

    WSC には他の連動関係がありますが、次のサンプルでは Rhino (js-1.7R2.jar) のみが必要です。これは、mvnrepository.com/artifact/rhino/js からダウンロードできます。

    メモ

  2. 自分のユーザ名とパスワードを使って、MetadataLoginUtil.login() メソッドの USERNAME 変数と PASSWORD 変数を更新します。現在の IP アドレスが組織の信頼済み IP 範囲内にない場合は、セキュリティトークンをパスワードに追加する必要があります。
  3. Sandbox を使用している場合は、必ずログイン URL を変更してください。

ログインユーティリティ

Java ユーザは、ConnectorConfig を使用して、Enterprise API、Partner API、および Metadata SOAP API に接続できます。MetadataLoginUtilConnectorConfig オブジェクトを作成し、Enterprise WSDL の login メソッドを使用してログインします。次に、sessionIdmetadataServerUrl を取得して ConnectorConfig を作成し、メタデータ API のエンドポイントに接続します。ConnectorConfig は WSC で定義されています。

MetadataLoginUtil クラスは、サンプルの他の部分からログインコードを抽象化するため、Salesforce API ごとに変更を行わずにこのコードの一部を再利用できます。

1swfobject.registerObject("clippy.codeblock-0", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import com.sforce.soap.enterprise.EnterpriseConnection;
18
19import com.sforce.soap.enterprise.LoginResult;
20
21import com.sforce.soap.metadata.MetadataConnection;
22
23import com.sforce.ws.ConnectionException;
24
25import com.sforce.ws.ConnectorConfig;
26
27
28
29/**
30
31 * Login utility.
32
33 */
34
35public class MetadataLoginUtil {
36
37
38
39    public static MetadataConnection login() throws ConnectionException {
40
41        final String USERNAME = "user@company.com";
42
43        // This is only a sample. Hard coding passwords in source files is a bad practice.
44
45        final String PASSWORD = "password"; 
46
47        final String URL = "https://login.salesforce.com/services/Soap/c/33.0";
48
49        final LoginResult loginResult = loginToSalesforce(USERNAME, PASSWORD, URL);
50
51        return createMetadataConnection(loginResult);
52
53    }
54
55
56
57    private static MetadataConnection createMetadataConnection(
58
59            final LoginResult loginResult) throws ConnectionException {
60
61        final ConnectorConfig config = new ConnectorConfig();
62
63        config.setServiceEndpoint(loginResult.getMetadataServerUrl());
64
65        config.setSessionId(loginResult.getSessionId());
66
67        return new MetadataConnection(config);
68
69    }
70
71
72
73    private static LoginResult loginToSalesforce(
74
75            final String username,
76
77            final String password,
78
79            final String loginUrl) throws ConnectionException {
80
81        final ConnectorConfig config = new ConnectorConfig();
82
83        config.setAuthEndpoint(loginUrl);
84
85        config.setServiceEndpoint(loginUrl);
86
87        config.setManualLogin(true);
88
89        return (new EnterpriseConnection(config)).login(username, password);
90
91    }
92
93}

ファイルベース開発用の Java のサンプルコード

サンプルコードは、ログインユーティリティを使用してログインします。次に、取得、リリース、および終了のメニューを表示します。

retrieve() コールおよび deploy() コールは両方とも components.zip という名前の .zip ファイルを処理します。retrieve() コールは組織のコンポーネントを components.zip に取得し、deploy() コールは components.zip のコンポーネントを組織にリリースします。コンピュータにサンプルを保存して実行する場合は、後でリリースできる components.zip ファイルを含めることができるように、まず取得オプションを実行します。retrieve コールの後、サンプルは、操作が完了するまで checkRetrieveStatus() コールをループします。同様に、deploy コールの後、サンプルは、操作が完了するまで checkDeployStatus() チェックをループします。

retrieve() コールは、マニフェストファイルを使用して組織から取得するコンポーネントを決定します。package.xml マニフェストファイルのサンプルは次のとおりです。マニフェストファイルの構造についての詳細は、「Zip ファイルの使用」を参照してください。このサンプルでは、マニフェストファイルはすべてのカスタムオブジェクト、カスタムタブ���およびページレイアウトを取得します。

1<?xml version="1.0" encoding="UTF-8"?>
2
3<Package xmlns="http://soap.sforce.com/2006/04/metadata">
4
5    <types>
6
7        <members>*</members>
8
9        <name>CustomObject</name>
10
11    </types>
12
13    <types>
14
15        <members>*</members>
16
17        <name>CustomTab</name>
18
19    </types>
20
21    <types>
22
23        <members>*</members>
24
25        <name>Layout</name>
26
27    </types>
28
29    <version>33.0</version>
30
31</Package>

API コールに続く、エラー処理コードに注意してください。

1swfobject.registerObject("clippy.codeblock-2", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import java.io.*;
18
19import java.nio.channels.Channels;
20
21import java.nio.channels.FileChannel;
22
23import java.nio.channels.ReadableByteChannel;
24
25import java.rmi.RemoteException;
26
27import java.util.*;
28
29
30
31import javax.xml.parsers.*;
32
33
34
35import org.w3c.dom.*;
36
37import org.xml.sax.SAXException;
38
39
40
41import com.sforce.soap.metadata.*;
42
43
44
45/**
46
47 * Sample that logs in and shows a menu of retrieve and deploy metadata options.
48
49 */
50
51public class FileBasedDeployAndRetrieve {
52
53
54
55    private MetadataConnection metadataConnection;
56
57
58
59    private static final String ZIP_FILE = "components.zip";
60
61
62
63    // manifest file that controls which components get retrieved
64
65    private static final String MANIFEST_FILE = "package.xml";
66
67
68
69    private static final double API_VERSION = 29.0;
70
71
72
73    // one second in milliseconds
74
75    private static final long ONE_SECOND = 1000;
76
77
78
79    // maximum number of attempts to deploy the zip file
80
81    private static final int MAX_NUM_POLL_REQUESTS = 50;
82
83
84
85    private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
86
87
88
89    public static void main(String[] args) throws Exception {
90
91        FileBasedDeployAndRetrieve sample = new FileBasedDeployAndRetrieve();
92
93        sample.run();
94
95    }
96
97
98
99    public FileBasedDeployAndRetrieve() {
100
101    }
102
103
104
105    private void run() throws Exception {
106
107        this.metadataConnection = MetadataLoginUtil.login();
108
109
110
111        // Show the options to retrieve or deploy until user exits
112
113        String choice = getUsersChoice();
114
115        while (choice != null && !choice.equals("99")) {
116
117            if (choice.equals("1")) {
118
119                retrieveZip();
120
121            } else if (choice.equals("2")) {
122
123                deployZip();
124
125            } else {
126
127                break;
128
129            }
130
131            // show the options again
132
133            choice = getUsersChoice();
134
135        }
136
137    }
138
139
140
141    /*
142
143     * Utility method to present options to retrieve or deploy.
144
145     */
146
147    private String getUsersChoice() throws IOException {
148
149        System.out.println(" 1: Retrieve");
150
151        System.out.println(" 2: Deploy");
152
153        System.out.println("99: Exit");
154
155        System.out.println();
156
157        System.out.print("Enter 1 to retrieve, 2 to deploy, or 99 to exit: ");
158
159        // wait for the user input.
160
161        String choice = reader.readLine();
162
163        return choice != null ? choice.trim() : "";
164
165    }
166
167
168
169    private void deployZip() throws Exception {
170
171        byte zipBytes[] = readZipFile();
172
173        DeployOptions deployOptions = new DeployOptions();
174
175        deployOptions.setPerformRetrieve(false);
176
177        deployOptions.setRollbackOnError(true);
178
179        AsyncResult asyncResult = metadataConnection.deploy(zipBytes, deployOptions);
180
181        DeployResult result = waitForDeployCompletion(asyncResult.getId());
182
183        if (!result.isSuccess()) {
184
185            printErrors(result, "Final list of failures:\n");
186
187            throw new Exception("The files were not successfully deployed");
188
189        }
190
191        System.out.println("The file " + ZIP_FILE + " was successfully deployed\n");
192
193    }
194
195
196
197    /*
198
199    * Read the zip file contents into a byte array.
200
201    */
202
203    private byte[] readZipFile() throws Exception {
204
205        byte[] result = null;
206
207        // We assume here that you have a deploy.zip file.
208
209        // See the retrieve sample for how to retrieve a zip file.
210
211        File zipFile = new File(ZIP_FILE);
212
213        if (!zipFile.exists() || !zipFile.isFile()) {
214
215            throw new Exception("Cannot find the zip file for deploy() on path:"
216
217                + zipFile.getAbsolutePath());
218
219        }
220
221
222
223        FileInputStream fileInputStream = new FileInputStream(zipFile);
224
225        try {
226
227            ByteArrayOutputStream bos = new ByteArrayOutputStream();
228
229            byte[] buffer = new byte[4096];
230
231            int bytesRead = 0;
232
233            while (-1 != (bytesRead = fileInputStream.read(buffer))) {
234
235                bos.write(buffer, 0, bytesRead);
236
237            }
238
239
240
241            result = bos.toByteArray();
242
243        } finally {
244
245            fileInputStream.close();
246
247        }
248
249        return result;
250
251    }
252
253
254
255    /*
256
257    * Print out any errors, if any, related to the deploy.
258
259    * @param result - DeployResult
260
261    */
262
263    private void printErrors(DeployResult result, String messageHeader) {
264
265        DeployDetails details = result.getDetails();
266
267        StringBuilder stringBuilder = new StringBuilder();
268
269        if (details != null) {
270
271            DeployMessage[] componentFailures = details.getComponentFailures();
272
273            for (DeployMessage failure : componentFailures) {
274
275                String loc = "(" + failure.getLineNumber() + ", " + failure.getColumnNumber();
276
277                if (loc.length() == 0 && !failure.getFileName().equals(failure.getFullName()))
278
279                {
280
281                    loc = "(" + failure.getFullName() + ")";
282
283                }
284
285                stringBuilder.append(failure.getFileName() + loc + ":" 
286
287                    + failure.getProblem()).append('\n');
288
289            }
290
291            RunTestsResult rtr = details.getRunTestResult();
292
293            if (rtr.getFailures() != null) {
294
295                for (RunTestFailure failure : rtr.getFailures()) {
296
297                    String n = (failure.getNamespace() == null ? "" :
298
299                        (failure.getNamespace() + ".")) + failure.getName();
300
301                    stringBuilder.append("Test failure, method: " + n + "." +
302
303                            failure.getMethodName() + " -- " + failure.getMessage() + 
304
305                            " stack " + failure.getStackTrace() + "\n\n");
306
307                }
308
309            }
310
311            if (rtr.getCodeCoverageWarnings() != null) {
312
313                for (CodeCoverageWarning ccw : rtr.getCodeCoverageWarnings()) {
314
315                    stringBuilder.append("Code coverage issue");
316
317                    if (ccw.getName() != null) {
318
319                        String n = (ccw.getNamespace() == null ? "" :
320
321                        (ccw.getNamespace() + ".")) + ccw.getName();
322
323                        stringBuilder.append(", class: " + n);
324
325                    }
326
327                    stringBuilder.append(" -- " + ccw.getMessage() + "\n");
328
329                }
330
331            }
332
333        }
334
335        if (stringBuilder.length() > 0) {
336
337            stringBuilder.insert(0, messageHeader);
338
339            System.out.println(stringBuilder.toString());
340
341        }
342
343    }
344
345    
346
347
348
349    private void retrieveZip() throws Exception {
350
351        RetrieveRequest retrieveRequest = new RetrieveRequest();
352
353        // The version in package.xml overrides the version in RetrieveRequest
354
355        retrieveRequest.setApiVersion(API_VERSION);
356
357        setUnpackaged(retrieveRequest);
358
359
360
361        AsyncResult asyncResult = metadataConnection.retrieve(retrieveRequest);
362
363        RetrieveResult result = waitForRetrieveCompletion(asyncResult);
364
365
366
367        if (result.getStatus() == RetrieveStatus.Failed) {
368
369            throw new Exception(result.getErrorStatusCode() + " msg: " +
370
371                    result.getErrorMessage());
372
373        } else if (result.getStatus() == RetrieveStatus.Succeeded) {  
374
375	        // Print out any warning messages
376
377	        StringBuilder stringBuilder = new StringBuilder();
378
379	        if (result.getMessages() != null) {
380
381	            for (RetrieveMessage rm : result.getMessages()) {
382
383	                stringBuilder.append(rm.getFileName() + " - " + rm.getProblem() + "\n");
384
385	            }
386
387	        }
388
389	        if (stringBuilder.length() > 0) {
390
391	            System.out.println("Retrieve warnings:\n" + stringBuilder);
392
393	        }
394
395	
396
397	        System.out.println("Writing results to zip file");
398
399	        File resultsFile = new File(ZIP_FILE);
400
401	        FileOutputStream os = new FileOutputStream(resultsFile);
402
403	
404
405	        try {
406
407	            os.write(result.getZipFile());
408
409	        } finally {
410
411	            os.close();
412
413	        }
414
415        }
416
417    }
418
419
420
421    private DeployResult waitForDeployCompletion(String asyncResultId) throws Exception {
422
423        int poll = 0;
424
425        long waitTimeMilliSecs = ONE_SECOND;
426
427        DeployResult deployResult;
428
429        boolean fetchDetails;
430
431        do {
432
433            Thread.sleep(waitTimeMilliSecs);
434
435            // double the wait time for the next iteration
436
437
438
439            waitTimeMilliSecs *= 2;
440
441            if (poll++ > MAX_NUM_POLL_REQUESTS) {
442
443                throw new Exception(
444
445                    "Request timed out. If this is a large set of metadata components, " +
446
447                    "ensure that MAX_NUM_POLL_REQUESTS is sufficient.");
448
449            }
450
451            // Fetch in-progress details once for every 3 polls
452
453            fetchDetails = (poll % 3 == 0);
454
455
456
457            deployResult = metadataConnection.checkDeployStatus(asyncResultId, fetchDetails);
458
459            System.out.println("Status is: " + deployResult.getStatus());
460
461            if (!deployResult.isDone() && fetchDetails) {
462
463                printErrors(deployResult, "Failures for deployment in progress:\n");
464
465            }
466
467        }
468
469        while (!deployResult.isDone());
470
471
472
473        if (!deployResult.isSuccess() && deployResult.getErrorStatusCode() != null) {
474
475            throw new Exception(deployResult.getErrorStatusCode() + " msg: " +
476
477                    deployResult.getErrorMessage());
478
479        }
480
481        
482
483        if (!fetchDetails) {
484
485            // Get the final result with details if we didn't do it in the last attempt.
486
487            deployResult = metadataConnection.checkDeployStatus(asyncResultId, true);
488
489        }
490
491        
492
493        return deployResult;
494
495    }
496
497
498
499    private RetrieveResult waitForRetrieveCompletion(AsyncResult asyncResult) throws Exception {
500
501    	// Wait for the retrieve to complete
502
503        int poll = 0;
504
505        long waitTimeMilliSecs = ONE_SECOND;
506
507        String asyncResultId = asyncResult.getId();
508
509        RetrieveResult result = null;
510
511        do {
512
513            Thread.sleep(waitTimeMilliSecs);
514
515            // Double the wait time for the next iteration
516
517            waitTimeMilliSecs *= 2;
518
519            if (poll++ > MAX_NUM_POLL_REQUESTS) {
520
521                throw new Exception("Request timed out.  If this is a large set " +
522
523                "of metadata components, check that the time allowed " +
524
525                "by MAX_NUM_POLL_REQUESTS is sufficient.");
526
527            }
528
529            result = metadataConnection.checkRetrieveStatus(
530
531                    asyncResultId);
532
533            System.out.println("Retrieve Status: " + result.getStatus());
534
535        } while (!result.isDone());         
536
537
538
539        return result;
540
541    }
542
543
544
545    private void setUnpackaged(RetrieveRequest request) throws Exception {
546
547        // Edit the path, if necessary, if your package.xml file is located elsewhere
548
549        File unpackedManifest = new File(MANIFEST_FILE);
550
551        System.out.println("Manifest file: " + unpackedManifest.getAbsolutePath());
552
553
554
555        if (!unpackedManifest.exists() || !unpackedManifest.isFile()) {
556
557            throw new Exception("Should provide a valid retrieve manifest " +
558
559                "for unpackaged content. Looking for " +
560
561                unpackedManifest.getAbsolutePath());
562
563        }
564
565
566
567        // Note that we use the fully quualified class name because
568
569        // of a collision with the java.lang.Package class
570
571        com.sforce.soap.metadata.Package p = parsePackageManifest(unpackedManifest);
572
573        request.setUnpackaged(p);
574
575    }
576
577
578
579    private com.sforce.soap.metadata.Package parsePackageManifest(File file)
580
581            throws ParserConfigurationException, IOException, SAXException {
582
583        com.sforce.soap.metadata.Package packageManifest = null;
584
585        List<PackageTypeMembers> listPackageTypes = new ArrayList<PackageTypeMembers>();
586
587        DocumentBuilder db =
588
589                DocumentBuilderFactory.newInstance().newDocumentBuilder();
590
591        InputStream inputStream = new FileInputStream(file);
592
593        Element d = db.parse(inputStream).getDocumentElement();
594
595        for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling()) {
596
597            if (c instanceof Element) {
598
599                Element ce = (Element) c;
600
601                NodeList nodeList = ce.getElementsByTagName("name");
602
603                if (nodeList.getLength() == 0) {
604
605                    continue;
606
607                }
608
609                String name = nodeList.item(0).getTextContent();
610
611                NodeList m = ce.getElementsByTagName("members");
612
613                List<String> members = new ArrayList<String>();
614
615                for (int i = 0; i < m.getLength(); i++) {
616
617                    Node mm = m.item(i);
618
619                    members.add(mm.getTextContent());
620
621                }
622
623                PackageTypeMembers packageTypes = new PackageTypeMembers();
624
625                packageTypes.setName(name);
626
627                packageTypes.setMembers(members.toArray(new String[members.size()]));
628
629                listPackageTypes.add(packageTypes);
630
631            }
632
633        }
634
635        packageManifest = new com.sforce.soap.metadata.Package();
636
637        PackageTypeMembers[] packageTypesArray =
638
639                new PackageTypeMembers[listPackageTypes.size()];
640
641        packageManifest.setTypes(listPackageTypes.toArray(packageTypesArray));
642
643        packageManifest.setVersion(API_VERSION + "");
644
645        return packageManifest;
646
647    }
648
649}