N Hidden Gems in Hippo Forge and
Experience Plugins
Woonsan Ko
December 6, 2017
Sequel to N Hidden Gems You Didn’t Know… (2016)
● slideshare.net/woonsan
● woonsanko.blogspot.com
The Ecosystem around BR Experience
3
OSS
Libraries
Hippo Forge
Plugins
BR Experience
Plugins
OSS*
Frameworks
Generic vs. Specific
Complexity
* OSS: Open Source Software
The Ecosystem around BR Experience (cont.)
4
OSS
Libraries
Hippo Forge
Plugins
BR Experience
Plugins
OSS*
Frameworks
1. IFrame Perspective Plugin
2. Copy/Move Folder Plugin
3. External Document Picker
4. Doc. Commenting Plugin
5. HST Content Version Utils
6. Hipshoot for Spring Boot Deploy
* OSS: Open Source Software
7. Content HAL API
Complexity
Generic vs. Specific
Gem #1: Too Simple to iFrame?
5
“Why don’t you simply frame the goody in it?”
Gem #1: Why IFrame Perspective Plugin*?
● Built-in CMS Perspective Plugin to embed an IFrame to include a web
application.
● Sometimes it is most cost effective to simply embed an IFrame for a
good feature by a web application.
6
* More at https://onehippo-forge.github.io/iframe-perspective/
Gem #1: IFrame Perspective Plugin
● Configurations*
○ title, src, icon infos, any other IFrame element attributes (iframe.*)
○ X-Frame-Options , Content-Security-Policy ,
X-Content-Security-Policy , X-Webkit-CSP
● WicketSessionFilter in web.xml
○ To limit access only to CMS authenticated users.
7
* More at https://onehippo-forge.github.io/iframe-perspective/install.html
Gem #1: IFrame Perspective Plugin (cont.)
8
Gem #2: Copy or Move Folder
in CMS UI
9
“Can I copy or move a folder as a whole in CMS UI?”
Gem #2: Why Folder Context Menus Plugin*?
● Built-in CMS Folder Context Menu(s) to provide business users with
features to copy or move folders in CMS UI.
○ Let business users organize content folders by themselves.
● Also provides a common code library for copying/moving folders.
○ Use it in Java / Groovy code. E.g, Batch Processing
10* More at https://onehippo-forge.github.io/folder-context-menus/
Gem #2: Copy or Move Folder* in CMS UI
11
Gem #2: Copy or Move Folder in CMS UI (cont.)
12
● Code Library Support for Batch Processing - FolderCopyTask
// Example: Copy /content/documents/myhippoproject/news/
// to /content/documents/myhippoproject/news2/
String sourceFolderPath = "/content/documents/myhippoproject/news";
String destBaseFolderPath = "/content/documents/myhippoproject";
String destFolderNodeName = "news2";
String destFolderDisplayName = "News 2";
Node sourceFolderNode = jcrSession.getNode(sourceFolderPath);
Node destBaseFolderNode = jcrSession.getNode(destBaseFolderPath);
FolderCopyTask task = new FolderCopyTask(jcrSession, Locale.ENGLISH, sourceFolderNode,
destBaseFolderNode, destFolderNodeName,
destFolderDisplayName);
task.execute();
jcrSession.save();
Gem #2: Copy or Move Folder in CMS UI (cont.)
13
● Code Library Support for Batch Processing - FolderMoveTask
// Example: Move /content/documents/myhippoproject/news/2011/
// to /content/documents/myhippoproject/common/2011/
String sourceFolderPath = "/content/documents/myhippoproject/news";
String destBaseFolderPath = "/content/documents/myhippoproject";
String destFolderNodeName = "news2";
String destFolderDisplayName = "News 2";
Node sourceFolderNode = jcrSession.getNode(sourceFolderPath);
Node destBaseFolderNode = jcrSession.getNode(destBaseFolderPath);
FolderMoveTask task = new FolderMoveTask(jcrSession, Locale.ENGLISH, sourceFolderNode,
destBaseFolderNode, destFolderNodeName,
destFolderDisplayName);
task.execute();
jcrSession.save();
Gem #3: External Document Picker
(with new feature additions)
14
“Enrich your content by including metadata
of related external content in CMS UI!”
Gem #3: Why External Document Picker Plugin*?
● Built-in Generic Picker UI Plugin in CMS for:
○ Selecting an associated external documents for a field in the document editor.
○ Selecting a linked external documents for a RichText field in a document.
○ Selecting external documents from Folder Context Menu to do something.
■ E.g, creating documents in the folder, tagging the folder, etc.
● For both flat-list data and tree-list data.
● Most effective way to enrich your content
○ Highly extensible.
○ CRISP API can be used in backend integration.
15* More at https://onehippo-forge.github.io/external-document-picker/
Gem #3: External Document Picker
16
ExternalDocumentServiceFacade
is responsible for data to
display each item.
17
Gem #3: External Document Picker (cont.)
ExternalDocumentServiceFacade
in Tree List View option,
resolving parent-child
relationship!
* More at https://onehippo-forge.github.io/external-document-picker/field/dev-howto-treeview.html
NEW!
18
Gem #3: External Document Picker (cont.)
* More at https://onehippo-forge.github.io/external-document-picker/folder/architecture.html
NEW!
ExternalDocumentServiceFacade
in CMS Folder Menu, allowing
custom folder settings or
content creation!
Gem #4: Document Commenting
in CMS UI
19
“Comment on what you’re doing
in collaboration with others!”
Gem #4: Why Document Commenting Plugin*?
● Built-in Field UI Plugin to allow commenting among collaborators in
Document Editor.
● Simple, cost-effective collaboration in document authoring and reviewing.
● No burden in document storage level as it’s stored separately.
● Highly extensible.
20* More at https://onehippo-forge.github.io/document-commenting/
21
Gem #4: Document Commenting
Add a
commenting field
anywhere in a
document type!
22
Gem #4: Document Commenting (cont.)
Gem #4: Document Commenting (cont.)
● Very Extensible for different backends!
23
Document
Commenting
CMS UI Plugin
<<interface>>
CommentPersistence
Manager*
Default JCR
CommentPersistence
Manager
Other
Storage-based
CommentPersistence
Manager?
* https://onehippo-forge.github.io/document-commenting/apidocs/org/onehippo/forge/document/commenting/cms/api/CommentPersistenceManager.html
Only very simple 9
methods to
implement!
JCR
ES?
NoSQL?
Gem #5: Live Version As-Of
via HST Content Version Utils
24
“Show content in specific version,
live as of December 6, 2017!”
Gem #5: Why HST Content Version Utils*?
● Utility to retrieve JCR Version data through dynamic proxy of
HST Content Beans, generated at runtime automatically.
○ Instead of low-level JCR Version API: VersionManager, Frozen Nodes, etc.
● No need to have separate Java code and FreeMarker templates.
○ Just stick with HST Content Beans API, even for versioned, frozen nodes.
25
* More at https://onehippo-forge.github.io/hst-content-version-utils/
Gem #5: Live Version As-Of via HST Content Version Utils
● Retrieve a specific version of content using HST Content Beans API.
○ Dynamic proxying, and automatic link resolutions between versioned documents.
○ cf) JcrVersionUtils , HippoBeanVersionUtils (see javadoc for details)
26
HstRequestContext requestContext = RequestContextProvider.get();
// First, get the current live news document.
News curNewsDoc = requestContext.getContentBean();
// Then let’s get the specific version, live as of December 6, 2017 if any.
Calendar asOfDate = ISO8601.parse("2017-12-06T00:00:00-04:00");
News newsDocAsOf =
HippoBeanVersionUtils.getVersionedBeanAsOf(news.getCanonicalHandlePath(),
News.class, asOfDate);
// Pass along the News (dynamically proxied) bean to template!
request.setAttribute("document", newsDocAsOf);
Gem #6: Spring Boot Deploy Support
27
“Package and deploy it onto PCF Cloud!”
Gem #6: Why hipshoot Spring Boot Deploy Support*?
● Package a CMS project into single Spring Boot executable JAR.
○ Spring Boot is one of the best Framework for 12 Factor Apps (Cloud Native) development.
● Allow to deploy it to PCF (Pivotal Cloud Foundry) cloud env.
● Control the lifecycle of the application yourself.
○ E.g, environment initialization, Lucene index loading from storage, etc.
28
* https://onehippo-forge.github.io/hipshoot/
Gem #6: Spring Boot Support Deploy Support
29
● Build
$ mvn clean verify
● Running Example
$ java -Xms512m -Xmx1024m 
-Drepo.path="storage" 
-jar spring-boot-deploy/target/myhippoproject-deploy.jar
● Pushing Example to PCF (Pivotal Cloud Foundry)
$ cf login -a https://api.run.pivotal.io
$ cf push hippo-on-spring-boot 
-t 180 -f spring-boot-deploy/manifest.yml 
-p spring-boot-deploy/target/myhippoproject-deploy.jar
Gem #6: What does hipshoot provide?
30
● Extending TomcatEmbeddedServletContainerFactory
○ To support multi-wars packaging, JNDI resource configuration, etc.
● Demo project for details
○ https://github.com/woonsanko/hippo-on-spring-boot
Gem #6: What does hipshoot provide? (cont.)
31
● Example application.yaml with hipshoot configuration
hipshoot:
embedded:
catalina:
persistSession: 'false'
appBase: '${server.tomcat.basedir}/webapps'
wars: ${parameters.catalina.deployableWars}
server:
defaultContext:
parameters:
- name: 'repository-directory'
value: '${catalina.base}/repository'
override: 'false'
# SNIP
namingResources:
- name: 'jdbc/repositoryDS'
auth: 'Container'
type: 'javax.sql.DataSource'
properties:
# SNIP
Gem #6: Considering Lucene Index Rebuilding
32
● Each cluster node needs local Lucene on each node. *
Load Balancer
Node 1
Node N
DBMS
Lucene Index
on local FS
Lucene Index
on local FS
Journal
Global
Revision
Local
Revision
* https://wiki.apache.org/jackrabbit/Clustering
Gem #6: Considering Lucene Index Rebuilding (cont.)
33
● Solution Candidate
* https://wiki.apache.org/jackrabbit/Clustering
Node #N
DBMS
Lucene Index
on local FS
Journal
Global
Revision
Local
Revision
S3, SFTP, WebDAV,
...
Download and Restore
Lucene Index
From New Node
Export and Backup
Lucene Index
From Existing Node
Node #M
Gem #6: Considering Lucene Index Rebuilding (cont.)
34
● Solution Candidate, using Lucene Index Export/Import feature* (v12.1)
* https://www.onehippo.org/library/administration/export-the-lucene-index-from-a-running-production-environment.html
@SpringBootApplication
@RestController
public class Application {
// --->8--- SNIP --->8---
@PostConstruct
public void synchronizeLuceneIndex() {
// 1. Check if local lucene index directory exists.
// 2. If not existing, download the latest stable lucene export zip file.
}
@RequestMapping(path = "/backup-lucene-index")
public String backupLuceneIndex() {
// 1. Download lucene index export from https://{hostname}/cms/ws/indexexport.
// 2. Backup to a cloud storage such as S3, SFTP, WebDAV, etc.
}
}
Gem #7: Content HAL API
35
“Consume Content Right Away in your Apps!”
Gem #7: Why Content HAL API*?
● Another Built-in Generic Content REST API
based on HAL (Hypertext Application Language),
a specification draft as a HATEOAS
(Hypermedia as the Engine of Application State).
● Much easier, more performant and more extensible.
36
* More at https://tools.ietf.org/html/draft-kelly-json-hal-08 and http://stateless.co/hal_specification.html
Gem #7: Content HAL API
37
● What is HAL?
○ A specification draft for HATEOAS (Hypermedia as the Engine of Application State), a
constraint of the REST application architecture.
○ Minimum Valid HAL Resource: an empty JSON object
○ Mostly, a resource SHOULD have a self link ("_links" is reserved):
{}
{
"_links": {
"self": { "href" : "/orders/523" }
}
}
Gem #7: Content HAL API (cont.)
38
● You can have domain specific links and properties:
{
"_links": {
"self": { "href": "/orders/523" },
"invoice": { "href": "/invoices/873" }
},
"currency": "USD",
"status": "shipped",
"total": 10.20
}
Gem #7: Content HAL API (cont.)
39
● You can embed other resources in "_embedded" that is reserved:
{
"_links": {
"self": { "href": "/orders" }
},
"_embedded": {
"orders": [{
"_links": { "self": { "href": "/orders/523" } },
"total": 30.00
},{
"_links": { "self": { "href": "/orders/524" } },
"total": 20.00
}]
}
"currentlyProcessing": 14,
"shippedToday": 20
}
Gem #7: Content HAL API (cont.)
40
● Better use logical field names which are already defined in Document Types!
Gem #7: Content HAL API (cont.)
41
● Better use logical field names which are already defined in Document Types!
{
"_links": {
"self": { "href": "/site/api/events/b8f5eb45-7200-3118a0dc60b8" }
},
"title": "Breakfast",
"introduction": "Start the day with a nice breakfast.",
"date": 1478292471762,
"enddate": 1478292570000
}
Gem #7: Content HAL API (cont.)
42
● URL Patterns
○ Collection
■ /{type}/
■ e.g. http://localhost:8080/site/api/documents ,
http://localhost:8080/site/api/folders ,
http://localhost:8080/site/api/newsdocument
http://localhost:8080/site/api/resourcebundles
○ Item
■ /{type}/{id} or /{type}/{relPath}
■ e.g. http://localhost:8080/site/api/documents/{id },
http://localhost:8080/site/api/documents/{relPath },
http://localhost:8080/site/api/folders/{id },
http://localhost:8080/site/api/folders/{relPath },
http://localhost:8080/site/api/resourcebundles/{basename }
Gem #7: Content HAL API (cont.)
43
● Common Query Parameters
Name Description Examples
_scope Search scope node ID or path _scope=a_UUID or _scope=/content
_offset Offset of the iterating query result _offset=10
_limit Limit of the iterating query result _limit=10
_fields Field names to include or exclude _fields=title,introduction,-content
_sort Sort field names _sort=title,-date
_q Full text search query term _q=lorem+ipsum
_expr Custom JCR XPath expression to narrow the search
result
_expr=jcr:contains(@my:title,'hippo')
Gem #7: Content HAL API (cont.)
44
● Comparison with other options
Content REST API HST Plain JAX-RS REST Content HAL API
Standard Hippo Specific Custom HAL Specification
Built-in Yes No Yes
Chatty
Communication
Chatty Up to implementation Not Chatty
(w/ option to be chatty)
Logical Model
Support
No Yes Yes
Need Java
Beans
No Yes No
Extensible Yes No Yes
45
https://onehippo-forge.github.io/
https://github.com/onehippo-forge
Stay in Touch!
● www.onehippo.org
● slideshare.net/woonsan
● woonsanko.blogspot.com

