この文章は 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;
18import com.sforce.soap.enterprise.LoginResult;
19import com.sforce.soap.metadata.MetadataConnection;
20import com.sforce.ws.ConnectionException;
21import com.sforce.ws.ConnectorConfig;
22
23/**
24 * Login utility.
25 */
26public class MetadataLoginUtil {
27
28    public static MetadataConnection login() throws ConnectionException {
29        final String USERNAME = "user@company.com";
30        // This is only a sample. Hard coding passwords in source files is a bad practice.
31        final String PASSWORD = "password"; 
32        final String URL = "https://login.salesforce.com/services/Soap/c/34.0";
33        final LoginResult loginResult = loginToSalesforce(USERNAME, PASSWORD, URL);
34        return createMetadataConnection(loginResult);
35    }
36
37    private static MetadataConnection createMetadataConnection(
38            final LoginResult loginResult) throws ConnectionException {
39        final ConnectorConfig config = new ConnectorConfig();
40        config.setServiceEndpoint(loginResult.getMetadataServerUrl());
41        config.setSessionId(loginResult.getSessionId());
42        return new MetadataConnection(config);
43    }
44
45    private static LoginResult loginToSalesforce(
46            final String username,
47            final String password,
48            final String loginUrl) throws ConnectionException {
49        final ConnectorConfig config = new ConnectorConfig();
50        config.setAuthEndpoint(loginUrl);
51        config.setServiceEndpoint(loginUrl);
52        config.setManualLogin(true);
53        return (new EnterpriseConnection(config)).login(username, password);
54    }
55}

