Use the Apache HTTP library to interact with the XWiki RESTful API

Last modified by Eduard Moraru on 2016/05/25

May 25 2016

XWiki provides fine-grain access to virtually every element through an API that is based on HTTP semantics, i.e., a RESTful API. 

Find more information about the XWiki RESTful API in these 2 links:

In this post you will find all the details to take advantage of this API and interact with it from Java or Groovy using Apache HttpComponents 4.x. 

The Apache HttpComponents project is responsible for creating and maintaining a toolset of low level Java components focused on HTTP and associated protocols.
This project functions under the Apache Software Foundation, and is part of a larger community of developers and users.

Interacting With the RESTful API

Bellow we will see how to send GET, POST, PUT and DELETE HTTP requests to the XWiki REST service using Apache HttpComponents.

Note that the XWiki RESTful API supports HTTP basic authentication. This method will be used to authenticate the Apache HttpClient to reach or update XWiki resources that needs authentication.

Get resources without authentication

In this example, a GET http request will be sent to the XWiki REST service.

import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.util.EntityUtils;
...
String url = "http://localhost:8080/xwiki/rest";

CloseableHttpClient httpclient = HttpClients.createDefault();

try {
  HttpGet httpGet = new HttpGet(url);

 // Change the ACCEPT header to json.
 httpGet.addHeader(HttpHeaders.ACCEPT, "application/json");

  CloseableHttpResponse response = httpclient.execute(httpGet);
 try {
   // Request status
   int requestStatus = response.getStatusLine().getStatusCode();

    HttpEntity entity = response.getEntity();
   // Do something useful with the response body

   // Request String response
   String requestResponse = EntityUtils.toString(entity);
    EntityUtils.consume(entity);
 } finally {
    response.close();
 }
} finally {
  httpclient.close();
}

JSON Response

{
 "syntaxes": null,
 "version": "7.4.2",
 "links": [
    {
     "href": "http://localhost:8080/xwiki/rest/wikis",
     "rel": "http://www.xwiki.org/rel/wikis",
     "hrefLang": null,
     "type": null
    },
    {
     "href": "http://localhost:8080/xwiki/rest/syntaxes",
     "rel": "http://www.xwiki.org/rel/syntaxes",
     "hrefLang": null,
     "type": null
    }
  ]
}

Get resources with authentication

In this example we have requested a resource that needs authorization in order to be accessed.
We execute an HTTP GET request against an XWiki resource that requires BASIC authentication scheme.

import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.HttpHost;
import org.apache.http.client.AuthCache;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.HttpHeaders;
...
String host = "localhost";
int port = 8080;
String url = "http://localhost:8080/xwiki/rest/wikis/xwiki/spaces/Main/pages/Private";
String user = "Admin";
String password = "admin";

HttpHost target = new HttpHost(host, port, "http");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
     new AuthScope(target.getHostName(), target.getPort()),
     new UsernamePasswordCredentials(user, password));
CloseableHttpClient httpclient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();

try {
 // Create AuthCache instance
 AuthCache authCache = new BasicAuthCache();

 // Generate BASIC scheme object and add it to the local auth cache
 BasicScheme basicAuth = new BasicScheme();
  authCache.put(target, basicAuth);

 // Add AuthCache to the execution context
 HttpClientContext localContext = HttpClientContext.create();
  localContext.setAuthCache(authCache);
  localContext.setAttribute("preemptive-auth", basicAuth);      
  HttpGet httpget = new HttpGet(url);
  CloseableHttpResponse response = httpclient.execute(target, httpget, localContext);

 try {
   // Request status
   int requestStatus = response.getStatusLine().getStatusCode();
    HttpEntity entity = response.getEntity();

   // Do something useful with the response body

   // Request String response
   String requestResponse = EntityUtils.toString(entity);
 } finally {
    response.close();
 }
} finally {
  httpclient.close();
}

XML Response

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<page xmlns="http://www.xwiki.org">
   <link href="http://localhost:8080/xwiki/rest/wikis/xwiki/spaces/Main" .../>
   <link href="http://localhost:8080/xwiki/rest/wikis/xwiki/spaces/Main/pages/WebHome" .../>
    ...
   <id>xwiki:Main.Private</id>
   <fullName>Main.Private</fullName>
   <wiki>xwiki</wiki>
   <space>Main</space>
   <name>Private</name>
   <title>Private</title>
   <parent>Main.WebHome</parent>
   <parentId>xwiki:Main.WebHome</parentId>
    ...
</page>

Create, modify and delete resources

Resource update is usually done by using the PUT method, while resource creation is done via PUT or POST.

Create a new object using the POST method

In this example we will add an "XWiki.XWikiUsers" object to the page "XWiki.JohnDoe".

import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.HttpHost;
import org.apache.http.client.AuthCache;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.HttpHeaders;
...
String host = "localhost";
int port = 8080;
String url = "http://localhost:8080/xwiki/rest/wikis/xwiki/spaces/XWiki/pages/JohnDoe/objects";
String user = "Admin";
String password = "admin";

HttpHost target = new HttpHost(host, port, "http");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
  new AuthScope(target.getHostName(), target.getPort()),
  new UsernamePasswordCredentials(user, password));
CloseableHttpClient httpclient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();

