A shift in Alfresco Community license to LGPL

January 28, 2010

Alfresco has annouced that they will change (with the Alfresco 3.3 Community release in March) the licence for the free version of Alfresco.

As John Newton said:
“What the LGPL license provides over GPL is the ability to link in the Alfresco repository without affecting proprietary software that links it.”
(…)
“We do this in the spirit of making Alfresco available as a CMIS platform and a general ECM platform to build content applications without inhibiting your business opportunities. What we hope is that your applications will build demand for Alfresco services from Alfresco Software, particularly in larger enterprise environments.”

So basically the target is to allow other software vendor (and OEM ?) to use Alfresco as a core repository, used to manage persistency of content/documents, and to expose it through CMIS.

To give you a concrete example, look at the IBM partnership announced recently at Lotusphere in Janaury:
Alfresco Content Services for IBM Lotus

With CMIS as the “SQL for unstructured content”, Alfresco probably target to becomes the universal “database for documents”.

From my point of view, this strategy clearly make sense !

For more info (John Newton’s blog):


Alfresco Share in 1 hour

January 26, 2010

I don’t know if another more detailed webinar exists for Share, but all these screencam will give you a very good overview of the Share product :

Demo alfresco share


Count the total number of documents in Alfresco (using SQL)

January 20, 2010

For reporting purpose, we had to count the exact number of documents stored in Alfresco.
(This is mainly because we are using an external search engine, and we wanted to make sure this tool is able to index the full document repository).

My constraints was that:
– We have about 1TB of document (so a javascript is not probably not appropriate, should takes too long to execute…),
– We are using Alfresco v2.1.1 (so this info is not exposed in JMX console, as it should be the case in 3.1 or 3.2).

So I had to deal with SQL request….

Here is some sample requests I did. Hope this could help you if you have the same need:

========================================================
Count total number of documents in Alfresco (note: this includes all the live “cm:content” object visible under “Company Home”, so also the .js or .ftl files located in “Data Dictionary”):

