Merged V3.1 to HEAD

13965: Line-endings only
   13967: Enable upgrade of MT env from 3.0.x to 3.1.1+ (with out-of-date config warning on startup rather than errors later)
   13976: Line-endings only
   13977: MT - add unit test (for dynamic models)


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13980 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Jan Vonka
2009-04-16 12:51:43 +00:00
parent 2af3695451
commit 3774f9ed01
10 changed files with 484 additions and 272 deletions

View File

@@ -20,12 +20,10 @@
<bean id="tenantAdminService" parent="baseMultiTAdminService" /> <bean id="tenantAdminService" parent="baseMultiTAdminService" />
<bean id="tenantInterpreter" class="org.alfresco.repo.tenant.TenantInterpreter"> <bean id="tenantInterpreter" class="org.alfresco.repo.tenant.TenantInterpreter" parent="interpreterBase">
<property name="transactionService" ref="transactionComponent"/>
<property name="tenantAdminService" ref="tenantAdminService"/> <property name="tenantAdminService" ref="tenantAdminService"/>
<property name="tenantService" ref="tenantService"/> <property name="tenantService" ref="tenantService"/>
<property name="authenticationService" ref="AuthenticationService"/> <property name="authenticationService" ref="AuthenticationService"/>
<property name="authorityService" ref="AuthorityService"/>
<property name="baseAdminUsername"><value>${alfresco_user_store.adminusername}</value></property> <property name="baseAdminUsername"><value>${alfresco_user_store.adminusername}</value></property>
</bean> </bean>

View File

@@ -25,3 +25,6 @@ system.locks.err.failed_to_acquire_lock=Failed to get lock ''{0}'' using token '
system.locks.err.lock_resource_missing=Failed to manipulate lock ''{0}'' using token ''{1}''. The lock resource no longer exists. system.locks.err.lock_resource_missing=Failed to manipulate lock ''{0}'' using token ''{1}''. The lock resource no longer exists.
system.locks.err.lock_update_count=Failed to update lock ''{0}'' using token ''{1}''. {2} locks were updated when {3} should have been. system.locks.err.lock_update_count=Failed to update lock ''{0}'' using token ''{1}''. {2} locks were updated when {3} should have been.
system.locks.err.excl_lock_exists=Failed to get lock ''{0}'' using token ''{1}''. An exclusive lock exists: {2} system.locks.err.excl_lock_exists=Failed to get lock ''{0}'' using token ''{1}''. An exclusive lock exists: {2}
# Multi-Tenant
system.mt.warn.upgrade_mt_admin_context=Please update your alfresco/extension/mt/mt-admin-context.xml (to use latest alfresco/extension/mt/mt-admin-context.xml.sample).>>>>>>> .merge-right.r13967

View File

@@ -3,6 +3,18 @@
<beans> <beans>
<!--
Bootstrap Data: Prototype beans for the per-tenant bootstrap.
These are fetched by the MultiTAdminServiceImpl when new tenant is created.
-->
<bean id="userBootstrap-mt" parent="userBootstrap-base" singleton="false" />
<bean id="systemBootstrap-mt" parent="systemBootstrap-base" singleton="false" />
<bean id="versionBootstrap-mt" parent="versionBootstrap-base" singleton="false" />
<bean id="version2Bootstrap-mt" parent="version2Bootstrap-base" singleton="false" />
<bean id="spacesArchiveBootstrap-mt" parent="spacesArchiveBootstrap-base" singleton="false" />
<bean id="spacesBootstrap-mt" parent="spacesBootstrap-base" singleton="false" />
<bean id="baseMultiTAdminService" class="org.alfresco.repo.tenant.MultiTAdminServiceImpl" abstract="true"> <bean id="baseMultiTAdminService" class="org.alfresco.repo.tenant.MultiTAdminServiceImpl" abstract="true">
<!-- <!--

View File

@@ -3,6 +3,13 @@
<beans> <beans>
<bean id="interpreterBase" abstract="true">
<property name="transactionService" ref="transactionComponent"/>
<property name="authorityService" ref="AuthorityService"/>
</bean>
<bean id="repoAdminService" class="org.alfresco.repo.admin.RepoAdminServiceImpl"> <bean id="repoAdminService" class="org.alfresco.repo.admin.RepoAdminServiceImpl">
<property name="dictionaryDAO" ref="dictionaryDAO"/> <property name="dictionaryDAO" ref="dictionaryDAO"/>
@@ -17,11 +24,9 @@
</bean> </bean>
<bean id="repoAdminInterpreter" class="org.alfresco.repo.admin.RepoAdminInterpreter"> <bean id="repoAdminInterpreter" class="org.alfresco.repo.admin.RepoAdminInterpreter" parent="interpreterBase">
<property name="transactionService" ref="transactionComponent"/>
<property name="repoAdminService" ref="RepoAdminService"/> <property name="repoAdminService" ref="RepoAdminService"/>
<property name="authorityService" ref="AuthorityService"/>
</bean> </bean>

