Creating your own Rest Plugin ( extending REST API )
You can create your own REST Plugin.
Conditions:
- The new REST class must implement the “RestPlugin” interface.
- The new REST class must be declared under the package “com.openkm.plugin.rest”.
- The new REST class must be annotated with “@PluginImplementation”.
- The new REST class must extend “BasePlugin”.
REST interface:
package com.openkm.plugin.rest;
import net.xeoh.plugins.base.Plugin;
import java.io.InputStream;import java.util.Map;
/** * RestPlugin */public interface RestPlugin extends Plugin {
Object executePlugin(Map<String, String> parameters, InputStream is) throws Exception;
}The new class must be located in the package com.openkm.plugin.rest because the application plugin system will try to load it from there.
Method description
Section titled “Method description”| Method | Type | Description |
|---|---|---|
| executePlugin | Object | The method executes a REST plugin and returns an object. |
Example of REST plugin implementation
Section titled “Example of REST plugin implementation”package com.openkm.plugin.rest;
import com.openkm.plugin.BasePlugin;import net.xeoh.plugins.base.annotations.PluginImplementation;import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import java.io.InputStream;import java.util.Map;
/** * Sample rest plugin */@PluginImplementationpublic class TestRestPlugin extends BasePlugin implements RestPlugin {
private static Logger log = LoggerFactory.getLogger(TestRestPlugin.class);
@Override public Object executePlugin(Map<String, String> parameters, InputStream is) throws Exception { log.debug("executePlugin({})", parameters); StringBuilder sb = new StringBuilder(); sb.append("{"); sb.append("className=").append(this.getClass().getCanonicalName()); for (String key : parameters.keySet()) { sb.append(", " + key + "=").append(parameters.get(key)); } return sb.toString(); }}Example of REST plugin implementation that returns a file
Section titled “Example of REST plugin implementation that returns a file”package com.openkm.plugin.rest;
import com.openkm.bean.Document;import com.openkm.module.db.DbDocumentModule;import com.openkm.plugin.BasePlugin;import com.openkm.util.PathUtils;import net.xeoh.plugins.base.annotations.PluginImplementation;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.core.io.InputStreamResource;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpStatus;import org.springframework.http.ResponseEntity;
import java.io.InputStream;import java.util.Map;
/** * Sample rest plugin */@PluginImplementationpublic class TestGetDocumentRestPlugin extends BasePlugin implements RestPlugin {
private static Logger log = LoggerFactory.getLogger(TestGetDocumentRestPlugin.class);
@Autowired private DbDocumentModule dbDocumentModule;
@Autowired private PathUtils pathUtils;
@Override public Object executePlugin(Map<String, String> parameters, InputStream is) throws Exception { log.debug("executePlugin({})", parameters); String docId = parameters.get("docId"); boolean inline = parameters.containsKey("inline"); Document doc = dbDocumentModule.getProperties(null, docId); String mimeType = doc.getMimeType(); String fileName = pathUtils.getName(doc.getPath()); InputStream isContent = dbDocumentModule.getContent(null, docId, false);
HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.add("Content-Type", mimeType);
// inline true when you want to embedded the content into if (inline) { responseHeaders.add("Content-disposition", "inline; filename=\"" + fileName + "\""); } else { responseHeaders.add("Content-Disposition", "attachment; filename=\"" + fileName + "\""); }
responseHeaders.setContentLength(doc.getActualVersion().getSize()); InputStreamResource inputStreamResource = new InputStreamResource(isContent); log.debug("TestGetDocumentRestPlugin: [BINARY]"); return new ResponseEntity<>(inputStreamResource, responseHeaders, HttpStatus.OK); }}Objects declaration
Section titled “Objects declaration”The method executionPlugin returns an Object. This object will be processed - marshalled - by OpenKM. Basic types like String, Integer, etc. can be used directly, but for complex objects you need to use annotations on classes.
Marshalling and unmarshalling strategies:
- The result of the executed method is always a String. Internally, the method converts complex objects to JSON.
- The result of the executed method is a complex object.
String scenario
Section titled “String scenario”From the plugin side - server side - you must convert the object to JSON:
return new Gson().toJson(someObject)From the client side you must convert the JSON string to an object:
// value contains the returned String value by the REST callSomeObject someObject = new Gson().fromJson(value, SomeObject.class);Complex Object scenario
Section titled “Complex Object scenario”You can use existing OpenKM classes like Document, Folder, Record, Mail among others, because these classes already have the annotations.
Example of complex classes:
Section titled “Example of complex classes:”Return a list of Activities:
package com.openkm.ws.rest.util;
import com.openkm.db.bean.Activity;
import java.util.ArrayList;import java.util.List;
public class ActivityList {
List<Activity> activities = new ArrayList<>();
private int totalElements;
public List<Activity> getActivities() { return activities; }
public void setActivities(List<Activity> activities) { this.activities = activities; }
public int getTotalElements() { return totalElements; }
public void setTotalElements(int totalElements) { this.totalElements = totalElements; }}Complex object:
package com.openkm.bean;
public class Record extends Parent {
private static final long serialVersionUID = 1L; public static final String TYPE = "okm:record"; public static final String NAME = "okm:name";
private boolean locked; private LockInfo lockInfo; private String title; private boolean hasLinks;
public boolean isLocked() { return locked; }
public void setLocked(boolean locked) { this.locked = locked; }
public LockInfo getLockInfo() { return lockInfo; }
public void setLockInfo(LockInfo lockInfo) { this.lockInfo = lockInfo; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public boolean hasLinks() { return hasLinks; }
public void setHasLinks(boolean hasLinks) { this.hasLinks = hasLinks; }
@Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("{"); sb.append("uuid=").append(uuid); sb.append(", parent=").append(parent); sb.append(", path=").append(path); sb.append(", permissions=").append(permissions); sb.append(", created=").append(created == null ? null : created.getTime()); sb.append(", subscribed=").append(subscribed); sb.append(", subscriptors=").append(subscriptors); sb.append(", keywords=").append(keywords); sb.append(", categories=").append(categories); sb.append(", notes=").append(notes); sb.append(", locked=").append(locked); sb.append(", lockInfo=").append(lockInfo); sb.append(", title=").append(title); sb.append(", nodeClass=").append(getNodeClass()); sb.append(", nodeClassChildren=").append(getNodeClassChildren()); sb.append(", dispositionCurrentStage=").append(getDispositionCurrentStage()); sb.append("}"); return sb.toString(); }}Advanced REST sample
Section titled “Advanced REST sample”The next sample is a project that uses a low-level API implementation for quick uploads and setting metadata at the same time. The sample comes with a plugin implementation and a client plugin test.
If you have a large upload process and are looking for better performance, this is a good approach.
- Download the sample project sample-rest.zip.