Daisy documentation
 PreviousHomeNext 
4.16 ReplicationBook Index4.17.2 Scripting the repository using Javascript

4.17 Programming interfaces

The native API of the Daisy repository server is its Java interface. To allow other processes (on the same or another computer) to talk to the repository server, a HTTP+XML based interface is available. Lastly, the Java API of the Daisy repository server is also implemented in a "remote" variant, whereby it transparently uses the HTTP+XML interface to talk to the repository server.

Since a variety of scripting languages can be run on top of the Java VM, it is possible to use the Java API from such scripting languages, which is convenient for smaller jobs.

4.17.1 Java API

4.17.1.1 Introduction

Daisy is written in Java and thus its native interface is a Java API. This Java API is packaged separately, and consists of two jars:

daisy-repository-api-<version>.jar
daisy-repository-xmlschema-bindings-<version>.jar

The second jar, the xmlschema-bindings, are Java classes generated from XML Schemas, and form a part of the API. To write client code that talks to Daisy, at compile you need only the above two jars in the classpath (at runtime, you need a concrete implementation, see further on).

There are two implementations of this API available:

This is illustrated in the diagram below.

To be workable, the remote implementation caches certain information: the repository schema (document, field and part types), the collections, and the users (needed to be able to quickly map user IDs to user names). To be aware of changes done by other clients, the remote implementation can listen to the JMS events broadcasted by the server to update these caches. This is optional, for example a short-running client application that performs a specific task probably doesn't care much about this, especially since the cached information is not the kind of information that changes frequently. Even when JMS-based cache invalidation is disabled, the caches of a certain remote implementation instance are of course kept up-to-date for changes done through that specific instance.

Examples of applications making use of the remote API implementation are the Daisy Wiki, and the installation utilities daisy-wiki-init and daisy-wiki-add-site. Especially the source of those last two can serve as useful but simple examples of how to write client applications. The shell scripts to launch them show the required classpath libraries.

4.17.1.2 Reference documentation

See the javadoc documentation.

4.17.1.3 Quick introduction to the Java API

The Daisy Java API is quite high-level, and thus easy-to-use. The start point to do any work is the RepositoryManager interface, which has the following method:

Repository getRepository(Credentials credentials) throws RepositoryException;

The Credentials parameter is simply an object containing the user name and password. By calling the getRepository method, you get an instance of Repository, through which you can access all the repository functionality. The obtained Repository instance is specific for the user specified when calling getRepository. The Repository object does not need to be released after use. It is a quite lightweight object, mainly containing the authentication information.

Let's have a look at some of the methods of the Repository interface.

Document createDocument(String name, String documentTypeName);

Creates a new document with the given name, and using the named document type. The document is not immediately created in the repository, to do this you need to call the save() mehod on the Document. But first you need to set all required fields and parts, otherwise the save will fail (it is possible to circumvent this, see the full javadocs).

Document getDocument(long documentId, boolean updateable) throws RepositoryException;

Retrieves an existing document, specified by its ID. If the flag 'updateable' is false, the repository will return a read-only Document object, which allows it to return a shared cached copy. In the remote implementation, this doesn't matter since it doesn't perform any caching, but in the local implementation this can make a very huge difference.

RepositorySchema getRepositorySchema();

Returns an instance of RepositorySchema, through which you can inspect and modify the repository schema (these are the document, part and field types).

AccessManager getAccessManager();

Returns an instance of AccessManager, through which you can inspect and modify the ACL, and get the ACL evaluation result for a certain document-user-role combination.

QueryManager getQueryManager();

Returns an instance of QueryManager, through which you can perform queries on the repository using the Daisy Query Language.

CollectionManager getCollectionManager();

Returns an instance of CollectionManager, through which you can create, modify and delete document collections.

UserManager getUserManager();

Returns an instance of UserManager, through which you can create, modify and delete users.

The above was just to give a broad idea of the functionality available through the API. For more details, consult the complete JavaDoc of the API.

4.17.1.4 Writing a Java client application

Let's now look at a practical example. To use the remote repository API implementation, you need to have a number of jars in your classpath. The easiest way to get them right is to use the following dependencies in maven 2:

The list below was last updated for Daisy 2.4

