Orienteed logo verde y blanco
Go to blog

WebSphere Commerce – Management Center: New tool

by Rúnar Sverrisson, 3/26/2020, 12:47:08 PM

We will start by giving a quick overview of what WCS Management Center is and how it works before we move on to the main subject of this article: Explain by example how a new custom tool can be added to Management Center. All code relevant to the tool can be found on GitHub.

WebSphere Management Center Overview

The IBM Management Center for WebSphere Commerce, or simply Management Center is a collection of tools that support store management, merchandising and marketing tasks for business user. It comes with several tools out-of-the-box:

  • Catalogs tool
  • Promotions tool
  • Marketing tool
  • Assets tool
  • Installments tool
  • Store Management tool
  • Catalog Filter and Pricing tool
  • Workspace Management tool
  • Commerce Composer

See details about the tools here. Certain aspects of these tools can be customized, but we will not get into that here. Before we dive into the creation of a new tool lets consider briefly how Management Center works. On the IBM Knowledge Center there are several articles discussing the technical details of the Management Center framework. We will not go deep into the weeds here, but rather give a simplified overview of how a tool works and then go through an example to create a new tool.

In essence a Management Center tool is nothing but a collection of XML files. In these XML files (or just a single XML file) we define different objects that our tool will use. There are several different object types that serve a distinct purposes. Additionally, services can be defined on the objects which can either map to a REST service or a command. The information that will be displayed in the Main Work Area of the Management Center console will be a result from a service call. The service will return with an XML response, which will be mapped to the appropriate object and subsequently displayed accordingly.

Creating a Custom Tool

We want to create a custom tool that can integrate with a Jenkins server. The tool should be able to display a list of jobs from Jenkins and execute build of jobs. The idea is to create a custom command that communicates with Jenkins. This command will be executed from Management Center and it will return the response from Jenkins in way that Management Center can understand and display in the Main Work Area of the Management Center console.

cmc_jenkinsJobs_edited.png This is how the completed tool will look like. The two main sections of the Management Center console have been marked with red letters.[/caption]

The XML files that define the Management Center tools live in the LOBTools project: LOBTools/WebContent/WEB-INF/src/xml. The standard out-of-the-box tools are located in the commerce sub folder. We will place the new custom tool in a new sub folder called orienteed/integration. For simplicity we will keep our whole tool definition in a single XML file. The definition of a tool can be split up in many different XML files, as can be seen by exploring the standard tools. When the complexity of the tool increases and more objects need to be defined, it is advisable to split the definition as the standard tools do.

Objects definitions

The fundamental building block of a Management Center tool is the BusinessObjectEditor. It supports several of the functionalities of the Management Center console. Inside of the BusinessObjectEditor element we need several things:

  • ObjectFilterType: Filters the objects that are visible in the Explorer view. We only want objects of type JenkinsTop to be visible in the Explorer, so we filter on them. If we would want other object types as well, we could add them to the filter.
  • TopObjectDefinition: The root object that defines the navigation tree in the Explorer view. The Xml element defines the structure of the tree that we want to create. We only want to have one node of the type JenkinsTop.
  • OrganizationalObjectDefinition: An object that is used by the TopObjectDefinition to create the navigation tree. Here we define the JenkinsTop object that we referenced above. On this object we define a GetChildrenService that will get the list of jobs from Jenkins. To list these objects in the Main Work Area we need to define a NavigationListDefinition that will tell Management Center how to visualize the objects. The list definition depends on objects created outside of the BusinessObjectEditor.
  • PrimaryObjectDefinition: This is the object that keeps track of the data we are working with. An instance of this object will represent a Jenkins job. We do not define the object here, but rather reference a base definition.
	<BusinessObjectEditor definitionName="cmc/orienteed/integration/IntegrationTool" explorerFilterTypes="Jenkins" 
			displayName="Integration Tool" showStorePreview="false" showStoreSelection="false" showUtilitiesView="false">
		<ObjectTypeFilter displayName="Jenkins" filterType="Jenkins" objectTypes="JenkinsTop"/>

		<TopObjectDefinition>
			<Xml name="template">
				<object objectType="JenkinsTop"/>
			</Xml>
		</TopObjectDefinition>
		
		<OrganizationalObjectDefinition displayName="Jenkins" objectType="JenkinsTop">
			<GetChildrenService url="/cmc/integration/jenkins/jobList">
				<ServiceParam name="storeId"/>
			</GetChildrenService>
			
			<NavigationListDefinition definitionName="cmc/orienteed/integration/JenkinsChildList" displayName="Jenkins Job List" 
					listDefinition="cmc/orienteed/integration/JenkinsListEditor" listTitle="Job List"/>
		</OrganizationalObjectDefinition>

		<PrimaryObjectDefinition baseDefinition="cmc/orienteed/integration/JenkinsPrimaryObjectDefinition" creatable="true"/>
	</BusinessObjectEditor>

