-
Notifications
You must be signed in to change notification settings - Fork 10
Getting Started
Integrating Docet into an existing application is a process involving two layers of your application's architecture: the server side and the client side.
First things first, integration occurs on the client side, in other words, in the layer running on the Web browser. This activity simply comes down to include a small javascript library and a base css into a Web page: the library takes care of shaping and issuing requests for pages, parsing responses and showing the corresponding content along with table of contents and navigation bars. The provided css allows for a base theme and layout which, in any way, can be customized accordinlgly to the look-and-feel of your application.
On the server side is it necessary to include the actual Docet engine so than requests for documentation pages coming to your backend can be forwarded to the engine which - via a locator service - will find the requested page, pre-process it (so as to correctly rendering links and others interactive content) and return the page ready to the client ready to be shown on the Web browser.
In the following sections, a step-by-step guide on how integrating Docet into your existing Java-based applications is provided: the code snipped adopted are taken from the sample application example included in the code under the docet-sample-app
folder.
In order to work Docet simply requires jQuery 1.x and Java 8.
Docet has been conceived as a single-page application: the simplest way to include it in your application is to define a Web page including the necessary javascript and css files, such as in the following sample code snippet:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="js/jquery.min.js" type="text/javascript"></script>
<link href="docetres/docet/docet.css" type="text/css" rel="stylesheet" />
<script src="docetres/docet/docet.js" type="text/javascript"></script>
</head>
<body>
...
</body>
</html>
First of all, as shown above, docet.js
javascript library and docet.css
stylesheet are imported along with jQuery script, which is needed as docet.js relies on jQuery functions. The docet.css
stylesheet provides the base classes that define a default look-and-feel and layout for the documentation: these classes can be overridden in order to devise a completely customized layout depending on the theme of the hosting application.
Second, it necessary to define a base structure of html elements that will be adpoted by the javascript engine to render the actual documentation. More specifically, Docet needs:
- an html element acting as a "container" for the whole Docet Web application;
- an html element acting as the anchor for the actual page content to be shown;
- an html element necessary to host the table of contents (TOC) of the documentation;
- one exploited in order to render the search bar;
- one adopted to render a navigation bar (breadcrumbs);
- an element acting as a footer, so that the js script can hook any content meant to be shown at the bottom of the page; Once defined in the html page, these elements can be arranged in a way that suits your need and annotated with a set of default css classes providing a base layout definition.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="js/jquery.min.js" type="text/javascript"></script>
<link href="docetres/docet/docet.css" type="text/css" rel="stylesheet" />
<script src="docetres/docet/docet.js" type="text/javascript"></script>
</head>
<body>
<div id="docet">
<div class="docet-titlebar-container">
<div class="docet-layout">
<div id="docet-maintitle" class="docet-maintitle">Docet</div>
</div>
</div>
<div class="docet-header-container">
<div class="docet-layout">
<div id="crumbs-anchor" class="docet-breadcrumbs-container docet-breadcrumbs"></div>
<div id="docet-search" class="docet-search-container"></div>
</div>
</div>
<div id="docet-main-container" class="docet-main-container">
<div class="docet-layout">
<div id="menu-anchor" class="docet-menu-container"></div>
<div id="content-anchor" class="docet-content-container docet-content"></div>
</div>
</div>
<div id="docet-footer-container" class="docet-footer-container">
<div class="docet-layout">
<div id="footer-anchor" class="docet-footer"></div>
</div>
</div>
</div>
...
</body>
</html>
Then, Docet javascript needs to be instructed of the ids of the elements above and, also, properly configured with a few additional information necessary so that the library can behave correctly.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="js/jquery.min.js" type="text/javascript"></script>
<link href="docetres/docet/docet.css" type="text/css" rel="stylesheet" />
<script src="docetres/docet/docet.js" type="text/javascript"></script>
</head>
<body>
<div id="docet">
<div class="docet-titlebar-container">
<div class="docet-layout">
<div id="docet-maintitle" class="docet-maintitle">Docet</div>
</div>
</div>
<div class="docet-header-container">
<div class="docet-layout">
<div id="crumbs-anchor" class="docet-breadcrumbs-container docet-breadcrumbs"></div>
<div id="docet-search" class="docet-search-container"></div>
</div>
</div>
<div id="docet-main-container" class="docet-main-container">
<div class="docet-layout">
<div id="menu-anchor" class="docet-menu-container"></div>
<div id="content-anchor" class="docet-content-container docet-content"></div>
</div>
</div>
<div id="docet-footer-container" class="docet-footer-container">
<div class="docet-layout">
<div id="footer-anchor" class="docet-footer"></div>
</div>
</div>
</div>
<script>
Docet.init({
elements: {
main: "#docet-main-container",
content: '#content-anchor',
menu: '#menu-anchor',
search: '#docet-search',
breadcrumbs: '#crumbs-anchor',
footer: '#footer-anchor',
footerContainer: '#docet-footer-container'
},
localization: {
pageTitle: "Docet's Sample App",
mainPageDescription: "",
language: 'en',
product: {
name: 'ACMe Docet\'s Sample app',
version: '0.0.1'
}
},
packages: {
list: ['sampledoc']
},
callbacks: {
response_error: function (response) {
var msg = '';
msg += 'Status code: ' + response.status + "\n";
msg += response.responseText;
console.log(msg);
},
search_error: function (res) {
var msg = '';
msg += "Error on searching on package " + res.packageid + "\n";
msg += "Message: " + res.errorMessage;
console.log(msg);
},
packagelist_error: function (res) {
var msg = '';
msg += "Error on retrieving info for package " + res.packageid + "\n";
msg += "Message: " + res.errorMessage;
console.log(msg);
},
page_changed: function (info) {
console.log('page changed', info);
}
}
});
Docet.jumpToHomepage();
</script>
</body>
</html>
Configuration is done by calling method init with an input param consisting of a Javascript object containing the necessary configuration details:
-
elements
allows to initialize Docet with the html id of the elements previously defined with the goal of rendering the different parts of the online documentation; -
packages
to specify a list of documentation packages available for browsing (though static in this example, it is very likely that a real application generates this list in a dynamic way); -
localization
information regarding localization such as language to be used on documentation packages along with a few additional info such as pagetitle, product name, etc. Below a list of values that can be configured (if left unspecified a default value will be used):
Name | Description |
---|---|
mainPageDescription |
Message to show on the documentation dashboard (see below) |
emptyPackageList |
Message to display on the main documentation dashboard when no documentation package is available for browsing |
language |
A two-letter code corresponding to the language of the application (typically generated dynamically) |
searchButtonLabel |
Label to show on the search button on the search bar |
searchInputPlaceholder |
A message to be shown in the search box |
searchResultTitle |
title to be shown of the page showing the results of a text search |
showMoreResults |
label for the "show more results" button on the search results' page |
noResultsFound |
Message to show on the search results' page when the searched word/sentence did not match any document |
someResultsFound |
Message to show when the searched keyword produced actual results |
topLink |
Label to use for the "back-to-top" button |
-
callbacks
that defines functions to be called by docet.js when the following circumstances occur:-
page_changed
, a documentation page is loaded -
search_error
, an error occurs during a search request -
packagelist_error
, an error occurs while retrieving the list of available packages (their description to be shown on the dashboad) -
response_error
, an error happens during retrieval of a documentation resource in general.
-
Finally, in order to actually initialize and start (the client side of) Docet, Docet.jumpToHomepage()
is called so as to initialize any necessary front-end component and show the main dashboard reporting the list of available packages. An example of Web page rendered after invoking jumpToHomepage
is shown below (of course for a correct rendering it is mandatory to have correctly integrated Docet on the server side as well).
On the server side integration comes down to expose an instance of the docet runtime manager (an instance of Java class DocetManager
) so as HTTP requests for documentation resources can be forwarded to the engine: to this end the class provides a method
public void serveRequest(HttpServletRequest request, HttpServletResponse response) throws DocetException
accepting an instance of HttpServletRequest
and one of HttpServletResponse
used by the engine to send responses to the client (browser).
Accordingly, integration consists of setting up a servlet in your application so as to redirect requests/responses to the docet runtime manager. As an example, you can refer to docet-sample-app
, specifically to DocetSimpleServlet
:
package docet.servlets;
...
public class DocetSimpleServlet extends HttpServlet {
private static final Logger LOGGER = Logger.getLogger(DocetSimpleServlet.class.getName());
/**
* Handles the HTTP <code>GET</code> method.
*
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("ServletPath:" + request.getServletPath() + " " + request.getContextPath() + " " + request.getRequestURI());
try {
processRequest(request, response);
} catch (DocetException ex) {
LOGGER.log(Level.SEVERE, "Error on serving request, go to error page", ex);
throw new ServletException(ex);
}
}
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
*
* @param request servlet request
* @param response servlet response
* @throws DocetException in case errors occurs on handling doc requests
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws DocetException {
DocetManager docetEngine = (DocetManager) request.getServletContext().getAttribute("docetEngine");
System.out.println("ServletPath:" + request.getServletPath() + " " + request.getContextPath() + " " + request.getRequestURI());
docetEngine.serveRequest(request, response, new DocetSampleDocumentAccessor());
}
}
Anyway, first of all it is necessary to initialize and create an instance of DocetManager
: this can be achieved for instance by adopting a ServletContextListener
in order to instantiate a DocetManager
and add it to the ServletContext
. As an example, take a look at DocetConfigurator
in docet-sample-app
:
package docet.servlets;
...
public class DocetConfigurator implements ServletContextListener {
private static final Logger LOGGER = Logger.getLogger(DocetConfigurator.class.getName());
@Override
public void contextInitialized(ServletContextEvent ctx) {
LOGGER.log(Level.SEVERE, "Docet is starting");
ServletContext application = ctx.getServletContext();
Properties configuration = new Properties();
Properties docPackages = new Properties();
try {
configuration.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("docet.conf"));
docPackages.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("docet-packages.conf"));
final DocetConfiguration docetConf = new DocetConfiguration(configuration);
docPackages.entrySet().stream().forEach(docPackage -> {
Path packagePath = Paths.get(docPackage.getValue().toString());
if (!packagePath.isAbsolute()) {
packagePath = Paths.get(application.getRealPath("/")).resolve(packagePath);
}
docetConf.addPackage(docPackage.getKey().toString(), packagePath.toString());
});
final DocetManager manager = new DocetManager(docetConf, new DocetSamplePackageLocator(docetConf));
manager.start();
application.setAttribute("docetEngine", manager);
LOGGER.log(Level.SEVERE, "Docet configured, config:" + docetConf);
} catch (DocetException | IOException e) {
LOGGER.log(Level.SEVERE, "Impossible to properly setting up Docet configuration for Manager. ", e);
}
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
LOGGER.log(Level.INFO, "DOCet is shutting DOWN");
try {
((DocetManager) sce.getServletContext().getAttribute("docetEngine")).stop();
} catch (InterruptedException e) {
LOGGER.log(Level.SEVERE, "Error on shutting down Docet. ", e);
Thread.currentThread().interrupt();
}
}
}
Actual configuration parameters are taken from file docet.conf
in docet-sample-app
:
docet.debugmode=true
docet.version=${pom.version}
#package and searchindex path are relative to package docs main folder
#usually docet.package.docs.dirpath and docet.package.searchindex.dirpath
#do not need to be specified (here is done only for dev mode)
docet.package.docs.dirpath=main/docs
docet.package.searchindex.dirpath=../target/docet/index
docet.previewmode=true
docet.language.default=en