Friday, April 27, 2012

Alfresco cloud service

Alfresco started a cloud service. More detailed it is is an instance of Alfresco Share which is avaiable in the WWW. The smallest offering is for FREE and it allows you to use Share functions like:
  • The document library
  • The dashboard
  • Collaborate on documents
  • Manage site members
Further features and space is available for monthly fees. However, if you want to try it out then it is possible to register here: http://cloud.alfresco.com .

I just created an instance for magicable.de and created two user accounts. However both have to log-in to be able to see the content. So this service is not suitable for sharing your content accross the web. It's more for companies or cloesed communities those need to access and collaborate on their documents inside the web. So there seems to be no guest access to your Share instance in the cloud.

Unfortunately the free instance does not allow to access it via an API. So you can't use it as content repo in the web. As far as I understand this functionality will be available later for the paid version of it.

However, if you want to store some documents online (including meta data - this is something which can't drop box do for you), then Alfresco in the Cloud may be an alternative for you.
 

Are we brain-washed?

In fact I am coming from the database world. This means I worked as an Engineer for the vendor of an relational database and also did Consulting for a No-SQL company. In both cases I had contact with ECM and related systems. So as I worked for Ingres I did Partner Certification work for systems like Alfresco and Liferay. In the past the system borders of an ECM system were very clear to me. So everything beyond the storage of just Meta Data was out of the scope of the Database System itself. I became a 'border liner' during my time as a Senior Consultant for a Graph Database System. The vertices could store not just meta data but also provide you a Content Stream. The system aimed to support unstructured data very well (as mentioned it supported Content streams and also something that was named Undefined Attribute). There were even Document Management use cases those were covered by this system. However ... . During my work with ECM, I realized that ECM companies understand themself more and more as Data Management companies. (Another point seems to be that today everything has to be Social or in the Cloud.) We tend to see everything as document. By definition a document is a set of properties thoses are used to store the meta data and the content itself. This raises questions like:
  • Is a document without content really a document?
  • Is really everything which has meta data and content a document?
I am sure the answer is 'It depends', but I think we should go back to the roots by not using ECM-Systems like Databases. We should ask questions like:
  • Is there a real paper document involved in a given use case?
  • Are there some real workflows with real persons those are handling real documents?
  • What should the person know about the document?
If the answer is 'Yes', then we can be sure that  we are doing right by storing a digital document which has the right set of properties regarding the given processes and requirements.

But what's if the answer is 'No'. In my opinion we should then not use an ECM/DM system to store such data, even if we want to do it because it seems to be close because there is already one available. Just use a Database System (NoSQL or Relational, whatever the use cases are requiring) to store the data regarding the required data model. Be not brain-wahsed! Do not belive that ECM solves all your Data Management problems and the answers to the above questions will be often (but not every time):
  • A document without content should be an object in a datbase (row, vertex, ...).
  • Not everything which has meta data and content is really a document!
What do you think about?


Monday, April 16, 2012

Alfresco Web Scripts

A few days ago I talked about 'Server side Java Script'. This post describes a technique which is named 'Web Script' and explains for which purpose it could be useful. With Web Scripts Alfresco allows to easily deploy content oriented RESTFul Web Services to the Repository. The logic behind these services is then often realized by using Java Script.

A Web Script contains 4 pieces:
  • A descriptor file
  • A Java Script (or a Java Class)
  • A freemarker template
  • Language bundles
The descriptor describes how (which URL) and who can run the Web Script. The Java Script file works as a kind of Controller by setting a model. The Freemarker template contains the presentation logic and the language bundles are allowing multi language support.

Let's begin by investigating the Desctiptor file in detail. Such an descriptor contains:
  • The short name (shortname)
  • The description (description)
  • The url by including the parameters (url)
  • The default format
  • The authentication method
Here some example code:

<webscript>
  <shortname>Hello World</shortname>
  <description>Greet a user</description>
  <url>/helloworld?to={name?}</url>
  <url>/hello/world?to={name?}</url>
  <format default="html">extension</format>
  <authentication>user</authentication>
</webscript>
 Above you can see a Web Script which has the name 'Hello Word'. It 'Greets a user'. The URL is mapped to '/helloworld', whereby one Parameter 'to' is expected. The default response should be 'html' and a user authentication is required in order to execute the script. The value 'extension' means that the requested format is determined by the extension which is used as part of the URL. So for instance 'world.html' or 'world.txt'. As authentication the following values are possible: 'none', 'guest', 'user' or 'admin. Possible formats are: 'html', 'text', 'xml', 'atom', 'rss' or 'json'. There is an optional parameter which is named 'runas'. This parameter is used to execute the Web Script inside the context of another user's session. To be able to fully use this feature it is required that the Web Script is deployed in a static way. (We will talk about the deployment options later in this article.)

What we need next is to investigate the Java Script file. There are specifc naming conventions. So a Java Script which is accessible via HTTP GET should have an Descriptor and a Java Script file which is named as the following:
  • ${id}.${http method}.desc.xml
  • ${id}.${http method}.js
For instance: helloworld.get.desc.xml and helloworld.get.js .



The Java Script file can contain basic Java Script (or even Java because it is interpreted by a Java based engine) and calls of the Alfresco Java Script API.  Let me give you a short overview about this API. It is even useful if you want to implement Actions or Workflows for the Alfresco System. You can think about this Java Script API like a built in language to access Content. If you know Procedural Languages for Database Systems, then you know what I mean. Indeed, the possibilities those are provided by this API are quite beyond the ones of for instance PL/SQL. So even if you are not a Java Script guy, it should be possible to use the API. There are multiple versios of the API available. This article focuses on the 3.4 one.

A script can import another one:

 <import resource="/Company Home/Data Dictionary/Scripts/library.js">
The example above shows a 'dynamic' import. Which means that the imported script is stored in Alfresco itself. It's also possible to just import from the classpath by using "classpath:${path to js}".

 The API provides some root objects. Those objects are available out of the box.

  • companyhome: The company home root folder
  • userhome: The current user's home folder
  • person: The current user object
  • search: The search API
  • people: The people API
  • actions: The action API
  • logger: A logger
  • session: Provides session specific information
  • classification: The classification API
  • utils: Some helpers
  • groups: To access group authorities
  • stites: The sites API
As you can see the API-s can often be accessed by using root object. Often the result of an API call is a document (Or at least the reference to one). If you use the Java Script API, then this is named 'Script Node'. For instance a 'userhome', 'companyhome', 'document', 'space' (Is äquivalent to a folder in Alfresco) or a 'person' is script node. So let's investigate the API-s a little bit more detailed!

The Script Node API has the following important methods:
  • properties
  • children
  • assocs
  • aspects
  • content
  • id
  • nodeRef
  • name
  • type
  • parents
  • childByNamePath
  • getSite
  For all of you who are not such familar with Alfresco: A node has a specific type. A type defines a set of properties. So Properties can be inherited by creating sub-types. An aspect is a bag of properties which can be assigned to a type independent from the inheritance hierarchy.  A node can also have associations to other nodes. A specific association is the child association (if you delete the parent then the childs will become deleted, too).

The properties attribute is an associative array. You can access it by using 'node.properties.propx' or 'node.properties["propx"]'.

Beyond the Script Node API there is also the "Modify and Creating" API. Here some important methods:
  • createFile
  • createFolder
  • createNode
  • addNode (as child)
  • removeNode (remove child assocs)
  • createAssociation
  • move
  • copy
  • addAspect
Also as an extension of the Script Node API, you can think of the Check-in/out and Versioning API
  • checkout
  • checkin
  • cancelCheckout
  • isVersioned
  • versionHistory
  • getVersion
  • createdDate
  • creator
  • label
  • type
  • descrption
  • nodeRef
  • node
The methods are used the same way as the Script node API ones.

The content of the node was accessed by using the content attribute. This one provides the following API:
  • mimetype
  • encoding
  • size
  • url
  • downloadURL
So a node can also have content of a specific mime type.

The search API allows you to search for specific documents. The following methods are part of the search API:
  • luceneSearch
  • xpathSearch
  • savedSearch
  • findNode (by given node reference)
  • query (by using an object which consists a search method and the search query)
The following query is a CMIS one:

var query = {query: "SELECT e.* FROM ecg:mytype AS e WHERE e.ecg:myprop=" + myvar, language: "cmis-alfresco"};

 The people API allows to handle users those are stored inside Alfresco. Here the methods of it:
  • createPerson
  • deletePerson
  • getGroup
  • createGroup
  • parentGroup
  • getMembers
  • isAdmin
  • changePassword
  • setPassword
 The Actions API is used to create an Action object. Then the actions parameters can be set. Afterwards it is possible to execute the action:

var myaction = create("myaction");
myaction.parameters.myparam = 'myvalue';
myaction.execute;
 The classification API provides the following methods:
  • getAllCategoryNodes
  • getAllClassificationAspects
  • createRootCategory
  • isCategory
  • categoryMembers
  • subCategories
  • createSubCategory
  • removeCategory
This section covered not all available API-s. Further more there are the Permission API, the Transformation API, the Thumbnailing API, the Tagging API, the Workflow API, the AVM API and the WCM API.

A special root object for Web Scripts is the one which is named 'model'. It allows you to set the result of the execution of you web script. Here an example:

var username = person.properties.userName;
model.username = username;
The model object is used to transfer data from the controlling Web Script to the Freemarker template. So let's take a closer look on Freemarker templates!

Basically a freemarker template can be anything which is textual. So you can write it as html, as text as xml. The idea behind it is to use some static text with some dynamic text from the model. There is a whole language about this freemarker stuff. We just look on the most important parts:
  • Place holders
  • Data model
  • Variables and Types
  • Sequences
  • Directives
  • Comments
  • Built-ins
Place holders can be found as ${myPlaceholder} inside the template. Such a placeholder will then become replaced regarding the data from the model.

The data model is a Tree and can be set. Every value which you access via a place holder is stored inside the data model. Everything which is not a leaf inside the data model's tree is named 'Hash'. The variables inside the tree those are storing single values (the leafs of the tree) are named 'Scalars'. You can navigate through the model's tree by using indexes. For instance 'animals[0].name'.  Scalars are typed: String, Number, Date/Time, Boolean .

Sequences are lists of strings:

["myval1", ... , "myvaln"]

There are several directives. The 'if' directive looks as the following:

<#if myvar = "mystringval">  My text <#else> My other text </#if>
Possible operators are: <, >, !=, = .

The list directive is used to itterate over elements of the data model.

<# list myhashvar as myvar> ${myvar.myscalarvar} </#list>
 <# list myseq as myvar> ${myvar} </#list>

The include directive can be used to insert content from another file to the template:

<#include "/myfile.html">
It is possible to create user defined directives the following way:

<@mydirective myparam1=myval1, ... myparamn=myvaln>
    <#--   Some commands --#>
</@mydirective>
 Comments are used the following way:
<#-- My comment --#>
The following built in functions are available:

  • myvar!"My optional value": Uses the optional value if  myvar is not set
  • myvar??: Returns true if myvar is set
  • myvar?upper_case: Returns the variable value in upper case letters
  • myvar?cap_first: Converts the first letter to upper case
  • myvar?trim
  • myvar?size
  • myvar?int: The integer part of a number (E.G. 5 in case of 5.432)
  • myvar?string_short: Date to String conversion
  • myvar?foo:string : Boolean to Strng conversion 
Alfresco extended the capabilities of Freemarker templates a bit, so that you can access some specific API elements directly from the Freemarker Template without the need of a Java Script as the controller. However, I would recommend to stay with the MVC-pattern!

Let's now investigate how multiple languages are supported. The default message bundle is a properties-file with the following name:
  • ${id}.${http method}.properties
 To support multiple languages, you can create a new file which is named:
  • ${id}.${method}_${locale}.properties
The messages are then accessible directly from your Freemarker template via a function call:

 ${msg("myprop")}
So the final question of this article is: How can I deploy and use such a Web Script. There are multiple ways to deploy a web script:
  • Dynamic deployment: To the Content Repository itself. Which mean you need to import it to 'Data Dictionary/Web Scripts' or 'Data Dictionary/Web Script Extensions' (The second folder should be used to override scripts from the first folder for testing purposes.)
  • Static deployment by copying the folder which contains the Web Script files  to ${CATALINA_HOME}/webapps/alfresco/WEB-INF/classes/alfresco/templates/webscripts. This can be simplified by bundling the Web Script into an Alfresco Module Package.
  • Extension deployment by copying the folder which contains the Web Script files to ${CATALINA_HOME}/shared/classes/alfresco/extension/templates/webscripts
Afterwards you have to refresh the list of available Web Scripts. No server restart is required:

  • Navigate to 'http://${myhost}:8080/alfresco/service/index'
  • Click on the 'Refresh Web Scripts' button