In the last two points in the above list, we have referenced other object definitions that are defined outside of the BusinessObjectEditor:

  • PrimaryObjectDefinition: This is the base definition of the primary object that we want to define. We define the two services that we need and the parameters that we need to pass to them. The services will allow us to refresh an object and to build the corresponding Jenkins job. The RefreshService is executed when the refresh button is clicked (while the object is selected). The CustomService is executed when the custom Jenkins build button is clicked. Both of these buttons are in the toolbar of the Management Center. To display the custom Jenkins build icon, we define an Image element that points to the location of the image.
  • ChildListEditor & ObjectGrid: These two objects are used to define the list view that we create for displaying the list of Jenkins jobs in the Main Work Area. The ChildListEditor defines the type of object the list expects, meanwhile the ObjectGrid object defines the structure of the actual list (such as columns and which data to display).
 
   <PrimaryObjectDefinition definitionName="cmc/orienteed/integration/JenkinsPrimaryObjectDefinition" objectType="Jenkins"
			 idProperty="integrationId" displayNameProperty="jenkinsName"
			 propertiesDefinition="cmc/orienteed/integration/JenkinsProperties" initializeObjectStoreId="false">
		<RefreshService url="/cmc/integration/jenkins/refresh">
			<ServiceParam name="jobName" propertyName="jobName"/>
			<ServiceParam name="storeId"/>			 
		</RefreshService>
		
		<CustomService url="/cmc/integration/jenkins/build" displayName="Build job" toolbarIcon="jenkinsBuild">
			<ServiceParam name="jobName" propertyName="jobName"/>
			<ServiceParam name="storeId"/>			 		 
		</CustomService>
	</PrimaryObjectDefinition>
	
	<Image name="jenkinsBuild" src="/images/orienteed/integration/resources/jenkins_build.png"/>
		
	<ChildListEditor definitionName="cmc/orienteed/integration/JenkinsListEditor" 
			listDefinition="cmc/orienteed/integration/JenkinsGrid" objectTypes="Jenkins"/>

	<ObjectGrid definitionName="cmc/orienteed/integration/JenkinsGrid">
		<GridText editable="false" name="color" propertyName="color" text="Color" width="80"/>
		<GridText editable="false" name="jobName" propertyName="jobName" text="Job Name" width="350"/>
		<GridText editable="false" name="lastBuild" propertyName="lastBuild" text="Last Build" width="350"/>
		<GridText editable="false" name="lastDuration" propertyName="lastDuration" text="Last Duration" width="350"/>
		<GridText editable="false" name="lastResult" propertyName="lastResult" text="Last Result" width="350"/>
	</ObjectGrid>

