Creating your own Rest Plugin ( extending REST API )
The Rest Plugin feature helps you to extending the REST API.
To create your own REST plugin you must create a new class that implements RestPlugin interface:
public interface RestPlugin extends Plugin {
Object executePlugin(Map<String, String> parameters, InputStream is);
}
The new class must be located into the package com.openkm.plugin.rest because the application plugins system will try to load it from there. See the sample below:
Do not miss the tag @PluginImplementation otherwise the application plugin system won't be able to use the class.
More information at Register a new plugin.
Method description
Method | Type | Description |
---|---|---|
executePlugin | String |
The method executes a REST plugin an return an object. |
Example of REST plugin implementation
package com.openkm.plugin.rest;
import java.util.Map;
import net.xeoh.plugins.base.annotations.PluginImplementation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Sample REST plugin
*
*/
@PluginImplementation
public class TestRestPlugin implements RestPlugin {
private static Logger log = LoggerFactory.getLogger(TestRestPlugin.class);
@Override
public Object executePlugin(Map<String, String> parameters, InputStream is) {
log.debug("executePlugin({})", parameters);
StringBuilder sb = new StringBuilder("{");
sb.append("className=").append(this.getClass().getCanonicalName());
for (String key : parameters.keySet()) {
sb.append(", "+key+"=").append(parameters.get(key));
}
sb.append("}");
return sb.toString();
}
}
Example of REST plugin implementation what returns file
The sample below goes in combination of REST webservice "/rest/plugin/executeGetPluginReturnFile" method.
package com.openkm.plugin.rest;
import com.openkm.bean.Document;
import com.openkm.integration.cifs.device.PathUtils;
import com.openkm.module.DocumentModule;
import com.openkm.module.ModuleManager;
import net.xeoh.plugins.base.annotations.PluginImplementation;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
/**
* Sample rest plugin
*/
@PluginImplementation
public class TestGetDocumentRestPlugin implements RestPlugin {
private static Logger log = LoggerFactory.getLogger(TestGetDocumentRestPlugin.class);
@Override
public Object executePlugin(Map<String, String> parameters, InputStream is) throws Exception {
log.debug("executePlugin({})", parameters);
DocumentModule dm = ModuleManager.getDocumentModule();
String docId = parameters.get("docId");
boolean inline = parameters.containsKey("inline");
Document doc = dm.getProperties(null, docId);
String mimeType = doc.getMimeType();
String fileName = PathUtils.getFileNameFromPath(doc.getPath());
final InputStream isContent = dm.getContent(null, docId, false);
StreamingOutput stream = new StreamingOutput() {
@Override
public void write(OutputStream os) throws IOException, WebApplicationException {
IOUtils.copy(isContent, os);
IOUtils.closeQuietly(isContent);
IOUtils.closeQuietly(os);
}
};
Response.ResponseBuilder response = Response.ok(stream);
response.type(mimeType); // because the method produces MediaType.APPLICATION_OCTET_STREAM can be set any document mime type
// inline true when you want to embedded the content into
if (inline) {
response.header("Content-disposition", "inline; filename=\"" + fileName + "\"");
} else {
response.header("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
}
return response;
}
}
Objects declaration
The method executionPlugin returns an Object. This object will be processed - marshall - by OpenKM. Basic types like String, Integer, etc. can be directly used, but for complex objects you need to use annotation on classes.
Marshall and unmarshall strategies:
- The result of the executed method is always an String. Internally the method converts the complex objects to JSON.
- The result of the executed mehod is a complex Object.
String scenario
From the plugin side - server side - you must convert the Object to JSON:
return new Gson().toJson(someObject)
From the cliend side you must convert JSON String to Object:
// value contains the returned String value by the REST call
SomeObject someObject = new Gson().fromJson(value, SomeObject.class);
Complex Object scenario
You can use existing OpenKM classes like Document, Folder, Record, Mail among others, because theses clases have already the annotation.
Use the anotation ( in the sample below the object will be marshalled with name "mail" ):
@XmlRootElement(name = "mail")
Example of complex classes:
Return a list of Strings:
package com.openkm.ws.rest.util;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "languages")
public class LanguageList {
@XmlElement(name = "language", required = true)
List<String> languages = new ArrayList<String>();
public List<String> getList() {
return languages;
}
}
Return a list of Mails:
package com.openkm.ws.rest.util;
import com.openkm.bean.Mail;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;
@XmlRootElement(name = "mails")
public class MailList {
@XmlElement(name = "mail", required = true)
List<Mail> mails = new ArrayList<Mail>();
public List<Mail> getList() {
return mails;
}
}
Complex object:
package com.openkm.bean;
import javax.xml.bind.annotation.XmlRootElement;
/**
* Record
*/
@XmlRootElement(name = "record")
public class Record {
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;
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 String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{");
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(", uuid=").append(uuid);
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("}");
return sb.toString();
}
}