5.4.2.3.1. Creating an action extension

This section shows you how to write an action in eXo Platform. When all the steps (including deployment step in next section), a "ShowNodePath" button will be displayed in Sites Explorer. A click on the button will show the node path of the current node.

  1. Create a Maven project which has the following directory structure:

    • pom.xml: The project's POM file.

    • ShowNodePathActionComponent.java: The simple action to view the node path.

    • configuration.xml: The configuration file to register your action with the org.exoplatform.webui.ext.UIExtensionManager service.

    Here is content of the pom.xml file:

    
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.acme</groupId>
        <artifactId>action-example</artifactId>
        <version>1.0</version>
        <packaging>jar</packaging>
        
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
        
        <dependencies>
            <dependency>
                <groupId>org.gatein.portal</groupId>
                <artifactId>exo.portal.webui.core</artifactId>
                <version>3.5.2.Final</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.exoplatform.commons</groupId>
                <artifactId>commons-webui-ext</artifactId>
                <version>4.0.0</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.exoplatform.ecms</groupId>
                <artifactId>ecms-core-webui-explorer</artifactId>
                <version>4.0.0</version>
            </dependency>
        </dependencies>
    </project>
  2. Create a new action and its corresponding listener by editing the ShowNodePathActionComponent class as below:

    package com.acme;
    
    
    import javax.jcr.Node;
    import org.exoplatform.ecm.webui.component.explorer.UIJCRExplorer;
    import org.exoplatform.ecm.webui.component.explorer.control.listener.UIActionBarActionListener;
    import org.exoplatform.web.application.ApplicationMessage;
    import org.exoplatform.webui.config.annotation.ComponentConfig;
    import org.exoplatform.webui.config.annotation.EventConfig;
    import org.exoplatform.webui.core.UIComponent;
    import org.exoplatform.webui.event.Event;
    @ComponentConfig(
        events = { @EventConfig(listeners = ShowNodePathActionComponent.ShowNodePathActionListener.class) })
    public class ShowNodePathActionComponent extends UIComponent {
        public static class ShowNodePathActionListener extends UIActionBarActionListener<ShowNodePathActionComponent> {
            @Override
            protected void processEvent(Event<ShowNodePathActionComponent> event) throws Exception {
                UIJCRExplorer uiJCRExplorer = event.getSource().getAncestorOfType(UIJCRExplorer.class);
                Node node = uiJCRExplorer.getCurrentNode();
                event.getRequestContext()
                .getUIApplication()
                .addMessage(new ApplicationMessage("Node path:" + node.getPath(), null, ApplicationMessage.INFO));
            }
        }
    }
  3. Register the new action with UIExtensionManager in the configuration.xml file as below:

    
    <configuration xmlns="http://www.exoplatform.org/xml/ns/kernel_1_2.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplatform.org/xml/ns/kernel_1_2.xsd http://www.exoplatform.org/xml/ns/kernel_1_2.xsd">
        <external-component-plugins>
            <target-component>org.exoplatform.webui.ext.UIExtensionManager</target-component>
            <component-plugin>
                <name>add.action</name>
                <set-method>registerUIExtensionPlugin</set-method>
                <type>org.exoplatform.webui.ext.UIExtensionPlugin</type>
                <init-params>
                    <object-param>
                        <name>ShowNodePath</name>
                        <object type="org.exoplatform.webui.ext.UIExtension">
                            <field name="type">
                                <string>org.exoplatform.ecm.dms.UIActionBar</string>
                            </field>
                            <field name="name">
                                <string>ShowNodePath</string>
                            </field>
                            <field name="component">
                                <string>com.acme.ShowNodePathActionComponent</string>
                            </field>
                        </object>
                    </object-param>
                </init-params>
            </component-plugin>
        </external-component-plugins>
    </configuration>

    Some remarks about the Java code and the configuration:

    • ShowNodePath will be used to label the action, until you configure the label in resource bundle that will be explained later.

    • ShowNodePathActionComponent is the class name of your action.

    • There is a matching rule between the action name (ShowNodePath) and the listener class name (ShowNodePathActionListener): the listener class name = the action name + ActionListener.

  4. Build your project: mvn clean install

  5. Copy the .jar file (target/action-example-1.0.jar) to the lib folder of eXo Platform.

  6. Restart the server.

Testing

  1. Log in as an administrator and go to Content Administration.

  2. Edit a view to add the action to one of tabs of the view. At this step, you will see the ShowNodePath action as below:

    Make sure there is a drive that applies the view. For example, you can choose the Admin view and the Collaboration drive.

  3. Go to Sites Explorer and select the drive, then switch to the edited view.

  4. Select any node. The "ShowNodePath" button now displays in Action bar as below:

