User Tools

Site Tools


forum:alfresco:custom-action

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

forum:alfresco:custom-action [2008/05/23 11:23]
sebastian
forum:alfresco:custom-action [2023/11/19 22:46] (current)
Line 34: Line 34:
  
 ===== Implementation ===== ===== Implementation =====
 +This example is separated in two parts. ​
 +  - Part one is about creating the QuickCheckout as a custom action. This action will be available in the list of actions for a document.
 +  - Part two shows how to make this action available as a button in the web client UI.
 +For deployment it is assumed that there is an exploded alfresco.war in the deployment directory of the application server. The action is available as soon as the files are copied into the specified directories and the application server is restarted. The names of the files are given above the file contents. The directory the files have to be deployed to can be found at the bottom of the file contents.
 +
 +==== Part 1: Creating a custom action ====
 +To create the QuickCheckout action the following steps have to be done:
 +  - An action implementation must be created.
 +  - A file with message properties must be created for the action.
 +  - The action must be bound into the Spring context.
 +Basic Spring knowledge is presumed for the rest of this example.
 +
 === The action class === === The action class ===
-The QuickCheckout class is the actual implementation of the QuickCheckout action. It extends ActionExecuterAbstractBase and overrides executeImpl(). ​+The QuickCheckout class is the actual implementation of the QuickCheckout action. It extends ActionExecuterAbstractBase and overrides executeImpl(). This method will later be called to start the action.
  
-=== Making the action available to the web client ====+''​QuickCheckout.java''​ 
 +<​code>​ 
 +package de.hmedia.alfresco.actions;​ 
 + 
 +import java.io.Serializable;​ 
 +import java.util.List;​ 
 +import java.util.HashMap;​ 
 +import java.util.Map;​ 
 + 
 +import org.alfresco.model.ContentModel;​ 
 +import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;​ 
 +import org.alfresco.service.cmr.action.Action;​ 
 +import org.alfresco.service.cmr.repository.NodeRef;​ 
 + 
 +import org.alfresco.service.cmr.repository.NodeService;​ 
 +import org.alfresco.service.cmr.coci.CheckOutCheckInService;​ 
 +import org.alfresco.service.cmr.security.PersonService;​ 
 +import org.alfresco.service.namespace.NamespaceService;​ 
 + 
 +import org.alfresco.service.namespace.QName;​ 
 +import org.alfresco.repo.security.authentication.AuthenticationUtil;​ 
 + 
 +import org.alfresco.service.cmr.action.ParameterDefinition;​ 
 +import org.alfresco.web.bean.repository.Repository;​ 
 +import org.apache.commons.logging.Log;​ 
 +import org.apache.commons.logging.LogFactory;​ 
 + 
 +/** 
 + * This is the implementation of the QuickCheckout action. It checks out a document into a given workspace. 
 + *  
 + * @author Sebastian Lorenz 
 + * @author Andreas Hartmann 
 + * 
 + */ 
 + 
 +public class QuickCheckout extends ActionExecuterAbstractBase { 
 + /** 
 + * the current user; 
 + */ 
 + private NodeRef person; 
 + /** 
 + * the working copy 
 + */ 
 + private NodeRef workingCopy;​ 
 + /** 
 + * the target folder name (sub part of home folder only) 
 + */ 
 + private String targetSubFolder;​ 
 + /** 
 + * the target 
 + */ 
 + private NodeRef targetSpace;​ 
 + /** 
 + * the node service 
 + */ 
 + private NodeService nodeService;​ 
 + /** 
 + * the coci service 
 + */ 
 + private CheckOutCheckInService cociService;​ 
 + /** 
 + * the person service 
 + */ 
 + private PersonService personService;​ 
 +  
 + private static Log logger ​LogFactory.getLog(QuickCheckout.class);​ 
 +  
 + /** 
 + * Set the target folder 
 + *  
 + * @param targetSubFolder ​ the target subfolder below the home folder  
 + */ 
 + public void setTargetSubFolder(String targetSubFolder) { 
 + this.targetSubFolder ​targetSubFolder;​ 
 +
 +  
 + /** 
 + * Set the node service 
 +
 + * @param nodeService ​ the node service 
 + */ 
 + public void setNodeService(NodeService nodeService) 
 +
 + this.nodeService ​nodeService;​ 
 +
 +  
 + /** 
 + * Set the coci service 
 +
 + * @param cociService ​ the coci service 
 + */ 
 + public void setCociService(CheckOutCheckInService cociService) 
 +
 + this.cociService = cociService;​ 
 +
 +  
 + /** 
 + * Set the person service 
 +
 + * @param personService ​ the person service 
 + */ 
 + public void setPersonService(PersonService personService) 
 +
 + this.personService = personService;​ 
 +
 +  
 + /** 
 + * Returns the destination for the checkout as a subfolder with a given name in the homespace of the current user 
 + * The space is created automatically if it doesn'​t exist 
 + *  
 + * @param user as NodeRef - the current user 
 + * @param targetName as String - the subfolder of the homefolder 
 + * @return target folder as NodeRef 
 + */ 
 + public NodeRef getTargetSpace(NodeRef user, String targetName) { 
 + NodeRef target = null; 
 + 
 + // 1.get home folder 
 + NodeRef homeFolder = (NodeRef) nodeService.getProperty(user,​ ContentModel.PROP_HOMEFOLDER);​ 
 + 
 + // 2. get target NodeRef from target folder name 
 + target = nodeService.getChildByName(homeFolder,​ ContentModel.ASSOC_CONTAINS,​ targetName);​ 
 +  
 + // 2.1. create the target if it doesn'​t exist 
 + if (target == null) { 
 +  
 + Map<​QName,​ Serializable>​ contentProperties = new HashMap<​QName,​Serializable>​();​ 
 + contentProperties.put(ContentModel.PROP_NAME,​ targetName);​ 
 +//​ contentProperties.put(ApplicationModel.PROP_ICON,​ this.icon);​ 
 +//​ contentProperties.put(ContentModel.PROP_TITLE,​ this.title);​ 
 +//​ contentProperties.put(ContentModel.PROP_DESCRIPTION,​ this.description);​ 
 +  
 +         nodeService.createNode(homeFolder,​ 
 +                   ContentModel.ASSOC_CONTAINS,​ 
 +                   Repository.resolveToQName(ContentModel.TYPE_FOLDER.toString()),​ 
 +                   ContentModel.TYPE_FOLDER,​ 
 +                   contentProperties);​ 
 +           
 +          ​target = nodeService.getChildByName(homeFolder,​ ContentModel.ASSOC_CONTAINS,​ targetName);​ 
 +           
 +          if (target == null) 
 +              ​logger.warn("​Could not create folder node with name: " + targetName);​ 
 +          ​else 
 +                 ​logger.debug("​Created folder node with name: " + this.name);​  
 +
 + 
 + return target; 
 +
 + 
 + @Override 
 + protected void executeImpl(Action action, NodeRef actionedUponNodeRef) { 
 +  
 + person=personService.getPerson(AuthenticationUtil.getCurrentUserName());​ 
 +  
 + targetSpace = getTargetSpace(person,​ targetSubFolder);​ 
 +  
 + if(nodeService.exists(actionedUponNodeRef)  
 + &&​ ! nodeService.hasAspect(actionedUponNodeRef,​ ContentModel.ASPECT_WORKING_COPY)  
 + &&​ nodeService.exists(targetSpace)  
 + &&​ nodeService.getType(targetSpace).equals(ContentModel.TYPE_FOLDER)) { 
 +  
 + String workingCopyName = nodeService.getProperty(actionedUponNodeRef,​ ContentModel.PROP_NAME).toString();​ 
 + 
 + //​checkout the node 
 + workingCopy = cociService.checkout(actionedUponNodeRef,​ 
 + targetSpace,​ 
 + ContentModel.ASSOC_CONTAINS,​ 
 + QName.createQName(NamespaceService.CONTENT_MODEL_PREFIX,​ workingCopyName));​ 
 + 
 +
 +  
 +
 + 
 + @Override 
 + protected void addParameterDefinitions(List<​ParameterDefinition>​ paramList) { 
 + //no parameters for this action 
 +
 + 
 +    /** 
 +     * @return the targetSubFolder 
 +     */ 
 +    public String getTargetSubFolder() { 
 +        return targetSubFolder;​ 
 +    } 
 + 
 + 
 +    /** 
 +     * @return the workingCopy 
 +     */ 
 +    public NodeRef getWorkingCopy() { 
 +        return workingCopy;​ 
 +    } 
 + 
 +
 +</​code>​ 
 +The class must be copied to deploy/​Alfresco.war/​WEB-INF/​classes. 
 + 
 +=== The messages file === 
 +The messages file for an action must at least contain a title and a description for the action. 
 + 
 +''​quick-checkout-messages.properties''​ 
 +<​code>​ 
 +
 +* Quick Checkout Action I18N File 
 +
 +quick-checkout.title=Quick Checkout 
 +quick-checkout.description=This will check out matched content into a special individual work folder. 
 +</​code>​ 
 + 
 +The file has to be saved in conf/​alfresco/​extension 
 + 
 +=== Adding the action to the Spring context === 
 +To make the action class available for Alfresco it has to be added in the Spring context. While adding it to the context the QuickCheckout class can also be given references to other classes already available in the Alfresco Spring context. That is how the parameters needed be the class are set. A reference to the message properties file of the QuickCheckout action must also be given here. This is done in the bean with id ''​extension.actionResourceBundles''​ in the ''​resourceBundles''​ property. 
 + 
 +''​quick-checkout-context.xml''​ 
 +<code xml> 
 +<?xml version='​1.0'​ encoding='​UTF-8'?>​ 
 +<​!DOCTYPE beans PUBLIC '​-//​SPRING//​DTD BEAN//​EN'​ '​http://​www.springframework.org/​dtd/​spring-beans.dtd'>​ 
 +  
 +<​beans>​ 
 +    <!-- QuickCheckout Action Bean --> 
 +    <bean id="​quick-checkout"​ class="​de.hmedia.alfresco.actions.QuickCheckout"​ parent="​action-executer">​ 
 +        <​property name="​targetSubFolder">​ 
 +            <​value>​In Arbeit</​value>​ 
 +        </​property>​ 
 +        <​property name="​nodeService">​ 
 +            <ref bean="​nodeService"​ /> 
 +        </​property>​ 
 +        <​property name="​cociService">​ 
 +            <ref bean="​checkOutCheckInService"​ /> 
 +        </​property>​ 
 +        <​property name="​personService">​ 
 +            <ref bean="​personService"​ /> 
 +        </​property>​ 
 +        <​property name="​applicableTypes">​ 
 +            <​list>​ 
 +                <​value>​{http://​www.alfresco.org/​model/​content/​1.0}content</​value>​ 
 +            </​list>​ 
 +        </​property>​ 
 +    </​bean>​ 
 + 
 +    <bean id="​extension.actionResourceBundles"​ parent="​actionResourceBundles">​ 
 +        <​property name="​resourceBundles">​ 
 +            <​list>​ 
 +                <​value>​alfresco.extension.quick-checkout-messages</​value>​ 
 +            </​list>​ 
 +        </​property>​ 
 +    </​bean>​ 
 + 
 +</​beans>​ 
 +</​code>​ 
 + 
 +The file has to be saved in conf/​alfresco/​extension 
 + 
 + 
 +==== Part 2: Making the action available to the web client ====
 To make the QuickCheckout available to the web client the following steps have to be done: To make the QuickCheckout available to the web client the following steps have to be done:
   - Create a backing bean for the action.   - Create a backing bean for the action.
   - Make the backing bean managed.   - Make the backing bean managed.
 +  - Create an icon for the action.
   - Customize the web client configuration to include the action.   - Customize the web client configuration to include the action.
 For the rest of this example some Java Server Faces (JSF) knowledge is presumed. For the rest of this example some Java Server Faces (JSF) knowledge is presumed.
  
-== The backing bean == +=== The backing bean === 
-This is the code of the backing bean:+The backing bean has a ''​doQuickCheckout''​ method that will later be bound as a JSF action listener to the quick checkout button. This method will call the QuickCheckout class to actually do the quick checkout. If the checkout was successful the navigation will be set to the space where the checked out file can be found. 
 + 
 +This is the code of the backing bean ''​QuickCheckoutBean.java''​: 
 <​code>​ <​code>​
 package de.hmedia.alfresco.web.actions;​ package de.hmedia.alfresco.web.actions;​
Line 195: Line 466:
 </​code>​ </​code>​
  
 +The class must be copied to deploy/​Alfresco.war/​WEB-INF/​classes.
  
-== Making the backing bean managed ==+=== Making the backing bean managed ==
 +To make the backing bean a JSF managed bean the bean has to be listed in the faces-config-custom.xml file. This file can be found in deploy/​alfresco.war/​WEB-INF. The properties needed by the backing bean have to be set here too.
  
-== Include ​the action in the web client == +''​faces-config-custom.xml''​ 
-To make the action available to Alfresco the web-client-config-custom.xml file has to be altered. This file resides in the /conf/​alfresco/​extension/​ directory. The following lines have to be added:+<code xml> 
 +<?xml version='​1.0'​ encoding='​UTF-8'?>​ 
 +<​!DOCTYPE faces-config PUBLIC "​-//​Sun Microsystems,​ Inc.//DTD JavaServer Faces Config 1.1//​EN"​ 
 +                              "​http://​java.sun.com/​dtd/​web-facesconfig_1_1.dtd">​ 
 +<​faces-config>​ 
 + 
 +   <​!-- *************************************************************** --> 
 +   <​!-- Empty JSF config file to prevent errors being thrown during JSF --> 
 +   <​!-- initialisation. Overwrite this file with your custom version. ​  ​-->​ 
 +   <​!-- *************************************************************** --> 
 + 
 +    
 +   <​managed-bean>​ 
 +      <​description>​ 
 +         The bean that checks out a document into a given workspace. 
 +      </​description>​ 
 +      <​managed-bean-name>​QuickCheckout</​managed-bean-name>​ 
 +      <​managed-bean-class>​de.hmedia.alfresco.web.actions.QuickCheckoutBean</​managed-bean-class>​ 
 +      <​managed-bean-scope>​session</​managed-bean-scope>​ 
 +      <​managed-property>​ 
 +         <​property-name>​nodeService</​property-name>​ 
 +         <​value>#​{NodeService}</​value>​ 
 +      </​managed-property>​ 
 +      <​managed-property>​ 
 +         <​property-name>​personService</​property-name>​ 
 +         <​value>#​{PersonService}</​value>​ 
 +      </​managed-property>​ 
 +      <​managed-property>​ 
 +         <​property-name>​cociService</​property-name>​ 
 +         <​value>#​{CheckoutCheckinService}</​value>​ 
 +      </​managed-property>​ 
 +      <​managed-property>​ 
 +         <​property-name>​navigator</​property-name>​ 
 +         <​value>#​{NavigationBean}</​value>​ 
 +      </​managed-property>​ 
 +  </​managed-bean>​ 
 +    
 +</​faces-config>​ 
 +</​code>​ 
 + 
 +This file resides in the deploy/​alfresco.war/​WEB-INF directory 
 + 
 +=== The icon for the action === 
 +Action icons are available in the deploy/​alfresco.war/​images directory. A custom icon can be added there. See next section for how to attach the icon to the action. 
 + 
 +=== Including ​the action in the web client ​=== 
 +To make the action available to Alfresco the web-client-config-custom.xml file has to be altered. This file resides in the conf/​alfresco/​extension/​ directory. The following lines have to be added to ''​web-client-config-custom.xml''​:
 <code xml> <code xml>
 <​config>​ <​config>​
Line 224: Line 543:
         <!-- Actions Menu for Document Details screen -->         <!-- Actions Menu for Document Details screen -->
         <​action-group id="​doc_details_actions">​         <​action-group id="​doc_details_actions">​
-            <action idref="​quitck_checkout_doc" />+            <action idref="​quick_checkout_doc" />
         </​action-group>​         </​action-group>​
     </​actions>​     </​actions>​
Line 230: Line 549:
 </​code>​ </​code>​
  
 +This file resides in the conf/​alfresco/​extension/​ directory
 +
 +===== TODO =====
 +  * The bean classes shouldn'​t reside directly in the alfresco.war deploy dir. This can be achived by packaging the files into an Alfresco module (.amp) file.
  
 ~~DISCUSSION~~ ~~DISCUSSION~~
forum/alfresco/custom-action.1211541826.txt.gz · Last modified: 2023/11/19 22:45 (external edit)