This chapter provides you with the basic knowledge of overridden components, internal APIs implemented in Knowledge. Also, you will know how to set up a default template for the FAQ portlet, and how to create a sample action extension in Wiki.
In this chapter, there are the following main topics:
Details of configuration plug-in and tutorial of ForumEventLifeCycle, AnswerEventLifeCycle and BBCodeRenderer.
Description of REST Services of internal APIs which the Knowledge applications (Forum, Answers and Polls) use to communicate with the server.
Description of Wiki Service API used in the Knowledge function.
Instructions on how to configure the FQA template and to change its look and feel, information of APIs provided by the UIComponent.
Actions over a wiki page from external jars
Instructions on how to extend your own actions packaged in external jars to the Wiki toolbar via the following particular topics:
Create a new project for action extension
Create new actions and their corresponding listeners
Register new actions with UIExtensionManager
Deploy new action extension
Description of the JCR structure of the main Knowledge applications, including Forum, FAQ, Poll and Wiki.
Introduction to ForumEventLifeCycle that enables you to listen to the lifecycle of a forum, its configuration plug-in, and steps to use the ForumEventLifeCycle class.
Introduction to AnswerEventLifeCycle that installs event updates for the Answers data, its configuration plug-in, and steps to use the AnswerEventLifeCycle class.
Introduction to BBCodeRenderer that is used in the core of Knowledge to render BBCodes, its configuration file, and how to register BBCodeRenderer.
There are some extension points in Knowledge, so that you can control how these components work by implementing or extending default implementations, then reconfigure these new components in the configuration.xml file.
See also
ForumEventLifeCycle enables you to listen to the lifecycle of a forum. By implementing ForumEventLifeCycle, you can be notified of new posts and replies, categories and topics. This installation will be injected when the data flow is called to save data.
You can find the configuration file of this component at: ext/social-integration/src/main/resources/conf/portal/configuration.xml.
For example, to add a Forum to a space of the Social application and keep new activities of Forum (such as new posts and topics) updated to the activities of space, do as follows:
<external-component-plugins>
<target-component>org.exoplatform.forum.service.ForumService</target-component>
<component-plugin>
<name>ForumEventListener</name>
<set-method>addListenerPlugin</set-method>
<type>org.exoplatform.ks.ext.impl.ForumSpaceActivityPublisher</type>
</component-plugin>
</external-component-plugins>
To use ForumEventLifeCycle class, do the following steps:
1. Create a new class that extends ForumEventListener.
For example: class ABCActivityPublisher
public class ABCActivityPublisher extends ForumEventListener {
..............
}
2. Override fuctions in this created class. In each function, you can write anythings to meet your needs.
public class ABCActivityPublisher extends ForumEventListener {
public void saveCategory(Category category){
....
}
public void saveForum(Forum forum){
....
}
public void addTopic(Topic topic, String categoryId, String forumId)){
....
}
public void updateTopic(Topic topic, String categoryId, String forumId){
....
}
public void addPost(Post post, String categoryId, String forumId, String topicId){
....
}
public void updatePost(Post post, String categoryId, String forumId, String topicId){
....
}
}
The function saveCategory is called when a category is added and/or edited.
The function saveForum is called when a forum is added and/or edited.
The function addTopic is called when a topic is added.
The function updateTopic is called when a topic is updated.
The function addPost is called when a post is added.
The function updatePost is called when a post is updated.
3. Add a new configuration to the configuration.xml file with the type that is the class created in the Step 1.
<external-component-plugins>
<target-component>org.exoplatform.forum.service.ForumService</target-component>
<component-plugin>
<name>ForumEventListener</name>
<set-method>addListenerPlugin</set-method>
<type>{package}.{class name}</type>
<!-- example
<type>org.exoplatform.ks.ext.impl.ABCActivityPublisher</type>
-->
</component-plugin>
</external-component-plugins>
AnswerEventLifeCycle installs event updates for the Answers data that is injected while saving answers, saving questions or posting comments.
You can find the configuration file of this component at: ext/social-integration/src/main/resources/conf/portal/configuration.xml.
For example, to add Answers to a space of the Social application and keep new activities of Answers updated to the activities of space, do as follows:
<external-component-plugins>
<target-component>org.exoplatform.faq.service.FAQService</target-component>
<component-plugin>
<name>AnswerEventListener</name>
<set-method>addListenerPlugin</set-method>
<type>org.exoplatform.ks.ext.impl.AnswersSpaceActivityPublisher</type>
</component-plugin>
</external-component-plugins>
In which, AnswersSpaceActivityPublisher is the class to implement ForumEventLifeCycle.
To use the AnswerEventLifeCycle class, do the following steps:
1. Create a new class that extends AnswerEventListener.
For example: ABCActivityPublisher
public class ABCActivityPublisher extends AnswerEventListener {
....
}
2. Override fuctions in this created class. In each function, you can write anything to meet your needs.
public class ABCActivityPublisher extends AnswerEventListener {
public void saveQuestion(Question question, boolean isNew){
....
}
public void saveAnswer(String questionId, Answer answer, boolean isNew){
....
}
public void saveAnswer(String questionId, Answer[] answers, boolean isNew){
....
}
public void saveComment(String questionId, Comment comment, boolean isNew){
....
}
}
The function saveQuestion is called when a question is added and/or edited.
The function saveAnswer is called when an answer is added and/or edited.
The function saveAnswer is called when answers are added and/or edited.
The function saveComment is called when a comment is added and/or edited.
3. Add a new configuration to the configuration.xml file with the type that is the class created in the Step 1.
<external-component-plugins>
<target-component>org.exoplatform.faq.service.FAQService</target-component>
<component-plugin>
<name>AnswerEventListener</name>
<set-method>addListenerPlugin</set-method>
<type>{package}.{class name}</type>
<!-- example
<type>org.exoplatform.ks.ext.impl.ABCActivityPublisher</type>
-->
</component-plugin>
</external-component-plugins>
BBCodeRenderer is used in the core of Knowledge to render BBCodes. In which, the data input is text, containing BBCode tags. The data output will be BBCode tags which have been encrypted into HTML tags.
You can find the configuration file of this component at: extension/webapp/src/main/webapp/WEB-INF/ks-extension/ks/forum/bbcodes-configuration.xml.
For example, to register BBCodeRenderer, do as follows:
<external-component-plugins>
<target-component>org.exoplatform.ks.rendering.MarkupRenderingService</target-component>
<component-plugin>
<name>BBCodeRenderer</name>
<set-method>registerRenderer</set-method>
<type>org.exoplatform.ks.rendering.spi.RendererPlugin</type>
<description>BBCode renderer</description>
<init-params>
<object-param>
<name>renderer</name>
<description>Extended BBCodeRenderer</description>
<object type="org.exoplatform.ks.bbcode.core.BBCodeRenderer">
<field name="bbCodeProvider">
<object type="org.exoplatform.ks.bbcode.core.ExtendedBBCodeProvider"/>
</field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
In which, ExtendedBBCodeProvider is the class to implement BBCodeProvider.
This section describes REST Services of internal APIs which applications (Forum, Answers and Polls) of Knowledge use to communicate with the server.
| Resource | Description |
|---|---|
| GET /viewpoll/{resourceid} | Return information of a poll via the poll's Id. |
| GET /votepoll/{pollId}/{indexVote} | Allow saving the vote information of a user for a poll. |
Return information of a poll via the poll's Id.
URL:
http://{domain_name}/{rest_context_name}/private/ks/poll/viewpoll/{resourceid}
Parameters:
Required (path parameters):
| Parameter | Description |
|---|---|
| resourceid | The poll Id. |
Optional (query parameters): No
Allow saving the vote information of a user for a poll.
URL:
http://{domain_name}/{rest_context_name}/private/ks/poll/votepoll/{pollId}/{indexVote}
Parameters:
Required (path parameters):
| Parameter | Description |
|---|---|
| pollId | The poll Id. |
| indexVote | Index of the option that is selected by a user. |
Optional (query parameters): No
| Resource | Description |
|---|---|
| GET rss/{resourceid} | Get public RSS of a given resource via its Id. |
| Resource | Description |
|---|---|
| GET getmessage/{maxcount} | Return a list of recent posts of the current user limited by posts number. |
| GET getpublicmessage/{maxcount} | Return a list of recent public posts limited by posts number. |
| GET filter/{strIP} | Return a list of banned IPs filtered by the input string. |
| GET filterIpBanforum/{strForumId}/{strIP} | Return a list of banned IPs for a forum filtered by the input string. |
| GET filterTagNameForum/{userAndTopicId}/{strTagName} | Return a list of tags in a topic of a user filtered by the input string. |
| GET rss/{resourceid} | Get public RSS of a given resource via its Id. |
| GET rss/user/{resourceid} | Get public RSS of a given resource of the current user via this resource's Id. |
Return a list of recent posts of the current user limited by posts number.
URL:
http://{domain_name}/{rest_context_name}/private/ks/forumgetmessage/{maxcount}
Parameters:
Required (path parameters):
| Parameter | Description |
|---|---|
| maxcount | Limitation of returned posts. |
Optional (query parameters): No
Return a list of recent public posts limited by posts number.
URL:
http://{domain_name}/{rest_context_name}/private/ks/forumgetpublicmessage/{maxcount}
Parameters:
Required (path parameters):
| Parameter | Description |
|---|---|
| maxcount | Limitation of returned posts. |
Optional (query parameters): No
Return a list of banned IPs filtered by the input string.
URL:
http://{domain_name}/{rest_context_name}/private/ks/forumfilter/{strIP}
Parameters:
Required (path parameters):
| Parameter | Description |
|---|---|
| strIP | Filter a IPs list. If strIP is set to "all", this function will get all banned IPs. |
Optional (query parameters): No
Return a list of banned IPs for a forum filtered by the input string.
URL:
http://{domain_name}/{rest_context_name}/private/ks/forumfilterIpBanforum/{strForumId}/{strIP}
Parameters:
Required (path parameters):
| Parameter | Description |
|---|---|
| strForumId | The forum Id. |
| strIP | Filter a IPs list. If strIP is set to "all", this function will get all banned IPs. |
Optional (query parameters): No
Return a list of tags in a topic of a user filtered by the input string.
URL:
http://{domain_name}/{rest_context_name}/private/ks/forumfilterTagNameForum/{userAndTopicId}/{strTagName}
Parameters:
Required (path parameters):
| Parameter | Description |
|---|---|
| strTagName |
Filter a tags list. If strTagName is " ", the function will return an empty list. If strTagName is "onclickForm", the function will return all tags of the topic. If strTagNamestr is any, the function will return the tags name based on this filter. |
| userAndTopicId | The Id of the current user and topic that has the form of {userId,topicId} |
Optional (query parameters): No
Get public RSS of a given resource via its Id.
URL:
http://{domain_name}/{rest_context_name}/private/ks/forumrss/{resourceid}
Parameters:
Required (path parameters):
| Parameter | Description |
|---|---|
| resourceid | The resource Id, such as Category, Forum, Topic, and more. |
Optional (query parameters): No
Get public RSS of a given resource of the current user via this resource's Id.
URL:
http://{domain_name}/{rest_context_name}/private/ks/forumrss/user/{resourceid}
Parameters:
Required (path parameters):
| Parameter | Description |
|---|---|
| resourceid | The user Id. |
Optional (query parameters): No
This service is used to show the differences between two strings.
This service is used for the WYSIWYG editor to get the configuration.
This service is used to get the rendered content of a wiki page with the support of the cache.
This service is used to resize the image to a desired size.
This service provides functions to render between syntaxes.
This service provides functions to access Wiki data, such as tree data, Help content, images and more.
This service provides interface for processing database with wikis and pages, including adding, editing, removing and searching data.
See also
This service is used to show the differences between two strings.
| Method | Param | Return | Description |
|---|---|---|---|
| getDifferencesAsList(String text1, String text2) throws DifferentiationFailedException |
|
List |
Return a list of differences between lines of text1 and text2. |
| getWordDifferencesAsList(String text1, String text2) throws DifferentiationFailedException, |
|
List |
Return a list of differences between words of text1 and text2. |
| getWordDifferencesAsHTML(String text1, String text2) throws DifferentiationFailedException, |
|
DiffResult |
Return a DiffResult object representing differences between words of text1 and text2. |
| getDifferencesAsHTML(String text1, String text2, boolean allDoc) throws DifferentiationFailedException, |
|
DiffResult |
Return a DiffResult object representing differences between lines of text1 and text2. |
This service is used for the WYSIWYG editor to get the configuration.
| Method | Param | Return | Description |
|---|---|---|---|
| getEntityConfig(EntityReference origin, ResourceReference destination); |
|
EntityConfig: The link configuration object that can be used to insert the link in the origin page. |
Create an entity link configuration object (URL, link reference) for a link with the specified origin and destination. The link reference in the returned EntityConfig is relative to the link origin. |
| parseLinkReference(String linkReference, EntityReference baseReference); |
|
ResourceReference: A reference to the linked entity. |
Parse the given link reference and extract a reference to the linked entity. The returned entity reference is resolved relative to the given base entity reference. |
This service is used to get the rendered content of a wiki page with the support of the cache.
| Method | Param | Return | Description |
|---|---|---|---|
| getRenderedContent(WikiPageParams param, String targetSyntax); |
|
String: The rendered content. |
Get the rendered content of a wiki page. |
| getRenderingCache(); | N/A
|
ExoCache<MarkupKey, MarkupData>: The rendering cache. |
Get the rendering cache. |
| getPageLinksMap() |
N/A |
Map<WikiPageParams, List<WikiPageParams>>: The map of connection. |
Return the collection of page connections. In details, a connection is built if the page content includes a link to another page. |
| addPageLink(WikiPageParams param, WikiPageParams entity) |
|
void
|
Record a link between two pages. |
| invalidateCache(WikiPageParams param) |
param: The identity parameter of a page to remove in cache. |
void |
Invalidate all cache entries linking to a page in case this page is removed, changed or renamed. |
This service is used to resize the image to a desired size.
| Method | Param | Return | Description |
|---|---|---|---|
| resizeImage(String imageName, InputStream is, int requestWidth, int requestHeight, boolean keepAspectRatio); |
|
InputStream: The resized input stream. |
Resize the given image to the specified dimensions. |
| resizeImageByWidth(String imageName, InputStream is, int requestWidth); |
|
InputStream
|
Resize the given image to the requested width and keep the aspect ratio. |
| resizeImageByHeight(String imageName, InputStream is, int requestHeight); |
|
InputStream |
Resize the given image to the requested height and keep the aspect ratio. |
This service provides functions to render between syntaxes.
| Method | Param | Return | Description |
|---|---|---|---|
| getExecution() throws ComponentLookupException, ComponentRepositoryException; | N/A |
Execution |
Get the execution from the XWIKI component manager. |
| getComponentManager(); | N/A |
ComponentManager: The XWIKI coponent manager. |
Get the XWIKI component manager. |
| render(String markup, String sourceSyntax, String targetSyntax, boolean supportSectionEdit) throws Exception; |
|
String: The markup in the target syntax. |
Render the markup from the source syntax to the target syntax. |
| getContentOfSection(String markup, String sourceSyntax, String sectionIndex) throws Exception; |
|
String: The content of section. |
Get the content of a section specified by sectionIndex. |
| updateContentOfSection(String markup, String sourceSyntax, String sectionIndex, String newSectionContent) throws Exception; |
|
String: The new content of markup. |
Update the content of a section specified by sectionIndex. |
| parse(String markup, String sourceSyntax) throws Exception; |
|
XDOM: The tree representation of the content as org.xwiki.rendering.block.Block. |
Parse the markup to XDOM. |
| getCssURL(); | N/A |
String: The URL of CSS. |
Get the CSS URL. |
| setCssURL(String cssURL); |
cssURL: The URL of CSS. |
void |
Set the CSS URL. |
This service provides functions to access Wiki data, such as tree data, Help content, images and more.
| Method | Param | Return | Description |
|---|---|---|---|
| getWikiPageContent(String sessionKey, String wikiContextKey, boolean isMarkup, String data); |
|
Response: Status.OK and the page content as TEXT_HTML. Status.INTERNAL_SERVER_ERROR if the exception occurs when getting the content of wiki page. |
Get the content of a wiki page. |
| upload(String wikiType, String wikiOwner, String pageId) |
|
Response: Status.OK if the upload is successful. HTTPStatus.BAD_REQUEST if the upload fails. |
Update a file to the wiki page specified by the parameters. |
| getTreeData(String type, String path, String currentPath, Boolean showExcerpt, String depth); |
|
Response: Status.OK and the tree data as APPLICATION_JSON. Status.INTERNAL_SERVER_ERROR if the exception occurs when getting the tree data. |
Get data to create a page tree. |
| getRelated(String path); | path: The JCR path of the wiki page from which will get the related pages. |
Response: Status.OK and JsonRelatedData as APPLICATION_JSON. Status.NOT_FOUND if the wiki page cannot be found by the input JCR path. Status.INTERNAL_SERVER_ERROR if the exception occurs when getting related pages. |
Get a list of the related pages of a wiki page. |
| searchData(String keyword, String wikiType, String wikiOwner) throws Exception; |
|
Response: Status.OK and search result as APPLICATION_JSON. Status.INTERNAL_SERVER_ERROR if the exception occurs when searching for a page. |
Search through the title of wiki pages by a keyword. |
| getImage(UriInfo uriInfo, String wikiType, String wikiOwner, String pageId, String imageId, Integer width); |
|
Response: Status.OK and the resized image. Status.INTERNAL_SERVER_ERROR if the exception occurs when getting the image. |
Get an image from a wiki page. |
| getHelpSyntaxPage(String syntaxId); | syntaxId: The syntax Id. |
Response: Status.OK and Help content as TEXT_HTML. Status.INTERNAL_SERVER_ERROR if the exception occurs when getting the Help content. |
Get the Help content by the syntax Id. |
This service provides interface for processing database with wikis and pages, including adding, editing, removing and searching data.
| Method | Param | Return | Description |
|---|---|---|---|
| createPage(String wikiType, String wikiOwner, String title, String parentId) throws Exception; |
|
Page: The new wiki page. |
Create a wiki page specified by the parameters. |
| createTemplatePage(String title, WikiPageParams params) throws Exception; |
|
Template: A new draft page. |
Create a new template specified by the parameters. |
| initDefaultTemplatePage(String path) ; |
path: The JCR path where the default template is created. |
void |
Initialize default templates of wiki. |
| createDraftNewPage(String draftNewPageId) throws Exception; |
draftNewPageId: The Id of the draft page. |
void |
Create a draft page for a new wiki page. |
| deletePage(String wikiType, String wikiOwner, String pageId) throws Exception; |
|
boolean |
Delete a wiki page specified by the parameters. |
| deleteTemplatePage(String wikiType, String wikiOwner, String templateId) throws Exception; |
|
void |
Delete a template specified by the parameters. |
| deleteDraftNewPage(String draftNewPageId) throws Exception; |
draftNewPageId: The Id of the draft page which is deleted. |
void |
Delete a draft page specified by the parameter. |
| renamePage(String wikiType, String wikiOwner, String pageName, String newName, String newTitle) throws Exception; |
|
boolean
|
Rename a wiki page specified by the parameters. |
| movePage(WikiPageParams currentLocationParams, WikiPageParams newLocationParams) throws Exception; |
|
boolean |
Move a wiki page to another location. |
| getWikiPermission(String wikiType, String wikiOwner) throws Exception; |
|
List<PermissionEntry>: List of permission entry. |
Get the permission of wiki. |
| setWikiPermission(String wikiType, String wikiOwner, List<PermissionEntry> permissionEntries) throws Exception; |
|
void |
Set the permission for wiki. |
| getPageById(String wikiType, String wikiOwner, String pageId) throws Exception; |
|
Page |
Get a wiki page specified by parameters. |
| getRelatedPage(String wikiType, String wikiOwner, String pageId) throws Exception; |
|
Page: The wiki page. |
Get a renamed wiki page by its old Id. After being renamed, the wiki page Id was changed. The old Id of the wiki page is stored to the link registry of wiki and used to get the wiki page. |
| getExsitedOrNewDraftPageById(String wikiType, String wikiOwner, String pageId) throws Exception; |
|
Page: The wiki page for the draft page. |
Get a wiki page or create a draft for it if it does not exist. |
| getPageByUUID(String uuid) throws Exception |
uuid: The JCR node UUID of the wiki page. |
Page: The wiki page. |
Get a wiki page by the node UUID. |
| getTemplatePage(WikiPageParams params, String templateId) throws Exception |
|
Template |
Get a template specified by the parameters. |
| searchContent(WikiSearchData data) throws Exception; |
data: The wiki search data that contain the search query. |
PageList<SearchResult> |
Search through the content of wiki pages and return search results. |
| getBreadcumb(String wikiType, String wikiOwner, String pageId) throws Exception; |
|
List<BreadcrumbData> |
Get a list of breadcrumb data of a wiki page. |
| getWikiPageParams(BreadcrumbData data) throws Exception |
data: The breadcrumb data. |
WikiPageParams |
Get the wiki page param from breadcrumb data. |
| search(WikiSearchData data) throws Exception |
data: The Wiki Search data that contain the search query. |
PageList<SearchResult> |
Search for wiki pages that match the search query in the input search data. |
| searchTemplate(TemplateSearchData data) throws Exception |
data: The Wiki Search data that contain the search query. |
List<TemplateSearchResult> |
Search for wiki templates that match the search query in input search data. |
| searchRenamedPage(String wikiType, String wikiOwner, String pageId) throws Exception |
|
List<SearchResult> |
Get a list of renamed wiki pages. |
| searchDataByTitle(WikiSearchData data) throws Exception |
data: The wiki search data that contain the search query. |
List<TitleSearchResult> |
Search for the title of wiki pages and return search results. |
| findByPath(String path, String objectNodeType) throws Exception |
|
Object: The object that has been got from the JCR node. |
Get a wiki object (PageImpl, AttachmentImpl, Template) by the JCR path. |
| getDefaultWikiSyntaxId() | N/A |
String: The default wiki syntax Id. |
Get the default wiki syntax Id. |
| getPageTitleOfAttachment(String path) throws Exception; |
path: The JCR path of the attachment. |
String: The page title. |
Get the page title of an attachment. |
| getAttachmentAsStream(String path) throws Exception |
path: The path of the attachment. |
InputStream: The input stream. |
Get the attachment as an stream. |
| getHelpSyntaxPage(String syntaxId) throws Exception |
syntaxId: The syntax Id to get the Help page. |
PageImpl: The wiki page that contains the Help content for the syntax. |
Get the wiki page that contains the Help content for the syntax. |
| getMetaDataPage(MetaDataPage metaPage) throws Exception |
metaPage: The type of Metadata. |
Page: The wiki page that contains the metadata information. |
Get the wiki page that contains the metadata information. |
| getTemplates(WikiPageParams params) throws Exception |
params: The location of templates. |
Map<String, Template>: The map of templates. |
Get the map of template specified by the parameters. |
| getTemplatesContainer(WikiPageParams params) throws Exception |
params: The location of the template container. |
TemplateContainer: The template container. |
Get the template container specified by the parameters. |
| modifyTemplate(WikiPageParams params, Template template, String newName, String newDescription, String newContent, String newSyntaxId) throws Exception |
|
void |
Modify the wiki template. |
| isExisting(String wikiType, String wikiOwner, String pageId) throws Exception |
|
boolean |
Check if the wiki page exists or not. |
| addComponentPlugin(ComponentPlugin plugin) |
plugin: The component plugin. |
void |
Register a PageWikiListener. |
| addWikiTemplatePagePlugin(WikiTemplatePagePlugin templatePlugin) |
templatePlugin: The template plugin. |
void |
Add a wiki template plugin. |
| getPageListeners() | N/A |
List<PageWikiListener>: The list of PageWikiListener. |
Get page listeners. |
| addRelatedPage(WikiPageParams orginaryPageParams, WikiPageParams relatedPageParams) throws Exception |
|
boolean |
Add related pages. |
| getRelatedPage(WikiPageParams pageParams) throws Exception |
pageParams: The parameter which refers to the wiki page. |
List<Page>: The list of related pages. |
Get a list of related pages of a wiki page. |
| removeRelatedPage(WikiPageParams orginaryPageParams, WikiPageParams relatedPageParams) throws Exception |
|
boolean |
Remove related pages from the related pages list of a wiki page. |
Information about the configuration plug-in which is used to automatically set up a default template for the FAQ portlet, and details of properties of the template configuration plug-in.
Instructions on how to change the template FAQ viewer, either by using plug-in or by using the Edit mode.
API provided by the UIComponent (UIViewer.java)
Introduction to UIViewer, details of APIs and classes (CategoryInfo, QuestionInfo, SubCategoryInfo).
See also
Configuration plug-in is used to automatically set up a default template for the FAQ portlet. When the FAQ service starts, it will get values which are returned from the TemplatePlugin component to initialize the template for the FAQ portlet.
The template configuration plug-in is configured in the templates-configuration.xml file.
In details:
At runtime of the FAQ Service, FAQService component is called, then templates-configuration.xml file is executed. The component-plugin named addTemplatePlugin will be referred to org.exoplatform.faq.service.TemplatePlugin to execute some objects and create default data for the Forum application.
<external-component-plugins>
<target-component>org.exoplatform.faq.service.FAQService</target-component>
<component-plugin>
<name>faq.default.template</name>
<set-method>addTemplatePlugin</set-method>
<type>org.exoplatform.faq.service.TemplatePlugin</type>
<init-params>
<value-param>
<name>viewerTemplate</name>
<value>war:/ks-extension/ks/faq/templates/FAQViewerPortlet.gtmpl</value>
</value-param>
</init-params>
</component-plugin>
</external-component-plugins>
The properties of template configuration plug-in are defined in the init-params tag as follows:
<init-params>
<value-param>
<name>viewerTemplate</name>
<value>war:/ks-extension/ks/faq/templates/FAQViewerPortlet.gtmpl</value>
</value-param>
</init-params>
| Name | Description | Value |
|---|---|---|
| viewerTemplate | Path of file template. | war:/ks-extension/ks/faq/templates/ FAQViewerPortlet.gtmpl |
You can change the template FAQ viewer in one of the following two ways:
1. Create a file named FAQViewerPortlet.gtmpl . The content of the file is the template of the FAQ viewer.
2. Copy this file and paste into ks-extension/WEB-INF/ks-extension/ks/faq/templates/ that is in the webapps folder of the server (tomcat, jboss).
When the server runs, FAQViewerPortlet.gtmpl will initialize the template of the FAQ viewer.
1. Run the server and open the FAQ Portlet.
2. Go to edit mode and open the Edit Template tab.
3. Edit the content of text-area-input and click Save.
UIViewer is the child of the component UIFAQPortlet. It shows the main content of FAQ portlet.
List of APIs:
| Function name | Param | Return | Description |
|---|---|---|---|
| getCategoryInfo | Empty | CategoryInfo object | Get the object CategoryInfo. |
| arrangeList |
(List< String > list): List of path |
A new list is arranged | Arrange a list of path. |
| render | (String): The content of answers or comments |
A new string is converted by function render | Render the content of answers or comments. |
...
private String id;
private String path;
private String name;
private List<String> pathName;
private List<QuestionInfo> questionInfos = new ArrayList<QuestionInfo>();
private List<SubCategoryInfo> subCateInfos = new ArrayList<SubCategoryInfo>();
...
| Param | Type | Description |
|---|---|---|
| id |
String
|
The jcr node name of the category node. |
| path |
String
|
The jcr node path of the category node. |
| name |
String
|
The name of the category. |
| pathName |
List<String>
|
The path to the category includes a list of category names. |
| questionInfos |
List<QuestionInfo>
|
The list of QuestionInfo object. |
| subCateInfos |
List<SubCategoryInfo>
|
The list of SubCategoryInfo object. |
The QuestionInfo class:
...
private String id;
private String question;
private String detail;
private List<String> answers = new ArrayList<String>();
...
| Param | Type | Description |
|---|---|---|
| id | String |
The jcr node name of the question node. |
| question | String
|
The content of the question. |
| details | String |
Details of the question. |
| answers | List<String> |
The list of answers for the question. |
The SubCategoryInfo class: The params of this class are the same as those of the CategoryInfo class. See here for more information.
Create a new project for action extension
Introduction to the structure of a new project and content of the pom.xml file.
Create new actions and their corresponding listeners
Details of modifying the ViewSourceActionComponent class that allows creating new actions and their corresponding listeners.
Register new actions with UIExtensionManager
Details of modifying the configuration.xml file that allows registering new actions with UIExtensionManage, and information of the types of action extensions.
Instructions on how to deploy a new action extension.
The toolbar in Wiki is built basing on the UI Extensions framework as described in Extend eXo applications, so you can add your own actions packaged in external jars to it. After reading this section, you will know how to extend actions over a wiki page from external jars.
See also
Create a Maven project which has the following directory structure:

Navigating in the project's folder, you will see the following structure:
pom.xml: the project's POM file.
src/main/java/.../ViewSourceActionComponent.java: a simple action supporting user to view the wiki markup of a page.
src/main/resources/conf/portal/configuration.xml: the configuration file to register your actions with the org.exoplatform.webui.ext.UIExtensionManager service.
Here is the content of the pom.xml file:
<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>
<groupId>com.acme</groupId>
<artifactId>example</artifactId>
<version>1.0-SNAPSHOT</version>
<name>eXo Wiki action - Example</name>
<description>eXo Wiki action - Example</description>
<dependencies>
<dependency>
<groupId>org.exoplatform.portal</groupId>
<artifactId>exo.portal.webui.core</artifactId>
<version>3.2.0-PLF-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.exoplatform.commons</groupId>
<artifactId>exo.platform.commons.webui.ext</artifactId>
<version>1.1.3-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.exoplatform.ks</groupId>
<artifactId>exo.ks.eXoApplication.wiki.service</artifactId>
<version>2.2.4-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.exoplatform.ks</groupId>
<artifactId>exo.ks.eXoApplication.wiki.webapp</artifactId>
<version>2.2.4-SNAPSHOT</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Edit the ViewSourceActionComponent class as below:
package com.acme;
import java.util.Arrays;
import java.util.List;
import org.exoplatform.webui.config.annotation.ComponentConfig;
import org.exoplatform.webui.config.annotation.EventConfig;
import org.exoplatform.webui.event.Event;
import org.exoplatform.webui.ext.filter.UIExtensionFilter;
import org.exoplatform.webui.ext.filter.UIExtensionFilters;
import org.exoplatform.wiki.commons.Utils;
import org.exoplatform.wiki.mow.core.api.wiki.PageImpl;
import org.exoplatform.wiki.webui.UIWikiContentDisplay;
import org.exoplatform.wiki.webui.UIWikiPageContentArea;
import org.exoplatform.wiki.webui.UIWikiPortlet;
import org.exoplatform.wiki.webui.control.action.core.AbstractEventActionComponent;
import org.exoplatform.wiki.webui.control.filter.IsViewModeFilter;
import org.exoplatform.wiki.webui.control.listener.MoreContainerActionListener;
@ComponentConfig (
template = "app:/templates/wiki/webui/control/action/AbstractActionComponent.gtmpl",
events = {
@EventConfig(listeners = ViewSourceActionComponent.ViewSourceActionListener.class)
}
)
public class ViewSourceActionComponent extends AbstractEventActionComponent {
public static final String ACTION = "ViewSource";
private static final List<UIExtensionFilter> FILTERS = Arrays.asList(new UIExtensionFilter[] { new IsViewModeFilter() });
@UIExtensionFilters
public List<UIExtensionFilter> getFilters() {
return FILTERS;
}
@Override
public String getActionName() {
return ACTION;
}
@Override
public boolean isAnchor() {
return false;
}
public static class ViewSourceActionListener extends MoreContainerActionListener<ViewSourceActionComponent> {
@Override
protected void processEvent(Event<ViewSourceActionComponent> event) throws Exception {
UIWikiPortlet wikiPortlet = event.getSource().getAncestorOfType(UIWikiPortlet.class);
UIWikiContentDisplay contentDisplay = wikiPortlet.findFirstComponentOfType(UIWikiPageContentArea.class)
.getChildById(UIWikiPageContentArea.VIEW_DISPLAY);
PageImpl wikipage = (PageImpl) Utils.getCurrentWikiPage();
contentDisplay.setHtmlOutput(wikipage.getContent().getText());
event.getRequestContext().addUIComponentToUpdateByAjax(contentDisplay);
}
}
}
Edit the configuration.xml file as below:
<configuration xmlns="http://www.exoplatform.org/xml/ns/kernel_1_2.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplatform.org/xml/ns/kernel_1_2.xsd http://www.exoplatform.org/xml/ns/kernel_1_2.xsd">
<external-component-plugins>
<target-component>org.exoplatform.webui.ext.UIExtensionManager</target-component>
<component-plugin>
<name>add.action</name>
<set-method>registerUIExtensionPlugin</set-method>
<type>org.exoplatform.webui.ext.UIExtensionPlugin</type>
<init-params>
<object-param>
<name>ViewSource</name>
<object type="org.exoplatform.webui.ext.UIExtension">
<field name="type"><string>org.exoplatform.wiki.webui.control.MoreExtensionContainer</string></field>
<field name="rank"><int>1000</int></field>
<field name="name"><string>ViewSource</string></field>
<field name="component"><string>com.acme.ViewSourceActionComponent</string></field>
</object>
</object-param>
</init-params>
</component-plugin>
</external-component-plugins>
</configuration>
Besides the MoreExtensionContainer type, action extension may be one of these following types:
| Type | Description |
|---|---|
org.exoplatform.wiki.webui.control.UIPageToolBar |
Actions will be placed on the Wiki page toolbar at the view mode. |
org.exoplatform.wiki.webui.control.AddExtensionContainer |
Actions will be placed on the Add Page drop-down list on the Wiki page toolbar at the view mode. |
org.exoplatform.wiki.webui.control.MoreExtensionContainer |
Actions will be placed on the More drop-down list on the Wiki page toolbar at the view mode. |
org.exoplatform.wiki.webui.control.UISubmitToolBar |
Actions will be placed on the Wiki page toolbar at the edit mode. |
org.exoplatform.wiki.webui.control.UIEditorTabs |
Actions will be placed the on Wiki editor tabs. |
org.exoplatform.wiki.webui.control.BrowseExtensionContainer |
Actions will be placed on the Browse drop-down list at the view mode. |
org.exoplatform.wiki.webui.popup.UIWikiSettingContainer |
Actions will be placed on the Wiki setting tabs. |
Follow these steps to deploy your new action extension:
1. Build the project by using the mvn clean install command.
2. Copy the target/example-1.0-SNAPSHOT.jar file into the PLATFORM_TOMCAT_HOME/webapps/wiki.war/WEB-INF/lib/ directory.
3. Run the tomcat and go to Wiki application, you should see the result as below:


Introduction to the whole JCR structure of Forum, and comprehensive knowledge of its main nodes: Forum System and Forum Data.
Introduction to the whole JCR structure of FAQ, and comprehensive knowledge of its main nodes: Category, FAQ setting, Template for FAQ.
Introduction to the whole JCR structure of Poll, and properties of its node type (exo:polls).
Introduction to the whole JCR structure of Wiki, and comprehensive knowledge of its main nodes: Wiki data and Wikimetadata.
Knowledge is a JCR-based product which uses JCR to store data. The root node of Knowledge is exo:application which includes these child nodes: exo:forumHome, exo:faqHome.
In this section, you will have opportunity to further understand about the JCR structure of Knowledge via the main topics above.
See also
Forum is a JCR-based application. The Forum data are saved in eXo-JCR under the Forum Service data directory. The whole JCR structure of Forum can be visualized in the diagram below:

The Forum System node is created from the node type exo:forumSystem. That is defined as a child node of Forum Service and can store nodes with these following node types: exo:banIP, exo:forumUserProfile, exo:statistic, exo:administration under the Forum System. The Forum System node is stored in /exo:applications/ForumService/ForumSystem.
The User Profile and User Profile Home node are used to store information of each user. User Profile is automatically created by a listener when a user registers to the organization service. Private message and forum subscription can be added to User Profile as a child node. These node types exo:forumUserProfile, exo:userProfileHome, exo:privateMessage and exo:forumSubscription are defined as child nodes of exo:forumUserProfile. The User Profile node is stored under ForumSystem node: /exo:applications/ForumService/ForumSystem/exo:userProfileHome/exo:forumUserProfile.
The node type exo:forumUserProfile has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:userId | String | false | The user id. |
| exo:fullName | String | false | The user's full name. |
| exo:firstName | String | false | The user's first name. |
| exo:lastName | String | false | The user's last name. |
| exo:email | String | false | The user's email address. |
| exo:userTitle | String | false | The user's title: Administrator, Moderator or User. |
| exo:screenName | String | false | The displayed name of user in Forum. |
| exo:userRole | Long | false | The user's role. The value can be: "O": Administrator, "1": Moderator, "2": User, "3": guest. |
| exo:signature | String | false | The signature displayed at the end of each user's post. |
| exo:totalPost | Long | false | The total posts submitted by the user. |
| exo:totalTopic | Long | false | The total topics started by the user. |
| exo:jobWattingForModerator | Long | false | The number of jobs that are waiting to be moderated. |
| exo:moderateForums | String | true | The list of forum ids that user is the moderator. |
| exo:moderateCategory | String | true | The list of category ids that user is the moderator. |
| exo:readTopic | String | true | The list of topics that user has read. |
| exo:readForum | String | true | The list of forums that user has read. |
| exo:lastReadPostOfTopic | String | true | The list of the last read posts id in a topic that user has read. |
| exo:lastReadPostOfForum | String | true | The list of the last read posts id in a forum that user has read. |
| exo:isAutoWatchMyTopics | Boolean | false | Enable/disable the auto-watch the topics created by user. Topics created by a user will be watched automatically if the value is set to "true". |
| exo:isAutoWatchTopicIPost | Boolean | false | Enable/disable the auto-watch posts submitted by user. Topics posted by an user will be watched automatically if the value is set to "true". |
| exo:bookmark | String | true | The list of topics/posts bookmarked by user. |
| exo:lastLoginDate | Date | false | The date of the last login. |
| exo:joinedDate | Date | false | The date when user joined forum. |
| exo:lastPostDate | Date | false | The date of the last post. |
| exo:isDisplaySignature | Boolean | false | User's signature will be displayed at the end of their post if the value is set to "true". |
| exo:isDisplayAvatar | Boolean | false | User's avatar is displayed if the value is set to "true". |
| exo:newMessage | Long | false | The number of new messages. |
| exo:timeZone | Double | false | The time zone configured by user. |
| exo:timeFormat | String | false | The time format configured by user: 12h or 24h format. |
| exo:shortDateformat | String | false | The format of short date configured by user. Example: 'dd/MM/yyyy'. |
| exo:longDateformat | String | false | The format of long date configured by user. Example: 'dd mmm, yyyy'. |
| exo:maxPost | Long | false | The number of the maximum posts displayed per page. |
| exo:maxTopic | Long | false | The number of the maximum topics displayed per page |
| exo:isShowForumJump | Boolean | false | Display/hide the forum jump drop-down list. This jump list will be shown if the value is set to "true". |
| exo:collapCategories | String | true | The list of categories collapsed by user. |
| exo:isBanned | Boolean | false | The user's condition. User is currently banned if the value is set to "true". |
| exo:banUntil | Long | false | The time when the ban period expires. |
| exo:banReason | String | false | The description for the reason that user was banned. |
| exo:banCounter | String | false | The number of bans that user has committed. |
| exo:banReasonSummary | String | true | The list of ban reason summaries when a user is banned for more than one time. |
| exo:createdDateBan | Date | false | The date when the ban period starts. |
The child node type exo:privateMessage has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:from | String | false | The user id of the sender. |
| exo:sendTo | String | false | The user id of the receiver. |
| exo:name | String | false | The private message subject. |
| exo:message | String | false | The message contents. |
| exo:type | String | false | The private message type: sent messages or received messages. |
| exo:receivedDate | Date | false | The date when the private message was received. |
| exo:isUnread | Boolean | false | The status of private message: read/unread. |
The child node type exo:forumSubscription has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:categoryIds | String | true | The ids of the subscribed categories. |
| exo:forumIds | String | true | The ids of the subscribed forums. |
| exo:topicIds | String | true | The ids of the subscribed topics. |
Statistic and Statistic Home are used to store statistic information of forum, such as number of posts, topics, users, active users. The node type is exo:forumStatistic, exo:statisticHome.
The Statistic node is stored under the Forum System node: /exo:applications/ForumService/ForumSystem/exo:statisticHome/exo:forumStatistic and its node type has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:postCount | Long | false | The total number of submitted posts in Forum. |
| exo:topicCount | Long | false | The number of total created topics in Forum. |
| exo:membersCount | Long | false | The number of the registered users. |
| exo:newMembers | String | false | The id of the latest registered user. |
| exo:mostUsersOnline | String | false | The highest number of the online users. |
| exo:activeUsers | Long | false | The number of active users. |
The Ban IP and Ban IP Home node are used to store data about banned IP addresses. The node type exo:banIPHome contains the child node exo:IPHome.
The Ban IP node is stored under the Forum System node: /exo:applications/ForumService/ForumSystem/exo:banIPHome/exo:banIP and its node type has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:ips | String | true | The list of ip addresses of the banned users. |
Administration and Administration Home are used to store data for setting the layout, notification email format and censor jobs. The node type of the Administration Home node is exo:administrationHome and the its child node type is exo:administration. The Administration node is stored under the ForumSystem node /exo:applications/ForumService/ForumSystem/exo:administrationHome/exo:administration and its node type has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:forumSortBy | String | false | Sort forum by criteria: post count, topic count, lock status. |
| exo:forumSortByType | String | false | Sort forum by ascending/descending type. |
| exo:topicSortBy | String | false | Sort topic by criteria. |
| exo:topicSortByType | String | false | Sort topic by ascending type or descending type. |
| exo:censoredKeyword | String | false | The list of censored words. |
| exo:headerSubject | String | false | The subject header. |
| exo:enableHeaderSubject | Boolean | false | Enable/disable the subject header. The subject header is displayed if the value is set to "true". |
| exo:notifyEmailContent | String | false | Define if the notification email will be sent when there is a new added topic/post. |
| exo:notifyEmailMoved | String | false | Define if the notification email will be sent when there are any moved topic/post. |
The Forum Data node is created from the node type exo:forumData. The data nodes like category, forum, topic, post, tag, BBcode and topic type will be stored under the Forum Data node:/exo:applications/ForumService/ForumData.
The Category node is used to store all categories of forum, this node is a child node of the Forum Data node and only Category node type can be added to the Category Home. The node type of the Category Home node is exo:categoryHome is stored in /exo:applications/ForumService/ForumData/CategoryHome. The Category node has the node type exo:forumCategory which is a child node of the CategoryHome node. This node type is defined to allow adding child nodes as exo:forum and exo:forumRSS.
The node type exo:forumCategory has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:id | String | false | The category id. |
| exo:owner | String | false | The category creator. |
| exo:path | String | false | The node path of the category. |
| exo:createdDate | Date | false | The date when the category was created. |
| exo:modifiedBy | String | false | The id of the user who made the last modification on the category. |
| exo:name | String | false | The category name. |
| exo:modifiedDate | Date | false | The date when the modifications on category were made. |
| exo:description | String | false | The category description. |
| exo:moderators | String | true | The list of moderators of the category. |
| exo:tempModerators | String | true | The temporary moderator of the category. |
| exo:createTopicRole | String | true | The topic role. |
| exo:poster | String | true | The list of ids of the users and groups who can post in the category. |
| exo:viewer | String | true | The list of ids of the users and groups who can only view posts in the category. |
| exo:categoryOrder | Long | false | The order number of category in the category list. |
| exo:userPrivate | String | true | The list of user ids whose access are restricted from the category. |
| exo:forumCount | Long | false | The total number of forums in the category. |
The Forum node is defined as a child node of category and allowed adding child nodes as Topic and RSS type. The node type of Forum is exo:forum. The Forum node is stored in /exo:applications/ForumService/ForumData/CategoryHome/%Category-id%/%Forum-id% and its node type has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:id | String | false | The forum id. |
| exo:owner | String | false | The forum creator. |
| exo:path | String | false | The node path of the forum. |
| exo:name | String | false | The forum title. |
| exo:forumOrder | Integer | false | The order number in the list of forums. Forum with smaller number will get higher order. |
| exo:createdDate | Date | false | The date and time when the forum was created. |
| exo:modifiedBy | String | false | The id of user who modified the category. |
| exo:modifiedDate | Date | false | The time of modification, including date, time and time zone. |
| exo:lastTopicPath | String | false | The id of the last topic in the forum. |
| exo:description | String | false | The description of forum. |
| exo:postCount | Long | false | The total number of submitted posts in the forum. |
| exo:topicCount | Long | false | The total number of created topics in the forum. |
| exo:isAutoAddEmailNotify | Boolean | false | Enable/disable the notification email to moderators. |
| exo:notifyWhenAddTopic | String | true | Email addresses to notify when there is a new topic in the forum. |
| exo:notifyWhenAddPost | String | true | Email addresses to notify when there is a new post in the forum. |
| exo:isModerateTopic | Boolean | false | All new topic will be moderated if the value is set to "true". |
| exo:isModeratePost | Boolean | false | All new posts will be moderated if the value is set to "true". |
| exo:isClosed | Boolean | false | The forum status: closed/open. Forum is closed if the value is set to "true". |
| exo:isLock | Boolean | false | The forum status: locked/unlocked. Forum is locked if the value is set to "true". |
| exo:createTopicRole | String | true | The list of ids of the users or groups who can create topic in the forum. |
| exo:poster | String | true | The list of ids of the users or groups who can submit post in the forum. |
| exo:viewer | String | true | The list ids of the users or groups who can view posts in the forum. |
| exo:moderators | String | true | The list of user ids who are the moderators of forum. |
| exo:tempModerators | String | true | The list of user ids who are the temporary moderators. |
| exo:banIPs | String | true | The list of banned IP addresses. |
The child node pruneSetting has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:id | String | False | The forum id. |
| exo:inActiveDay | Long | False | The number of days/weeks/months that the topics in forum have not been active. |
| exo:periodTime | Long | False | The number of days/weeks/months that the prune job will be executed to check for the old topics and deactivate them. |
| exo:isActive | Boolean | False | The current status of the prune job. If the value is set to "True", the prune job will be run. |
| exo:lastRunDate | Date | False | The date that prune job runs for the last time. |
The Topic node is defined as a child node of the Forum node and allowed adding child nodes as Topic, Poll and RSS type. The node type of the Topic and Poll node is exo:topic, exo:poll.
The Topic node is stored in /exo:applications/ForumService/ForumData/CategoryHome/%Category-id%/%Forum-id%/%Topic-id% and its node type has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:id | String | false | The topic id. |
| exo:owner | String | false | The user id of the topic creator. |
| exo:path | String | false | The node path of the topic. |
| exo:name | String | false | The subject of the topic |
| exo:createdDate | Date | false | The time when the topic was created. |
| exo:modifiedBy | String | false | The id of the user who made the latest modification in the topic. |
| exo:modifiedDate | Date | false | The date when the modifications were made. |
| exo:lastPostBy | String | false | The user id of the last poster in topic. |
| exo:lastPostDate | Date | false | The date when the last post was submitted. |
| exo:description | String | false | The topic description. |
| exo:topicType | String | false | The id of the topic type. |
| exo:postCount | Long | false | The number of posts in the topic. |
| exo:viewCount | Long | false | The number of topic views. |
| exo:numberAttachments | Long | false | The number of attachments in the topic. |
| exo:icon | String | false | The name of the topic icon. |
| exo:link | String | false | The link to the topic. Example: http://localhost:8080/ksdemo/public/classic/forum/topic/%Topic-id%. |
| exo:isModeratePost | Boolean | false | All posts in the topic will have to wait for moderation if the value is set to "true". |
| exo:isNotifyWhenAddPost | Boolean | false | When there is a new post in a topic, a notification message will be sent to the topic owner if this value is set to "true". |
| exo:isClosed | Boolean | false | The state of the topic: closed/open. If the value is set to "true", the topic is closed. |
| exo:isLock | Boolean | false | The lock status of the topic: lock/unlocked. If the value is set to "true", the topic is locked. |
| exo:isApproved | Boolean | false | The topic is approved to be published if the value is set to "true". |
| exo:isSticky | Boolean | false | If the value is set to "true", the topic is currently sticky. |
| exo:isWaiting | boolean | false | The topic status. The topic is waiting for moderation if the value is set to "true". |
| exo:isActive | boolean | false | The topic activity status: active/inactive. The topic is active (topic gets new posts in a period of time) if the status is set to "true". |
| exo:isActiveByForum | Boolean | false | The topic status based on the forum state. Example: When the topic is active and the forum that contains it is closed, this topic will be considered as inactive. |
| exo:canView | String | true | List of user ids who can view the topic contents. |
| exo:canPost | String | true | List of user ids who can post in the topic. |
| exo:isPoll | Boolean | false | The topic contains poll if the value is set to "true". |
| exo:userVoteRating | String | true | The list of user id who voted. |
| exo:tagId | String | true | The list of the topic tag id. |
| exo:voteRating | Double | false | The average vote score of the topic. |
The child node type exo:poll has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:id | String | false | The poll id. |
| exo:owner | String | false | The user id of poll creator. |
| exo:createdDate | Date | false | The date and time when the poll was created. |
| exo:modifiedBy | String | false | The user id who modified the poll. |
| exo:modifiedDate | Date | false | The time when the poll is modified. |
| exo:lastVote | Date | false | The date of the last vote. |
| exo:question | String | false | The contents of the question for poll. |
| exo:timeOut | Long | false | The time when the polled is closed. |
| exo:option | String | true | The list of options for poll. |
| exo:vote | String | true | The list of votes by users. |
| exo:userVote | String | true | The list of user ids who voted. |
| exo:isMultiCheck | Boolean | false | User can choose more than one option if the value is set to "true". |
| exo:isAgainVote | Boolean | false | Users can change their vote if the value is set to "true". |
| exo:isClosed | Boolean | false | The poll status. Poll is closed if the value is set to "true". |
The Post node is defined as child node of Topic and allowed adding only the Attachment child node type. The Post node type is exo:post, and the child node type is exo:forumAttachment.
The Post node is stored in /exo:applications/ForumService/ForumData/CategoryHome/%Category-id%/%Forum-id%/%Topic-id%/%Post-id% and its node type has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:id | String | false | The post id. |
| exo:owner | String | false | The user id of the poster. |
| exo:path | String | false | The node path of the post. |
| exo:createdDate | Date | false | The date time when post is submitted, including date, time, time zone. |
| exo:modifiedBy | String | false | The id of the user who modified the post. |
| exo:editReason | String | false | The reason for editing the post. |
| exo:modifiedDate | Date | false | The date when the post was modified. |
| exo:name | String | false | The post title. |
| exo:message | String | false | The message of the post. |
| exo:remoteAddr | String | false | The remote IP address of the post. |
| exo:icon | String | false | The name of the icon for the post. |
| exo:userPrivate | String | true | The list of user ids that are restricted from the post. |
| exo:link | String | false | The link to open the topic. |
| exo:isApproved | Boolean | false | The state of the post: approved/unapproved. The post is approved if the value is set to "true". |
| exo:numberAttach | Long | false | The number of attachments in the post. |
| exo:isActiveByTopic | Boolean | false | The post is activity status based on the topic state. If the topic is close, all post in it will be considered as inactive. |
| exo:isHidden | Boolean | false | The post status: shown/hidden. The post is hidden if the value is set to "true". |
| exo:isFirstPost | Boolean | false | The post is the first one in a topic if the value is set to "true". |
The Tag node is used to store data about tag name, topics with tag added, number of users using this tag, number of tags in use. The node type of the Tag node is exo:forumTag and its child node type is "exo:tagHome". The Tag node is stored in /exo:applications/ForumService/ForumData/TagHome/%tag-id% and its node type has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:id | String | false | The id of tag. |
| exo:name | String | false | The tag name. |
| exo:useCount | Long | false | The number of times that the tag was used. |
| exo:userTag | String | true | The number of users using the tag. |
The BBCode node is used to define what BBCode will be used in the forum. The node type of the BBCode node is exo:forumBBCode. The BBCode node is stored in /exo:applications/ForumService/ForumData/forumBBCode/%BBCode_tag% and its node type has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:description | String | false | The description about the tag purpose. Example: 'The [url] tag allows creating links to other websites and files'. |
| exo:example | String | false | The example about using the tag. Example: [URL]http://www.exoplatform.com[/URL]'. |
| exo:isActive | Boolean | false | The BBCode tag is active/deactive. The BBCode tag is active if the value is set to "true". |
| exo:isOption | Boolean | false | If the value is set to "true", user can create a tag with atributes and values. |
| exo:replacement | String | false | The HTML code that will be replaced by the tag. Example: [url] tag replaces '<a target='_blank' href="{param}">{param}</a>'. |
| exo:tagName | String | false | The BBCode tag name. |
The Topic type home contains a child node with the node type exo:topicType. The Topic node is stored in /exo:applications/ForumService/ForumData/TopicTypeHome/%Topic-id% and its node type has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:id | String | false | The id of the topic type. |
| exo:name | String | false | The name of the topic type. |
| exo:icon | String | false | The icon of the topic type. |
FAQ is a JCR-based application. The FAQ data are stored in the eXo-JCR under the faqApp data directory. The whole FAQ JCR structure can be visualized in the following diagram:

The system will automatically create the Category Home node under the FAQ application node at the first time the user launches application. All users-created categories are the sub-categories of Category Home. The home of the Category node is automatically created in /exo:applications/faqApp/categories.
In fact, Sub-category is also a category. FAQ has defined a mixin node type called mix:faqSubCategory to allow adding a node having the same type with category to an existing category. When a category is created, this mixin node type will be mixed to that category.
The node type exo:faqCategory has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:id | String | false | The sub-category id. |
| exo:name | String | false | The name of the sub-category. |
| exo:userPrivate | String | true | The list of user ids that are restricted from the category. |
| exo:description | String | false | The description of the sub-category. |
| exo:isModerateQuestions | Boolean | false | The question post moderation status. All questions posted in the sub-category will have wait for moderation if the value is set to "true". |
| exo:isModerateAnswers | Boolean | false | The answer post moderation status. All answers posted in the sub-category will have to wait for moderation if the value is set to "true". |
| exo:isView | Boolean | false | The category is shown/hidden. The category will be shown if the value is set to "true". |
| exo:viewAuthorInfor | Boolean | false | The category enables user to view the information of questions poster if the value is set to "true'. |
| exo:moderators | String | true | The list of user ids who are the category moderator. |
| exo:createdDate | Date | false | The time when the sub-category is created. |
| exo:index | Long | false | The index number of the category. |
Each category has a RSS child node that stores a RSS feed representing all questions in this category as the binary data type. The RSS node is stored in /exo:applications/faqApp/categories/ks.rss and its node type is exo:faqRSS.
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:content | Binary | false | The content of the RSS. |
The Question Home node is created from the exo:faqQuestionHome node type that is defined as a child node of category. This node cantains all question nodes that created in side a category. Only the Question node type exo:faqQuestion can be added to the question Home. The Question Home node is created as a child node of Categories /exo:applications/faqApp/categories/questions.
Question node is created from exo:faqQuestion node type under the Question Home node. The Answers, Comments and Attachments node are defined as child nodes of the Question node. The Question node is created under the Question Home: /exo:applications/faqApp/categories/questions/%Question-id%.
The exo:faqQuestion node type has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:id | String | false | The question id. |
| exo:language | String | false | The language of the question. |
| exo:name | String | false | The question details. |
| exo:title | String | false | The question title. |
| exo:author | String | false | The the user id of the question poster. |
| exo:email | String | false | The email of the question author |
| exo:isActivated | Boolean | false | The question status: activated/inactivated. The question is activated if the value is set to "true". |
| exo:isApproved | Boolean | false | The state of the question: approved/unapproved. The question is approved to be published if the value is set to "true". |
| exo:categoryId | String | false | The id of the category containing the question. |
| exo:createdDate | Date | false | The date and time when the question was submitted. |
| exo:relatives | String | true | The list of the related questions ids. |
| exo:usersVote | String | true | The list of user ids who voted. |
| exo:markVote | Double | false | The average vote scores of the question. |
| exo:topicIdDiscuss | String | false | The topic id in the forum where the question is discussed. |
| exo:nameAttachs | String | true | The file name of attachments in the question. |
| exo:lastActivity | String | false | The user id and time when the last activity of the question was made. |
| exo:numberOfPublicAnswers | Long | false | The number of all posted answers that has been published. |
| exo:link | String | false | The link to open the question. |
| exo:responses | String | true | The responses of the question. |
| exo:dateResponse | Date | true | The date when the question received the answer. |
| exo:responseBy | String | true | The user id of the answer poster. |
A question can support multilanguages, all other languages are stored as a child node of the question and can be add to the question via a mixin node type called mix:faqi18n. After the mixin node type mix:faqi18n is added to the question, the node type exo:questionLanguageHome can be added to the question node and this node type will contain all languages node with the node type exo:faqLanguage. All display properties of the question are defined in the node type exo:faqLanguage.
The node type exo:faqLanguage has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:language | String | false | The language of the question. |
| exo:name | String | false | The name of the language. |
| exo:title | String | false | The title of the question in the selected language. |
| exo:questionId | String | false | The id of the question. |
| exo:categoryId | String | false | The id of the category. |
The Answer, Comment and Attachment node is defined as the child nodes of the Question node. Attachment node is defined as a nt:file node type and stored right under the Question node. Answers and comments node are stored under the Answer home and the Comment home node.
The Answer node is stored in /exo:applications/faqApp/categories/questions/%Question-id%/faqAnswerHome/%Answer-id% and its node type has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:id | String | false | The id of the answer. |
| exo:answerPath | String | false | The path to the answer. |
| exo:questionId | String | false | The id of the question. |
| exo:categoryId | String | false | The id of the category containing the question. |
| exo:responses | String | false | The content of the answer. |
| exo:dateResponse | Date | false | The date when the response was posted. |
| exo:responseBy | String | false | The id of the user who responded the answer. |
| exo:responseLanguage | String | false | The language of the answer response. |
| exo:approveResponses | Boolean | false | The response is pending for approval if the value is set to "false". |
| exo:activateResponses | Boolean | false | The state of the answer: activated/deactivated . |
| exo:usersVoteAnswer | String | true | The list of user ids who voted for the answer. |
| exo:MarkVotes | Long | false | The average vote scores of the answer. |
| exo:postId | String | false | The post id. |
| exo:fullName | String | false | The answer author's full name. |
The Comment node is stored in /exo:applications/faqApp/categories/questions/%Question-id%/faqCommentHome/%Comment-id% and its node type has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:id | String | false | The comment id. |
| exo:comments | String | false | The comment contents. |
| exo:dateComment | Date | false | The date when the comment is posted. |
| exo:commentBy | String | false | The user id of the comment poster. |
| exo:postId | String | false | The id of the post. |
| exo:fullName | String | false | The full name of the comment poster. |
| exo:categoryId | String | false | The id of the category in which the comment is posted. |
| exo:questionId | String | false | The id of the question in which the comment is posted. |
| exo:commentLanguage | String | false | The language of the comment. |
The Attachment node is stored in /exo:applications/faqApp/categories/questions/%Question-id%/faqAttachment and its node type has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:fileName | String | false | The name of the attachment file. |
This FAQ Setting node stores the user settings data, such as how answer is ordered (in alphabetical order or by created date), the order type (descending or ascending) or the user's selection to sort questions by popularity. Each user has a dedicated settings data to select the display preferences in FAQ . The default setting will be used if the users has never changed and saved their setting.
The User Setting node of an individual user is stored in /exo:applications/faqApp/settingHome/userSettingHome/%user-id% and has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:ordeBy | string | false | Define how questions are ordered, by "alphabet/index" or "created date". |
| exo:ordeType | string | false | The value "asc" = ascending and "des" = descending. |
| exo:sortQuestionByVote | Boolean | false | All questions will be sorted by the popularity (based on the number of votes) if the value is set to "true". |
The Poll data are saved in eXo-JCR under the eXoPolls data directory. The whole JCR structure of Poll can be visualized in the diagram below:

The Poll node is used to store the default data in a poll. The node type of the Poll node is exo:poll. The Poll node is stored under eXoPolls node /exo:applications/eXoPolls/%PortalName%/Polls/Poll-id% and its node type (exo:polls) has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| exo:id | String | false | The poll id. |
| exo:owner | String | false | The user id of the poll creator. |
| exo:createdDate | Date | false | The date and time when the poll is created. |
| exo:modifiedBy | String | false | The id of the user who made the last modification on the poll. |
| exo:modifiedDate | Date | false | The date and time when the latest modification on poll was made. |
| exo:lastVote | Date | false | The date and time when the last vote was made. |
| exo:question | String | false | The question content of poll. |
| exo:timeOut | Long | false | The time when the poll will be closed. |
| exo:option | String | true | The list of options for poll. Each option is separated by a comma. |
| exo:vote | String | true | The list of votes by users. |
| exo:userVote | String | true | The list of user ids who voted. |
| exo:isMultiCheck | Boolean | false | Enable/disable the multi check. User can vote for more than one option if the value is set to "true". |
| exo:isAgainVote | Boolean | false | Enable/disable the option to vote again. User can change their vote if the value is set to "true". |
| exo:isClosed | Boolean | false | The poll status: open/closed. The poll is closed if the value is set to "true". |
The Wiki portlet is a JCR-based application. The Wiki data are stored in the eXo JCR storage. The Wiki application of Knowledge supports several wikis, each wiki is organized as a tree of pages and hosted in different locations, depending on the type of wiki:
Portal wikis: /exo:applications/eXoWiki/wikis/$PORTAL/WikiHome
Group wikis: /Groups/$GROUP/ApplicationData/eXoWiki/WikiHome
User wikis: /Users/$USERNAME/ApplicationData/eXoWiki/WikiHome
WikiHome a conventional name of the root page of a Wiki. The type of WikiHome is "exo:wikihome". Each page may have a number of sub-pages and attachments.
Other Wiki metadata are organized below /exo:applications/eXoWiki/wikimetadata.
The whole Wiki JCR structure can be visualized in the following diagram:

Depending on the Wiki type (portal, group or user); its pages, attachments and default syntax are stored under a node with either of node types: "wiki:portalwiki", "wiki:groupwiki" or "wiki:userwiki", respectively. Such a node has four child nodes: WikiHome, Preferences, LinkRegistry and Trash. These node types have the super type "wiki:wiki" that has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| ref | Reference | false | The reference to one of three following nodes: portalwikis, groupwikis or userwikis. |
| owner | String | false | The name of the wiki. |
| wikiPermissions | String | true | The property consists of the permission information of the wiki. The permission string has the format: VIEWPAGE,EDITPAGE,ADMINPAGE,ADMINSPACE:USER:john; VIEWPAGE:GROUP:/platform/users; VIEWPAGE,EDITPAGE,ADMINPAGE,ADMINSPACE:MEMBERSHIP:manager:/platform/administrators. |
| isDefaultPermissionsInited | Boolean | true | Check whether the default permission is applied to all the wiki tree or not. Its default value is "false". |
The WikiHome node stores the root page of a Wiki. It has the node type "exo:wikihome" that has the super type "wiki:page" inherited from "nt:folder". The super type has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| owner | String | false | The creator of the page. |
| author | String | false | The last person who modifies the page. |
| createdDate | Date | false | The date when the page is created. |
| updatedDate | Date | false | The last date when the page is updated. |
| syntax | String | false | The Wiki syntax is used to write the page. |
| title | String | false | The title of the page. |
| comment | String | false | The comment explains what is modified in the page. |
| url | String | false | The URL to the page. |
| isOverridePermission | Boolean | false | Check whether the default permission is overridden on the page or not. Its default value is "false". |
| exo:relation | Reference | true | The property consists of the UUIDs of the related pages. |
The nodes that have the type "wiki:page", have a child node named "content" and other child nodes including attachments with the type "wiki:attachment" inherited from "nt:file". The node type "wiki:attachment" has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| title | String | false | The name of the attachment. |
| fileType | String | false | The type of the attachment. |
| creator | String | false | The creator of the attachment. |
Three mixin node types: "wiki:removed", "wiki:renamed" and "wiki:watched" may be added to the node type "wiki:page".
The mixin node type "wiki:removed" has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| removedBy | String | false | The person who deleted the page. |
| removedDate | Date | false | The date when the page is deleted. |
| parentPath | String | false | The path to the parent page of the deleted page. |
The mixin node type "wiki:renamed" has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| oldPageIds | String | true | The old Ids of the renamed page. |
The mixin node type "wiki:watched" has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| watcher | String | false | The Id of the person who is watching the page. |
The "Preferences" node stores the default syntax and page templates of the Wiki. It has the node type "wiki:preferences" and two child nodes "PreferencesSyntax" and "TemplateContainer".
The "PreferencesSyntax" node has the node type "wiki:preferencessyntax" that has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| defaultSyntax | String | false | The default Wiki syntax of each wiki. |
| allowMutipleSyntaxes | Boolean | false | Specify whether multiple syntaxes are enabled or not. |
The "TemplateContainer" node stores the page templates. Its child node has the node type "wiki:template" inherited from the node type "wiki:page". The node type "wiki:template" has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| description | String | false | The description of the template. |
The "LinkRegistry" node stores the entries to keep track of renaming or moving pages. Each link entry has the node type "wiki:linkentry" that has the following properties:
| Properties name | Required type | Multiple | Description |
|---|---|---|---|
| alias | String | false | The Id of a page that is moved or renamed. Its format is "wikitype@wikiowner@pagename". |
| newlink | Path | false | A new path to the wiki page that has been moved or renamed. |
The "Trash" node stores deleted pages.
The "Template Container" node stores the templates to create Wiki pages.
Wiki metadata are stored in the node wikimetadata that has the node type "wiki:store". These metadata consist of information about help contents, draft contents and the way to find the wikis in the system. The nodes portalwikis, groupwikis and userwikis allow finding the wikis under the type: portal, group and user, basing on the JCR reference features. These nodes have the node types "wiki:portalwikis", "wiki:groupwikis" and "wiki:userwikis" relatively.
Help pages
Help-related information about Wiki syntaxes are stored under the "helppages" node which has the node type "wiki:page". For syntax help, there are two help pages (summary and detailed) for each syntax. The summary page suggests the simple syntax, while the detailed page provides the full syntax-related information. The detailed page is arranged as the child page of the summary page, and both of which have the same node type "wiki:page".
Draft pages
The unsaved content of a new page is stored under the "draftNewPages" node that has the node type "wiki:page".