Next, you can perform the followings for your action extension:

Customizing label and icon

Customizing labels

As you can see in the screenshots in previous section, your action displays in UI as "showNodePath" or "ShowNodePath". You can change this label to something in more friendly way, like "Show Node Path", by adding and registering your resource bundle to ResourceBundle service:

  1. Add the src/main/resources/locale/com/acme folder to your project.

  2. Add the ShowNodePath_en.xml file to this folder, with the following content:

    
    <bundle>
        <UITabForm>
            <label>
                <showNodePath>Show Node Path</showNodePath>
            </label>
        </UITabForm>
        <UIActionBar>
            <tooltip>
                <ShowNodePath>Show Node Path</ShowNodePath>
            </tooltip>
        </UIActionBar>
    </bundle>

    Note

    Notice the "showNodePath" tag (lowercase for first letter) in UITabForm. What you configure in UITabForm element will be displayed in Content Administration portlet. The other, UIActionBar, is for Sites Explorer portlet.

  3. Add the following configuration to src/main/resources/conf/portal/configuration.xml:

    
    <external-component-plugins>
        <target-component>org.exoplatform.services.resources.ResourceBundleService</target-component>
        <component-plugin>
            <name>UI Extension</name>
            <set-method>addResourceBundle</set-method>
            <type>org.exoplatform.services.resources.impl.BaseResourceBundlePlugin</type>
            <init-params>
                <values-param>
                    <name>init.resources</name>
                    <value>locale.com.acme.ShowNodePath</value>
                </values-param>
                <values-param>
                    <name>portal.resource.names</name>
                    <value>locale.com.acme.ShowNodePath</value>
                </values-param>
            </init-params>
        </component-plugin>
    </external-component-plugins>

    The locale.com.acme.ShowNodePath value expresses that your resource files should be located in the locale/com/acme/ folder and have the "ShowNodePath" prefix in name. ShowNodePath_en.xml is resource for English of which "en" is the locale code. You can add other resources for many languagues.

Now re-build your project and deploy. Restart server and test, you will see the labels change into "Show Node Path".

See more details about ResourceBundle service and locale codes.

If you want more samples of such configuration, see:

  • webapps/ecmexplorer.war!/WEB-INF/classes/locale/portlet/explorer/JCRExplorerPortlet_en.xml

  • webapps/ecmadmin.war!/WEB-INF/classes/locale/portlet/administration/ECMAdminPortlet_en.xml

Customizing icons

Edit the webapps/ecmexplorer.war!/skin/icons/24x24/DefaultStylesheet.css file (for the default Skin) and add the icon definition as below (in this case, the "ManageUnLock" icon is re-used but you could add your own picture into the webapps/ecmexplorer.war!/skin/icons/24x24/DefaultSkin directory):

.ShowNodePathIcon{
width: 24px; height: 24px;
background: url('DefaultSkin/ManageUnLock.gif') no-repeat left center; /* orientation=lt */
background: url('DefaultSkin/ManageUnLock.gif') no-repeat right center; /* orientation=rt */
}
Filtering your action
  1. Write your filter class (com/acme/MyUIFilter.java):

    package com.acme;
    
    
    import java.util.Map;
    import javax.jcr.Node;
    import org.exoplatform.webui.ext.filter.UIExtensionFilter;
    import org.exoplatform.webui.ext.filter.UIExtensionFilterType;
    public class MyUIFilter implements UIExtensionFilter {
        /*
        * This method checks if the current node is a file.
        */
        public boolean accept(Map<String, Object> context) throws Exception {
            //Retrieve the current node from the context
            Node currentNode = (Node) context.get(Node.class.getName());
            return currentNode.isNodeType("nt:file");
        }
        
        /*
        * This is the type of the filter.
        */
        public UIExtensionFilterType getType() {
            return UIExtensionFilterType.MANDATORY;
        }
        
        /*
        * This is called when the filter has failed.
        */
        public void onDeny(Map<String, Object> context) throws Exception {
            System.out.println("This node is not a file!");
        }
    }

    This filter checks if the current node is a file. Because the filter type is MANDATORY, the action will hide if the current node is a folder. (Thus, with MANDATORY you cannot test onDeny method. Change the type into OPTIONAL if you want to test the method.)

  2. Apply the filter in your action class (com/acme/ShowNodePathActionComponent.java):

    ...
    
    import java.util.List;
    import java.util.Arrays;
    import org.exoplatform.webui.ext.filter.UIExtensionFilter;
    import org.exoplatform.webui.ext.filter.UIExtensionFilters;
    import com.acme.MyUIFilter;
    ...
    public class ShowNodePathActionComponent extends UIComponent {
    ...
        /*
        * Add filters (MyUIFilter in this example)
        */
        private static final List<UIExtensionFilter> FILTERS = Arrays.asList(new UIExtensionFilter[] {new MyUIFilter()});
        
        @UIExtensionFilters
        public List<UIExtensionFilter> getFilters() {
            return FILTERS;
        }
    }

