Article overview

/ JOSS library for Java

One of our customers, the development house 42, has created JOSS a Java library for OpenStack based object stores like the CloudVPS Object Store. The project can also be found on GitHub. Below you can see how you can use this library for the CloudVPS Object Store.

We start by opening up a stateful client and authenticating ourselves:

    Account account = new AccountFactory()

On failure, the client will throw an exception. On success, the account can now be used to execute actions on the Object Store. The account takes care of adding the token to the calls, so you don't have to worry about that. You should be aware, however, that tokens expire after 24 hours. The client will get a new token when it encounters a 401 and retry the original command just once.

Next, we want to create a public container, where we can store our images:

    Container container = account.getContainer("images");

A container is private by default, so you will have to explicitly set it to public to be able to access it through its public URL.

To check whether the creation succeeded, list the containers.

    Collection<Container> containers = account.list();
    for (Container currentContainer : containers) {

Now it is time to upload a file to the Object Store. In this example, we take an image located in the root directory of the file system.

    StoredObject object = container.getObject("dog.png");
    object.uploadObject(new File("/dog.png"));
    System.out.println("Public URL: "+object.getPublicURL());

If you fire up your browser, you can navigate to the public URL to see your resource for real. This is only possible because the container has been set to public. If it was private, you would not be able to do this.

You can also check whether the upload succeeded by listing the objects in a container or by fetching the object information.

    System.out.println("Last modified:  "+object.getLastModified());
    System.out.println("ETag:           "+object.getEtag());
    System.out.println("Content type:   "+object.getContentType());
    System.out.println("Content length: "+object.getContentLength());
    Collection<StoredObject> objects = container.list();
    for (StoredObject currentObject : objects) {

Alternatively, besides File, you could also use a byte[] or an InputStream to upload a file.

It is time to download what you just uploaded. Here we go.

    object.downloadObject(new File("/dog2.png"));

Open the file "/dog2.png" on the file system to verify that the operation worked. Again, also byte[] and InputStream are at your disposal. On using InputStream be aware that you are responsible for closing the stream by calling close() on the wrapper.

Now, if you want the object to be retrievable through another URL, you will have to move the object. This is accomplished by executing first a copy, then a delete action.

    StoredObject newObject = container.getObject("new-dog.png");
    object.copyObject(container, newObject);
    System.out.println("Public URL: "+object.getPublicURL()); // no longer retrievable
    System.out.println("Public URL: "+newObject.getPublicURL()); // the new URL

You can once more use the browser to access both resources. You will see that the first URL gives you a 404, while the second one now gives you the original resource.

It is possible to add metadata to both containers and objects.

    Map<String, Object> metadata = new TreeMap<String, Object>();
    metadata.put("title", "Some Title");
    metadata.put("department", "Some Department");

Likewise, this information can be retrieved, as seen above.

    Map<String, Object> returnedMetadata = container.getMetadata();
    for (String name : returnedMetadata.keySet()) {
        System.out.println("META / "+name+": "+returnedMetadata.get(name));

There are many situations in which it is not necessary, not possible, or even plain clumsy, to be connected to external dependencies. For those situations, JOSS offers the InMemory implementation of the OpenStackClient.

    AccountConfig config = new AccountConfig()
            .setUsername( username)
    Account account = new AccountFactory(config).createAccount();

All the operations work basically in the same way. It is possible to run the in-memory client and have it hold the resources for a local run of your application.

Share this article