N hidden gems in hippo forge and experience plugins (dec17)

  • 1.
    N Hidden Gemsin Hippo Forge and Experience Plugins Woonsan Ko December 6, 2017
  • 2.
    Sequel to NHidden Gems You Didn’t Know… (2016) ● slideshare.net/woonsan ● woonsanko.blogspot.com
  • 3.
    The Ecosystem aroundBR Experience 3 OSS Libraries Hippo Forge Plugins BR Experience Plugins OSS* Frameworks Generic vs. Specific Complexity * OSS: Open Source Software
  • 4.
    The Ecosystem aroundBR Experience (cont.) 4 OSS Libraries Hippo Forge Plugins BR Experience Plugins OSS* Frameworks 1. IFrame Perspective Plugin 2. Copy/Move Folder Plugin 3. External Document Picker 4. Doc. Commenting Plugin 5. HST Content Version Utils 6. Hipshoot for Spring Boot Deploy * OSS: Open Source Software 7. Content HAL API Complexity Generic vs. Specific
  • 5.
    Gem #1: TooSimple to iFrame? 5 “Why don’t you simply frame the goody in it?”
  • 6.
    Gem #1: WhyIFrame Perspective Plugin*? ● Built-in CMS Perspective Plugin to embed an IFrame to include a web application. ● Sometimes it is most cost effective to simply embed an IFrame for a good feature by a web application. 6 * More at https://onehippo-forge.github.io/iframe-perspective/
  • 7.
    Gem #1: IFramePerspective Plugin ● Configurations* ○ title, src, icon infos, any other IFrame element attributes (iframe.*) ○ X-Frame-Options , Content-Security-Policy , X-Content-Security-Policy , X-Webkit-CSP ● WicketSessionFilter in web.xml ○ To limit access only to CMS authenticated users. 7 * More at https://onehippo-forge.github.io/iframe-perspective/install.html
  • 8.
    Gem #1: IFramePerspective Plugin (cont.) 8
  • 9.
    Gem #2: Copyor Move Folder in CMS UI 9 “Can I copy or move a folder as a whole in CMS UI?”
  • 10.
    Gem #2: WhyFolder Context Menus Plugin*? ● Built-in CMS Folder Context Menu(s) to provide business users with features to copy or move folders in CMS UI. ○ Let business users organize content folders by themselves. ● Also provides a common code library for copying/moving folders. ○ Use it in Java / Groovy code. E.g, Batch Processing 10* More at https://onehippo-forge.github.io/folder-context-menus/
  • 11.
    Gem #2: Copyor Move Folder* in CMS UI 11
  • 12.
    Gem #2: Copyor Move Folder in CMS UI (cont.) 12 ● Code Library Support for Batch Processing - FolderCopyTask // Example: Copy /content/documents/myhippoproject/news/ // to /content/documents/myhippoproject/news2/ String sourceFolderPath = "/content/documents/myhippoproject/news"; String destBaseFolderPath = "/content/documents/myhippoproject"; String destFolderNodeName = "news2"; String destFolderDisplayName = "News 2"; Node sourceFolderNode = jcrSession.getNode(sourceFolderPath); Node destBaseFolderNode = jcrSession.getNode(destBaseFolderPath); FolderCopyTask task = new FolderCopyTask(jcrSession, Locale.ENGLISH, sourceFolderNode, destBaseFolderNode, destFolderNodeName, destFolderDisplayName); task.execute(); jcrSession.save();
  • 13.
    Gem #2: Copyor Move Folder in CMS UI (cont.) 13 ● Code Library Support for Batch Processing - FolderMoveTask // Example: Move /content/documents/myhippoproject/news/2011/ // to /content/documents/myhippoproject/common/2011/ String sourceFolderPath = "/content/documents/myhippoproject/news"; String destBaseFolderPath = "/content/documents/myhippoproject"; String destFolderNodeName = "news2"; String destFolderDisplayName = "News 2"; Node sourceFolderNode = jcrSession.getNode(sourceFolderPath); Node destBaseFolderNode = jcrSession.getNode(destBaseFolderPath); FolderMoveTask task = new FolderMoveTask(jcrSession, Locale.ENGLISH, sourceFolderNode, destBaseFolderNode, destFolderNodeName, destFolderDisplayName); task.execute(); jcrSession.save();
  • 14.
    Gem #3: ExternalDocument Picker (with new feature additions) 14 “Enrich your content by including metadata of related external content in CMS UI!”
  • 15.
    Gem #3: WhyExternal Document Picker Plugin*? ● Built-in Generic Picker UI Plugin in CMS for: ○ Selecting an associated external documents for a field in the document editor. ○ Selecting a linked external documents for a RichText field in a document. ○ Selecting external documents from Folder Context Menu to do something. ■ E.g, creating documents in the folder, tagging the folder, etc. ● For both flat-list data and tree-list data. ● Most effective way to enrich your content ○ Highly extensible. ○ CRISP API can be used in backend integration. 15* More at https://onehippo-forge.github.io/external-document-picker/
  • 16.
    Gem #3: ExternalDocument Picker 16 ExternalDocumentServiceFacade is responsible for data to display each item.
  • 17.
    17 Gem #3: ExternalDocument Picker (cont.) ExternalDocumentServiceFacade in Tree List View option, resolving parent-child relationship! * More at https://onehippo-forge.github.io/external-document-picker/field/dev-howto-treeview.html NEW!
  • 18.
    18 Gem #3: ExternalDocument Picker (cont.) * More at https://onehippo-forge.github.io/external-document-picker/folder/architecture.html NEW! ExternalDocumentServiceFacade in CMS Folder Menu, allowing custom folder settings or content creation!
  • 19.
    Gem #4: DocumentCommenting in CMS UI 19 “Comment on what you’re doing in collaboration with others!”
  • 20.
    Gem #4: WhyDocument Commenting Plugin*? ● Built-in Field UI Plugin to allow commenting among collaborators in Document Editor. ● Simple, cost-effective collaboration in document authoring and reviewing. ● No burden in document storage level as it’s stored separately. ● Highly extensible. 20* More at https://onehippo-forge.github.io/document-commenting/
  • 21.
    21 Gem #4: DocumentCommenting Add a commenting field anywhere in a document type!
  • 22.
    22 Gem #4: DocumentCommenting (cont.)
  • 23.
    Gem #4: DocumentCommenting (cont.) ● Very Extensible for different backends! 23 Document Commenting CMS UI Plugin <<interface>> CommentPersistence Manager* Default JCR CommentPersistence Manager Other Storage-based CommentPersistence Manager? * https://onehippo-forge.github.io/document-commenting/apidocs/org/onehippo/forge/document/commenting/cms/api/CommentPersistenceManager.html Only very simple 9 methods to implement! JCR ES? NoSQL?
  • 24.
    Gem #5: LiveVersion As-Of via HST Content Version Utils 24 “Show content in specific version, live as of December 6, 2017!”
  • 25.
    Gem #5: WhyHST Content Version Utils*? ● Utility to retrieve JCR Version data through dynamic proxy of HST Content Beans, generated at runtime automatically. ○ Instead of low-level JCR Version API: VersionManager, Frozen Nodes, etc. ● No need to have separate Java code and FreeMarker templates. ○ Just stick with HST Content Beans API, even for versioned, frozen nodes. 25 * More at https://onehippo-forge.github.io/hst-content-version-utils/
  • 26.
    Gem #5: LiveVersion As-Of via HST Content Version Utils ● Retrieve a specific version of content using HST Content Beans API. ○ Dynamic proxying, and automatic link resolutions between versioned documents. ○ cf) JcrVersionUtils , HippoBeanVersionUtils (see javadoc for details) 26 HstRequestContext requestContext = RequestContextProvider.get(); // First, get the current live news document. News curNewsDoc = requestContext.getContentBean(); // Then let’s get the specific version, live as of December 6, 2017 if any. Calendar asOfDate = ISO8601.parse("2017-12-06T00:00:00-04:00"); News newsDocAsOf = HippoBeanVersionUtils.getVersionedBeanAsOf(news.getCanonicalHandlePath(), News.class, asOfDate); // Pass along the News (dynamically proxied) bean to template! request.setAttribute("document", newsDocAsOf);
  • 27.
    Gem #6: SpringBoot Deploy Support 27 “Package and deploy it onto PCF Cloud!”
  • 28.
    Gem #6: Whyhipshoot Spring Boot Deploy Support*? ● Package a CMS project into single Spring Boot executable JAR. ○ Spring Boot is one of the best Framework for 12 Factor Apps (Cloud Native) development. ● Allow to deploy it to PCF (Pivotal Cloud Foundry) cloud env. ● Control the lifecycle of the application yourself. ○ E.g, environment initialization, Lucene index loading from storage, etc. 28 * https://onehippo-forge.github.io/hipshoot/
  • 29.
    Gem #6: SpringBoot Support Deploy Support 29 ● Build $ mvn clean verify ● Running Example $ java -Xms512m -Xmx1024m -Drepo.path="storage" -jar spring-boot-deploy/target/myhippoproject-deploy.jar ● Pushing Example to PCF (Pivotal Cloud Foundry) $ cf login -a https://api.run.pivotal.io $ cf push hippo-on-spring-boot -t 180 -f spring-boot-deploy/manifest.yml -p spring-boot-deploy/target/myhippoproject-deploy.jar
  • 30.
    Gem #6: Whatdoes hipshoot provide? 30 ● Extending TomcatEmbeddedServletContainerFactory ○ To support multi-wars packaging, JNDI resource configuration, etc. ● Demo project for details ○ https://github.com/woonsanko/hippo-on-spring-boot
  • 31.
    Gem #6: Whatdoes hipshoot provide? (cont.) 31 ● Example application.yaml with hipshoot configuration hipshoot: embedded: catalina: persistSession: 'false' appBase: '${server.tomcat.basedir}/webapps' wars: ${parameters.catalina.deployableWars} server: defaultContext: parameters: - name: 'repository-directory' value: '${catalina.base}/repository' override: 'false' # SNIP namingResources: - name: 'jdbc/repositoryDS' auth: 'Container' type: 'javax.sql.DataSource' properties: # SNIP
  • 32.
    Gem #6: ConsideringLucene Index Rebuilding 32 ● Each cluster node needs local Lucene on each node. * Load Balancer Node 1 Node N DBMS Lucene Index on local FS Lucene Index on local FS Journal Global Revision Local Revision * https://wiki.apache.org/jackrabbit/Clustering
  • 33.
    Gem #6: ConsideringLucene Index Rebuilding (cont.) 33 ● Solution Candidate * https://wiki.apache.org/jackrabbit/Clustering Node #N DBMS Lucene Index on local FS Journal Global Revision Local Revision S3, SFTP, WebDAV, ... Download and Restore Lucene Index From New Node Export and Backup Lucene Index From Existing Node Node #M
  • 34.
    Gem #6: ConsideringLucene Index Rebuilding (cont.) 34 ● Solution Candidate, using Lucene Index Export/Import feature* (v12.1) * https://www.onehippo.org/library/administration/export-the-lucene-index-from-a-running-production-environment.html @SpringBootApplication @RestController public class Application { // --->8--- SNIP --->8--- @PostConstruct public void synchronizeLuceneIndex() { // 1. Check if local lucene index directory exists. // 2. If not existing, download the latest stable lucene export zip file. } @RequestMapping(path = "/backup-lucene-index") public String backupLuceneIndex() { // 1. Download lucene index export from https://{hostname}/cms/ws/indexexport. // 2. Backup to a cloud storage such as S3, SFTP, WebDAV, etc. } }
  • 35.
    Gem #7: ContentHAL API 35 “Consume Content Right Away in your Apps!”
  • 36.
    Gem #7: WhyContent HAL API*? ● Another Built-in Generic Content REST API based on HAL (Hypertext Application Language), a specification draft as a HATEOAS (Hypermedia as the Engine of Application State). ● Much easier, more performant and more extensible. 36 * More at https://tools.ietf.org/html/draft-kelly-json-hal-08 and http://stateless.co/hal_specification.html
  • 37.
    Gem #7: ContentHAL API 37 ● What is HAL? ○ A specification draft for HATEOAS (Hypermedia as the Engine of Application State), a constraint of the REST application architecture. ○ Minimum Valid HAL Resource: an empty JSON object ○ Mostly, a resource SHOULD have a self link ("_links" is reserved): {} { "_links": { "self": { "href" : "/orders/523" } } }
  • 38.
    Gem #7: ContentHAL API (cont.) 38 ● You can have domain specific links and properties: { "_links": { "self": { "href": "/orders/523" }, "invoice": { "href": "/invoices/873" } }, "currency": "USD", "status": "shipped", "total": 10.20 }
  • 39.
    Gem #7: ContentHAL API (cont.) 39 ● You can embed other resources in "_embedded" that is reserved: { "_links": { "self": { "href": "/orders" } }, "_embedded": { "orders": [{ "_links": { "self": { "href": "/orders/523" } }, "total": 30.00 },{ "_links": { "self": { "href": "/orders/524" } }, "total": 20.00 }] } "currentlyProcessing": 14, "shippedToday": 20 }
  • 40.
    Gem #7: ContentHAL API (cont.) 40 ● Better use logical field names which are already defined in Document Types!
  • 41.
    Gem #7: ContentHAL API (cont.) 41 ● Better use logical field names which are already defined in Document Types! { "_links": { "self": { "href": "/site/api/events/b8f5eb45-7200-3118a0dc60b8" } }, "title": "Breakfast", "introduction": "Start the day with a nice breakfast.", "date": 1478292471762, "enddate": 1478292570000 }
  • 42.
    Gem #7: ContentHAL API (cont.) 42 ● URL Patterns ○ Collection ■ /{type}/ ■ e.g. http://localhost:8080/site/api/documents , http://localhost:8080/site/api/folders , http://localhost:8080/site/api/newsdocument http://localhost:8080/site/api/resourcebundles ○ Item ■ /{type}/{id} or /{type}/{relPath} ■ e.g. http://localhost:8080/site/api/documents/{id }, http://localhost:8080/site/api/documents/{relPath }, http://localhost:8080/site/api/folders/{id }, http://localhost:8080/site/api/folders/{relPath }, http://localhost:8080/site/api/resourcebundles/{basename }
  • 43.
    Gem #7: ContentHAL API (cont.) 43 ● Common Query Parameters Name Description Examples _scope Search scope node ID or path _scope=a_UUID or _scope=/content _offset Offset of the iterating query result _offset=10 _limit Limit of the iterating query result _limit=10 _fields Field names to include or exclude _fields=title,introduction,-content _sort Sort field names _sort=title,-date _q Full text search query term _q=lorem+ipsum _expr Custom JCR XPath expression to narrow the search result _expr=jcr:contains(@my:title,'hippo')
  • 44.
    Gem #7: ContentHAL API (cont.) 44 ● Comparison with other options Content REST API HST Plain JAX-RS REST Content HAL API Standard Hippo Specific Custom HAL Specification Built-in Yes No Yes Chatty Communication Chatty Up to implementation Not Chatty (w/ option to be chatty) Logical Model Support No Yes Yes Need Java Beans No Yes No Extensible Yes No Yes
  • 45.
  • 46.
    Stay in Touch! ●www.onehippo.org ● slideshare.net/woonsan ● woonsanko.blogspot.com