ファイルベース開発用の 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<Package xmlns="http://soap.sforce.com/2006/04/metadata">
3    <types>
4        <members>*</members>
5        <name>CustomObject</name>
6    </types>
7    <types>
8        <members>*</members>
9        <name>CustomTab</name>
10    </types>
11    <types>
12        <members>*</members>
13        <name>Layout</name>
14    </types>
15    <version>34.0</version>
16</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.*;
18import java.nio.channels.Channels;
19import java.nio.channels.FileChannel;
20import java.nio.channels.ReadableByteChannel;
21import java.rmi.RemoteException;
22import java.util.*;
23
24import javax.xml.parsers.*;
25
26import org.w3c.dom.*;
27import org.xml.sax.SAXException;
28
29import com.sforce.soap.metadata.*;
30
31/**
32 * Sample that logs in and shows a menu of retrieve and deploy metadata options.
33 */
34public class FileBasedDeployAndRetrieve {
35
36    private MetadataConnection metadataConnection;
37
38    private static final String ZIP_FILE = "components.zip";
39
40    // manifest file that controls which components get retrieved
41    private static final String MANIFEST_FILE = "package.xml";
42
43    private static final double API_VERSION = 29.0;
44
45    // one second in milliseconds
46    private static final long ONE_SECOND = 1000;
47
48    // maximum number of attempts to deploy the zip file
49    private static final int MAX_NUM_POLL_REQUESTS = 50;
50
51    private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
52
53    public static void main(String[] args) throws Exception {
54        FileBasedDeployAndRetrieve sample = new FileBasedDeployAndRetrieve();
55        sample.run();
56    }
57
58    public FileBasedDeployAndRetrieve() {
59    }
60
61    private void run() throws Exception {
62        this.metadataConnection = MetadataLoginUtil.login();
63
64        // Show the options to retrieve or deploy until user exits
65        String choice = getUsersChoice();
66        while (choice != null && !choice.equals("99")) {
67            if (choice.equals("1")) {
68                retrieveZip();
69            } else if (choice.equals("2")) {
70                deployZip();
71            } else {
72                break;
73            }
74            // show the options again
75            choice = getUsersChoice();
76        }
77    }
78
79    /*
80     * Utility method to present options to retrieve or deploy.
81     */
82    private String getUsersChoice() throws IOException {
83        System.out.println(" 1: Retrieve");
84        System.out.println(" 2: Deploy");
85        System.out.println("99: Exit");
86        System.out.println();
87        System.out.print("Enter 1 to retrieve, 2 to deploy, or 99 to exit: ");
88        // wait for the user input.
89        String choice = reader.readLine();
90        return choice != null ? choice.trim() : "";
91    }
92
93    private void deployZip() throws Exception {
94        byte zipBytes[] = readZipFile();
95        DeployOptions deployOptions = new DeployOptions();
96        deployOptions.setPerformRetrieve(false);
97        deployOptions.setRollbackOnError(true);
98        AsyncResult asyncResult = metadataConnection.deploy(zipBytes, deployOptions);
99        DeployResult result = waitForDeployCompletion(asyncResult.getId());
100        if (!result.isSuccess()) {
101            printErrors(result, "Final list of failures:\n");
102            throw new Exception("The files were not successfully deployed");
103        }
104        System.out.println("The file " + ZIP_FILE + " was successfully deployed\n");
105    }
106
107    /*
108    * Read the zip file contents into a byte array.
109    */
110    private byte[] readZipFile() throws Exception {
111        byte[] result = null;
112        // We assume here that you have a deploy.zip file.
113        // See the retrieve sample for how to retrieve a zip file.
114        File zipFile = new File(ZIP_FILE);
115        if (!zipFile.exists() || !zipFile.isFile()) {
116            throw new Exception("Cannot find the zip file for deploy() on path:"
117                + zipFile.getAbsolutePath());
118        }
119
120        FileInputStream fileInputStream = new FileInputStream(zipFile);
121        try {
122            ByteArrayOutputStream bos = new ByteArrayOutputStream();
123            byte[] buffer = new byte[4096];
124            int bytesRead = 0;
125            while (-1 != (bytesRead = fileInputStream.read(buffer))) {
126                bos.write(buffer, 0, bytesRead);
127            }
128
129            result = bos.toByteArray();
130        } finally {
131            fileInputStream.close();
132        }
133        return result;
134    }
135
136    /*
137    * Print out any errors, if any, related to the deploy.
138    * @param result - DeployResult
139    */
140    private void printErrors(DeployResult result, String messageHeader) {
141        DeployDetails details = result.getDetails();
142        StringBuilder stringBuilder = new StringBuilder();
143        if (details != null) {
144            DeployMessage[] componentFailures = details.getComponentFailures();
145            for (DeployMessage failure : componentFailures) {
146                String loc = "(" + failure.getLineNumber() + ", " + failure.getColumnNumber();
147                if (loc.length() == 0 && !failure.getFileName().equals(failure.getFullName()))
148                {
149                    loc = "(" + failure.getFullName() + ")";
150                }
151                stringBuilder.append(failure.getFileName() + loc + ":" 
152                    + failure.getProblem()).append('\n');
153            }
154            RunTestsResult rtr = details.getRunTestResult();
155            if (rtr.getFailures() != null) {
156                for (RunTestFailure failure : rtr.getFailures()) {
157                    String n = (failure.getNamespace() == null ? "" :
158                        (failure.getNamespace() + ".")) + failure.getName();
159                    stringBuilder.append("Test failure, method: " + n + "." +
160                            failure.getMethodName() + " -- " + failure.getMessage() + 
161                            " stack " + failure.getStackTrace() + "\n\n");
162                }
163            }
164            if (rtr.getCodeCoverageWarnings() != null) {
165                for (CodeCoverageWarning ccw : rtr.getCodeCoverageWarnings()) {
166                    stringBuilder.append("Code coverage issue");
167                    if (ccw.getName() != null) {
168                        String n = (ccw.getNamespace() == null ? "" :
169                        (ccw.getNamespace() + ".")) + ccw.getName();
170                        stringBuilder.append(", class: " + n);
171                    }
172                    stringBuilder.append(" -- " + ccw.getMessage() + "\n");
173                }
174            }
175        }
176        if (stringBuilder.length() > 0) {
177            stringBuilder.insert(0, messageHeader);
178            System.out.println(stringBuilder.toString());
179        }
180    }
181    
182
183    private void retrieveZip() throws Exception {
184        RetrieveRequest retrieveRequest = new RetrieveRequest();
185        // The version in package.xml overrides the version in RetrieveRequest
186        retrieveRequest.setApiVersion(API_VERSION);
187        setUnpackaged(retrieveRequest);
188
189        AsyncResult asyncResult = metadataConnection.retrieve(retrieveRequest);
190        RetrieveResult result = waitForRetrieveCompletion(asyncResult);
191
192        if (result.getStatus() == RetrieveStatus.Failed) {
193            throw new Exception(result.getErrorStatusCode() + " msg: " +
194                    result.getErrorMessage());
195        } else if (result.getStatus() == RetrieveStatus.Succeeded) {  
196	        // Print out any warning messages
197	        StringBuilder stringBuilder = new StringBuilder();
198	        if (result.getMessages() != null) {
199	            for (RetrieveMessage rm : result.getMessages()) {
200	                stringBuilder.append(rm.getFileName() + " - " + rm.getProblem() + "\n");
201	            }
202	        }
203	        if (stringBuilder.length() > 0) {
204	            System.out.println("Retrieve warnings:\n" + stringBuilder);
205	        }
206	
207	        System.out.println("Writing results to zip file");
208	        File resultsFile = new File(ZIP_FILE);
209	        FileOutputStream os = new FileOutputStream(resultsFile);
210	
211	        try {
212	            os.write(result.getZipFile());
213	        } finally {
214	            os.close();
215	        }
216        }
217    }
218
219    private DeployResult waitForDeployCompletion(String asyncResultId) throws Exception {
220        int poll = 0;
221        long waitTimeMilliSecs = ONE_SECOND;
222        DeployResult deployResult;
223        boolean fetchDetails;
224        do {
225            Thread.sleep(waitTimeMilliSecs);
226            // double the wait time for the next iteration
227
228            waitTimeMilliSecs *= 2;
229            if (poll++ > MAX_NUM_POLL_REQUESTS) {
230                throw new Exception(
231                    "Request timed out. If this is a large set of metadata components, " +
232                    "ensure that MAX_NUM_POLL_REQUESTS is sufficient.");
233            }
234            // Fetch in-progress details once for every 3 polls
235            fetchDetails = (poll % 3 == 0);
236
237            deployResult = metadataConnection.checkDeployStatus(asyncResultId, fetchDetails);
238            System.out.println("Status is: " + deployResult.getStatus());
239            if (!deployResult.isDone() && fetchDetails) {
240                printErrors(deployResult, "Failures for deployment in progress:\n");
241            }
242        }
243        while (!deployResult.isDone());
244
245        if (!deployResult.isSuccess() && deployResult.getErrorStatusCode() != null) {
246            throw new Exception(deployResult.getErrorStatusCode() + " msg: " +
247                    deployResult.getErrorMessage());
248        }
249        
250        if (!fetchDetails) {
251            // Get the final result with details if we didn't do it in the last attempt.
252            deployResult = metadataConnection.checkDeployStatus(asyncResultId, true);
253        }
254        
255        return deployResult;
256    }
257
258    private RetrieveResult waitForRetrieveCompletion(AsyncResult asyncResult) throws Exception {
259    	// Wait for the retrieve to complete
260        int poll = 0;
261        long waitTimeMilliSecs = ONE_SECOND;
262        String asyncResultId = asyncResult.getId();
263        RetrieveResult result = null;
264        do {
265            Thread.sleep(waitTimeMilliSecs);
266            // Double the wait time for the next iteration
267            waitTimeMilliSecs *= 2;
268            if (poll++ > MAX_NUM_POLL_REQUESTS) {
269                throw new Exception("Request timed out.  If this is a large set " +
270                "of metadata components, check that the time allowed " +
271                "by MAX_NUM_POLL_REQUESTS is sufficient.");
272            }
273            result = metadataConnection.checkRetrieveStatus(
274                    asyncResultId);
275            System.out.println("Retrieve Status: " + result.getStatus());
276        } while (!result.isDone());         
277
278        return result;
279    }
280
281    private void setUnpackaged(RetrieveRequest request) throws Exception {
282        // Edit the path, if necessary, if your package.xml file is located elsewhere
283        File unpackedManifest = new File(MANIFEST_FILE);
284        System.out.println("Manifest file: " + unpackedManifest.getAbsolutePath());
285
286        if (!unpackedManifest.exists() || !unpackedManifest.isFile()) {
287            throw new Exception("Should provide a valid retrieve manifest " +
288                "for unpackaged content. Looking for " +
289                unpackedManifest.getAbsolutePath());
290        }
291
292        // Note that we use the fully quualified class name because
293        // of a collision with the java.lang.Package class
294        com.sforce.soap.metadata.Package p = parsePackageManifest(unpackedManifest);
295        request.setUnpackaged(p);
296    }
297
298    private com.sforce.soap.metadata.Package parsePackageManifest(File file)
299            throws ParserConfigurationException, IOException, SAXException {
300        com.sforce.soap.metadata.Package packageManifest = null;
301        List<PackageTypeMembers> listPackageTypes = new ArrayList<PackageTypeMembers>();
302        DocumentBuilder db =
303                DocumentBuilderFactory.newInstance().newDocumentBuilder();
304        InputStream inputStream = new FileInputStream(file);
305        Element d = db.parse(inputStream).getDocumentElement();
306        for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling()) {
307            if (c instanceof Element) {
308                Element ce = (Element) c;
309                NodeList nodeList = ce.getElementsByTagName("name");
310                if (nodeList.getLength() == 0) {
311                    continue;
312                }
313                String name = nodeList.item(0).getTextContent();
314                NodeList m = ce.getElementsByTagName("members");
315                List<String> members = new ArrayList<String>();
316                for (int i = 0; i < m.getLength(); i++) {
317                    Node mm = m.item(i);
318                    members.add(mm.getTextContent());
319                }
320                PackageTypeMembers packageTypes = new PackageTypeMembers();
321                packageTypes.setName(name);
322                packageTypes.setMembers(members.toArray(new String[members.size()]));
323                listPackageTypes.add(packageTypes);
324            }
325        }
326        packageManifest = new com.sforce.soap.metadata.Package();
327        PackageTypeMembers[] packageTypesArray =
328                new PackageTypeMembers[listPackageTypes.size()];
329        packageManifest.setTypes(listPackageTypes.toArray(packageTypesArray));
330        packageManifest.setVersion(API_VERSION + "");
331        return packageManifest;
332    }
333}