written by Bernfried Howe, 12. December 2012:
One of my favorite topics is to establish a standard structure in OT WSM Delivery Server (aka WSM DS) for modules. But what is a “module”? From a business point of view it is an piece of functionality which solves a certain requirement e.g. a basket for a shopping area or the “my profile” functionality of an intranet. From a technical point of view it is a set of actions and views, which are encapsulated by an central piece of logic.
With the knowledge of this article you should be able to create Delivery Server modules in a structured way using OT WSM Management Server (aka WSM MS) to maintain and WSM DS to execute them. You will understand the interaction of XML controllers, XML actions, and XSL(T) templates.
You need a WSM DS instance and a sample project which has activated the project option “Content and group names are only unique within the respective parent group”.
In this article we will create a little profile management module which allows the end user to store personal data to the WSM DS user profile (first name, last name, email). This module provides a create/update and delete action for the profile data.
The module architecture I will use is based on the MVC model and therefore consists of an controller, actions and views. I don’t use the Web Components feature of the WSM DS, but a similiar structure of content und content groups, which are created manually.
Naming conventions are very important to make the solution more structured and readable. Therefore I always used following conventions:
First we need to know all actions of our module and if they produce xml for a view.
The xml of the controller stored as “modProfileController.xml” in content group “xml-actions” will look like this:
<modProfileController> <rde-dm:attribute mode="condition"> <rde-dm:constraint>request:action eq "write"</rde-dm:constraint> <rde-dm:include content="xml-actions/modProfileActionWrite.xml" process-mode="execute"/> </rde-dm:attribute> <rde-dm:attribute mode="condition"> <rde-dm:constraint>request:action eq "delete"</rde-dm:constraint> <rde-dm:include content="xml-actions/modProfileActionWrite.xml" process-mode="execute"/> </rde-dm:attribute> <rde-dm:attribute mode="condition"> <rde-dm:constraint>request:xsl ne "no"</rde-dm:constraint> <rde-dm:if> <rde-dm:include content="xml-actions/modProfileActionShow.xml" stylesheet="xsl/modProfileActionShow.xsl"/> </rde-dm:if> <rde-dm:else> <rde-dm:include content="xml-actions/modProfileActionShow.xml"/> </rde-dm:else> </rde-dm:attribute> </modProfileController>
Based on the Attribute DynaMent the request variable “action” will be checked and the related action xml is loaded. Every action which does not provide any result xml will be called with process-mode=”execute”. The action “show” will provide the view to represent the current state of the user profile. Therefore an xsl stylesheet is assigned to the “show” action which makes it to a so called PSX module. This kind of modules get their own caching behavior (typically Caching Time = 0, in order to get refreshed every time). The constraint “request:xsl ne ‘no'” is needed if you still want to be able to call the module without xsl(t) rendering. Just add a “?xsl=no to the url and the controller will return not rendered xml.
As defined we need 3 actions for this module:
<modProfileActionDelete> <rde-dm:attribute mode="delete" op="delete" attribute="user:profile"/> </modProfileActionDelete>
<modProfileActionWrite> <rde-dm:attribute mode="write" attribute="user:profile.firstname" op="set" value="[#request:firstname#]"/> <rde-dm:attribute mode="write" attribute="user:profile.lastname" op="set" value="[#request:lastname#]"/> <rde-dm:attribute mode="write" attribute="user:profile.email" op="set" value="[#request:email#]"/> </modProfileActionWrite>
<modProfileActionShow> <rde-dm:include content="xml-textresources/modProfileTextResources.xml"/> <profile-values> <rde-dm:attribute mode="read" attribute="user:profile.firstname" tag="firstname"/> <rde-dm:attribute mode="read" attribute="user:profile.lastname" tag="lastname"/> <rde-dm:attribute mode="read" attribute="user:profile.email" tag="email"/> </profile-values> </modProfileActionShow>
For the profile module we just need one view (xsl content) for the “show” action:
<xsl:stylesheet> <xsl:template match="modProfileActionShow"> <form action="/cps/rde/SID-289FC1EB-BCA11365/owug_2015/hs.xsl/{$rdeXmlID}" method="post"> <input type="hidden" name="action" value="write"/> <p><xsl:value-of select="modProfileTextResources/labelFirstName"/>: <input name="firstname" value="{profile-values/firstname}"/></p> <p><xsl:value-of select="modProfileTextResources/labelLastName"/>: <input name="lastname" value="{profile-values/lastname}"/></p> <p><xsl:value-of select="modProfileTextResources/labelEmail"/>: <input name="email" value="{profile-values/email}"/></p> <input type="submit" name="submit" value="Submit"/> <p>Please delete all my profile data: <a href="/cps/rde/SID-289FC1EB-BCA11365/owug_2015/hs.xsl/{$rdeXmlID}?action=delete"><xsl:value-of select="modProfileTextResources/buttonDelete"/></a> </p> </xsl:template> </xsl:stylesheet>
The text ressources can be accessed as they have been included into the “show” action. The action parameter of the form uses the /cps/rde/SID-289FC1EB-BCA11365/owug_2015/hs.xsl/{$rdeXmlID} Placeholder which automatically creates a full WSM DS url for the parent page. Currently the result url of the placeholder has an /- at the end of the request uri, which should not be the case. I will check that later.
This xml file is needed in order to separate all localized text resources from the view.
<modProfileTextResources> <labelFirstName>First name</labelFirstName> <labelLastName>Last name</labelLastName> <labelEmail>Email</labelEmail> <buttonDelete>Delete</buttonDelete> </modProfileTextResources>
The text resources are typically maintained in WSM MS in order to use the translation capabilities. Later on the modProfileTextResources.xml is published in all requiredlanguages to the WSM DS. We have now a complete WSM DS Module which can be included in any HTML page using the following Statement:
<rde-dm:include content="xml-actions/modProfileController.xml"/>
If the request parameter “action” is not set, the “show” action is executed and the current state of the profile is presented. If the “delete” or “write” action is called, the corresponding DynaMents are called and finally the “show” action presents the manipulated profile data.
All xml and xsl content can also be created as WSM MS Content Classes in order to
It’s up do you if you accept some kind of redundancy to get the described advantages.
This is my first blog article and I would be glad to get feedback.
Source: Module Development with Delivery Server
© copyright 2012 by Bernfried Howe