The last object that we define for the tool is a properties object for the primary object. We have already referenced this object in the PrimaryObjectDefinition.

  • ObjectProperties: This object defines the properties object that we link to our primary object. It defines which properties the Jenkins jobs object will have.
	<ObjectProperties definitionName="cmc/orienteed/integration/JenkinsProperties">

		<PropertyPane>
			<PropertyGroup groupTitle="General Job Properties" open="true">
				<PropertyViewLongText promptText="Color" propertyName="color" required="true"/>
				<PropertyViewLongText promptText="Job Name" propertyName="jobName" required="true"/>
				<PropertyViewLongText promptText="URL" propertyName="integrationId" required="true"/>
			</PropertyGroup>

			<PropertyGroup groupTitle="Last Build Information" open="false">
				<PropertyViewLongText promptText="Last Build" propertyName="lastBuild" required="false"/>
				<PropertyViewLongText promptText="Last Duration" propertyName="lastDuration" required="false"/>
				<PropertyViewLongText promptText="Last Result" propertyName="lastResult" required="false"/>
			</PropertyGroup>
			
			<PropertyGroup groupTitle="Last Build Console Log">
				<PropertyViewLongText promptText="Last Console Log" propertyName="lastConsoleLog" required="false"/>
			</PropertyGroup>
		</PropertyPane>
			
	</ObjectProperties>

Service definitions

In order to make the tool functional we need to define the services that we have declared in the above XML definition. We have defined three services, one on the OrganizationalObjectDefinition and two on the PrimaryObjectDefinition. Respectively, those are:

  • GetChildrenService: This service gets the list of jobs from the Jenkins server by executing a custom command. It is triggered when the Jenkins node is selected in the Explorer view, or when the list is refreshed. The custom command will query the Jenkins server for a list of jobs. The response will be parsed by Management Center and it will create the corresponding primary objects.
  • RefreshService: This service is run when a Jenkins object is selected and the refresh button is clicked. It works basically in the same way as the GetChildrenService, except it only requests information about the specific job that is selected.
  • CustomService: This service is triggered by the click of a custom toolbar button. It sends a request to the Jenkins server to build the selected job. The Jenkins server does not respond with any information that Management Center needs to parse, only a status on whether or not the build request was successfully created.

Management Center uses the Spring framework to manage service calls. We have to add beans to /LOBTools/WebContent/WEB-INF/spring-extension.xml configuration file for the services we want to define. We need two beans, since the GetChildrenService and RefreshService will use the same bean.

	<bean id="/integration/jenkins/jobList"
		class="com.ibm.commerce.foundation.internal.client.lobtools.controllers.ControllerCommandController">
		<property name="commandInterface"
			value="com.orienteed.commerce.integration.commands.IntegrationJenkinsCmd" />
		<property name="defaultParameters">
			<props>
				<prop key="function">joblist</prop>
			</props>
		</property>

		<property name="contextParameters">
			<props>
				<prop key="storeId">storeId</prop>
			</props>
		</property>

		<property name="successView"
			value="/jsp/orienteed/integration/JenkinsJobList.jsp" />
	</bean>
  • Note that when declaring the services (in the tool definition), we need to reference the bean that it will invoke and the id of the bean needs to be prepended by ‘/cmc’.
  • We specify the parameters that will be passed on to the command. We can both pass static parameters that are defined the XML, or dynamic ones that are specified in the declaration of the service. We use the defaultParameters property to pass static parameters and the contextParameters from dynamic ones.
  • We specify the command that we want to execute and the post processing (if any) to be done after the command has run. For the bean that will get information from Jenkins, we need to parse the response from Jenkins to Management Center objects. We do that be defining a succsessView. This is a jsp file that will map the XML response from Jenkins to the Jenkins primary object.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://commerce.ibm.com/foundation" prefix="wcf"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix = "x" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

<c:set var="responseMap" value="${requestScope['com.ibm.commerce.responseMap']}"/>

