RPC Module

Available:

Confluence 1.4 and later

RPC plugins allow you to deploy arbitrary SOAP or XML-RPC services within Confluence. These services may be completely independent of Confluence, or may take advantage of the Confluence APIs to provide a remote, programmatic interface to the Confluence server. Confluence's packaged remote API is implemented entirely as a plugin.

XML-RPC Plugins

Here is an example atlassian-plugin.xml file containing a single XML-RPC service:

<atlassian-plugin name="Sample XML-RPC" key="confluence.extra.xmlrpc">
    ...
    <rpc-xmlrpc key="helloworld-xmlrpc"
                name="Hello World XML-RPC"
                class="com.atlassian.confluence.extra.helloworldrpc.HelloWorld">
        <description>A public example XML-RPC service</description>
        <service-path>helloworld</service-path>
    </rpc-xmlrpc>
    ...
</atlassian-plugin>
  • the class attribute defines the class that will be servicing XML-RPC requests. One instance of this class will be instantiated, and all of its public methods will be made available remotely. The instance is autowired from the Spring context.
  • the service-path attribute is the method-prefix that is used to determine which XML-RPC method calls are routed to this plugin.

Confluence listens for XML-RPC requests at a single end-point. If your server is deployed at http://www.example.com then all XML-RPC requests must be made to http://www.example.com/rpc/xmlrpc. As such, the service-path is used to distinguish which plugin each request is directed at. If your RPC implementing class has a method provideGreeting(), and a service-prefix of helloworld, then the XML-RPC method call will be helloworld.provideGreeting().

XML-RPC Interfaces

The XML-RPC specification is more limited than Java code. in particular:

  • all method parameters in the class you have deployed must take as arguments, and return as values only the "XML-RPC-friendly types" listed below
  • null is not a valid XML-RPC type, so you must never send null as an argument, or return null as a value
  • void is not a valid XML-RPC return type, so all methods exposed via XML-RPC must return some value

Valid types for use as arguments in methods exposed via XML-RPC, or as return values from XML-RPC methods are:

  • int
  • boolean
  • java.lang.String
  • double
  • java.util.Date
  • java.util.Hashtable
  • java.util.Vector
  • byte[]

The object wrappers for the primitive types (java.lang.Integer, java.lang.Boolean, etc) may be used as return values, but not as method arguments. For more information, see: http://ws.apache.org/xmlrpc/types.html

SOAP Plugins

Here is an example atlassian-plugin.xml file containing a single SOAP service:

<atlassian-plugin name="Sample XML-RPC" key="confluence.extra.xmlrpc">
    ...
    <rpc-soap key="helloworld-soap" name="Hello World SOAP" class="com.atlassian.confluence.extra.helloworldrpc.HelloWorld">
        <description>A public example SOAP service</description>
        <service-name>HelloWorldPublic</service-name>
        <service-path>helloworld</service-path>
        <published-interface>com.atlassian.confluence.extra.helloworldrpc.HelloWorldPublic</published-interface>
    </rpc-soap>
    ...
</atlassian-plugin>
  • the class attribute defines the class that will be servicing SOAP requests. One instance of this class is instantiated and autowired from the Spring context.
  • the service-path element defines the SOAP service-path for this plugin, and where its WSDL file will be located.
  • the published-interface element defines a Java interface that will be exposed via the SOAP service. The class defined in the class attribute must implement this interface.

Confluence listens for SOAP requests at a single end-point. If your server is deployed at http://www.example.com then all XML-RPC requests must be made to http://www.example.com/rpc/soap. The preferred method for calling a SOAP service on Confluence is by parsing the Axis WSDL file that is generated automatically for any deployed SOAP plugin. If your plugin has a service-path of helloworld, its WSDL file will be available at http://www.example.com/rpc/soap-axis/helloworld?WSDL

Unlike XML-RPC, SOAP can accept and return complex types.

RPC Authentication

Confluence supplies a very simple, token-based authentication service for its remote API. Users log in over the remote interface using a login(username, password) method, and are supplied with a String token. This String token is then supplied as the first argument of any subsequent remote call, to authenticate the user with their previous login. More information about this protocol can be found in the Confluence XML-RPC and SOAP APIs documentation.

Any RPC plugin can take advantage of the authentication service. To do so you must make some changes to your remote service objects, and to the configuration.

Here is an atlassian-plugin.xml containing SOAP and XML-RPC services that require authentication:

<atlassian-plugin name="Sample XML-RPC" key="confluence.extra.xmlrpc">
    ...
    <rpc-xmlrpc key="helloworldsecure-xmlrpc"
                name="Secure Hello World XML-RPC"
                class="com.atlassian.confluence.extra.helloworldrpc.HelloWorldSecureImpl">
        <description>An example XML-RPC service that requires a login</description>
        <service-name>HelloWorldSecure</service-name>
        <service-path>helloworld-secure</service-path>
        <published-interface>com.atlassian.confluence.extra.helloworldrpc.HelloWorldSecure</published-interface>
        <authenticate>true</authenticate>
    </rpc-xmlrpc>

    <rpc-soap key="helloworldsecure-soap"
              name="Secure Hello World SOAP"
              class="com.atlassian.confluence.extra.helloworldrpc.HelloWorldSecureImpl">
        <description>An example SOAP service that requires a login</description>
        <service-name>HelloWorldSecure</service-name>
        <service-path>helloworld-secure</service-path>
        <published-interface>com.atlassian.confluence.extra.helloworldrpc.HelloWorldSecure</published-interface>
        <authenticate>true</authenticate>
    </rpc-soap>
    ...
</atlassian-plugin>

An authenticated XML-RPC service requires an additional published-interface element that behaves like the published-interface element in the SOAP plugin: you must supply a Java Interface to represent which methods of your plugin class are being exposed remotely. The class represented by the class attribute must implement this interface.

There are two changes you have to make to your remote service objects (and their published interfaces) to allow them to take advantage of authentication:

  1. You must implement the String login(String username, String password) and boolean logout(String token) methods in com.atlassian.confluence.rpc.SecureRpc. However, since these methods will be intercepted by the Confluence RPC framework, they will never actually be called on your object. As such, you can leave the implementations empty.
  2. All methods in your published interface must have an initial argument that is a String (the authentication token). This token will also be intercepted by the Confluence RPC framework. Your code must not rely on this token having any value by the time the method is called on your plugin.

If you are providing an authenticated service, the logged-in User will be available to you from com.atlassian.confluence.user.AuthenticatedUserThreadLocal.getUser()

If anonymous RPC is enabled for your server, the logged-in user may be null

Hibernate Session

If you use the Confluence API within your plugin you will probably need to create a Hibernate session, and start a transaction. Getting an error like: net.sf.hibernate.HibernateException: Could not initialize proxy - the owning Session was closed is one indication. As a version 2 plugin does not have access to the transactionManager anymore, the SAL TransactionTemplate can be used instead.

Using a simple HelloWorld example:

package com.atlassian.confluence.extra.helloworldrpcv2;

public interface HelloWorld
{
    String sayHello();
}

this is a simple implementation with a programmatic transaction using the SAL TransactionTemplate.

package com.atlassian.confluence.extra.helloworldrpcv2;

import com.atlassian.confluence.spaces.SpaceManager;
import com.atlassian.sal.api.transaction.TransactionCallback;
import com.atlassian.sal.api.transaction.TransactionTemplate;

public class DefaultHelloWorld implements HelloWorld
{
    private final TransactionTemplate transactionTemplate;
    private final SpaceManager spaceManager;

    public DefaultHelloWorld(final SpaceManager spaceManager, final TransactionTemplate transactionTemplate)
    {
        this.spaceManager = spaceManager;
        this.transactionTemplate = transactionTemplate;
    }

    public String sayHello()
    {
        return (String) transactionTemplate.execute(new TransactionCallback()
        {
            public Object doInTransaction()
            {
                return String.format("Hello world! Number of spaces: %d", spaceManager.getAllSpaces().size());
            }
        });
    }
}

In order to use the TransactionTemplate a component-import module needs to be added to the plugin descriptor:

    <rpc-xmlrpc key="helloworld-xmlrpc"
                name="Hello World XML-RPC"
                class="com.atlassian.confluence.extra.helloworldrpcv2.DefaultHelloWorld">
        <description>A public example XML-RPC service</description>
        <service-path>helloworld</service-path>
    </rpc-xmlrpc>

    <component-import key="transactionTemplate">
        <description>Import the com.atlassian.sal.api.transaction.TransactionTemplate</description>
        <interface>com.atlassian.sal.api.transaction.TransactionTemplate</interface>
    </component-import>

and the dependency to the project's pom:

        <dependency>
            <groupId>com.atlassian.sal</groupId>
            <artifactId>sal-api</artifactId>
            <version>${sal.version}</version>
            <scope>provided</scope>
        </dependency>

[...]

    <properties>
        <sal.version>2.0.11</sal.version>
        <confluence.version>3.1.1</confluence.version>
        <confluence.data.version>3.1</confluence.data.version>
    </properties>

    <scm>

Instead of using the TransactionTemplate directly please consider using a DynamicProxy or Spring AOP to wrap your business logic inside a transaction using the SAL TransactionTemplate.

Example

Example XML-RPC and SOAP plugins are available in the Confluence distribution under plugins/helloworldrpc.
It can also be[found here.

The full source to the Confluence remote API plugin can be found in the Confluence distribution under plugins/confluencerpc. The Confluence Remote API uses a mixture of RPC plugins and Component Module, along with a simple mechanism to serialise Java objects into an XML-RPC compatible struct, to serve the same API over both SOAP and XML-RPC. We strongly recommend you use a similar mechanism to provide both RPC APIs.

Was this page helpful?

Have a question about this article?

See questions about this article

Powered by Confluence and Scroll Viewport