try {
 // Create AuthCache instance
 AuthCache authCache = new BasicAuthCache();

 // Generate BASIC scheme object and add it to the local auth cache
 BasicScheme basicAuth = new BasicScheme();
  authCache.put(target, basicAuth);

 // Add AuthCache to the execution context
 HttpClientContext localContext = HttpClientContext.create();
  localContext.setAuthCache(authCache);
  localContext.setAttribute("preemptive-auth", basicAuth);

  HttpPost httpPost = new HttpPost(url);

  List <NameValuePair> nvps = new ArrayList <NameValuePair>();
  nvps.add(new BasicNameValuePair("className", "XWiki.XWikiUsers"));
  nvps.add(new BasicNameValuePair("property#first_name", "John"));
  nvps.add(new BasicNameValuePair("property#last_name", "Doe"));

  httpPost.addHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
  httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
  httpPost.setEntity(new UrlEncodedFormEntity(nvps));

  CloseableHttpResponse response = httpclient.execute(target, httpPost, localContext);

 try {
   // Request status
   int requestStatus = response.getStatusLine().getStatusCode();
    HttpEntity entity = response.getEntity();

   // do something useful with the response body

   // Request String response
   String requestResponse = EntityUtils.toString(entity);
    EntityUtils.consume(entity);
 } finally {
    response.close();
 }
} finally {
  httpclient.close();
}

Update an object property using the PUT method

In this example we will modify the "email" property of the "XWiki.XWikiUsers" object attached to the "XWiki.JohnDoe" page.
The number of the object to modify is specified in the resource URL. 

import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.HttpHost;
import org.apache.http.client.AuthCache;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.HttpHeaders;
...
String host = "mouhb-bu401lg";
int port = 8089;
String url = "http://localhost:8080/xwiki/rest/wikis/xwiki/spaces/XWiki/pages/JohnDoe/objects/XWiki.XWikiUsers/0/properties/email";
String user = "Admin";
String password = "admin";

HttpHost target = new HttpHost(host, port, "http");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
  new AuthScope(target.getHostName(), target.getPort()),
  new UsernamePasswordCredentials(user, password));
CloseableHttpClient httpclient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();

try {
 // Create AuthCache instance
 AuthCache authCache = new BasicAuthCache();

 // Generate BASIC scheme object and add it to the local auth cache
 BasicScheme basicAuth = new BasicScheme();
  authCache.put(target, basicAuth);

 // Add AuthCache to the execution context
 HttpClientContext localContext = HttpClientContext.create();
  localContext.setAuthCache(authCache);
  localContext.setAttribute("preemptive-auth", basicAuth);

  HttpPut httpPut = new HttpPut(url);

  List <NameValuePair> nvps = new ArrayList <NameValuePair>();
  nvps.add(new BasicNameValuePair("property#email", "[email protected]"));
  httpPut.addHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
  httpPut.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
  httpPut.setEntity(new UrlEncodedFormEntity(nvps));

  CloseableHttpResponse response = httpclient.execute(target, httpPut, localContext);

 try {
   // Request status
   int requestStatus = response.getStatusLine().getStatusCode();
    HttpEntity entity = response.getEntity();

   // Do something useful with the response body

   // Request String response
   String requestResponse = EntityUtils.toString(entity);
    EntityUtils.consume(entity);
 } finally {
    response.close();
 }
} finally {
  httpclient.close();
}
XML Response
<?xml version="1.0" encoding="UTF-8"?>
<property xmlns="http://www.xwiki.org" name="email" type="Email">
 <link href="http://localhost:8080/xwiki/rest/wikis/xwiki/spaces/XWiki/pages/JohnDoe/objects/XWiki.XWikiUsers/0/properties/email" rel="self" />
 <attribute name="name" value="email" />
 <attribute name="prettyName" value="e-Mail" />
 <attribute name="unmodifiable" value="0" />
 <attribute name="disabled" value="0" />
 <attribute name="size" value="30" />
 <attribute name="validationRegExp" value="/^(([^@\s]+)@((?:[-a-zA-Z0-9]+\.)+[a-zA-Z]{2,}))?$/" />
 <attribute name="number" value="3" />
 <value>[email protected]</value>
</property>

Delete a page using the DELETE method

In this example we will delete the user page "XWiki.JohnDoe".

import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.HttpHost;
import org.apache.http.client.AuthCache;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.HttpHeaders;
...
String host = "mouhb-bu401lg";
int port = 8089;
String url = "http://localhost:8080/xwiki/rest/wikis/xwiki/spaces/XWiki/pages/JohnDoe";
String user = "Admin";
String password = "admin";

HttpHost target = new HttpHost(host, port, "http");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
  new AuthScope(target.getHostName(), target.getPort()),
  new UsernamePasswordCredentials(user, password));
CloseableHttpClient httpclient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();

try {
 // Create AuthCache instance
 AuthCache authCache = new BasicAuthCache();

 // Generate BASIC scheme object and add it to the local auth cache
 BasicScheme basicAuth = new BasicScheme();
  authCache.put(target, basicAuth);

 // Add AuthCache to the execution context
 HttpClientContext localContext = HttpClientContext.create();
  localContext.setAuthCache(authCache);
  localContext.setAttribute("preemptive-auth", basicAuth);
  HttpDelete httpDelete = new HttpDelete(url);

  CloseableHttpResponse response = httpclient.execute(target, httpDelete, localContext);

 try {
   // Request status
   // requestStatus=204 if the request was successful.
   int requestStatus = response.getStatusLine().getStatusCode();
 } finally {
    response.close();
 }
} finally {
  httpclient.close();
}

Conclusion

This post is just an entry point to the exploitation of the XWiki RESTful API using the Apache HTTP API, both APIs are well documented, so it will be easy for you to use both APIs.

Tags:
Created by Mohamed Boussaa on 2016/05/25
   

Get Connected