<x:parse xml="${responseMap.jenkins}" var="parsedResponse"/>
<x:set var="jobList" select="$parsedResponse/hudson/job"/>
<objects>
	<x:forEach select="$jobList" var="job">
		<object objectType="Jenkins">
			<integrationId readonly="true"><x:out select="$job/url"/></integrationId>
			<jobName readonly="true"><x:out select="$job/name"/></jobName>
			<color readonly="true"><x:out select="$job/color"/></color>
			<lastBuild readonly="true"><x:out select="$job/lastBuild/timestamp"/> - #<x:out select="$job/lastBuild/number"/></lastBuild>
			<lastDuration readonly="true"><x:out select="$job/lastBuild/duration"/></lastDuration>
			<lastResult readonly="true"><x:out select="$job/lastBuild/result"/></lastResult>
		</object>
	</x:forEach>
</objects>

The last piece that is missing before our new custom tool is fully functional, is to implement the custom command that the beans will use. We will just create a single command for both of the beans to use and distinguish functionality by passing different parameters to the command. We will not go into details here on how to create a custom command in WebSphere Commerce, but we note that all code related to this tool can be found on GitHub.

Conclusion

We have gone through the process of adding a brand new custom tool to Management Center and explained what is needed to get it up and running. We will conclude this article with a few tips and tricks that may help with developing customizations to Management Center:

  • Run the test server in debug mode, so certain code changes can be hot swapped without a restart
  • Changes to XML configuration files can be realized by closing Management Center and re-opening it after clearing caches in the browser. It is not needed to re-publish.
  • Start simple! Get a simple tool (as the one implemented here) to work and try to understand the structure of the tool. Then move onto adding complexity to the tool. The fully fledged standard tools are very complex and it is hard to get an overview of how they work, since the definition of each tool is split up into many different XML files.
  • When opening Management Center, append &logger.display=true to the URL to add a logging tool to Management Center. Open the logging tool and turn on the needed logs. For server side logging consider adding com.ibm.commerce.lobtools.*=all: com.ibm.commerce.foundation.*=all to the trace. Keep in mind that this may slow Management Center down considerably.
  • It can be useful to edit restricted XML files while debugging an issue in development. Just remember to revert any changes to restricted XML files. For example, in commerce/shell/foundation/restricted/Service.xml, we found it useful to edit the handleResponse function and add extra logging to see exactly what XML it was receiving.
  • Last but not least, dig into the IBM Knowledge Center and get a fundamental understanding of the architecture of the Management Center and how a tool is structured.

Useful links

GitHub: https://github.com/orienteed/wcs-to-jenkins

Description of out-of-the-box tools: https://www.ibm.com/support/knowledgecenter/en/SSZLC2_8.0.0/com.ibm.commerce.management-center.doc/concepts/ctfcmc.htm)

Management Center framework:

https://www.ibm.com/support/knowledgecenter/SSZLC2_9.0.0/com.ibm.commerce.management-center_customization.doc/concepts/ctf_managementcenter_framework_overview.htm

 

Related posts

Join our mailing list

Want to know more about e-commerce trends, industry articles and events? Subscribe now to our monthly newsletter!

We use cookies to improve your experience and our services by analyzing your navigation on our website. If you continue to browse, we consider that you accept its use. You can learn more by clicking here:
Cookies Policy
Logotipo de Orienteed

Cookies Policy

A cookie is a small text file that is downloaded to your computer when you access certain web pages. Cookies allow web pages, among other things, to store and retrieve information about the device or browsing habits of a user. Depending on the information retrieved, cookies can be used to recognize the user.
Technical Cookies are essential to provide the service offered and requested by a user, to remember configuration preferences, as well as for security and fraud prevention purposes. The website cannot function properly without these cookies.
Analytical cookies help us analyze the activity of users and the number of visitors on the website. They allow the collection of information on the number of visitors, their origin, the browser used, the duration spent on each page, the impact of ads, etc. These cookies are used exclusively for statistical purposes and do not allow identification of particular individuals.

How to deny or revoke cookie consent

Cookies can be blocked or deleted through the browser settings. The following links detail how to do it in each of the most used browsers.