App - Development: Sample java-client

Sample java-client shows how to use the rest-api of Matterial.

Preface

matterial-api

Take a look at the matterial-api, which is publicly available at github. This project defines the api-objects.

Maven POM

Example pom.xml to start implementing a simple java client for the matterial-app:

<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <name>mtr-sample-client</name>
    <groupId>matterial</groupId>
    <artifactId>mtr-sample-client</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <url>http://maven.apache.org</url>

    <organization>
        <name>Matterial</name>
        <url>http://www.matterial.com</url>
    </organization>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jackson2-provider</artifactId>
            <version>3.5.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-client</artifactId>
            <version>3.5.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>matterial</groupId>
            <artifactId>matterial-api</artifactId>
            <version>1.5.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <compilerVersion>1.8</compilerVersion>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <version>2.1.2</version>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>jar-no-fork</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>

</project>

Session handling

Matterial is based on a standard cookie based session handling.
You may want to implement something like that:

protected static final String SESSION_COOKIE_NAME = "JSESSIONID";

protected String sessionId;
protected String getSessionId() {
    if(this.sessionId == null) {
        this.sessionId = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase().concat(".node1");
    }
    return this.sessionId;
}
protected void updateSession(Response resp) {
    Map<String, NewCookie> cookies = resp.getCookies();
    NewCookie sessionCookie = cookies.get(SESSION_COOKIE_NAME);
    if(sessionCookie != null) {
        String sessionId = sessionCookie.getValue();
        this.sessionId = sessionId;
    }
}

Basic rest-client

You have to implement a basic rest-client to invoke matterial-api.
A possible implemenation will define some constants for the request-options and uses Resteasy to create a basic client:

public static final int REQUEST_NOTHING = 0;
public static final int REQUEST_XML = 1;
public static final int REQUEST_JSON = 2;
public static final int REQUEST_PLAIN = 3;
public static final int REQUEST_HTML = 4;
protected Builder createClient(String path, int acceptedResponse) {
        Client client = ResteasyClientBuilder.newClient();
    WebTarget target = client.target(path);
    Builder builder = null;
    if(acceptedResponse == REQUEST_XML) {
        builder = target.request(MediaType.APPLICATION_XML_TYPE);
    }
    else if(acceptedResponse == REQUEST_JSON) {
        builder = target.request(MediaType.APPLICATION_JSON_TYPE);
    }
    else if(acceptedResponse == REQUEST_PLAIN) {
        builder = target.request(MediaType.TEXT_PLAIN_TYPE);
    }
    else if(acceptedResponse == REQUEST_HTML) {
        builder = target.request(MediaType.TEXT_HTML_TYPE);
    }
    else {
        builder = target.request();
    }
    builder.cookie(SESSION_COOKIE_NAME, this.getSessionId());
    return builder;
}

You can use this code to implement the request-methods your application needs.

GET requesting JSON

protected Response get(String path) {
    return this.createClient(path, REQUEST_JSON).get();
}

PUT JSON and requesting JSON

protected Response put(String path, Object entity) {
    return this.createClient(path, REQUEST_JSON).put(Entity.json(entity));
}

DELETE requesting PLAIN

protected Response deleteRequestPlain(String path) {
    return this.createClient(path, REQUEST_PLAIN).delete();
}

...

Base-path

The base-path of your matterial-app-client should always be:

String basePath = "https://my.matterial.com/mtr-backend/";

Example

Hello world

A simple hello world would look like this:

String path = basePath+"test";
Response resp = this.getNothing(path);
String hello = resp.readEntity(String.class);
logger.info("helloworld() - RESULT: {}", hello);

Login

A basic login with username / password could be implemented like this:

public LoginData login(String userName, String password) {
    String path = this.basePath + APPLICATION_PATH + "/" + Api.LOGON;
    Logon logon = new Logon(userName, password);
    LoginData loginData = null;
    try(Response resp = this.post(path, logon)) {
        this.updateSession(resp);
        loginData = resp.readEntity(LoginData.class);
    }
    return loginData;
}

Logout

A simple logout goes like this:

public void logout() {
    String path = this.basePath + APPLICATION_PATH + "/" + Api.LOGON;
    try(Response resp = this.deleteRequestPlain(path);) {
        boolean loggedOut = resp.readEntity(Boolean.class);
    }
}

Fetch documents

To fetch all documents (meta-data) from matterial:

public ListResult<Document> loadDocuments() {
    String path = this.basePath + APPLICATION_PATH+"/" + Api.DOCUMENT;
    ListResult<Document> lr = null;
    try(Response resp = this.get(path+
             "?"+PARAM_ALL_LANGUAGES+"=true"+
             "&"+PARAM_LOAD_ADDITIONAL_PROPERTIES+"=true"+
             "&"+PARAM_LOAD_ATTACHMENTS+"=true"+
             "&"+PARAM_LIMIT+"=10"+
             "&"+PARAM_COUNT+"=true")) {
        lr = resp.readEntity(new GenericType<ListResult<Document>>() {});
    }
    return lr;
}

Load document main content

Matterial stored meta-data and main-content of a document separately, so you have load it accordingly.

public String loadDocumentContent(long documentId, String languageKey) {
    String path = this.basePath + APPLICATION_PATH+"/" + Api.DOCUMENT;
    String content = null;
    try(Response resp = this.getNothing(path+"/"+documentId+"/"+FILE+"?"+PARAM_LANGUAGE_KEY+"="+languageKey)) {
        try(InputStream in = resp.readEntity(InputStream.class)) {
            if(in != null) {
                content = IOUtils.toString(in, CharEncoding.UTF_8);
            }
        }
        catch (IOException e) {
            logger.error("loadDocumentContent() - ", e);
        }
    }
    return content;
}

Complete example

You can find the complete example-project at github.

RestClient

package com.matterial.mtr.sample.client;

import java.util.Map;
import java.util.UUID;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation.Builder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;

import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <strong>RestClient</strong>
 */
public class RestClient {

    private static final Logger logger = LoggerFactory.getLogger(RestClient.class);

    public static final String SESSION_COOKIE_NAME = "JSESSIONID";

    public static final int REQUEST_NOTHING = 0;
    public static final int REQUEST_XML = 1;
    public static final int REQUEST_JSON = 2;
    public static final int REQUEST_PLAIN = 3;
    public static final int REQUEST_HTML = 4;

    protected String sessionId;


