Writing /volume1/Web/Public/dokuwiki/data/log/deprecated/2024-11-14.log failed

Java consuming SharePoint REST API

SharePoint2016オンプレ環境のREST APIと連携するJava Clientの実装例を紹介します。

SharePoint RESTサービスの概要

SharePoint 2016ではREST(REpresentational State Transfer)サービスを導入しています。
これにより開発者は、標準のREST Web要求をサポートするテクノロジを使用してSharePointデータとリモートで対話できるようになました。
つまり、クライアントアプリケーションからREST Webテクノロジと標準のOData(Open Data Protocol)構文を使用して、CRUD操作が実行できるようになりました。

SharePoint RESTサービスエンドポイントを決定する

SharePoint リソース用のRESTエンドポイントを作成するには、次の手順に従います。

1. REST サービスの参照から始めます。

http://<app site url>/_api

2. 適切なエントリポイントを指定します。 次にその例を示します。

http://<app site url>/_api/web

3. エントリポイントから、アクセスする特定のリソースに移動します。
これには、クライアントオブジェクトモデルのメソッドに対応するエンドポイントのパラメータの指定が含まれます。
次にその例を示します。

http://<app site url>/_api/web/lists/getbytitle('listname')

client.svcサービスの直接参照の代わりに_apiを使用する

SharePoint REST サービスのアーキテクチャ1)を見ると分かりますが、client.svcがREST サービスへの参照するURIを認識し受け入れます。
たとえば、http://<app site url>/_vti_bin/client.svc/web/lists でアクセスできます。
しかし、これに加え、後に説明するパラメーターが入ってくるとURLが長くなり、URL制限の256文字に引っかかります。
これを回避するために、_apiを使用してclient.svc web サービスを明示的に参照する必要性を取り除きます。
_apiを使用することで、URLを短縮し、残り部分を構築するために使用できる文字数を増やすことができます。

REST エンドポイント URIでパラメータを指定する

SharePointではOData仕様が拡張されており、かっこ()を使用してメソッドのパラメーターとインデックスの値を指定することができます。
複数のパラメーターを指定するには、次のように、名前と値をペアにしたパラメーターを指定し、各パラメーターをコンマで区切ります。

http://<app site url>/_api/web/getAvailableWebTemplates(lcid=1033, includeCrossLanguage=true)

context infoへのHTTP要求例

form digest value2)はcontext情報から取得可能です。
context情報のHTTP要求例を次に示します。

区分value
endpointhttp://<api site url>/_api/contextinfo
HTTP methodPOST
HTTP headercontent-type: application/json;odata=verbose
accept: application/json;odata=verbose

フォルダー作成のHTTP要求例

e-キャビネットにフォルダーを作成するHTTP要求例を次に示します。

区分value
endpointhttp://<api site url>/_api/web/folders/add('/document library relative url/folder name')
HTTP methodPOST
HTTP headercontent-type: application/json;odata=verbose
accept: application/json;odata=verbose
X-RequestDigest: <form digest value>

ここでdocument library relative url3)は<api site url>のhost対しての相対パスを指定します。

ドキュメント・ライブラリの指定フォルダーへファイル追加のHTTP要求例

あるドキュメント・ライブラリの指定フォルダーにファイルを追加するHTTP要求例を次に示します。

区分value
endpointhttp://<api site url>/_api/web/getfolderbyserverrelativeurl('/document library relative url/folder name')/files/add(overwrite=true, url='file name')
HTTP methodPOST
HTTP headercontent-type: multipart/form-data
accept: application/json;odata=verbose
X-RequestDigest: <form digest value>

REST Clientの実装概要

REST サービスへのHTTP要求/応答を実装するために、Spring-web及びApacheのhttpclientを利用します。
また、ResponseのJSONを解析するために、json-libを利用します。
その他、エンドポイントURLのエスケープにgoogleのguavaライブラリを、ロギングにslf4jを使っています。

必要ライブラリ

以下にREST Client実装で必要なライブラリを示します。
必要ライブラリをbuild-pathに追加してください。

ライブラリ説明
httpclient-4.5.6.jarApache httpclient
httpcore-4.4.10.jarhttpclientの依存ライブラリ
commons-codec-1.10.jarhttpclientの依存ライブラリ
logback-classic-1.2.3.jarloggingライブラリ
logback-core-1.2.3.jarlogback-classicの依存ライブラリ
slf4j-api-1.7.25.jarlogback-classicの依存ライブラリ
spring-core-4.3.18.RELEASE.jarspring-webの依存ライブラリ
spring-web-4.3.18.RELEASE.jarspring-web
spring-aop-4.3.18.RELEASE.jarspring-webの依存ライブラリ
spring-beans-4.3.18.RELEASE.jarspring-webの依存ライブラリ
spring-context-4.3.18.RELEASE.jarspring-webの依存ライブラリ
spring-expression-4.3.18.RELEASE.jarspring-contextの依存ライブラリ
guava-25.1-android.jargoogle guava
json-20210307.jarJSON解析用ライブラリ

SharePointService.java code snippet

SharePointServiceコードの一部を示します。

/**
 * return Form Digest value
 * @return Form Digest value
 */
public String getFormDigestValue() {
	String _output = "";
	try {
		//endpoint
		String _endpoint = MessageFormat.format("{0}/_api/contextinfo", properties.getProperty("siteUrl"));
 
		//request entity
		RequestEntity<String> _requestEntity = RequestEntity
				.post(new URI(_endpoint))
				.header("content-type", "application/json;odata=verbose")
				.header("accept", "application/json;odata=verbose")
				.body(null);
 
		RestTemplate _restTemplate = new RestTemplate();
		_restTemplate.setRequestFactory(buildHttpComponentsClientHttpRequestFactory(properties.getProperty("username"),
				properties.getProperty("password"),
				properties.getProperty("host"),
				properties.getProperty("domain")));
 
		ResponseEntity<String> _responseEntity = _restTemplate.exchange(_requestEntity, String.class);
 
		if (_responseEntity.getStatusCode() != HttpStatus.OK) {
			throw new RuntimeException("Failed : HTTP error code : " + _responseEntity.getStatusCode());
		}
 
		logger.debug("response body=" + _responseEntity.getBody());
 
		//parse json
		_output = RestResponseUtil.parseJsonDigestValue(_responseEntity.getBody());
	} catch (Exception e) {
		logger.debug(e.getMessage(), e);
	}//try~catch
 
	return _output;
}
 
/**
 * Create a folder in the relative document library.<br>
 *
 * @param digestValue Form Digest value
 * @param folderName Folder name
 * @return relative folder path
 */
public String createEcabinetFolder(String digestValue, String folderName) {
	String _output = "";
	try {
		//endpoint
		String _endpoint = MessageFormat.format("{0}/_api/web/folders/add(''/{1}/{2}'')",
		properties.getProperty("siteUrl"), properties.getProperty("libraryName"), folderName);
 
		//escape url
		String _requestUrl = UrlEscapers.urlFragmentEscaper().escape(_endpoint);
		logger.debug("endpoint=" + _requestUrl);
 
		//request entity
		RequestEntity<String> _requestEntity = RequestEntity
		.post(new URI(_requestUrl))
		.header("content-type", "application/json;odata=verbose")
		.header("accept", "application/json;odata=verbose")
		.header("X-RequestDigest", digestValue)
		.body(null);
 
		RestTemplate _restTemplate = new RestTemplate();
		_restTemplate.setRequestFactory(buildHttpComponentsClientHttpRequestFactory(properties.getProperty("username"),
		properties.getProperty("password"),
		properties.getProperty("host"),
		properties.getProperty("domain")));
 
		ResponseEntity<String> _responseEntity = _restTemplate.exchange(_requestEntity, String.class);
 
		if (_responseEntity.getStatusCode() != HttpStatus.OK) {
			throw new RuntimeException("Failed : HTTP error code : " + _responseEntity.getStatusCode());	
		}
 
		logger.debug("response body=" + _responseEntity.getBody());
 
		//parse json
		_output = RestResponseUtil.parseJsonServletRelativeUrl(_responseEntity.getBody());
	} catch (Exception e) {
		logger.debug(e.getMessage(), e);
	}//try~catch
 
	return _output;
}
 
/**
 * Add a file to the folder in the relative document library.<br>
 *
 * @param digestValue
 * @param sourceUrl
 * @param folderName
 * @return relative file path
 */
public String addFileToEcabinet(String digestValue, String sourceUrl, String folderName) {
	String _output = "";
	try {
		File _f = new File(sourceUrl);
 
		//endpoint
		String _endpoint = MessageFormat.format("{0}/_api/web/getfolderbyserverrelativeurl(''/{1}/{2}'')/files/add(overwrite=true, url=''{3}'')",	
		properties.getProperty("siteUrl"), properties.getProperty("libraryName"), folderName, _f.getName());
 
		//escape url
		String _requestUrl = UrlEscapers.urlFragmentEscaper().escape(_endpoint);
		logger.debug("endpoint=" + _requestUrl);
 
		//request entity
		RequestEntity<FileSystemResource> _requestEntity = RequestEntity
		.post(new URI(_requestUrl))
		.contentType(MediaType.MULTIPART_FORM_DATA)
		.header("accept", "application/json;odata=verbose")
		.header("X-RequestDigest", digestValue)
		.contentLength(_f.length())
		.body(new FileSystemResource(_f));
 
		RestTemplate _restTemplate = new RestTemplate();
		_restTemplate.setRequestFactory(buildHttpComponentsClientHttpRequestFactory(properties.getProperty("username"),
		properties.getProperty("password"),
		properties.getProperty("host"),
		properties.getProperty("domain")));
 
		ResponseEntity<String> _responseEntity = _restTemplate.exchange(_requestEntity, String.class);
 
		if (_responseEntity.getStatusCode() != HttpStatus.OK) {
		throw new RuntimeException("Failed : HTTP error code : " + _responseEntity.getStatusCode());
		}	
 
		logger.debug("response body=" + _responseEntity.getBody());
 
		//parse json
		_output = RestResponseUtil.parseJsonServletRelativeUrl(_responseEntity.getBody());
	} catch (Exception e) {
		logger.debug(e.getMessage(), e);
	}//try~catch
 
	return _output;
}
 
/**
 * build HttpComponentsClientHttpRequestFactory<br>
 *
 * @param userName SharePoint userName
 * @param password SharePoint password
 * @param host Host
 * @param domain Domain
 * @return HttpComponentsClientHttpRequestFactory
 */
private HttpComponentsClientHttpRequestFactory buildHttpComponentsClientHttpRequestFactory(String userName, String password,
		String host, String domain) throws Exception {
	//create connection manager
	PoolingHttpClientConnectionManager _cm = new PoolingHttpClientConnectionManager();
	_cm.setMaxTotal(128);
	_cm.setDefaultMaxPerRoute(24);
 
	//request configuration
	RequestConfig.Builder _requestBuilder = RequestConfig.custom().setConnectTimeout(5000).setSocketTimeout(10000);
 
	//build registry and register authentication to its registry
	Registry<AuthSchemeProvider> _authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create()
				.register(AuthSchemes.NTLM, new NTLMSchemeFactory())
				.register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory()).build();
 
	//create NTCredential
	CredentialsProvider _credentialProvider = new BasicCredentialsProvider();
	_credentialProvider.setCredentials(AuthScope.ANY, new NTCredentials(userName, password, host, domain));
 
	//create HttpClient
	HttpClientBuilder _builder = HttpClientBuilder.create()
			.setConnectionManager(_cm)
			.setDefaultRequestConfig(_requestBuilder.build())
			.setDefaultAuthSchemeRegistry(_authSchemeRegistry)
			.setDefaultCredentialsProvider(_credentialProvider);
 
	HttpComponentsClientHttpRequestFactory _factory = new HttpComponentsClientHttpRequestFactory(_builder.build());
 
	return _factory;
}

reference

1)
アーキテクチャはこちらを参考してください。SharePoint REST サービスのアーキテクチャ
2)
REST APIを利用してサイトにオブジェクトを生成するためには、<form digest value>を指定する必要があります
3)
例)<api site url> = http://sps-op.example.com/sites/qua-app, document library = Test Data の場合,
document library relative url = sites/qua-app/Test%20Data
※ ここで、%20は半角スペースを表します。(半角スペースをエスケープした形)

コメント

コメントを入力. Wiki文法が有効です:
V K C P C
 

QR Code
QR Code study:java:sharepoint (generated for current page)