• ALL
  • CATEGORIES

Fix your aversion to WebCenter Sites versioning

WebCenter Sites versioning

Software systems these days can be hugely complex and contain many moving parts. In a regulated testing environment, it’s vital for QA Engineers to record everything about the constraints they’re working with when running through their testing. Lots of variables affect the behaviour of the system, from the physical architecture to the overrides applied in property files, and it all needs to be recorded when a defect is raised. In this post I’d like to introduce you to a reasonably simple, non-intrusive way to make the version of your WebCenter Sites Java code available to contributors at the click of a mouse, to enable that information to be recorded against a defect.

Versioning considerations

Packaging strategy

For a long time, when we’ve built software systems for clients that use Oracle WebCenter Sites, we have been applying versioning to the JAR files that contain artifacts that support the code base. We’ve also taken steps to work with our clients so that they are aware of this versioning.

We follow the industry best practice format of

project-X.Y[-Z].jar

where X is the major version, Y is the minor version and Z is an optional release candidate (RC) or SNAPSHOT number.

Promoting through environments

We like working with organisations that apply a rigorous release schedule. This should encompass promoting releases through environments, and recording and making that information freely available, in a structured fashion, in some form of collaboration platform. When we push a release into a WCS instance, we want to make sure that the relevant details are recorded so that when testing is applied and defects recorded, we know exactly which release to attribute these defects to.

Promoting into QA instances

When we consider how releases are deployed to QA, we realise that deployments are always more frequent than those from environment to environment. It entirely depends on your QA strategy within your organisation but it’s not uncommon to make two, three or maybe more, releases per week into an environment. As these releases are made, it can be time consuming for a QA Engineer to determine which version of a code drop they are looking at.

Adding that version

To try and remove some of this confusion, I’m going to describe a way to version JAR files with identifiable attributes, including build dates. Then we’ll examine a way in which you can easily display this information to contributors during the content entry phase of testing.

The first stage of this recipe involves modifying your pom.xml file in your project to add properties to your JAR. In my case, I wanted to add some information that identifies my organisation and also to note the time when the JAR was built. This timestamp is important because I wanted it to tie in with a time that could be readily associated with a Jenkins build number.

So, the first change we make is to add two new properties to our POM:

<properties>
 <maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
 <project.timestamp>${maven.build.timestamp}</project.timestamp>
 ...
</properties>

Next,we need to introduce the Maven Jar Plugin to our POM so that we can roll information into the MANIFEST.MF of our JAR:

<build>
 <!-- ... stuff ... -->

 <plugins>
  <!-- ... additional stuff ... -->

  <plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-jar-plugin</artifactId>
   <configuration>
    <archive>
     <manifestEntries>
      <Project-Author>Manifesto Digital Ltd.</Project-Author>
      <Project-Name>${project.name}</Project-Name>
      <Project-Version>${project.version}</Project-Version>
      <Project-Build-Timestamp>${project.timestamp}</Project-Build-Timestamp>
     </manifestEntries>
    </archive>
   </configuration>
  </plugin>
  <!-- ... more stuff ... -->

 </plugins>
 <!-- ... even more stuff ... -->

</build>

Notice that the timestamp is added as part of a set of Project directives to be rolled into the MANIFEST.MF

Now, when this JAR file is deployed, it will contain information that marks it as a JAR file that we’re interested in and will also have the build timestamp in it.

Manifest-Version: 1.0
Project-Name: my-java-files
Built-By: ian
Project-Author: Manifesto Digital Ltd.
Project-Version: 11.0-RC1
Project-Build-Timestamp: 2017-04-13 10:52
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_111

The visual cue

What use is this information if we cannot display it to the user ? There are a myriad of ways we can do this, but in this article I’m going to show you how to use a CustomElement to apply an alteration to the appearance of the Contribution UI.

CustomElements were introduced by the then Fatwire engineering team as a way to allow customization of ANY element within the system without directly altering the base code. It works like this; if you have an element, say Aaa/Bbb/Ccc and you want to customise that element, then you can create your own element called CustomElements/Aaa/Bbb/Ccc, and it will always be used in preference to the former element.

If you want to extend the functionality of the original element, then all you need do is duplicate the code from the original element and copy it into the CustomElement variant and then extend that.

After Oracle acquired Fatwire, the editorial and admin interfaces were changed to make use of the DoJo JavaScript framework. They also extended the idea behind CustomElements to give certain functional areas of the UI an ability to show Site-specific as well as Global variations. Briefly, this means that any element found in the UI package can have a Global or Site-specific variant of certain display elements depending on the way the element name is prefixed. This naming convention builds on that for CustomElements and works as follows for a site specific configuration:

CustomElements/[SITENAME]/UI/Config/SiteConfigHtml

and

CustomElements/UI/Config/GlobalHtml

for your version of a Global configuration item.

We are going to use the GlobalHtml element in this example, and we start by duplicating the system element into CustomElements/UI/Config/GlobalHtml and then extending it by adding some new lines and also referencing a new class that we’ve created to do the work of sifting through the Manifests;

/* add this to the start of the imports section */
<%@ page import="uk.co.manifesto.release.Release"%>

/* add this near the top of the code - It's the Release management code */
<%
Release release = new Release();
String relInfo = release.getReleaseInfo();
%>

/* now, add this at the very end of the config.menubar declaration */
 ,
 {
   "id": "about",
   "label": "About",
   "children": [
     {
       label: "Version",
       action: function () {
         alert ('<%=relInfo %>');
       }
     }
   ]
  }

This gives us an entirely new menu item (About) with a menu item (Version) that will display a dialog box showing the version information from our JAR.

release_dialog

A helping hand

And here is the helper class that builds that string with the information to show to the user. The format of the String is open to debate, but you should be able to see the general idea

package uk.co.manifesto.release;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Release {
  private static final String MANIFESTO_DIGITAL_LIMITED = "Manifesto Digital Ltd.";
  private static final String PROJECT_VERSION = "Project Version";
  private static final String PROJECT_BUILD_TIMESTAMP = "Project-Build-Timestamp";
  private static final Logger LOGGER = LoggerFactory.getLogger(Release.class);

  public String getReleaseInfo() {
     String resp = null;

     Enumeration<URL> resources;
     try {
       resources = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
       while (resp == null && resources.hasMoreElements()) {
         URL url = resources.nextElement();
         InputStream stream = url.openStream();

         Manifest manifest = new Manifest(stream);
         resp = createVersionString(manifest);
         stream.close();
       }
     } catch (IOException e) {
       LOGGER.error("Caught {} error while reading 'META-INF/MANIFEST.MF'file.", e.getMessage(), e);
     }
     return resp;
  }

  private String createVersionString(Manifest manifest) {
    Attributes attrs = manifest.getMainAttributes();
    String author = attrs.getValue("Project-Author");

    if (MANIFESTO_DIGITAL_LIMITED.equals(author)) {
      return buildVersionString(attrs.getValue("Project-Name"), attrs.getValue(PROJECT_VERSION),
             attrs.getValue(PROJECT_BUILD_TIMESTAMP));
    }
    return null;
  }

  private String buildVersionString(String projectName, String projectVersion, String projectBuildTimeStamp) {
    StringBuilder sb = new StringBuilder();
    if (projectName != null) {
      sb.append(projectName);
    } else {
      sb.append("Unnamed project");
    }
    sb.append(" (");

    if (projectVersion != null) {
      sb.append("Version: " + projectVersion);
    } else {
      sb.append("Unknown version");
    }

    if (projectBuildTimeStamp != null) {
      sb.append(" Build: " + projectBuildTimeStamp);
    } else {
      sb.append(" Unknown build date/time");
    }

    sb.append(")");
    return sb.toString();
   }
}

Extensions

Once we had that mechanism working, we had a platform upon which we could build that would give us information about the current version of the contribution environment.

The eagle-eyed among you will have already noted that the Java code is not particularly discriminatory about the Manifest aside from looking for ‘Manifesto Digital Ltd.’ productions. We’re not big fans of co-located sites, but it’s entirely possible your instance has them. If those sites use their own JARs to provide support code then, as it stands, you would see all of those JAR files being shown in the contribution interface for whichever site your were currently working in. To solve that problem you might consider adding a new Manifest attribute that specifically nominates a WCS site, and then use that as an argument to the createVersionString() method in the Release class.

We next considered how this might work out in Delivery. We wondered whether we could add this information to un-cached page wrappers and the like, in HTML comments, if we weren’t operating a Production environment, but I’ll let you work that one out!

For bonus points, it might be worth trying to figure out how you can add this version information to the CAS login JSP …

It’s a Wrap

I hope this piece has shown you how you can use defined extension points in WCS to add useful information to the environment. The suggestions made in this post are very raw at the moment, but with some refinement, and a certain amount of convention applied to the way artefacts are named, you can easily add a reasonable audit mechanism to your WCS instances that gives you pertinent information at the click of a mouse.

Finally, if you yearn to lose that aversion to versioning then please do get in contact with us to find out more about how we use this approach, as well as the many other ways we can help blend your build and testing processes into a smooth operation.

 

Leave a reply

You can use these tags:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Sign up for the Manifesto newsletter and exclusive event invites