Confluence Docs 3.0 : UPT 2.2 - The XWork Action Class This page last changed on Jun 30, 2006 by cmiller. ### The Skeleton XWork Action Confluence uses WebWork 2 as its web framework, which in turn uses a command framework called XWork. XWork plugins allow you to add new commands to Confluence's web framework, which allows you to add pretty much anything to the Confluence web application. For the userinfo plugin, I'm going to add a form page into which users can input their contact details. I need an action class. It needs to extend ConfluenceActionSupport, a base class that contains the minimum functionality necessary for an action to play well with Confluence. The Action will also need an instance of the UserInformation object that I defined earlier. I will expose that property with a standard Java getter method, which will make it available when we write our form in the next step.
    package com.atlassian.confluence.extra.userinfo;

    import com.atlassian.confluence.core.ConfluenceActionSupport;

    public class EditUserInfoAction extends ConfluenceActionSupport
    {
        private UserInformation userInfo = new UserInformation();

        public UserInformation getUserInfo()
        {
            return userInfo;
        }
    }
### Introducing XStream and the ContentPropertyManager XStream is a library for serializing Java objects to and from XML. The ContentPropertyManager is a Confluence component that allows you to associate arbitrary properties with any Confluence content object. Every Confluence user has a Content object associated with them, their PersonalInformation. The combination of these three things is how I am going to store a user's contact details, by adding the following to the `EditUserInfoAction`.
        private static final Category log = Category.getInstance(EditUserInfoAction.class);
        private static final String USERINFO_PROPERTY_KEY = "confluence.extra.userinfo";

        private PersonalInformationManager personalInformationManager;
        private ContentPropertyManager contentPropertyManager;
        private XStream xStream;

        private void setUserInformation(String username, UserInformation userInformation)
        {
            contentPropertyManager.setTextProperty(personalInformationManager.getPersonalInformation(username),
                    USERINFO_PROPERTY_KEY, xStream.toXML(userInformation));
        }

        private UserInformation getUserInformation(String username)
        {
            String userInfoXml = contentPropertyManager.getTextProperty(personalInformationManager.getPersonalInformation(username),
                    USERINFO_PROPERTY_KEY);

            if (TextUtils.stringSet(userInfoXml))
            {
                try
                {
                    return (UserInformation) xStream.fromXML(userInfoXml);
                }
                catch (Throwable t)
                {
                    log.warn("Error unpacking user's personal information: " + username + ": " + t.getMessage(), t);
                }
            }

            return new UserInformation();
        }

        public void setPersonalInformationManager(PersonalInformationManager personalInformationManager)
        {
            this.personalInformationManager = personalInformationManager;
        }

        public void setContentPropertyManager(ContentPropertyManager contentPropertyManager)
        {
            this.contentPropertyManager = contentPropertyManager;
        }

        public void setxStream(XStream xStream)
        {
            this.xStream = xStream;
        }
In the above code, we are relying on the fact that Spring, Confluence's component manager, will autowire XWork actions (or any other plugin module). If you need a reference to any Confluence component (Like the xStream service, ContentPropertyManager or PersonalInformationManager), all you need to do is provide the appropriate setter method, and the component will be provided to the action before it is executed. From there we can write the code to write and read our contact details from the appropriate content property. ### XWork Action Methods Our XWork action class is going to handle two situations. The user is viewing the 'edit my contact information' form. The form should be pre-filled with their contact information The user is submitting changes to the form. By convention, these two cases are dealt with using the action's `doDefault` and `execute` methods, respectively. For the `doDefault` method, all I have to do is make sure that the `userInfo` property contains the user's up-to-date contact details. `getRemoteUser` is a method on `ConfluenceActionSupport` that returns the currently logged-in user.
        public String doDefault() throws Exception
        {
            userInfo = getUserInformation(getRemoteUser().getName());
            return super.doDefault();
        }
For the `execute` method, I have to write the `userInfo` property back out. For now, let's assume that XWork is magic, and that by the time `execute()` is invoked, `userInfo` has been populated with the values submitted by the user.
        public String execute() throws Exception
        {
            setUserInformation(getRemoteUser().getName(), userInfo);
            return super.execute();
        }
### Validation One thing I'm not doing here is validating the form input. This is mostly because the data I am collecting requires more effort to validate than it is worth. I don't really care too much if someone types an invalid email address, they can just go fix it themselves. If you wanted to add validation to the action, you could do so by implemeting a `validate()` method, as described in the XWork custom validation documentation.

Document generated by Confluence on Nov 05, 2009 23:34