Checksum Aspect – Part 4

When I started this journey, I figured it would be easy to apply, view, verify, recalculate and remove checksums from objects in my repository directly from Webtop.  As I have previously mentioned, it turned out to not be exactly as easy as I had planned, but not impossibly hard as you will see in this post.

Before we dive into the code let me first state that Webtop is not my forte.  I am much more of a “server guy”.  I am also an engineer and not a UI expert.  Therefore, my UIs tend to be functional, but not elegant.  OK, having made those disclaimers, I hope you don’t find that what I have done too clunky and ugly.  There are probably more elegant ways to implement this capability and if you take the time to do it I would love to hear about it.

My first task was to build the menu structure that would expose the Aspect’s capabilities.  The basic menu hierarchy looks like this:

This hierarchy was defined in the /webtop/custom/config/checksum_menu_config.xml file.  Each menu item definition contains an “action” that is described in the /webtop/custom/config/checksum_actions.xml file.  For example:

checksum_menu_config.xml

<actionmenuitem
  dynamic = "singleselect"
  id = "file_generate_checksum_md5"
  name = "file_generate_checksum_md5"
  value = "MD5"
  action = "generate_checksum_md5"
  showifinvalid = "true"/>

checksum_actions.xml

<action id = "generate_checksum_md5">
  <execution>
   <component>generate_checksum_component</component>
   <container>dialogcontainer</container>
   <arguments>
    <argument name="algorithm" value="MD5"/>
   </arguments>
  </execution>
  <invocation>
   <modalpopup>
    <windowsize>medium</windowsize>
    <refreshparentwindow>onok</refreshparentwindow>
   </modalpopup>
   </invocation>
  </action>

Each action identifies the WDK component to launch, the container for the component, any arguments that are passed to the component, and how the container should behave.  The component is defined in the /webtop/custom/config/generate_checksum_component.xml file.

generate_checksum_component.xml

<scope type="dm_document">
  <component id="generate_checksum_component">
   <params>
    <param name="objectId" required="true"/>
    <param name="algorithm" required="true"/>
   </params>
   <pages>
    <start>/custom/checksum/checksum.jsp</start>
   </pages>
   <class>com.dm_misc.webtop.checksum.GenerateChecksum</class>
   <nlsbundle>com.dm_misc.webtop.checksum.GenerateChecksumNLS</nlsbundle>
  </component>
</scope>

Each component definition identifies all of the parameters for the component, the JSP page that embodies the component, and the server-side class that implements the logic for the component.  It seems like a really circuitous route from the menu definition to the JSP and server-side class, but it is what it is.

I addition to the Aspect, the XML files, and the JSP file, I had to write server-side classes that actually invoked the Aspect and updated the JSP file.  All of these class files were loaded into the /webtop/WEB-INF/classes folder.  As an example, this is what the guts of the GenerateChecksum class looks like.

public void onRender() {
	super.onRender();

	String msg = "";

	// #1 - get reference to form label controls
	Label objName = (Label) getControl(utils.LABEL_OBJECT_NAME, Label.class);
	Label objId = (Label) getControl(utils.LABEL_OBJECT_ID, Label.class);
	Label status = (Label) getControl(utils.LABEL_STATUS, Label.class);

	// #2 - get args
	String objectId = getInitArgs().get("objectId");
	String algorithm = getInitArgs().get("algorithm");

	// get object
	IDfSysObject sObj = null;

	try {
		if (session != null && objectId != null & objectId.length() > 0) {

                        // #3 - get the object
			sObj = (IDfSysObject) session.getObject(new DfId(objectId));
			if (sObj != null) {

				// #4 - set sysobj attrs
				objName.setLabel(sObj.getObjectName());
				objId.setLabel(sObj.getObjectId().toString());

				// #5 - make sure the object has content
				if (sObj.getContentSize() > 0) {

					// #6 - check for aspect
					if (! utils.isChecksumAspectAttached(sObj,utils.ASPECT)) {

						// attach aspect if it isn't already
						sObj = utils.attachChecksumAspect(session,sObj,utils.ASPECT);
					}

					// #7 - generate the checksum
					((IChecksumAspect) sObj).updateChecksum(algorithm);
					sObj.save();

					// build status msg with aspect attrs
					msg = utils.buildChecksumInfoMsg(sObj);

				} else {
					msg = "ERROR: This object does not have any content";
				}

				// #8 - set the status message on the form
				status.setLabel(msg);

			} else {
				System.out.println("Could not get object with ID: " + objectId);
			}

		} else {
			if (session == null)
				System.out.println("Could not get session.");
			else
				System.out.println("Object Id is null");
		}
	} catch (DfException e) {
		e.printStackTrace();
	}
}

Notes:

  1. Get references to the controls on the JSP page.
  2. Get the arguments passed to the component.  In our case, the object Id and the name of the checksum algorithm to use.
  3. Get the object.
  4. Set the object name and object Id labels on the JPS page.
  5. Make sure the object has content.  If not, post an error message instead of the checksum.
  6. Make sure the checksum Aspect is attached.  If it isn’t, attach it.
  7. Generate the checksum by calling the checksum Aspect updateChecksum() method.  Notice that to invoke the Aspect method, the object must be cast to the Aspect interface. Also notice that IDfSysObject.save() is called here. Once the checksum is generated, it must be saved to the object or it will not persist. Calling save() here was a deliberate design decision. I suppose the save() could have been called inside the Aspect, but to make setting the checksum as similar to the DFC as possible, I chose to issue an explicit save().
  8. Set the status label on the JSP with the checksum.

Here is the result:

Here are a couple of interesting things:

  • The techniques for invoking Aspect methods and addressing Aspect attributes that I learned while developing the test harness paid off here since many of them were reused with the server-side classes.
  • The Aspect class file and interface file had to be loaded on the app server in the /webtop/WEB-INF/classes folder also.  Though Aspects are part of the BOF and are supposed to be delivered dynamically, I continually got Java ClassDefNotFound errors until I copied the classes to the app server.  I’m not completely convinced this is always the case and it may have to do with how I wrote the server-side class files that invoke the Aspect methods.  If you know a better/different way I’d be interested to hear what you have to say.
  • The app server and the JMS must be running the same version of Java in order to correctly execute the Aspect classes.

I confess that making the checksum Aspect work in Webtop was more work than I expected, but in the end, I think it turned out OK.  You can download the complete Composer project here and install it for yourself if you like.

The next post will wrap up this series.  Keep reading!

Advertisements

About Scott
I have been implementing Documentum solutions since 1997. In 2005, I published a book about developing Documentum solutions for the Documentum Desktop Client (ISBN 0595339689). In 2010, I began this blog as a record of interesting and (hopefully) helpful bits of information related to Documentum, and as a creative outlet.

6 Responses to Checksum Aspect – Part 4

  1. Sergey Smirnov says:

    Hi Scott.

    About a error Java ClassDefNotFound its very strange becouse when any of a module’s JAR files are updated in the repository(in our case this Aspect), Documentum will automatically update the BOF object caches on all client machines to include the updated JAR files, and the DFC BOF ClassLoader will redeploy the classes loaded within a client application’s JVM without requiring an application restart. Try to find your aspect (ChecksumAspect.class, IChecksumAspect) in your cache-BOFs and if it doesn’t, trying to clear your cache and restart your app server.

    Thanks for your post!

    Like

    • Scott says:

      Thanks for the comment. I haven’t had a chance to explore this problem any further, but it has been nagging at the back of my mind. I don’t believe the Aspect classes should be deployed they way they are in Webtop and I would like to fix it. Hopefully, I will have some time in the near future to clear the caches and experiment with other configurations and deployments.

      Like

      • Jørg Krause says:

        Hi Scott,
        somehow I managed to have missed this entire post completely 😦
        Concerning the Java ClassDefNotFound, this is unfortunately the way it is, even in 6.7. As long as you don’t access BOF or Aspects class from WDK components, you’re completely fine, everything is handled as it should.

        But you definitely the the interfaces in the app server lib if you’re instantiating them from WDK. Drives me crazy as, but there is no way around this mess.

        Excellent post 🙂

        Like

  2. Pingback: Checksum Aspect – Part 0 « dm_misc: Miscellaneous Documentum Tidbits and Information

  3. Pingback: Checksum Aspect – Part 3 « dm_misc: Miscellaneous Documentum Tidbits and Information

  4. Pingback: Embedding Webtop Advanced Search in an iFrame « dm_misc: Miscellaneous Documentum Tidbits and Information

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: