Presentation by Florian Maul at the Alfresco community meetup in Hamburg on June 5th 2012 about my Javascript Console extension.
Some of the slides are German but the main technical part is in English.
http://alfresco.fme.de
http://www.fme.de
8. Alfresco APIs
• What kinds of API are there?
Java Foundation API
Javascript API & Javascript Services
CMIS
• Where can I use Javascript in Alfresco:
Webscripts developed in Javascript
Javascript run by Actions (Run Script Action)
Javascript attached to Tasks & Events in Workflows
9 (c) fme AG - #205626
9. Webscripts developed in Javascript
• Most of the Alfresco Webscript are developed in Javascript
• Example: GET /alfresco/service/sample/blog/category/{category}
// check category exists?
var category = search.luceneSearch(
"PATH:"/cm:generalclassifiable//cm:" + url.extension + """);
if (category == undefined) {
status.code = 404;
status.message = "Category " + url.extension + " not found.";
status.redirect = true;
} else {
// perform category search
var nodes = search.luceneSearch(
"PATH:"/cm:generalclassifiable//cm:" + url.extension +
"//member"");
model.resultset = nodes;
}
10 (c) fme AG - #205626
10. Javascript for Tasks & Events in Workflows
• Javascript can be executed from within Workflow definitions
• Example of Activti Workflow: parallelreview_group_processdefinition.xml
<decision name="isapproved">
<event type="node-enter">
<action class="org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript">
<script>
<variable name="wf_actualPercent" access="write"/>
<expression>
wf_actualPercent = ((wf_approveCount * 100) /
people.getMembers(bpm_groupAssignee).length);
</expression>
</script>
</action>
</event>
</decision>
11 (c) fme AG - #205626
11. Javascript run by Actions (Run Script Action)
• Alfresco Explorer has a Run Script Action
• For Share there is an Execute Script extension in Share-Extras:
12 (c) fme AG - #205626
12. But how to develop Javascript code?
• Webscripts
Develop in Eclipse
ANT build script to copy changes & reload the webscripts
Run the webscript manually in the browser
• Data Dictionary Scripts
upload script to Data Dictionary
run Script Action
watch errors in the Alfresco Log file (ScriptLogger=DEBUG)
fix bugs and iterate
• It takes to long to test out Javascript code and fix bugs.
13 (c) fme AG - #205626
15. Meet the Javascript Console
•
• Mike Farman (Director Product Management Alfresco):
„I really like the stuff you’ve been doing, my favourite is the JavaScript console, it’s the
first add-on I always install!“
• X
16 (c) fme AG - #205626
16. Javascript Console milestones
• End of 2010
Need to develop and execute Javascript code for a project sparked development
of the first prototype
First internal versions were a single standalone page in Share
• April 2011:
Contact with Will Abson
refactoring and integration into the admin console of Alfresco 3.4
• May 2011:
First checkin into the Share-Extras project and first public release
• Nov 2011:
Version 0.4 with basic code completion
• June 2012:
Version 0.5 with freemarker editor
17 (c) fme AG - #205626
17. Download & Installation
• Visit: http://code.google.com/p/share-extras/
• Download at http://code.google.com/p/share-extras/downloads/list
Installation
• For version 0.4.x copy the jar file to tomcat/shared/lib/
• With 0.5 there will be two jar files –repo.jar and –share.jar. The repo.jar must be
copied to tomcat/webapps/alfresco/WEB-INF/lib and the share.jar to
tomcat/webapps/share/WEB-INF/lib.
18 (c) fme AG - #205626
20. Selecting the file or folder to work with
• Select the space variable from • Open any document in the
a directory chooser: Javascript Console from the
document library:
21 (c) fme AG - #205626
21. Recurse() function
• The Javascript console has a special recurse function to iterate over a tree of nodes:
recurse(space, function(node) {
if (node.name.toLowerCase().indexOf("alfresco") >= 0) {
print("adding tag alfresco to " +
node.displayPath + "/" + node.name);
node.addTag("alfresco");
}
});
• If no function is given it returns the nodes as an array:
var allNodes = recurse(space);
22 (c) fme AG - #205626
22. Creating users and attaching avatars
function createUser(username,firstname, lastname, email, location, jobtitle)
{
var password = username; // use for testing only!
var p = people.createPerson(username, firstname, lastname,
email, password, true);
p.properties["cm:location"] = location;
p.properties["cm:jobtitle"] = jobtitle;
p.save();
}
createUser("homer", "Homer", "Simpson", "h.simpson@springfield.fox",
"Springfield", "Nuclear Safety Inspector");
23 (c) fme AG - #205626
23. Creating users and attaching avatars
// pseudo-code not working
for each (imageNode in space.children) {
var user = people.getPerson(name);
user.createAssociation(
imageNode, "cm:avatar");
}
Full source code here:
http://www.techbits.de/2011/12/02/using-the-javascript-console-creating-users-with-avatar-images/
24 (c) fme AG - #205626
24. Assign users to sites
var nodes = search.luceneSearch(
"TYPE:cm:person +@cm:lastName:Simpson");
for each(var simpson in nodes) {
var site = siteService.getSite(
"javascript-console-talk");
site.setMembership(
simpson.properties["cm:userName"],
"SiteCollaborator");
}
25 (c) fme AG - #205626
25. Creating Webscripts
• The new version 0.5 makes
it easy to create webscripts:
Write a controller javascript
using logger.log output
Create a freemarker
template
Test different URL
arguments and different
users
26 (c) fme AG - #205626
26. Creating Webscripts
var result = [];
for each(node in companyhome.childByNamePath(args.path).children) {
result.push({
name : node.name,
creator : node.properties["cm:creator"],
creationDate : node.properties["cm:created"]
});
}
model.folder = result;
[
<#list folder as f>
{
"name" : "${f.name}",
"creator" : "${f.creator}",
"creationDate" : "${f.creationDate?date}"
}
</#list>
]
27 (c) fme AG - #205626
27. Access spring beans / unlock documents
• Example unlock a document:
var ctx = Packages.org.springframework.
web.context.ContextLoader.getCurrentWebApplicationContext();
var lockService = ctx.getBean("lockService");
lockService.unlock(document.nodeRef);
• This looks like a hack but is perfectly valid Alfresco Javascript
• It only works in Javascript stored in the Classpath (not in the Data Dictionary)
• Also very useful to test your own Beans written in Java
28 (c) fme AG - #205626
28. Access spring beans / reindex nodes
• We faced the issue with nodes getting lost from the index. ALF-12588
• You can force the reindexing of single nodes:
var ctx =
Packages.org.springframework.web.context.ContextLoader.getCurrentWebAppl
icationContext();
var nodeIndexer = ctx.getBean("nodeIndexer");
var nodeService = ctx.getBean("nodeService");
function indexNode(node) {
var childAssoc = nodeService.getPrimaryParent(node.nodeRef);
nodeIndexer.indexCreateNode(childAssoc);
}
indexNode(search.findNode("workspace://SpacesStore/d4923a10-96dc-4565-
a471-d6b6c8f7b170"));
• Warning: With great power comes great responsibility!
29 (c) fme AG - #205626
29. Special access to logger configuration
• The Javascript Console allows you to change to log4j log level at runtime.
• For your own Java classes you can use:
logger.setLevel("de.fme.alfresco", "DEBUG");
• The Alfresco Javascript runtime uses the ScriptLogger class:
logger.setLevel("org.alfresco.repo.jscript.ScriptLogger",
"DEBUG");
30 (c) fme AG - #205626
30. Javascript Puzzlers – Alfresco Edition
What do these two do?
• node.properties["cm:name"] = "textfile.txt";
• node.name = "textfile.txt";
Comparing ScriptNode nodeRefs:
• node1.nodeRef.equals(node2.nodeRef)
• node1.nodeRef == node2.nodeRef
• " " +node1.nodeRef == " " + node2.nodeRef
31 (c) fme AG - #205626
31. Batch processing
• Examples:
Set all documents to inherit permissions
Disable automatic versioning for all documents
• Small batches can run in the Javascript Console in one Transaction (10000 nodes)
I install the Javascript Console on every production system
• Large batches currently only possible using Java with multiple Transactions.
• Batch processing (updates for >100000 nodes)
How to find the nodes? Search or recursion?
Can not run in one transaction: Transaction Management in Javascript?
Processing in smaller batches
How to make use of multithreading?
32 (c) fme AG - #205626