Ever thought it would be nice to have another button in the editing or read form for one or more content items? Well if you are running portal 8.0 or later this is quite simple to do.

The process is similar to creating your own custom workflow action. You create a java class that implements AuthoringAction and implement a few methods needed and create a plugin.xml for the package that will include the code. If you look att IBMs documentation you will see some parts that aren’t well explained how to do. The part I got stuck on is how to return the neccesary result. I solved this by implementing an ActionResult class that always returns a continue AuthoringDirective. This will make sure that the CustomActionButton will always allow WCM to continue it’s operation. If this is the best practice I’m not sure.

When we have our ActionResult class we have all the components needed to create our CustomActionButton. The interface for AuthoringAction specifies some methods that need to be implemented, isValidForForm, ordinal, execute, getTitle, getDescription and getLocales. The first method I wan’t to discuss is the isValidForForm, this is called for each time the button is about to be attached to an editing form. This method could be used to determine if the button should be used on a certain content item. I had issues with iterating over the content components when I did my implementations, my experience so far tells me to only check for systemfields such as authoringtemplate and not make decisions based on elements in the content item.

public boolean isValidForForm(final FormContext formContext) {
  logger.entering(ImageRenditions.class.toString(),"isValidForForm");
  logger.exiting(ImageRenditions.class.toString(),"isValidForForm");
  return true;
}

the next important method to implement is the execute method. This will be called when the editor clicks on the button. And it’s also here we need the ActionResult implementation.

public ActionResult execute(final FormContext formContext) {

Execute need to return a valid ActionResult to tell WCM how to proceed. From the formContext we can access the document and the current content. Below in this article is a sample implementation that iterates over the components in the current content item and scales the image down to a preset size to use as a thumbnail. This button will be available on every content item in WCM so don’t deploy this in a production environment without notifying the content editors how the button works. As a better implementation you should implement image renditions and create images of different sizes depending on the destination rendition.

My example implementation for the execute method:

ContinueResult result=new ContinueResult();
Content doc=(Content)formContext.document();
logger.entering(ThumbnailButton.class.toString(),"execute");
ContentComponentIterator it=doc.componentIterator();
while(it.hasNext()) {
  ContentComponent comp=it.next();
  if(comp instanceof ImageComponent) {
    ImageComponent imgComp=(ImageComponent)comp;
    logger.fine("Item has an image component");
    try {
      byte[] imageBytes = imgComp.getImage();

      // Convert to BufferedImage to use Scalr for resizing
      BufferedImage originalImage = null;
      InputStream in = new ByteArrayInputStream(imageBytes);
      try {
        originalImage = ImageIO.read(in);
      } catch (IOException e) {
        e.printStackTrace();
      }
      in.close();

      byte[] thumbnail=null;
      thumbnail = scaleToSize(originalImage, 160, 160);
      imgComp.setImage(imgComp.getImageFileName(),thumbnail);
      doc.setComponent(comp.getName(),imgComp);
    }
    catch (AuthorizationException e) {
      e.printStackTrace();
    } catch (PropertyRetrievalException e) {
      e.printStackTrace();
    } catch(OperationFailedException e) {
      e.printStackTrace();
    } catch (ComponentNotFoundException e) {
      e.printStackTrace();
    } catch (IllegalTypeChangeException e) {
      e.printStackTrace();
    }
    catch (IOException e) {
      e.printStackTrace();
    }

  }
}
logger.exiting(ThumbnailButton.class.toString(),"execute",result);
return result;

The example implemenation can be downlaoded here. To compile this project you need to supply the wcm api jar and a portal api jar. These will be included with your portal installation or RAD environment.

Other than these two classes you also need to create a plugin.xml file that is included in the package you deploy to WebSphere Portal. My recommendation is to crate an ear file containing a war file with the custom classes and plugin.xml file. This is primarily to simplify the installation process a part of that is to get a default context root. Other than that for a more complex project that might be composed of more war files a ear file with shared jar libraries is a good practice.

If you have any questions you can reach me on twitter and I’ll try to answer questions as best as possible.