Now build, deploy and test that your action displays only for nodes of type "nt:file".

You have added a filter by Java code. Another way is by configuration, that is extremely good when the filter itself allows flexible configuration. For example, you continue to add UserACLFilter (built-in) that allows you to configure who can use the action:

  • Add the following configuration to conf/portal/configuration.xml:

    
    <external-component-plugins>
        <target-component>org.exoplatform.webui.ext.UIExtensionManager</target-component>
        ...
            <field name="extendedFilters">
                <collection type="java.util.ArrayList">
                    <value>
                        <object type="org.exoplatform.webui.ext.filter.impl.UserACLFilter">
                            <field name="permissions">
                                <collection type="java.util.ArrayList">
                                    <value>
                                        <string>manager:/platform/administrators</string>
                                    </value>
                                </collection>
                            </field>
                        </object>
                    </value>
                </collection>
            </field>
            ...
    </external-component-plugins>

Then test that the action displays only for the users who have manager:/platform/administrators membership.

Built-in filters

There are many useful built-in filters in Content. In your real project, you should see if some of them meet your business logic before writing a new one:

  • org.exoplatform.webui.ext.filter.impl.UserACLFilter: Filters all nodes that do not have any permission on the current context.

  • org.exoplatform.webui.ext.filter.impl.FileFilter: Filters all nodes that do not exist in the given MIME type list.

  • org.exoplatform.ecm.webui.component.explorer.control.filter: This package includes many filters, see in the table.

FiltersDescription
CanAddCategoryFilterFilters nodes to which it is impossible to add categories.
CanCutNodeFilterFilters nodes which cannot be cut.
CanAddNodeFilterFilters nodes to which it is impossible to add nodes.
CanDeleteNodeFilterFilters nodes that cannot be deleted.
CanRemoveNodeFilterFilters nodes that cannot be removed.
CanEnableVersionFilterFilters nodes which do not allow versioning.
CanSetPropertyFilterFilters nodes that cannot be modified.
HasMetadataTemplatesFilterFilters nodes that do not have metadata templates.
HasPublicationLifecycleFilterFilters all nodes that do not have the publication plugins.
HasRemovePermissionFilterFilters nodes that do not have the Removepermission.
IsFavouriteFilterFilters nodes that are not favorite.
IsNotFavouriteFilterFilters nodes that are favorite.
IsNotNtFileFilterFilters nodes that are of nt:file.
IsHoldsLockFilterFilters nodes which do not hold lock.
IsNotHoldsLockFilterFilters nodes which are holding lock.
IsNotRootNodeFilterFilters the root node.
IsInTrashFilterFilters nodes that are not in the trash node.
IsNotInTrashFilterFilters nodes that are in the trash node.
IsNotSameNameSiblingFilterFilters nodes that allow the same name siblings.
IsMixCommentableFilters nodes that do not allow commenting.
IsMixVotableFilters nodes that do not allow voting.
IsNotSimpleLockedFilterFilters nodes that are locked.
IsNotSymlinkFilterFilters nodes that are symlinks.
IsNotCategoryFilterFilters nodes that are of the category type.
IsNotSystemWorkspaceFilterFilters actions of the system-typed workspace.
IsNotCheckedOutFilterFilters nodes that are checked out.
IsTrashHomeNodeFilterFilters nodes that are not trash ones.
IsNotTrashHomeNodeFilterFilters a node that is the trash one.
IsNotEditingDocumentFilterFilters nodes that are being edited.
IsPasteableFilterFilters nodes where the paste action is not allowed.
IsReferenceableNodeFilterFilters nodes that do not allow adding references.
IsNotFolderFilterFilters nodes that are folders.
IsCheckedOutFilterFilters nodes that are not checked out.
IsVersionableFilterFilters nodes which do not allow versioning.
IsVersionableOrAncestorFilterFilters nodes and ancestor nodes which do not allow versioning.
IsDocumentFilterFilters nodes that are not documents.
IsEditableFilterFilters nodes that are not editable.
Copyright ©. All rights reserved. eXo Platform SAS
blog comments powered byDisqus