Wednesday 16 April 2014

User and Group count in alfresco

Hello everyone !

At some point of time you must have come across a requirement to find out what is the total number of users and groups available in the repository.

This can be achieved by performing database queries against alfresco database. I tried to query against the database and identified the queries to get this done. For me it was giving accurate results.

This is how I identified the total number of users -
Step-1 - get the qname id for the user.
SELECT ID FROM alf_qname WHERE local_name='person'

Step-2 - Perform a query against the alf_node to get the total user count.
SELECT COUNT(*) FROM alf_node WHERE type_qname_id = 'id retrieve from step-1'

This will give you the user count including deleted and non-deleted users. In alfresco, deleted user entries do remain present in the database. Hence, if you just want to eliminate deleted users from the total user's count then use following -

Step-3 - Get the store id
SELECT ID FROM alf_store WHERE protocol='workspace' AND identifier='SpacesStore'

Step-4 - Get user count eliminating deleted users.
SELECT COUNT(*) FROM alf_node WHERE type_qname_id = 'id retrieve from step-1' AND node_deleted = 0 AND store_id='store_id retrieved in step-3'

That's it. You have got the user count. Now if you want to find out group count, you already know how to do it based on above queries, you just need to manipulate them for groups.

I have not tried the queries on the newer version of alfresco.

Hope this helps.

Thanks,
Ramesh C

Saturday 12 April 2014

Running action asynchronously in alfresco

Hello everyone !

We all are aware that we can set up business rules to run asynchronously.
 
Consider a scenario, wherein you don't have a business rule setup. However, you need to run the functionality through an action  (Invoked using View Details > Run Action) and this action is
processing around thousands of records. 
 
If you don't run this action in background, you may have to end-up waiting on the same screen (from where you invoked the action) until the action execution completes.
and you can not do anyother activities in the alfresco webclient until then.
 
There is a way where in we can have the actions run asynchronously through some customization.
 
Below is the implementation detail about it in brief.
1. For all the actions invoked from View Details > Run Action link, RunActionWizard.java is the backend wizard been for run action wizard.
2. In FinishImpl method, action is invoked as below.
   this.getActionService().executeAction(action, nodeRef);
3. Modify it as below to run it as asynchronously. You can make it conditional to have it run asynchronously explicitly for your action.
   this.getActionService().executeAction(action, nodeRef, false, true);
 
Hope this will be useful to you.
 
Thanks,
Ramesh C

Quick way to get all the users of a specific group

Consider a scenario where on your production server, you have thousands of groups and thousands of users.

Now, at some point of time, you need to find out all the users belonging to some specific group.

There is obviously a way, where in you can just login to alfresco and search for a group and find out users from that group. But do keep in mind that, this will take some time to give you the result. You also need to be careful while entering the search criteria like you are searching for All root groups or children groups.

Instead, To make your job simpler, You can use below webscript to get this done quickly for you. Putting it here for quick easy handy reference. I am sure this will be helpful to you at some point of time.
http://server:port/alfresco/service/api/groups/{groupName}/children?authorityType=USER

Example usage -
http://localhost:8080/alfresco/service/api/groups/TEST_GROUP/children?authorityType=USER

Note :
There is also an option that you can query for all sub groups of the given group. You need to pass authorityType as GROUP.

Thanks,
Ramesh C

Processing list in webscript response xml/json ftl

Hello everyone !

I am sure this would be helpful to you if you are looking for a solution about how to iterate over a list in the ftl. Let's start then.

Returning appropriate responses (xml/json ftls) are the must when you need to do further processing based on your webscript response.
Here, I am providing the code snippets which will be useful to you when you need to process/iterate over the list in your xml/josn ftls for your webscript response.

For example, consider a scenario, where in you have to get the name/noderefs of all the contents from one space. I am sure you would like to get this done by writing a webscript.
In your webscript backend class, you will perform a lucene query, and generally we prefer to use a List in java backed webscript. Hence, will populate the list with the result noderefs.
Now, you need to process this result list and return the name/noderef in the xml/json ftls as the webscript response.

To process a list in webscript response ftls, you need to do below things -

1. Java backed webscript -
 - In your java backed declarative webscript, initialize the model object.
   Map<String, Object> model = new HashMap<String, Object>();
 - Prepare the List object to be set.
   List<NodeRef>  resultList = new ArrayList<NodeRef>();
   resultList = queryResult(query) // You are invoking a function which has code for performing lucene query and return the list.
 - Populate the model object
   model.put("nodelist", resultList);
 - Do return the model object from your webcript backend class.
   return model;

2. If you want to return xml as the response. Then, use below code in your webscript's response xml.ftl (yourwebscript.xml.ftl)
   <?xml version="1.0" encoding="UTF-8"?>
    <#escape x as x?html>
    <nodes>
        <#list nodelist as node>
            <nodeid>${node.id}</nodeid>
            <name>${node.name}</name>      
        </#list>
    </nodes>
    </#escape>

3. If you want to return json as the response. Then, use below code in your webscript's response json.ftl (yourwebcript.json.ftl)
   <#escape x as jsonUtils.encodeJSONString(x)>
   {
   "nodes": [
         <#if nodelist??>      
             <#assign first=true>
             <#list nodelist as node>
                 <#if node??>
                    <#if !first>
                     ,
                    <#else>
                    <#assign first=false>
                     </#if>
                     {
                        "nodeid":"${node.id}",
                         "name":"${node.name}"
                     }                  
                 </#if>
             </#list>      
         <#else> </#if>
       ] 
   }
  </#escape>

Processing a list in ftl is simpler now. You may want to try it in your webscripts.

Thanks,
Ramesh C