How to safely inject alfresco service dependencies?

cancel
Showing results for 
Search instead for 
Did you mean: 

How to safely inject alfresco service dependencies?

Moderator
Moderator
0 0 946

We can inject the repository service dependencies using 2 methods. One method is a lower case e.g. “contentService” bean ref and other method is upper case e.g. “ContentService” bean ref, similarly we can use "nodeService" or "NodeService".

To use a service in your custom implementation, you usually use a spring config (spring context) file to inject service bean dependencies. So in your spring context file, for your class for example “com.abhinav.CustomAction”, you can either use "nodeService" [lower-case] or "NodeService" [upper-case].

 Method 1-

   <bean id="customAction" class="com.abhinav.CustomAction">

      <property name="nodeService">

          <!-- Lower case -->

          <ref bean="nodeService"/>

      </property>

      <property name="contentService">

          <!-- Lower case -->

          <ref bean="contentService"/>

      </property>

   </bean>

Method 2-

<bean id="customAction" class="com.abhinav.CustomAction">

      <property name="nodeService">

          <!-- Lower case -->

          <ref bean="NodeService"/>

      </property>

      <property name="contentService">

          <!-- Lower case -->

          <ref bean="ContentService"/>

      </property>

</bean>

The best practice is that we should always use services with upper case “NodeService”, “ContentService”, “FileFolderService” etc. because this lower case “nodeService”, ”contentService” etc.  bypasses security check, audit and transaction checks.

Technically Alfresco uses AOP (Aspect-Oriented Programming) to expose services as “AOP proxies”.

To prove that, let’s go through publicly exposed services and some core services such as nodeService and contentService:

  1. https://svn.alfresco.com/repos/alfresco-open-mirror/alfresco/COMMUNITYTAGS/V5.0.d/root/projects/repository/config/alfresco/public-services-context.xml
  2. https://svn.alfresco.com/repos/alfresco-open-mirror/alfresco/COMMUNITYTAGS/V5.0.d/root/projects/repository/config/alfresco/content-services-context.xml
  3. https://svn.alfresco.com/repos/alfresco-open-mirror/alfresco/COMMUNITYTAGS/V5.0.d/root/projects/repository/config/alfresco/node-services-context.xml

content-services-context.xml

<bean id="contentService" parent="baseContentService">

                <property name="store">

                   <ref bean="fileContentStore"/>

                </property>

</bean>

node-services-context.xml

<bean id="nodeService" class="org.springframework.aop.framework.ProxyFactoryBean">

                <!--  Lazy init to avoid circular dependencies  -->

                <property name="targetSource">

                                <bean class="org.alfresco.config.NonBlockingLazyInitTargetSource">

                                                <property name="targetBeanName">

                                                                <idref bean="_nodeService"/>

                                                </property>

                                </bean>

                </property>

                <property name="proxyInterfaces">

                                <list>

                                                <value>org.alfresco.service.cmr.repository.NodeService</value>

                                </list>

                </property>

</bean>


Note: you can look into the xml files for more details.

public-services-context.xml

<!--  Public Node Service  -->

<bean id="NodeService" class="org.springframework.aop.framework.ProxyFactoryBean">

                <property name="proxyInterfaces">

                                <list>

                                    <value>org.alfresco.service.cmr.repository.NodeService</value>

                                </list>

                </property>

                <property name="target">

                                <ref bean="nodeService"/>

                </property>

                <property name="interceptorNames">

                                <list>

                                                <idref local="NodeService_transaction"/>

                                                <idref local="AuditMethodInterceptor"/>

                                                <idref local="exceptionTranslator"/>

                                                <idref bean="NodeService_security"/>

                                                <idref bean="disableAuditablePolicySetPropertyInterceptor"/>

                                </list>

                </property>

</bean>

<!--  Public Content Service  -->

<bean id="ContentService" class="org.springframework.aop.framework.ProxyFactoryBean">

                <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>

Notice that, the property ‘interceptorNames’ which has list of interceptors, which force the execution of transaction check (ContentService_transaction), audit (AuditMethodInterceptor) and security check (ContentService_security) etc.

So when you directly call the “contentService” (lower case), all these check are bypassed.

This can leads to security issue because alfresco will not evaluate the security before running the corresponding service operation in this case. So, it is best practice to use upper case services always.