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

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.

Advertisements

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

  1. mejura says:

    lot of insight! I used small case nodeService without knowing the purpose of it! appreciate it…

    keep writing please…

    thank you
    mejura
    http://www.simplyecm.com

  2. That’s really interesting detail, I didn’t know before that all services in alfresco have ‘lower-case’ and ‘upperCase’ versions (does this concern all services?)
    I will surely keep that advise in mind!
    p.s i also post some articles about alfresco on my blog so you can check it out and we can link each other if you like 😉

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: