Complete frontend extension sample
This sample shows how to quickly extend OpenKM’s features with JSP, HTML, CSS and JavaScript technologies using the OpenKM Java API and how to use the JavaScript functions of the exposed frontend JAVA methods.
Download the extension sample code complete_extension_sample.zip.
Description
Section titled “Description”The sample is shown in a new Workspace tab.
The main screen is shown as a tool bar with three buttons:
- The first button goes to main screen of the sample.
- The second button shows sample 1
- The second button shows sample 2.
Project structure:

Installation
Section titled “Installation”- Stop the application.
- Open the content of the download file in the OpenKM.war (the $TOMCAT_HOME/webapps/OpenKM folder is a second option)
- Delete $TOMCAT_HOME/work/Catalina/localhost
- Start the application.
- Check the url http://localhost:8080/OpenKM/sample.
Implementation details
Section titled “Implementation details”index.jsp
Section titled “index.jsp”Index.jsp controls the iframe height with a JavaScript code.
another important fact is that, for example, after uploading a document (Sample 2), the parameter urlToOpen is used to indicate which url must be opened.
String urlToOpen = URLDecoder.decode(WebUtils.getString(request, "urlToOpen"),"UTF-8");if (urlToOpen.equals("")) { urlToOpen = "home.jsp";}menu.jsp
Section titled “menu.jsp”Has the menu url definitions.

home.jsp
Section titled “home.jsp”Set the main home screen.

Sample 1
Section titled “Sample 1”Is composed of 4 files:
- action.jsp (the main controller where the logic is set).
- distributor.jsp (the main layer with two columns at 50%).
- full_list.jsp (show the full list with no JavaScript special control).
- filtered_list.jsp (show a filtered list with no JavaScript special control).
action.jsp
Section titled “action.jsp”The main controller.
<%@page import="java.util.Map"%><%@page import="java.util.HashMap"%><%@page import="java.util.List"%><%@page import="java.util.ArrayList"%><%@ page import="java.text.SimpleDateFormat" %><%@ page import="java.io.IOException" %><%@ page import="org.slf4j.Logger" %><%@ page import="org.slf4j.LoggerFactory" %><%@ page import="com.openkm.bean.Document" %><%@ page import="com.openkm.util.WebUtils" %><%@ page import="com.openkm.api.OKMDocument" %><%@ page extends="com.openkm.extension.servlet.BaseServlet" %><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %><%!private static Logger log = LoggerFactory.getLogger("com.openkm.sample");public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { String action = WebUtils.getString(request, "action"); try { list(request, response); } catch (Exception e) { log.error(e.getMessage(), e); sendErrorRedirect(request, response, e); }}
// Used by fileupload return and filterpublic void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException,ServletException { String action = WebUtils.getString(request, "action"); try { list(request, response); } catch (Exception e) { log.error(e.getMessage(), e); sendErrorRedirect(request, response, e); }}
private void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, Exception { SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss"); String docPath = (String) request.getAttribute("docPath"); String nameFilter = WebUtils.getString(request,"nameFilter");
// Pending docs List<Map<String,String>> pendingDocMaps = new ArrayList<Map<String,String>>(); for ( Document doc : OKMDocument.getInstance().getChildren(null, "/okm:root")) { Map<String,String> docMap = new HashMap<String,String>(); docMap.put("name",doc.getPath().substring(doc.getPath().lastIndexOf("/")+1)); docMap.put("uuid",doc.getUuid()); docMap.put("path",doc.getPath()); docMap.put("mimeType",doc.getMimeType()); docMap.put("lastModified", df.format(doc.getLastModified().getTime())); pendingDocMaps.add(docMap); }
ServletContext sc = getServletContext(); sc.setAttribute("docPath",docPath); sc.setAttribute("nameFilter",nameFilter); sc.setAttribute("pendingDocuments",pendingDocMaps); sc.getRequestDispatcher("/sample/sample2/distributor.jsp").forward(request, response);}%>distributor.jsp
Section titled “distributor.jsp”The main layer.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %><?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link rel="stylesheet" type="text/css" href="<%=request.getContextPath() %>/sample/css/style.css" /> <script type="text/javascript" src="<%=request.getContextPath() %>/js/jquery-1.7.1.min.js"></script> <script type="text/javascript" src="<%=request.getContextPath() %>/js/vanadium-min.js" ></script></head><body> <table width="100%"> <tbody> <tr> <td valign="top" width="50%"> <jsp:include page="/sample/sample1/full_list.jsp"></jsp:include> </td> <td valign="top" width="10"></td> <td valign="top" width="50%"> <jsp:include page="/sample/sample1/filtered_list.jsp"></jsp:include> </td> </tr> </tbody> </table></body></html>full_list.jsp
Section titled “full_list.jsp”Show the document list.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %><script type="text/javascript"> // Note the parent.parent call because iframe is into other iframe function go(uuid) { alert('Document UUID:'+uuid); parent.parent.jsOpenPathByUuid(uuid); }</script><h1>Full list of /okm:root documents</h1><table class="results" style="white-space: nowrap;" cellpadding="3" width="100%"> <thead> <tr> <th></th><th>Author</th><th>Document</th><th>Date</th><th></th> </tr> </thead> <tbody> <c:forEach var="document" items="${leftDocsMaps}" varStatus="row"> <tr> <td valign="center"><img src="<%=request.getContextPath() %>/mime/${document.mimeType}"/></td> <td>${document.author}</td> <td>${document.name}</td> <td>${document.lastModified}</td> <td align="center"> <a href="javascript:go('${document.uuid}')"><img src="<%=request.getContextPath() %>/sample/img/action/goto_document.gif" alt="Show document" title="Show document"/></a> </td> </tr> </c:forEach> </tbody></table>Screenshot of sample1 view
Section titled “Screenshot of sample1 view”
Sample 2
Section titled “Sample 2”Is composed by 4 files:
- action.jsp (the main controller where the logic is set).
- add_form.jsp (form to upload a new document)
- distributor.jsp (the main layer with two columns at 50% with JavaScript).
- full_list.jsp (show the full list with JavaScript special control for table height).
- pending.jsp (static content).
action.jsp
Section titled “action.jsp”The main controller.
<%@page import="java.util.Map"%><%@page import="java.util.HashMap"%><%@page import="java.util.List"%><%@page import="java.util.ArrayList"%><%@ page import="java.text.SimpleDateFormat" %><%@ page import="java.io.IOException" %><%@ page import="org.slf4j.Logger" %><%@ page import="org.slf4j.LoggerFactory" %><%@ page import="com.openkm.bean.Document" %><%@ page import="com.openkm.util.WebUtils" %><%@ page import="com.openkm.api.OKMDocument" %><%@ page extends="com.openkm.extension.servlet.BaseServlet" %><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %><%!
private static Logger log = LoggerFactory.getLogger("com.openkm.sample");public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { String action = WebUtils.getString(request, "action"); try { list(request, response); } catch (Exception e) { log.error(e.getMessage(), e); sendErrorRedirect(request, response, e); }}
// Used by fileupload return and filterpublic void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException,ServletException { String action = WebUtils.getString(request, "action"); try { list(request, response); } catch (Exception e) { log.error(e.getMessage(), e); sendErrorRedirect(request, response, e); }}
private void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, Exception { SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss"); String docPath = (String) request.getAttribute("docPath"); String nameFilter = WebUtils.getString(request,"nameFilter"); // Pending docs List<Map<String,String>> pendingDocMaps = new ArrayList<Map<String,String>>(); for ( Document doc : OKMDocument.getInstance().getChildren(null, "/okm:root")) { Map<String,String> docMap = new HashMap<String,String>(); docMap.put("name",doc.getPath().substring(doc.getPath().lastIndexOf("/")+1)); docMap.put("uuid",doc.getUuid()); docMap.put("path",doc.getPath()); docMap.put("mimeType",doc.getMimeType()); docMap.put("lastModified", df.format(doc.getLastModified().getTime())); pendingDocMaps.add(docMap); } ServletContext sc = getServletContext(); sc.setAttribute("docPath",docPath); sc.setAttribute("nameFilter",nameFilter); sc.setAttribute("pendingDocuments",pendingDocMaps); sc.getRequestDispatcher("/sample/sample2/distributor.jsp").forward(request, response);}%>distributor.jsp
Section titled “distributor.jsp”The main layer.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %><?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link rel="stylesheet" type="text/css" href="<%=request.getContextPath() %>/sample/css/style.css" /> <link rel="stylesheet" type="text/css" href="<%=request.getContextPath() %>/css/jquery.tablescroll.css"/> <script type="text/javascript" src="<%=request.getContextPath() %>/js/jquery-1.7.1.min.js"></script> <script type="text/javascript" src="<%=request.getContextPath() %>/js/vanadium-min.js" ></script> <script type="text/javascript" src="<%=request.getContextPath() %>/js/jquery.tablescroll.js"></script></head><body> <div id="leftPanel" style="float: left;"> <jsp:include page="/sample/sample2/add_form.jsp"></jsp:include> <jsp:include page="/sample/sample2/full_list.jsp"></jsp:include> </div> <div id="centerPanel" style="float: left; width: 12px;"> <div id="verticalSeparator" class="verticalSeparator"></div> </div> <div id="rightPanel" style="float: left;"> <jsp:include page="/sample/sample2/pending.jsp"></jsp:include> </div>
<script type="text/javascript"> var width = $(window).width()-12; // Deleting middle panel var height = $(window).height();
// Setting height $('#verticalSeparator').height(height); $('#leftPanel').height(height); $('#rightPanel').height(height); // Setting width $('#leftPanel').width(parseInt(width/2)); $('#centerPanel').width(12); $('#rightPanel').width((width-parseInt((width/2)))); </script></body></html>add_form.jsp
Section titled “add_form.jsp”Form to upload a new document.
<%@ page import="com.openkm.frontend.client.constants.ui.UIFileUploadConstants" %><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><h2 id="headerTitle_new_register">Upload new file</h2><form enctype="multipart/form-data" method="post" action="<%=request.getContextPath() %>/frontend/FileUpload"> <input type="hidden" name="path" value="/okm:root"> <input type="hidden" name="action" value="<%=UIFileUploadConstants.ACTION_INSERT%>"> <input type="hidden" name="message" value=""> <input type="hidden" name="comment" value=""> <input type="hidden" name="redirect" value="/sample/sample2/action.jsp"> <table class="form"> <tbody> <c:if test="${docPath != null && docPath != ''}"> <tr> <td><div class="ok">Document sended</div></td> </tr> </c:if> <tr> <td> <div id="file_error" style="display:none; color : red;">File is mandatory.</div> <input type="file" name="file" class=":required;;file_error :only_on_blur"> </td> </tr> <tr> <td align="center"><input type="submit" value="Send"></td> </tr> </tbody> </table></form>full_list.jsp
Section titled “full_list.jsp”Show a list of documents.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %><script type="text/javascript"> // Note the parent.parent call because iframe is into other iframe function go(uuid) { alert('Document UUID:'+uuid); parent.parent.jsOpenPathByUuid(uuid); }</script><h2 class="top">Full document list from /okm:root</h2><div align="center" style="padding: 0px 20px 0px 5px"> <div class="tablescroll"> <table id="docsPendingTable" width="100%" cellspacing="0" style="white-space: nowrap;"> <thead> <tr> <td>Id</td><td>Document</td><td>Date</td><td></td> </tr> </thead> <tbody> <c:set var="first" value="true"></c:set> <c:forEach var="document" items="${pendingDocuments}" varStatus="row"> <c:choose> <c:when test="${first==true}"> <tr class="first"> </c:when> <c:otherwise> <tr> </c:otherwise> </c:choose> <td valign="center"><img src="<%=request.getContextPath() %>/mime/${document.mimeType}"/></td> <td>${document.name}</td> <td>${document.lastModified}</td> <td align="center"><a href="javascript:go('${document.uuid}')"><img src="<%=request.getContextPath() %>/sample/img/action/goto_document.gif" alt="Show document" title="Show document"/></a></td> </tr> <c:set var="first" value="false"></c:set> </c:forEach> </tbody> </table> </div></div>
<script type="text/javascript">//Calculating table height removing from total other elements heightvar pendingTableHeight = $(window).height() - (parseInt($('#docsPendingTable').offset().top) + 35);/*<![CDATA[*/jQuery(document).ready(function($){ $('#docsPendingTable').tableScroll({height:pendingTableHeight});});/*]]>*/</script>Screenshot of sample2 view
Section titled “Screenshot of sample2 view”