View File

@@ -42,7 +42,7 @@
<property name="tenantService" ref="tenantService"/> <property name="tenantService" ref="tenantService"/>
</bean> </bean>
<bean id="workflowInterpreter" class="org.alfresco.repo.workflow.WorkflowInterpreter"> <bean id="workflowInterpreter" class="org.alfresco.repo.workflow.WorkflowInterpreter" parent="interpreterBase">
<property name="workflowService" ref="WorkflowService"/> <property name="workflowService" ref="WorkflowService"/>
<property name="AVMService" ref="AVMService"/> <property name="AVMService" ref="AVMService"/>
<property name="AVMSyncService" ref="AVMSyncService"/> <property name="AVMSyncService" ref="AVMSyncService"/>
@@ -50,10 +50,8 @@
<property name="namespaceService" ref="namespaceService"/> <property name="namespaceService" ref="namespaceService"/>
<property name="personService" ref="PersonService"/> <property name="personService" ref="PersonService"/>
<property name="authorityDAO" ref="authorityDAO"/> <property name="authorityDAO" ref="authorityDAO"/>
<property name="transactionService" ref="transactionService"/>
<property name="fileFolderService" ref="FileFolderService"/> <property name="fileFolderService" ref="FileFolderService"/>
<property name="tenantService" ref="tenantService"/> <property name="tenantService" ref="tenantService"/>
<property name="authorityService" ref="AuthorityService"/>
</bean> </bean>
<bean id="workflowInterpreterHelp" class="org.alfresco.i18n.ResourceBundleBootstrapComponent"> <bean id="workflowInterpreterHelp" class="org.alfresco.i18n.ResourceBundleBootstrapComponent">

View File

@@ -38,6 +38,7 @@ import javax.transaction.UserTransaction;
import net.sf.acegisecurity.providers.encoding.PasswordEncoder; import net.sf.acegisecurity.providers.encoding.PasswordEncoder;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.admin.RepoModelDefinition; import org.alfresco.repo.admin.RepoModelDefinition;
import org.alfresco.repo.attributes.BooleanAttributeValue; import org.alfresco.repo.attributes.BooleanAttributeValue;
import org.alfresco.repo.attributes.MapAttribute; import org.alfresco.repo.attributes.MapAttribute;
@@ -68,6 +69,7 @@ import org.alfresco.util.PropertyCheck;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
@@ -76,7 +78,7 @@ import org.springframework.context.ApplicationContextAware;
* *
*/ */
public class MultiTAdminServiceImpl implements TenantAdminService, ApplicationContextAware public class MultiTAdminServiceImpl implements TenantAdminService, ApplicationContextAware, InitializingBean
{ {
// Logger // Logger
private static Log logger = LogFactory.getLog(MultiTAdminServiceImpl.class); private static Log logger = LogFactory.getLog(MultiTAdminServiceImpl.class);
@@ -222,21 +224,30 @@ public class MultiTAdminServiceImpl implements TenantAdminService, ApplicationCo
public static final String STORE_BASE_ID_VERSION2 = "version2Store"; public static final String STORE_BASE_ID_VERSION2 = "version2Store";
public static final String STORE_BASE_ID_SPACES = "SpacesStore"; public static final String STORE_BASE_ID_SPACES = "SpacesStore";
private static final String TENANTS_ATTRIBUTE_PATH = "alfresco-tenants"; private static final String TENANTS_ATTRIBUTE_PATH = "alfresco-tenants";
private static final String TENANT_ATTRIBUTE_ENABLED = "enabled"; private static final String TENANT_ATTRIBUTE_ENABLED = "enabled";
private static final String TENANT_ROOT_CONTENT_STORE_DIR = "rootContentStoreDir"; private static final String TENANT_ROOT_CONTENT_STORE_DIR = "rootContentStoreDir";
private List<TenantDeployer> tenantDeployers = new ArrayList<TenantDeployer>(); private List<TenantDeployer> tenantDeployers = new ArrayList<TenantDeployer>();
private static final String WARN_MSG = "Please update your alfresco/extension/mt/mt-admin-context.xml to use baseMultiTAdminService (see latest alfresco/extension/mt/mt-admin-context.xml.sample)"; private static final String WARN_MSG = "system.mt.warn.upgrade_mt_admin_context";
protected void checkProperties() public void afterPropertiesSet() throws Exception
{ {
if (moduleService == null || siteAVMBootstrap == null || baseAdminUsername == null) // for upgrade/backwards compatibility with 3.0.x (mt-admin-context.xml)
if (baseAdminUsername == null)
{ {
logger.warn(WARN_MSG); logger.warn(I18NUtil.getMessage(WARN_MSG));
} }
// for upgrade/backwards compatibility with 3.0.x (mt-admin-context.xml)
if (siteAVMBootstrap == null)
{
logger.warn(I18NUtil.getMessage(WARN_MSG));
siteAVMBootstrap = (SiteAVMBootstrap) ctx.getBean("siteAVMBootstrap");
}
PropertyCheck.mandatory(this, "NodeService", nodeService); PropertyCheck.mandatory(this, "NodeService", nodeService);
PropertyCheck.mandatory(this, "DictionaryComponent", dictionaryComponent); PropertyCheck.mandatory(this, "DictionaryComponent", dictionaryComponent);
PropertyCheck.mandatory(this, "RepoAdminService", repoAdminService); PropertyCheck.mandatory(this, "RepoAdminService", repoAdminService);
@@ -247,9 +258,9 @@ public class MultiTAdminServiceImpl implements TenantAdminService, ApplicationCo
PropertyCheck.mandatory(this, "TenantFileContentStore", tenantFileContentStore); PropertyCheck.mandatory(this, "TenantFileContentStore", tenantFileContentStore);
PropertyCheck.mandatory(this, "WorkflowService", workflowService); PropertyCheck.mandatory(this, "WorkflowService", workflowService);
PropertyCheck.mandatory(this, "RepositoryExporterService", repositoryExporterService); PropertyCheck.mandatory(this, "RepositoryExporterService", repositoryExporterService);
PropertyCheck.mandatory(this, "siteAVMBootstrap", siteAVMBootstrap);
PropertyCheck.mandatory(this, "moduleService", moduleService); PropertyCheck.mandatory(this, "moduleService", moduleService);
PropertyCheck.mandatory(this, "baseAdminUsername", baseAdminUsername); PropertyCheck.mandatory(this, "moduleService", moduleService);
PropertyCheck.mandatory(this, "siteAVMBootstrap", siteAVMBootstrap);
} }
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
@@ -259,8 +270,6 @@ public class MultiTAdminServiceImpl implements TenantAdminService, ApplicationCo
public void startTenants() public void startTenants()
{ {
checkProperties();
AuthenticationUtil.setMtEnabled(true); AuthenticationUtil.setMtEnabled(true);
// initialise the tenant admin service and status of tenants (using attribute service) // initialise the tenant admin service and status of tenants (using attribute service)

View File

@@ -24,6 +24,7 @@
*/ */
package org.alfresco.repo.tenant; package org.alfresco.repo.tenant;
import java.io.InputStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.Serializable; import java.io.Serializable;
import java.io.StringWriter; import java.io.StringWriter;
@@ -42,7 +43,10 @@ import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.admin.RepoAdminService;
import org.alfresco.service.cmr.coci.CheckOutCheckInService; import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.ContentWriter;
@@ -87,8 +91,10 @@ public class MultiTDemoTest extends TestCase
private AuthorityService authorityService; private AuthorityService authorityService;
private CategoryService categoryService; private CategoryService categoryService;
private CheckOutCheckInService cociService; private CheckOutCheckInService cociService;
private RepoAdminService repoAdminService;
private DictionaryService dictionaryService;
public static int NUM_TENANTS = 11; public static int NUM_TENANTS = 2;
public static final String TEST_TENANT_DOMAIN = "my.test"; public static final String TEST_TENANT_DOMAIN = "my.test";
public static final String TEST_TENANT_DOMAIN2 = TEST_TENANT_DOMAIN+"2"; public static final String TEST_TENANT_DOMAIN2 = TEST_TENANT_DOMAIN+"2";
@@ -143,6 +149,8 @@ public class MultiTDemoTest extends TestCase
authorityService = (AuthorityService) ctx.getBean("AuthorityService"); authorityService = (AuthorityService) ctx.getBean("AuthorityService");
categoryService = (CategoryService) ctx.getBean("CategoryService"); categoryService = (CategoryService) ctx.getBean("CategoryService");
cociService = (CheckOutCheckInService) ctx.getBean("CheckoutCheckinService"); cociService = (CheckOutCheckInService) ctx.getBean("CheckoutCheckinService");
repoAdminService = (RepoAdminService) ctx.getBean("RepoAdminService");
dictionaryService = (DictionaryService) ctx.getBean("DictionaryService");
} }
@Override @Override
@@ -654,6 +662,59 @@ public class MultiTDemoTest extends TestCase
} }
} }
public void testCustomDynamicModels()
{
logger.info("test custom/dynamic models");
final int defaultModelCnt = dictionaryService.getAllModels().size();
for (final String tenantDomain : tenants)
{
final String tenantAdminName = tenantService.getDomainUser(AuthenticationUtil.getAdminUserName(), tenantDomain);
AuthenticationUtil.runAs(new RunAsWork<Object>()
{
public Object doWork() throws Exception
{
// no custom models should be deployed yet (note: will fail if re-run)
assertEquals(0, repoAdminService.getModels().size());
assertEquals(defaultModelCnt, dictionaryService.getAllModels().size());
assertNull(dictionaryService.getClass(QName.createQName("{my.new.model}sop")));
// deploy custom model
InputStream modelStream = getClass().getClassLoader().getResourceAsStream("tenant/exampleModel.xml");
repoAdminService.deployModel(modelStream, "exampleModel.xml");
assertEquals(1, repoAdminService.getModels().size());
assertEquals(defaultModelCnt+1, dictionaryService.getAllModels().size());
ClassDefinition myType = dictionaryService.getClass(QName.createQName("{my.new.model}sop"));
assertNotNull(myType);
assertEquals(QName.createQName("{my.new.model}mynewmodel"),myType.getModel().getName());
// deactivate model
repoAdminService.deactivateModel("exampleModel.xml");
assertEquals(1, repoAdminService.getModels().size()); // still deployed, although not active
assertEquals(defaultModelCnt, dictionaryService.getAllModels().size());
assertNull(dictionaryService.getClass(QName.createQName("{my.new.model}sop")));
// re-activate model
repoAdminService.activateModel("exampleModel.xml");
assertEquals(1, repoAdminService.getModels().size());
assertEquals(defaultModelCnt+1, dictionaryService.getAllModels().size());
myType = dictionaryService.getClass(QName.createQName("{my.new.model}sop"));
assertNotNull(myType);
assertEquals(QName.createQName("{my.new.model}mynewmodel"),myType.getModel().getName());
return null;
}
}, tenantAdminName);
}
}
private void createGroup(String shortName, String parentShortName) private void createGroup(String shortName, String parentShortName)
{ {
// create new Group using authority Service // create new Group using authority Service
@@ -751,21 +812,24 @@ public class MultiTDemoTest extends TestCase
private NodeRef getUserHomesNodeRef(StoreRef storeRef) private NodeRef getUserHomesNodeRef(StoreRef storeRef)
{ {
// get the users' home location // get the "User Homes" location
String path = "/app:company_home/app:user_homes"; return findFolderNodeRef(storeRef, "/app:company_home/app:user_homes");
}
ResultSet rs = this.searchService.query(storeRef, SearchService.LANGUAGE_XPATH, path); private NodeRef findFolderNodeRef(StoreRef storeRef, String folderXPath)
NodeRef usersHomeNodeRef = null;
if (rs.length() == 0)
{ {
throw new AlfrescoRuntimeException("Cannot find user homes location: " + path); ResultSet rs = this.searchService.query(storeRef, SearchService.LANGUAGE_XPATH, folderXPath);
NodeRef folderNodeRef = null;
if (rs.length() != 1)
{
throw new AlfrescoRuntimeException("Cannot find folder location: " + folderXPath);
} }
else else
{ {
usersHomeNodeRef = rs.getNodeRef(0); folderNodeRef = rs.getNodeRef(0);
} }
return usersHomeNodeRef; return folderNodeRef;
} }
private NodeRef createFolderNode(NodeRef parentFolderNodeRef, String nameValue) private NodeRef createFolderNode(NodeRef parentFolderNodeRef, String nameValue)

View File

@@ -37,22 +37,35 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.security.AuthenticationService; import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.util.PropertyCheck;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
/** /**
* An interactive console for Tenants. * An interactive console for Tenants.
* *
*/ */
public class TenantInterpreter extends BaseInterpreter public class TenantInterpreter extends BaseInterpreter implements ApplicationContextAware, InitializingBean
{ {
private static Log logger = LogFactory.getLog(TenantInterpreter.class);
// Service dependencies // Service dependencies
private ApplicationContext ctx;
private TenantAdminService tenantAdminService; private TenantAdminService tenantAdminService;
protected TenantService tenantService; protected TenantService tenantService;
private AuthenticationService authenticationService; private AuthenticationService authenticationService;
private String baseAdminUsername = null; // default for backwards compatibility only - eg. upgrade of existing MT instance (mt-admin-context.xml.sample) private String baseAdminUsername = null;
private static final String WARN_MSG = "system.mt.warn.upgrade_mt_admin_context";
public void setTenantAdminService(TenantAdminService tenantAdminService) public void setTenantAdminService(TenantAdminService tenantAdminService)
{ {
@@ -83,6 +96,11 @@ public class TenantInterpreter extends BaseInterpreter
return AuthenticationUtil.getAdminUserName(); return AuthenticationUtil.getAdminUserName();
} }
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
this.ctx = applicationContext;
}
/** /**
* Main entry point. * Main entry point.
*/ */
@@ -91,6 +109,22 @@ public class TenantInterpreter extends BaseInterpreter
runMain("tenantInterpreter"); runMain("tenantInterpreter");
} }
public void afterPropertiesSet() throws Exception
{
// for upgrade/backwards compatibility with 3.0.x (mt-admin-context.xml)
if (authorityService == null || baseAdminUsername == null)
{
logger.warn(I18NUtil.getMessage(WARN_MSG));
}
if (authorityService == null)
{
authorityService = (AuthorityService)ctx.getBean("AuthorityService");
}
PropertyCheck.mandatory(this, "TransactionService", transactionService);
PropertyCheck.mandatory(this, "TenantService", tenantService);
}
protected boolean hasAuthority(String username) protected boolean hasAuthority(String username)
{ {

View File

@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Definition of new Model -->
<!-- The important part here is the name - Note: the use of the my: namespace
which is defined further on in the document -->
<model name="my:mynewmodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
<!-- Optional meta-data about the model -->
<description>Example custom Model</description>
<author></author>
<version>1.0</version>
<!-- Imports are required to allow references to definitions in other models -->
<imports>
<!-- Import Alfresco Dictionary Definitions -->
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
<!-- Import Alfresco Content Domain Model Definitions -->
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
</imports>
<!-- Introduction of new namespaces defined by this model -->
<!-- NOTE: The following namespace my.new.model should be changed to reflect your own namespace -->
<namespaces>
<namespace uri="my.new.model" prefix="my"/>
</namespaces>
<types>
<!-- Definition of new Content Type: Standard Operating Procedure -->
<type name="my:sop">
<title>Standard Operating Procedure</title>
<parent>cm:content</parent>
<properties>
<property name="my:publishedDate">
<type>d:datetime</type>
</property>
<property name="my:authorisedBy">
<type>d:text</type>
</property>
</properties>
<associations>
<association name="my:signOff">
<source>
<mandatory>false</mandatory>
<many>false</many>
</source>
<target>
<class>cm:content</class>
<mandatory>false</mandatory>
<many>false</many>
</target>
</association>
<child-association name="my:processSteps">
<source>
<mandatory>false</mandatory>
<many>false</many>
</source>
<target>
<class>cm:content</class>
<mandatory>false</mandatory>
<many>true</many>
</target>
</child-association>
</associations>
</type>
</types>
<aspects>
<!-- Definition of new Content Aspect: Image Classification -->
<aspect name="my:imageClassification">
<title>Image Classfication</title>
<properties>
<property name="my:width">
<type>d:int</type>
</property>
<property name="my:height">
<type>d:int</type>
</property>
<property name="my:resolution">
<type>d:int</type>
</property>
</properties>
</aspect>
</aspects>
</model>

View File

@@ -20,8 +20,7 @@
<bean id="tenantAdminService" parent="baseMultiTAdminService" /> <bean id="tenantAdminService" parent="baseMultiTAdminService" />
<bean id="tenantInterpreter" class="org.alfresco.repo.tenant.TenantInterpreter"> <bean id="tenantInterpreter" class="org.alfresco.repo.tenant.TenantInterpreter" parent="interpreterBase">
<property name="transactionService" ref="transactionComponent"/>
<property name="tenantAdminService" ref="tenantAdminService"/> <property name="tenantAdminService" ref="tenantAdminService"/>
<property name="tenantService" ref="tenantService"/> <property name="tenantService" ref="tenantService"/>
<property name="authenticationService" ref="AuthenticationService"/> <property name="authenticationService" ref="AuthenticationService"/>