SELECT count(a.id) FROM alfresco.alf_node as a
where a.protocol=”workspace” AND a.identifier=”SpacesStore”
AND a.type_qname=”{http://www.alfresco.org/model/content/1.0}content”;

Count total number of Spaces in Alfresco:

SELECT count(a.id) FROM alfresco.alf_node as a
where a.protocol=”workspace” AND a.identifier=”SpacesStore”
AND a.type_qname=”{http://www.alfresco.org/model/content/1.0}folder”;

Count number of documents in Alfresco, but exclude all “.log” files extension:

SELECT count(a.id) FROM alfresco.alf_node as a, alfresco.alf_node_properties as b
where a.id=b.node_id
AND a.protocol=”workspace” AND a.identifier=”SpacesStore”
AND a.type_qname=”{http://www.alfresco.org/model/content/1.0}content”
AND b.qname=”{http://www.alfresco.org/model/content/1.0}name”
AND b.string_value NOT like “%.log%”;

Count only the number of “.ftl” documents in Alfresco:

SELECT count(a.id) FROM alfresco.alf_node as a, alfresco.alf_node_properties as b
where a.id=b.node_id
AND a.protocol=”workspace” AND a.identifier=”SpacesStore”
AND a.type_qname=”{http://www.alfresco.org/model/content/1.0}content”
AND b.qname=”{http://www.alfresco.org/model/content/1.0}name”
AND b.string_value like “%.ftl%”;

********************
Note: I’m not a SQL expert, but I think this request is equivalent but more optimized:

SELECT count(*) FROM alfresco.alf_node a
inner join alfresco.alf_node_properties b on a.id=b.node_id AND b.qname='{http://www.alfresco.org/model/content/1.0}name’
where a.protocol=’workspace’ AND a.identifier=’SpacesStore’
AND a.type_qname='{http://www.alfresco.org/model/content/1.0}content’
AND b.string_value NOT like ‘%.log%’;

********************

========================================================

Another need was to be able to not take into account some spaces in the total count of documents.
I find a way, but partially only:

This request count the number of document object located in a specific space (at the root of the space only, please note that this request is not recursive….sorry):

The nodeID (uuid) of the space is passed as input: a.uuid=”19097e2d-0502-11df-80c7-0bb47275447a” (you can get that value from the web UI):

SELECT * FROM alfresco.alf_node a where a.id IN (SELECT b.child_node_id FROM alfresco.alf_node a, alfresco.alf_child_assoc as b
where a.uuid=”19097e2d-0502-11df-80c7-0bb47275447a”
AND a.type_qname=”{http://www.alfresco.org/model/content/1.0}folder”
AND a.id=b.parent_node_id)
AND a.type_qname=”{http://www.alfresco.org/model/content/1.0}content”;

Some more details about how the previous request is built:

First we perform this query to get all the children object ID of the specific space (this returns folder and documents):
(SELECT b.child_node_id FROM alfresco.alf_node a, alfresco.alf_child_assoc as b
where a.uuid=”19097e2d-0502-11df-80c7-0bb47275447a”
AND a.type_qname=”{http://www.alfresco.org/model/content/1.0}folder”
AND a.id=b.parent_node_id)

Then we filter the object list to retrieve only the documents (not the folders):
SELECT * FROM alfresco.alf_node a where a.id IN (…)
AND a.type_qname=”{http://www.alfresco.org/model/content/1.0}content”;

I did test these requests on a dedicated testing instance of Alfresco (with MySQL). So I was able to check that each document added was reflected in the new count value. There are some tests I did not do (like with versionning enabled….). So of course, should you have the same need for legal or contract reason, ask first the support to validate that the count method is correct.


IBM and Alfresco partnership : Portal, Collaboration and Social Networking

January 14, 2010

IBM and Alfresco started to work together to provide integration solutions between their respective products.

I do not have more technical details for the moment, but this has been just announced and will be soon at Lotusphere (January 17-21).

As far as I know, the approach is to use the Alfresco DM capabilities to manage the persistency of data created
through IBM UI (Lotus Quickr, Lotus Notes, Lotus Connections and WebSphere Portal). So web UI is provided by IBM software (like Quickr), primary meta-data are stored in IBM layer also, and the document binaries are stored in Alfresco repository. Integration is achieved through REST protocol.

This integration will be available in the spring of 2010.

I think this is a very good opportunity for Alfresco, to be part of such a strong Portal, Collaboration and SN (social networking) set of solutions.

This is also a good news for IBM/Alfresco customers (as we are) because they can leverage their software investments and get the benefits of both world:
– IBM Lotus has a very complete offer in term of “2.0” softwares (Websphere Portal, Lotus Quickr for collab., Connections for SN), but none of these solutions really provide a very highly scalable data repository (as Alfresco do) to store terabyte of documents.
– On the other side, Alfresco is still a young product and is not able (yet) to address SN or portal features. Its web UI are still quite basic, but its core repository is designed to scale up to more than 100 million documents.

I don’t know if IBM also plan to integrate Alfresco with their Portal WCM solution (IBM Lotus Web Content Management)…but this will be a good idea…

As John Newton said at Lotusphere:
“I think the combination of Lotus and Alfresco provides a real SharePoint killer as well. With the combination of the two, there’s nothing that Sharepoint can do that we can’t.”
“It’s an opportunity for IBM as well to have a set of capabilities where Filenet might be too large or complex for a customer”, he added.

Another well known SN competitor is Jive editor. A tighter collaboration between Alfresco and Jive would surely make sense….No doubt that Alfresco is already working on this…

For more info about Alfresco/IBM integration:
Alfresco Content Services for IBM Lotus

Alfresco ECM gilds IBM’s Lotus suite

Alfresco Enterprise CMS Cozies Up With IBM Lotus

Also, if you are interested about integration of Quickr IBM product with other ECM vendors, this is something I have already discussed on my other (portal) blog:

Quickr and ECM relationship

Quickr and ECM integration


Alfresco coding best practice : how to safely call java services ?

January 6, 2010

In alfresco there are two ways of calling a repository service: e.g., lower case “nodeService” and upper case “NodeService” etc (similarly for rest of the available repository services).

To be able to use a service bean in your custom code, you usually use a spring configuration file to inject it dynamically in your class (using spring IOC).
So in your spring configuration file, for your class “com.mycompany.MyBeanClass”, you can choose to inject the Alfresco service (nodeService below) using the “nodeService” (lower case) or “NodeService”(upper case) naming convention:

   <bean id="myBean" >
      <property name="nodeService">
          <ref bean="nodeService" />
      </property>
   </bean>

or:

   <bean id="myBean" >
      <property name="nodeService">
          <ref bean="NodeService" />
      </property>
   </bean>

As a coding best practice it is highly recommended to use services with upper case “NodeService” etc., because this “nodeService” bypasses security check, transaction check, etc.
The technical explanation is that Alfresco use AOP (Aspect-Oriented Programming) to expose services either as standard spring bean, or as “AOP proxies”.
To better understand that, let’s have a look at these 2 files, which contains a reference to the ContentService bean:

/webapps/alfresco/WEB-INF/classes/alfresco
public-services-context.xml
content-services-context.xml

The public-services-context.xml contains a reference to the “ContentService” (lower case) which is actually a proxy object (AOP proxy) for the  “contentService” (lower case) referenced in content-services-context.xml:

public-services-context.xml

    <bean id="ContentService">
        <property name="proxyInterfaces">
            <value>org.alfresco.service.cmr.repository.ContentService</value>
        </property>
        <property name="target">
            <ref bean="contentService"/>
        </property>
        <property name="interceptorNames">
            <list>
                <idref local="ContentService_transaction"/>
                <idref local="AuditMethodInterceptor"/>
                <idref local="exceptionTranslator"/>
                <idref bean="mlContentInterceptor"/>
                <idref bean="ContentService_security"/>
            </list>
        </property>
    </bean>
 

content-services-context.xml

   <!-- Abstract bean definition defining base definition for content service -->
   <bean id="baseContentService" abstract="true" init-method="init">
      <property name="retryingTransactionHelper">
          <ref bean="retryingTransactionHelper"/>
      </property>
      <property name="dictionaryService">
          <ref bean="dictionaryService" />
      </property>
      <property name="nodeService">
          <ref bean="nodeService" />
      </property>
      <property name="transformerRegistry">
          <ref bean="contentTransformerRegistry" />
      </property>
      <property name="policyComponent">
          <ref bean="policyComponent" />
      </property>
      <property name="avmService">
          <ref bean="avmService"/>
      </property>
      <property name="imageMagickContentTransformer">
         <ref bean="transformer.ImageMagick" />
      </property>
      <property name="eagerContentStoreCleaner" >
         <ref bean="eagerContentStoreCleaner" />
      </property>
   </bean>
  
   <bean id="contentService" parent="baseContentService">
      <property name="store">
          <ref bean="fileContentStore" />
      </property>
   </bean>

In the public-services-context.xml, we can see a list of interceptors, which force the execution of security check (ContentService_security) or audit action (AuditMethodInterceptor) or even transaction context (ContentService_transaction).

        <property name="interceptorNames">
            <list>
                <idref local="ContentService_transaction"/>
                <idref local="AuditMethodInterceptor"/>
                <idref local="exceptionTranslator"/>
                <idref bean="mlContentInterceptor"/>
                <idref bean="ContentService_security"/>
            </list>
        </property>

So when someone call directly the the  “contentService” (lower case), all these check are bypassed. This can leads to security issue (for instance) because the Alfresco system in this case does not evaluate the security before running the corresponding service operation.
So the conclusion is in almost all the cases it is best to use upper case services, especially in places where we know that there is a possibility of “no proper security check”. The only case where minor case service might be use safely is likely to be “admin treatment” (like batch), when one knows that we do not need to check security for such technical operation. But keep in mind that transaction are also bypassed, so I think they should be explicitly managed at the service call level if needed.