If you don't use maven 2, you can look at the CLASSPATH variable defined in the daisy-js script (daisy-js.bat on Windows). You can skip the the jars for rhino-js and the daisy-javascript-tool.

<project>

  ...

  <repositories>
    <id>daisyjms</id>
    <repository>
      <id>daisycms-maven2</id>
      <name>Daisycms maven2 repository</name>
      <layout>default</layout>
      <url>http://daisycms.org/maven2</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>

  ...

  <build>
    <dependencies>
      <dependency><groupId>daisy</groupId><artifactId>daisy-repository-client-impl</artifactId><version>2.4</version></dependency>
      <dependency><groupId>daisy</groupId><artifactId>daisy-doctaskrunner-client-impl</artifactId><version>2.4</version></dependency>
      <dependency><groupId>daisy</groupId><artifactId>daisy-emailer-client-impl</artifactId><version>2.4</version></dependency>
      <dependency><groupId>daisy</groupId><artifactId>daisy-emailnotifier-client-impl</artifactId><version>2.4</version></dependency>
      <dependency><groupId>daisy</groupId><artifactId>daisy-htmlcleaner</artifactId><version>2.4</version></dependency>
      <dependency><groupId>daisy</groupId><artifactId>daisy-navigation-client-impl</artifactId><version>2.4</version></dependency>
      <dependency><groupId>daisy</groupId><artifactId>daisy-publisher-client-impl</artifactId><version>2.4</version></dependency>
      <dependency><groupId>daisy</groupId><artifactId>daisy-workflow-client-impl</artifactId><version>2.4</version></dependency>

      <dependency><groupId>xerces</groupId><artifactId>xercesImpl</artifactId><version>2.9.0</version></dependency>
      <dependency><groupId>xerces</groupId><artifactId>xmlParserAPIs</artifactId><version>2.2.1</version></dependency>
      <dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.3.04</version></dependency>

    </dependencies>
  </build>
</project>

So depending on your own habits, you could set up a project in your IDE with these jars in the classpath, or use a plugin to integrate with maven.

Below a simple and harmless example is shown: performing a query on the repository.

package mypackage;

import org.outerj.daisy.repository.RepositoryManager;
import org.outerj.daisy.repository.Credentials;
import org.outerj.daisy.repository.Repository;
import org.outerj.daisy.repository.query.QueryManager;
import org.outerj.daisy.repository.clientimpl.RemoteRepositoryManager;
import org.outerx.daisy.x10.SearchResultDocument;

import java.util.Locale;

public class Search {
    public static void main(String[] args) throws Exception {
        RepositoryManager repositoryManager = new RemoteRepositoryManager(
            "http://localhost:9263", new Credentials("guest", "guest"));
        Repository repository =
            repositoryManager.getRepository(new Credentials("testuser", "testuser"));
        QueryManager queryManager = repository.getQueryManager();

        SearchResultDocument searchresults =
            queryManager.performQuery("select id, name where true", Locale.getDefault());
        SearchResultDocument.SearchResult.Rows.Row[] rows =
            searchresults.getSearchResult().getRows().getRowArray();

        for (int i = 0; i < rows.length; i++) {
            String id = rows[i].getValueArray(0);
            String name = rows[i].getValueArray(1);
            System.out.println(id + " : " + name);
        }

        System.out.println("Total number: " + rows.length);

    }
}

The credentials supplied in the constructor of the RemoteRepositoryManager specify a user to be used for filling the caches in the repository client. This can be any user, the user doesn't need any special access privileges.

4.17.1.5 Java client application with Cache Invalidation

For long-running client applications you may want to have the caches of the client invalidated when changes happen by other users. For a code sample of how to create a JMS client and pass it on to the RemoteRepositoryManager, see JMS Cache Invalidation Sample.

For this example to run, you'll need to add a dependency on the the JMS client, in addition to the dependencies listed earlier:

    <dependency><groupId>daisy</groupId><artifactId>daisy-jmsclient-impl</artifactId><version>2.4</version></dependency>

4.17.1.6 More

It might be interesting to also have a look at the notes on scripting using Javascript, since there essentially the same API is used from a different language.

 PreviousHomeNext 
4.16 Replication4.17.2 Scripting the repository using Javascript