    protected Response getNothing(String path) {
        Response resp = this.createClient(path, REQUEST_NOTHING).get();
        logger.trace("get() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response getPlain(String path) {
        Response resp = this.createClient(path, REQUEST_PLAIN).get();
        logger.trace("getPlain() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response get(String path) {
        Response resp = this.createClient(path, REQUEST_JSON).get();
        logger.trace("get() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response putNothing(String path) {
        Response resp = this.createClient(path, REQUEST_JSON).put(null);
        logger.trace("putNothing() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response putNothingRequestPlain(String path) {
        Response resp = this.createClient(path, REQUEST_PLAIN).put(null);
        logger.trace("putNothingRequestPlain() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response putNothingRequestNothing(String path) {
        Response resp = this.createClient(path, REQUEST_NOTHING).put(null);
        logger.trace("putNothingRequestNothing() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response putPlainRequestNothing(String path, String entity) {
        Response resp = this.createClient(path, REQUEST_NOTHING).put(Entity.text(entity));
        logger.trace("putPlainRequestNothing() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response putPlainRequestPlain(String path, String entity) {
        Response resp = this.createClient(path, REQUEST_PLAIN).put(Entity.text(entity));
        logger.trace("putPlainRequestPlain() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response putPlain(String path, String entity) {
        Response resp = this.createClient(path, REQUEST_JSON).put(Entity.text(entity));
        logger.trace("putPlain() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response putRequestNothing(String path, Object entity) {
        Response resp = this.createClient(path, REQUEST_NOTHING).put(Entity.json(entity));
        logger.trace("putRequestNothing() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response putRequestPlain(String path, Object entity) {
        Response resp = this.createClient(path, REQUEST_PLAIN).put(Entity.json(entity));
        logger.trace("putRequestPlain() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response put(String path, Object entity) {
        Response resp = this.createClient(path, REQUEST_JSON).put(Entity.json(entity));
        logger.trace("put() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response post(String path, Object entity) {
        Response resp = this.createClient(path, REQUEST_JSON).post(Entity.json(entity));
        logger.trace("post() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response postNothing(String path) {
        Response resp = this.createClient(path, REQUEST_JSON).post(null);
        logger.trace("post() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response postPlain(String path, Object entity) {
        Response resp = this.createClient(path, REQUEST_JSON).post(Entity.text(entity));
        logger.trace("post() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response postPlainRequestPlain(String path, Object entity) {
        Response resp = this.createClient(path, REQUEST_PLAIN).post(Entity.text(entity));
        logger.trace("post() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response postPlainRequestHtml(String path, Object entity) {
        Response resp = this.createClient(path, REQUEST_HTML).post(Entity.text(entity));
        logger.trace("post() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response postRequestNothing(String path, Object entity) {
        Response resp = this.createClient(path, REQUEST_NOTHING).post(Entity.json(entity));
        logger.trace("post() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response delete(String path) {
        Response resp = this.createClient(path, REQUEST_JSON).delete();
        logger.trace("delete() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response deleteRequestPlain(String path) {
        Response resp = this.createClient(path, REQUEST_PLAIN).delete();
        logger.trace("deletePlain() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Response deleteRequestNothing(String path) {
        Response resp = this.createClient(path, REQUEST_NOTHING).delete();
        logger.trace("deleteNothing() - STATUS: " + resp.getStatus());
        return resp;
    }

    protected Builder createClient(String path, int acceptedResponse) {
        Client client = ResteasyClientBuilder.newClient();
        WebTarget target = client.target(path);
        Builder builder = null;
        if(acceptedResponse == REQUEST_XML) {
            builder = target.request(MediaType.APPLICATION_XML_TYPE);
        }
        else if(acceptedResponse == REQUEST_JSON) {
            builder = target.request(MediaType.APPLICATION_JSON_TYPE);
        }
        else if(acceptedResponse == REQUEST_PLAIN) {
            builder = target.request(MediaType.TEXT_PLAIN_TYPE);
        }
        else if(acceptedResponse == REQUEST_HTML) {
            builder = target.request(MediaType.TEXT_HTML_TYPE);
        }
        else {
            builder = target.request();
        }
        builder.cookie(SESSION_COOKIE_NAME, this.getSessionId());
        return builder;
    }

    /**
     * generate a random session id
     */
    protected String getSessionId() {
        if(this.sessionId == null) {
            this.sessionId = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase().concat(".node1");
        }
        return this.sessionId;
    }

    protected void updateSession(Response resp) {
        Map<String, NewCookie> cookies = resp.getCookies();
        NewCookie sessionCookie = cookies.get(SESSION_COOKIE_NAME);
        if(sessionCookie != null) {
            String sessionId = sessionCookie.getValue();
            this.sessionId = sessionId;
            logger.trace("updateSession() - SESSION_ID UPDATED...");
        }
        logger.trace("updateSession() - USING SESSION: {} ", this.sessionId);
    }

}

MtrRestClient

package com.matterial.mtr.sample.client;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.Response;

import org.apache.commons.codec.CharEncoding;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.matterial.mtr.api.Api;
import com.matterial.mtr.api.object.AdditionalProperty;
import com.matterial.mtr.api.object.Attachment;
import com.matterial.mtr.api.object.Document;
import com.matterial.mtr.api.object.ListResult;
import com.matterial.mtr.api.object.LoginData;
import com.matterial.mtr.api.object.Logon;

/**
 * <strong>MtrRestClient</strong>
 */
public class MtrRestClient extends RestClient {

    private static final Logger logger = LoggerFactory.getLogger(MtrRestClient.class);

    public static final String APPLICATION_PATH = "api";

    protected String basePath;

    public MtrRestClient(String basePath) {
        this.basePath = basePath;
    }

    public LoginData login(String userName, String password) {
        String path = this.basePath + APPLICATION_PATH+"/" + Api.LOGON;
        logger.trace("login()");
        Logon logon = new Logon(userName, password);
        LoginData loginData = null;
        try(Response resp = this.post(path, logon)) {
            this.updateSession(resp);
            loginData = resp.readEntity(LoginData.class);
            logger.trace("login() - sessionId: " + this.sessionId);
        }
        return loginData;
    }

    public void logout() {
        String path = this.basePath + APPLICATION_PATH + "/" + Api.LOGON;
        logger.trace("logout() - -- LOGOUT ------------");
        try(Response resp = this.deleteRequestPlain(path);) {
            boolean loggedOut = resp.readEntity(Boolean.class);
            logger.trace("logout() - loggedOut: " + loggedOut);
        }
    }

    public ListResult<Document> loadDocuments() {
        String path = this.basePath + APPLICATION_PATH+"/" + Api.DOCUMENT;
        logger.debug("loadDocuments()");
        // *** load metadata of all default-documents;
        ListResult<Document> lr = null;
        try(Response resp = this.get(path+
                 "?"+Api.PARAM_ALL_LANGUAGES+"=true"+
                 "&"+Api.PARAM_LOAD_ADDITIONAL_PROPERTIES+"=true"+
                 "&"+Api.PARAM_LOAD_ATTACHMENTS+"=true"+
                 "&"+Api.PARAM_LIMIT+"=10"+
                 "&"+Api.PARAM_COUNT+"=true")) {
            lr = resp.readEntity(new GenericType<ListResult<Document>>() {});
        }
        return lr;
    }

    public String loadDocumentContent(long documentId, String languageKey) {
        String path = this.basePath + APPLICATION_PATH+"/" + Api.DOCUMENT;
        logger.debug("loadDocumentContent({}, {})", documentId, languageKey);
        // *** load content;
        String content = null;
        try(Response resp = this.getNothing(path+"/"+documentId+"/"+Api.FILE+"?"+Api.PARAM_LANGUAGE_KEY+"="+languageKey)) {
            logger.trace("loadDocumentContent() - mediaType: " + resp.getMediaType());
            logger.trace("loadDocumentContent() - length: " + resp.getLength());
            try(InputStream in = resp.readEntity(InputStream.class)) {
                if(in != null) {
                    content = IOUtils.toString(in, CharEncoding.UTF_8);
                }
            }
            catch (IOException e) {
                logger.error("loadDocumentContent() - ", e);
            }
        }
        return content;
    }

    @SuppressWarnings("resource")
    public InputStream loadAttachmentContent(long documentId, long documentLanguageVersionId, long attachmentId) {
        String path = this.basePath + APPLICATION_PATH+"/" + Api.DOCUMENT;
        logger.debug("loadAttachmentContent({}, {}, {})", documentId, documentLanguageVersionId, attachmentId);
        // *** load content;
        Response resp = this.getNothing(path+"/"+documentId+"/"+
                                        Api.VERSION+"/"+documentLanguageVersionId+"/"+
                                        Api.ATTACHMENT+"/"+attachmentId);
        logger.trace("loadAttachmentContent() - mediaType: " + resp.getMediaType());
        logger.trace("loadAttachmentContent() - length: " + resp.getLength());
        return resp.readEntity(InputStream.class);
    }

    /**
     * sample-usage;
     */
    public static void main(String[] args) {
        String basePath = "http://localhost:8080/mtr-backend/";
        logger.info("USING: "+basePath);

        MtrRestClient client = new MtrRestClient(basePath);
        LoginData ld = client.login("user", "xxx");
        logger.info("CURRENT DS: "+ld.getCurrentDataSource().getDisplayName());

        ListResult<Document> lr = client.loadDocuments();
        List<Document> docs = lr.getResults();
        long count = lr.getTotalHits();
        logger.info("COUNT OF DOCUMENTS: " + count);
        for (Document document : docs) {
            logger.info("DOCUMENT FOUND: "+document.getId()+"/"+document.getLanguageVersionLanguageKey()+" => "+document.getLanguageVersionTitle());
            for (AdditionalProperty ap : document.getAdditionalProperties()) {
                logger.info("ADDITIONAL PROPERTY: id: "+ap.getId()+", type: "+ap.getPropertyType()+", name: "+ap.getName());
            }
            List<Attachment> atts = document.getAttachments();
            for (Attachment att : atts) {
                logger.info("ATTACHMENT: "+att.getId()+" => "+att.getName());
                try(InputStream attStream = client.loadAttachmentContent(document.getId(), document.getLanguageVersionId(), att.getId())) {
                    System.out.println("ATTACHMENT: "+attStream);
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
            String content = client.loadDocumentContent(document.getId(), document.getLanguageVersionLanguageKey());
            logger.info("DOCUMENT CONTENT: \n" + content+"\n*********************************************************\n\n");
        }

        client.logout();
    }

}
×
Peter's Problem.