N hidden gems in hippo forge and experience plugins (dec17)
1. N Hidden Gems in Hippo Forge and
Experience Plugins
Woonsan Ko
December 6, 2017
2. Sequel to N Hidden Gems You Didn’t Know… (2016)
● slideshare.net/woonsan
● woonsanko.blogspot.com
3. The Ecosystem around BR Experience
3
OSS
Libraries
Hippo Forge
Plugins
BR Experience
Plugins
OSS*
Frameworks
Generic vs. Specific
Complexity
* OSS: Open Source Software
4. 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
5. Gem #1: Too Simple to iFrame?
5
“Why don’t you simply frame the goody in it?”
6. 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/
7. 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
9. Gem #2: Copy or Move Folder
in CMS UI
9
“Can I copy or move a folder as a whole in CMS UI?”
10. 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/
14. Gem #3: External Document Picker
(with new feature additions)
14
“Enrich your content by including metadata
of related external content in CMS UI!”
15. 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/
16. Gem #3: External Document Picker
16
ExternalDocumentServiceFacade
is responsible for data to
display each item.
17. 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. 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!
19. Gem #4: Document Commenting
in CMS UI
19
“Comment on what you’re doing
in collaboration with others!”
20. 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. 21
Gem #4: Document Commenting
Add a
commenting field
anywhere in a
document type!
23. 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?
24. Gem #5: Live Version As-Of
via HST Content Version Utils
24
“Show content in specific version,
live as of December 6, 2017!”
25. 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/
26. 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);
27. Gem #6: Spring Boot Deploy Support
27
“Package and deploy it onto PCF Cloud!”
28. 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/
29. 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
30. 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
32. 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
33. 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
34. 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.
}
}
35. Gem #7: Content HAL API
35
“Consume Content Right Away in your Apps!”
36. 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
37. 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" }
}
}
38. 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
}
39. 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
}
40. Gem #7: Content HAL API (cont.)
40
● Better use logical field names which are already defined in Document Types!
41. 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
}
42. 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 }
43. 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')
44. 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