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.
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.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.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
<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.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.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
<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.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.