Alien Skies II – JavaScript Yet Another Computer Language?


I tried to look into Web UI Development, especially in the context of RTC Extensions like dashboards and the like several times in the past. I couldn’t get it to fly. It was a total disaster so far. I couldn’t understand how all that works and what the fuzz was all about. The more I looked into it, the more confused I was.

Surprisingly, looking into Doors Next Extensions seems to have revealed the missing link(s) I needed to better understand the whole topic around JavaScript. I have talked to other people who had similar issues with JavaScript, so I hope it is worth sharing my thoughts here.

I am well aware that the topic and my approach to it could be very controversial. If you like to disagree with any of my assessment, please feel free to do so in the comments. I rarely dismiss comments, but please be aware that the comments in this blog are moderated xD.

I have a book about JavaScript, but I rarely see JavaScript like it is described in that book. So, how does this JavaScript stuff work?

Its Not The Language

As far as I can tell, the language itself does not really matter that much. The language syntax of JavaScript is very similar to other languages e.g. such as Java. The Language has inheritance mechanisms, the language can support event based, asynchronously processed and functional aspects. All in all, a collection of properties that are shared across several language families.

There are some issues with the language (at least from my, still uneducated, point of view). It is not type safe to get started. While this is very flexible it is also asking for trouble in my experience. JavaScript is very dynamic and does not get compiled. A lot of issues will be seen at run time and not during coding.

Anyway, to have a common language with a common syntax and semantic is probably useful if you have to switch the domains often. At least you don’t have to learn a new language over and over.

Its Not The Development Environment

I am missing a good library handling and context sensitive editor support. There might be some cool development environment out there, but it has eluded me so far. Any suggestions are welcome, as always.

I have seen the first computers making their appearance in schools. With enormous keyboards with two lines of 40 characters to display. Nothing one would associate with a computer today. I was lucky enough to be able to write my first own programs on Commodore PET, VIC-20, 64 and on the first IBM PC’s. Ignore the first program on a Texas Instruments calculator with 32 programmable steps. I have developed without debugger, because there were no debuggers available or not affordable e.g. you could buy in circuit debuggers for  embedded systems but that was sometimes unaffordable even for companies back then.

I have seen bad development environments and debugging by printf. It is not that bad with JavaScript, in browser based applications. It basically depends on what the use case is, if there is a good debugging environment available or not.

Feeding The Confusion

I am usually pretty good in spotting patterns. Looking into the JavaScript domain, I had a hard time finding the basic ones. A lot of the confusion I felt is also, in hind sight, probably related to the fact that there is not just one JavaScript. There are multiple. And they are used in different ways and using different patterns. In addition to that the expression JavaScript is often used in contexts, where it would probably be better to talk about Web or JavaScript libraries or frameworks instead.

  1. There is the JavaScript that runs in browsers. This JavaScript usually works together with CSS and HTML. It is used to create dynamic content and presentations in the Web to be able to provide more or less usable UI’s in a browser, designed to show more or less static HTML documents. The JavaScript engine is built into and shipped with the browser and there are different engines and development environments for different browsers. This type of JavaScript basically requires to understand how JavaScript, HTML and CSS work in combination and how to control their interaction.
  2. Browser based JavaScript is integrated in several different frameworks and tool kits such as Ajax/Dojo and others.
  3. There is NodeJS, which claims to be Java Script and actually is sever side JavaScript processing and a ton of libraries and frameworks that are available for it. The only common part I can identify here is the language that is used. I did not look into the details however, so maybe there is more e.g. the run time used could be one of the common ones.

So when I started to look at the Doors Next Extensions which said JavaScript, I realized quickly, that there were constructs in the examples that I had never seen before in any JavaScript example. The normal pattern again, every time I looked at something with JavaScript inside and thought I had some basic knowledge already, I saw something different. This time however I was able to figure out what I was missing and this seems to help with all the other cases as well.

The Doors Next Extension Mechanism

The Doors Next Extension mechanism is based on JavaScript, HTML and CSS. The API supports TypeScript which provides with a more type safe and compile like way of developing JavaScript. The Doors Next API itself comes with a Typescript interface definition. Some of the examples that are provided use jQuery a JavaScript based library and framework. The latter means that the extensions look a bit uncommon.

Uncommon Common

To some extend this seems to be fairly typical for my experience with JavaScript. Almost every solution I have seen has some common part that can be found in other solutions. But looking across all the examples there is only a tiny common core, which often is basic JavaScript functions. If the JavaScript based solution deals with UI’s, there is usually the common CSS and HTML, if it does not focus on UI’s this is missing. Since there are so many frameworks and libraries, Java Script based solutions can look very different and it is important to understand the detailed frameworks and resources that are used in the specific example.

Summary

Granted, it took a while for me to come to terms with JavaScript,  but looking into the Doors Next Generation Extension Mechanism provided me with some important insight. This will help me to understand these technologies in other contexts as well. I am looking forward to playing with Doors Next Extensions and add the results to this blog.

Posted in CLM, Doors Next Generation, extending, Jazz | Tagged | 1 Comment

Alien Skies – Peeking Into Doors Next Extensibility


I started a recon mission into the alien territory of Doors Next extensions recently and almost lost my way.

Doors Next is one of the products I am responsible for. I have some experience with requirement management and I understand Doors Next usually good enough to find my way, but I am way more familiar with RTC, especially since I did a lot with its Java API and extensions. So I thought if this is similar to the situation with RTC, capabilities to extend Doors Next will be in high demand soon and I better get my hands dirty and into it. Since the language available to extend Doors Next is JavaScript, this looked also like a good opportunity to have some more exposure to JavaScript.

First Steps – Look into the documentation

So I browsed through the documentation a bit to learn what there is to learn! Other than me, please start with reading the most recent version of the documentation. This will save you detours like looking at WAS Liberty Profile and publishing data. I followed the guidance and played around with the simple examples and the more complex ones provided. I became adventurous and wanted to modify the Hello World open social gadget example and create one that should be published in the widget catalog along with the other examples. The example worked as open social gadget already and I thought, I could use it as widget as well.

That did not work so good. Why? If I used the same xml code the open social gadget showed and the Dashboard widget showed a blank content.

The Widget

This is how the basic widget looks like. All the rest such as CSS, JavaScript and the like can be added to it based on this structure.

DashboardWidget

The Open Social Gadget

This is how the open social gadget looks like. I tried to spot what the difference was for a long time. Until I finally noticed that the difference between a working gadget and a working widget is the <html></html> tag that the open social gadget has and which is missing in the widget..

OpenSocialGadget

It took me quite some time to figure out what the problem was. Embarrassing, but on the other hand it shows again, that tool extensions, even the smallest, are complex business. Maybe there are better ways to debug these kinds of issues. Compared to RTC Java Extensions I felt like back in time, trying to debug C and Assembler with printf…..

See this site for some additional introduction into open social gadgets.

Deployment Structure

Similar to my description in Publishing XML and Other Data With the WAS Liberty Profile  the extensions where deployed in the apps folder like this:

WidgetDeployment

Compared to RTC Extensions, this is a relatively simple and accessible structure. As mentioned by Guido, in an enterprise context, it would make sense to have your own web server to publish the extensions. This would allow to have a more fine grained control about who can change what.

It would be possible to use a RTC Build workspace to publish these extensions. I think there is a need to come up with some naming pattern for the extensions, in order to avoid chaos and confusion over time.

This has been challenging in the past and I assume it will stay challenging. The structure above has a css folder, as well as a JavaScript folder just in case. There is also a need for some more documentation and the like.

Summary

Doors next has means to extend its capabilities. Provided some fundamental knowledge, this should allow for a lot of the automation needed in enterprise environment. My first steps into this alien territory where a bit shaky, but all in all, I think I now have the basic understanding where and how to get started with more complex extensions.

Posted in Doors Next Generation, extending, Jazz | Tagged , , | 2 Comments

Publishing XML and Other Data With the WAS Liberty Profile


Since CLM now ships the WebSphere Application Server Liberty Profile as default, you might want to be able to publish XML and other data similar to the easy way that was available in Tomcat, by just using the application server that is available. This avoids having to set up an additional Web or application server.

Problem

Sometimes it is necessary to provide access to some files using the HTTP/HTTPS protocol.

This is interesting for the Process Enactment Workshop, or if you want to publish your own XML data to be used with HTTP Filtered Value Sets, host custom Doors Next Extensions, or if you want to publish Build results.

It is convenient if there is already an application server available to host these files there and make them accessible, instead of having to set up a web server. This especially holds if it is necessary to provide the data using HTTPS, and not HTTP, because browsers these days reject to process content that is mixed from HTTP and HTTPS sources. The latter is important for Doors Next Generation extensions. Not having to set up a new server also avoids having to create a trusted certificate for it. It reduces the additional failure point, backup and maintenance and provides URI stability as well, since you don’t want to change the URI for the CLM applications hosted anyway.

Tomcat

With Tomcat, it was relatively easy to do that, by just adding a folder under \tomcat\webapps and placing your files there. Assuming the folder name is myfiles, Tomcat then provides the files with the public URI root https://serverpath:port/myfiles/fileName.

Another way was to simply drop the file into the tomcat/webapps/ROOT/ or a sub folder, which has the same effect.

Is there a similar way to achieve this with the WAS Liberty Profile shipped with CLM?

Example Scenario

Lets assume, like in the scenario explained in Publish and Host XML Data Using Tomcat – The Easy Way, we want to publish a file makers.xml to be accessible with a context root PEWEnactmentData on the server with the public URI root https://clm.example.com:9443/.

The expected outcome is to be able to access the XML file content using the URL https://clm.example.com:9443/PEWEnactmentData/makers.xml.

Solutions

There are two relative simple solutions for WAS Liberty. The solutions below are based on information from Lars, one of our WebSphere experts and the IBM WebSphere Application Server Liberty Profile Guide for Developers.

For WAS Liberty Profile, all solutions require to deploy an application. There are several ways to create and deploy an application in WAS Liberty Profile.

  1. Deploy an application in some folder and declare the context root and location of the application in the server.xml or specific location XML file
  2. Deploy an application in the dropins folder; for this to work, it is necessary to make sure the application server has the dropins monitoring enabled for this to work

Deploying an application in this context means

  1. Create a folder with some contend in a location (or copy the folder into the location)
  2. Deploy a compressed folder with some content

Please note: Any changes to any of the server configuration XML files are automatically picked up be WAS Liberty Profile. There is no need to reboot the server for the steps below to work.

1. Deploying an Application – Standard

The trick in this solution, is to pretend to deploy an uncompressed Web Application such as a WAR file. It is obviously possible to create a real WAR file or the structure that is contained in it, but that is not really necessary. See the last section here if you are interested in deploying the application as compressed WAR file.

1.1 Deploying the Application

The only thing necessary to trick the WAS Liberty Profile into making the data available with a correct context root is to create a folder with the context root as name and an extension .war, and to make the application location known in an XML file.

In the default setup of WAS Liberty Profile with CLM, after the first launch, all installed CLM applications end up in the folder <Install Folder>\server\liberty\servers\clm\apps. The screen shot below shows this structure.

FolderStructure

The applications are deployed as compressed WAR file and have been extracted to a folder with the name of the application. As an example the CCM application (RTC) came shipped as ccm.war.zip and was extracted to a folder ccm.war. The context root of the CCM application is ccm, which is basically the name without the extension war. The same pattern holds for all the other applications.

It is possible to create a folder to host the files to be published. The folder should be named <context root>.war to result in an application with the desired context root.

Files within this folder will be available with their file name.

A file in that folder with the name <filename> will be accessible as <public URI root>/<context root>/<filename>.

If the files are within sub folders, the folder path within the root folder and the file name compose the file name part of the URL. For example, the root folder has a sub folder names myfiles and a file test.xml in it, the file is accessible as <public URI root>/<context root>/myfiles/test.xml.

In our example with the given public URI root being https://clm.example.com:9443/, the folder name <context root> being PEWEnactmentData and <filename> being makers.xml the URL would be https://clm.example.com:9443/PEWEnactmentData/makers.xml.

1.1 Declaring the Application Location

The WAS Liberty Profile needs to know which application has to be published and where to find its resources. WAS Liberty Profile defines an XML element to declare which application is located where. The element is <appliction…./>. It supports various attributes and can come in many different forms. The most important attributes are

  • id: Must be unique and is used internally by the serve
  • location: The path to the application resource
  • context-root: The context root of the application
  • name: The name of the application
  • type: Specifies the type of application (war or ear)

The location and ID is required and either the name equal to the context root, or the context-root can be provided. The type can be omitted. I did not provide the ID and it worked for me, but since the server requires it, it should be provided. Use the same value as the name or context root for the ID.

It is necessary to add the application declaration to the server configuration for example by adding it to the server.xml file. In a CLM deployment a file appliction.xml is included in the server.xml, declaring all the applications and it makes sense to use that file instead.

Save the xml files after any change to activate the new setting. The server will pick up the change.

2. Deploying an Application – dropins

The WAS Liberty Profile has the capability to monitor a special dropins folder on a regular basis. If new content is detected, it is automatically made available by the server. The automatic monitoring needs to be enabled for this to work. A standard CLM deployment disables the monitoring to reduce server load.

2.1 Deploying the Application – dropins

In a default CLM install the dropins folder is located here:

<Install Folder>\server\liberty\servers\clm\dropins

Create a folder named <context root>.war in the dropins folder and add the files to publish. After detecting the addition, the files will be accessible like explained in 1.1.

The folder <Install Folder>\server\liberty\servers\clm\dropins should now look like below.

Published application with file

2.1 Enable Automatic Monitoring for Dropins

The automatic monitoring of the dropins folder is disabled for a standard CLM setup with WAS Liberty Profile. This saves processor cycles and I/O for the server operation. It has to be enabled once in the server.xml file for this solution to work. Find the XML element <applictionMonitor> and change the attribute dropinsEnabled from “false” to “true” and save the file. The image below shows the changed configuration file.

Enable Dropins Monitoring

The attribute pollingRate determines how often the server checks the location for changes. Adjust the value to your needs.

Save the server.xml file after any change to activate the new setting. The server will pick up the change.

The XML file content should now be accessible.

Example 1 – Standard

In the example we want to publish a document with the URI https://clm.example.com:9443/<context root>/makers.xml, where <context root>=PEWEnactmentData. The public URI root is already given by the server set up.

1.1 Create the “Application”

As first step create the application. Create a new folder named PEWEnactmentData.war in the folder <Install Folder>\server\liberty\servers\clm\apps. The folder could be created anywhere, but it makes sense to put it where the other applications are. If it is necessary to use a different folder, for example to allow other users to modify the content, place the folder in a different location and note the path. The path to the location will become important in the next step.

Put the files to be published underneath this folder. In the given example, put the file makers.xml into the folder.

The folder structure should look like the image below:

New Application folder

1.2 Publish the “Application”

The WAS Liberty Profile needs to know which application has to be published and where to find its resources. WAS Liberty Profile defines an XML element to declare which application is located where. The element is <appliction…./>. It supports various attributes and can come in many different forms. The most important attributes are

  • id: Must be unique and is used internally by the serve
  • location: The path to the application resource
  • context-root: The context root of the application
  • name: The name of the application
  • type: Specifies the type of application (war or ear)

The location and ID is required and either the name equal to the context root, or the context-root can be provided. The type can be omitted. I did not provide the ID and it worked for me, but since the server requires it, it should be provided. Use the same value as the name or context root for the ID.

The element can be put into several places. In a CLM installation, by default, the applications are declared in the file

<Install Folder>\server\liberty\servers\clm\conf\application.xml

The file is included in the file <Install Folder>\server\liberty\servers\clm\server.xml. It would be possible to place the application declaration in the file server.xml, but it seems to make more sense to put it into the file application.xml instead.

Add lines

<!–  My Application –>
<application id=”PEWEnactmentData” name=”PEWEnactmentData” location=”${server.config.dir}/apps/PEWEnactmentData.war”/>

to the file application.xml and save the file.

The file should look like below:

Declare new Application

In this case the location is relative to the server configuration folder which n our case is <Install Folder>\server\liberty\servers\clm\. The location could really be anywhere. If it is necessary to include a folder that, as an example, can be accessed by regular users, you could change the location to somewhere with less read and modification restrictions.

After the save of the application.xml, the published XML file should be accessible using the URL https://clm.example.com:9443/PEWEnactmentData/makers.xml.

The image below shows the browser access.

Browser Access To XML File

2. Deploying an Application – dropins

In the example we want to publish a document with the URI https://clm.example.com:9443/<context root>/makers.xml, where <context root>=PEWEnactmentData. The public URI root is already given by the server set up.

2.1 Create the “Application”

As first step create the application. Create a new folder named PEWEnactmentData.war in the folder <Install Folder>\server\liberty\servers\clm\dropins.

Put the files to be published underneath this folder. In the given example, put the file makers.xml into the folder.

The folder structure should look like the image below.

Published application with file

Assuming the automatic application monitoring is enabled, the file should be accessible after the next polling cycle, (at least after waiting the full pollingRate). If automatic application monitoring is not enabled, enable it as described in 2.2 and save the configuration file.

The XML file content should now be accessible using the URL https://clm.example.com:9443/PEWEnactmentData/makers.xml.

Deploying Compressed Folder Structures

It is also possible to publish real WAR, EAR similar to the way described above. For example create a WAR file as described in Publish XML Data Using Tomcat – Hotfix for The Process Enactment Workshop and attached to that post. Deploy the compressed WAR file, for example PEWEnactmentData.war in the dropins folder or declare it as an application and put it onto another location like explained below. This automatically deploys the application and makes the contained files accessible.

Just zipping the folder structure we created above into a zip file, name it PEWEnactmentData.war and trying to deploy does not seem to be working however. The WAR file needs to provide required supporting structures in this case.

Related Posts

The RM Extensions Hosting Guide for CLM 6.0.1 and later versions explain the dropins example as well.

Summary

This post shows how easy it is to publish supporting files on the WAS Liberty Profile. This is important if you want to host custom Doors Next Extensions, or if you want to publish your own XML data to be used with HTTP Filtered Value Sets, for the Process Enactment Workshop and it can possibly also used with Build result publishing. In the latter case, you would likely publish a root folder that contains all the build results.

As always I hope this post has some value to users out there, or is at least interesting to read.

 

 

 

 

 

 

 

 

Posted in CLM, Doors Next Generation, Jazz, RTC, RTC Process Customization, WAS Liberty Profile | Tagged , , , | 2 Comments

Check out the RTC Timebox Planning Widget with SAFe Support


Take a look at this great community contribution. If you ever wanted to be able to easily see the status of a plan and balance the load in the dashboard, this could be the ideal solution for you.

I already blogged about the great predecessor and other community content in the post Some Community Extensions for RTC.

In the newest post New RTC Timebox Planning Widget with SAFe Support, Markus Giacomuzzi from Siemens Switzerland explains the newest version of their RTC Timebox Planning Widget with SAFe Support. He also created videos on their You Tube channel, explaining how to use and set up the TimeBox Planning dashboard widget. The Time Box Planning widget is an excellent example for how community contributions can improve the useability of RTC and provide fresh ideas. Please read the post and view the videos. Don’t forget to share and give Markus a thumbs up.

The extension can be found here on IBM Bluemix DevOps Services, if I am not mistaken.

Markus is going to present this at the IBM InterConnect 2016 in Las Vegas in the session DOP-3145 and you might want to consider visiting the session to be able to see it and share your experiences and ideas.

Here is a screen shot of the program level planning.

TimeBox Planning with SAFe support program level

And here is a screen shot of the team level planning.

TimeBox Planning with SAFe support team level

Last but not least, I thought about delaying this reblog for a day, because I already created a post today, but I just can’t restrain myself to do it.

Posted in Jazz, RTC, RTC Automation, RTC Extensibility | Tagged , , , | Leave a comment

Watch Bartosz Chrabski on how to create Rational Team Concert – Advisor & Participant Extensions


If you are new to extending RTC, you might want to look at Bartosz Chrabskis post How to create Rational Team Concert – Advisor & Participant Extension (step by step) and the related video for creating a participant as well as the video for creating an advisor. Don’t forget to like the post and give the videos a thumbs up.

More information about the process can be found in Learning To Fly: Getting Started with the RTC Java API’s.
 

Posted in Jazz, RTC, RTC Extensibility | Tagged , , , , | Leave a comment

Running the RTC Extensions Workshop With RTC 6.0.1


RTC version 6.0.1 is available since end of December 2015. I ran a test to find out if the Rational Team Concert Extensions Workshop still works with RTC 6.0.1. This is what I found.

The version 6.0.1 does not ship Tomcat any more. The Rational Team Concert Extensions Workshop explains how to debug deployed extensions on a Tomcat test server. How does this change the workshop?

Important note: Debugging on Tomcat is only presented as an option, it can be useful if an extension has been fully developed on Jetty, but shows a different behavior on a real environment. Using this technique to develop an extension step by step is not a suggested procedure, instead using Jetty is the preferred way. From this perspective, Section 1.5 in the lab is unimportant for the rest of the workshop and this step could actually be skipped.

Summary

By installing the default values and basically choosing WAS Liberty Profile the workshop works. Basically Tomcat is replaced with WAS Liberty Profile and everything should work as expected. Due to the changes over time, some small adjustments are needed or useful. these adjustments can be found below.

Update

Please see the update for changing the development application server configuration to enable debugging.

Please note that currently The SDK for RTC6.0.2 has a defect that makes it impossible to be used. See 390811: RTC SDK breaks Extension workshop with missing feature com.ibm.team.rtc.update.site.content.rtc.feature. Use an earlier version of the SDK to develop for now.

Install and Setup Changes

Here some changes that make the workshop more effective. They are described in the workshop in several notes, here a more explicit description.

Section 1.1 Download and Unzip the Required Files from jazz.net

The easiest way to do the Rational Team Concert Extensions Workshop I have found is not to use the Web installer, but to use the ZIP version of RTC.This requires sone minor changes to the sections 1.1. and 1.2 as described below.

You can use the Web Installer, as well as the IBM Installation Manager. If using the Web Installer the changes for 6.0.1 begin in Section 1.3 Setup the RTC Tomcat Server. If using the Installation manager, make sure to install into the folder as described in the workshop.

 1.1__1. Download the product installation files.

In step _b: As alternative, download the ZIP version of RTC named “Jazz Team Server and the CCM Application, and Trial licenses for Rational Team Concert”.

RTC_ZIP Version

Follow the rest of the steps of 1.1_1 and 1.1_2 as described.

If you want to follow the steps from the Rational Team Concert Extensions Workshop and use the web installer, or a the IBM Installation Manager install, make sure to install

 1.1__3. Install the RTC Eclipse client and a test server.

In step _b: To install the zip version of RTC, extract the zip file JTS-CCM-keys-Win64_6.0.1.zip you downloaded for “Jazz Team Server and the CCM Application, and Trial licenses for Rational Team Concert” to the folder:

C:\RTC601Dev\installs\JazzTeamServer

Continue with step _h Unzip the Client for Eclipse IDE zip file

Section 1.3 Setup the RTC Tomcat Server

Instead of Tomcat RTC and CLM 6.0.x bundle WAS Liberty Profile.

 1.1__3. Setup to run the server in debug mode

On windows I have followed the original descriptions in the Extesnsions workshop and added the Java options to the server.startup.bat and it worked for me.

However Lewis Tsao reported in the comments below that on Linux there are changes. He reports the server just dies if he uses suggested lines. He found the article https://jazz.net/wiki/bin/view/Deployment/EnableLibertyRTCServerDebugMode. Based on this, even on Windows it might be worth exploring this and follow the link above. For mode details look at his comments below.

Note that

  • For 6.0.1 the server should be started as “./server.startup -debug” or modify “DEBUG=false” in server.startup to “DEBUG=true”
  • For 6.0.2 the server should be startd as “./server.startup debug”

1.1.__14_b. Open And Review the WorkshopSetup.bat file

The windows version of this file has sometimes problems with some Java versions, because the parameter order is kind of skewed. During development of the tool, this never came up. It will be fixed in a newer version.

Move the parameter -jar in front of the parameter WorkshopSetup.jar

Instead of

Fix workshopSetup.bat_1

the batch file should look like this:

Fix workshopSetup.bat_2

Follow the other suggestions to consider and change the file if needed and perform the rest of the steps as described.

When running the WorkshopSetup command I have very seldom seen errors, one I have seen today was maybe because of the server performance. If this happens, try running the WorkshopSetup again.

Section 1.4 Complete Setup of Your RTC Eclipse Client

For an unknown reason, the project was not initialized. Right click the project in the Team Artifacts view and click initialize to finish the project setup, if this happens.

Section 1.5 Test connecting the Eclipse debugger to Tomcat

If the changes to the server.startup.bat in section 1.3 where successfully performed, this section works the same way with the server deployed on WAS Liberty Profile.

Section 1.6 Test the Jetty Based Server Launch

The software needs more memory. In step

1.6__25__b.

change the memory available for the [RTCExt] Create RTC Test Database launch. The original setting is -Xmx256. With this setting I got a memory error in the JUnit test that creates the development time repository database.

Change the memory setting to -Xmx512 as shown below.

Memory Setting For JUnit launch

Section 1.7 Test the RTC Eclipse Client Launch

In step 1.7.__31.__b.__ii.

The Launch shows a missing bundle.

Eclipse Client launch Missing Bundle

This missing bundle does however not prevent you from running the launch and as far as I can tell at this point in time, the workshop is still working. You can remove the missing bundle as well.

The rest of the workshop should work as desired.

Related Posts

Summary

The  Rational Team Concert Extensions Workshop still works for version RTC 6.0.1. I will however try to find some time to do an overhaul for RTC 6.0.2.

Posted in Jazz, RTC, RTC Automation, RTC Extensibility | Tagged , , | 11 Comments

Setting Custom Attributes for SCM Versionables


This is the forth post in the series around very fine grained access control permissions for work items and SCM versionables. It explains the last requirement, which was to be able to set the custom attributes on elements in the SCM system using the RTC API.

See the problem description in the first post of the series

Related posts

The posts in this series are:

  1. Manage Access Control Permissions for Work Items and Versionables
  2. Setting Access Control Permissions for Work Items
  3. Setting Access Control Permissions for SCM Versionables
  4. Setting Custom Attributes for SCM Versionables – this post

License

The post contains published code, so our lawyers reminded me to state that the code in this post is derived from examples from Jazz.net as well as the RTC SDK. The usage of code from that example source code is governed by this license. Therefore this code is governed by this license. I found a section relevant to source code at the and of the license. Please also remember, as stated in the disclaimer, that this code comes with the usual lack of promise or guarantee. Enjoy!

Just Starting With Extending RTC?

If you just get started with extending Rational Team Concert, or create API based automation, start with the post Learning To Fly: Getting Started with the RTC Java API’s and follow the linked resources.

You should be able to use the following code in this environment and get your own automation or extension working.

Compatibility

This code has been used with RTC 5.0.2 and is prepared to be used with RTC 6.0.x with no changes and it is pretty safe to assume, that the code will work with newer versions of RTC.

The code in this post uses common libraries/services that are available in the Plain Java Client, Eclipse client and Jazz Eclipse server API. If client or server API is used, this is stated.

Note, some capabilities where only finalized in RTC 6.0.1 and are not available in versions before. Especially custom attributes for components and potentially for items other than SCM versionables.

Custom Attributes for SCM Versionables

Rational Team Concert 5.0.2 introduces support for creating custom attributes on source file versions.

The attributes can be set for every version of the SCM versionable. Dependent on the definition the attribute can be missing or different on different versions. This is different to the behavior we have seen in the post Setting Access Control Permissions for SCM Versionables, where the read access permission applies to all versions of the item.

The image below shows for which SCM elements custom attributes are available and how they can be set up to behave.

SCM Attributes

The behavior is important, because there are several very distinct requirements. For example it is desirable to be able to set some attribute only on one specific version. As an example to classify safety critical source code that needs special testing if changed, to allow for auditing. For others it is better to keep a value, once it is set.

Working with Custom Attributes for SCM Versionables

The following code shows how to work with the custom attributes for versionable handles. Please note, that there is no way to access these attributes in the RTC UI at the moment. They are accessible in the API otherwise they can only be set and read in the RTC SCM Commandline.

Getting the IScmService

To set custom attributes for versionables, requires the IScmService class com.ibm.team.scm.common.IScmService. As described in the post Setting Access Control Permissions for SCM Versionables, It is easy to get this service in the Server API, by basically using

IScmService fScmService = getService(IScmService.class);

However, in the Client API, this is not accessible as client library using the usual getClientLibrary() call.

I searched the client API and found about 6 different ways how this interface was requested by the product and test code in the RTC client SDK. For various reasons I picked the following approach and wrapped it into a utility class.

/*******************************************************************************
 * Licensed Materials - Property of IBM
 * (c) Copyright IBM Corporation 2015. All Rights Reserved. 
 *
 * Note to U.S. Government Users Restricted Rights:  Use, duplication or 
 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 *******************************************************************************/
package com.ibm.js.access.control.client;

import com.ibm.team.repository.client.ITeamRepository;
import com.ibm.team.repository.client.internal.TeamRepository;
import com.ibm.team.scm.common.IScmService;

public class ScmServiceClient {
	/**
	 * Get the SCM Service in a client application
	 * 
	 * @param teamRepository
	 * @return
	 */
	public static IScmService getSCMService(ITeamRepository teamRepository) {

		IScmService scmService = (IScmService) ((TeamRepository) teamRepository)
				.getServiceInterface(IScmService.class);
		return scmService;
	}
}

Note that the method uses the internal interface com.ibm.team.repository.client.internal.TeamRepository and not the interface ITeamRepository that is usually used to get a client library. The method getServiceInterface() is not exposed on ITeamRepository, so it is necessary to cast the ITeamRepository object to the actual class that implements the interface.

Setting Custom Attributes

The following code sets the custom attributes for versionable handles.

It basically gets the attributes available on the element. The data is returned as a hashmap with the attribute name being the key. This can be used for printing the data as well as shown below.

The code puts the attribute and its value in the hashmap and then this nap is passed to be saved.

/**
 * Set a specific attribute of versionable handles
 * 
 * @param vhandles
 * @param attributeName
 * @param attributeValue
 * @param scmService
 * @throws TeamRepositoryException
 */
public static void setAttribute(IVersionableHandle[] vhandles,
		String attributeName, String attributeValue, IScmService scmService )
		throws TeamRepositoryException {
	ICustomAttributeList[] versionableAttributesList = scmService
			.fetchCustomAttributesForVersionable(vhandles, null);
	
	for (int i = 0; i < versionableAttributesList.length; i++) {
		ICustomAttributeList attributeList = versionableAttributesList[i];
		Map<String, Object> attributeMap = attributeList
				.getCustomAttributes();
		attributeMap.put(attributeName, attributeValue);
		attributeList.setCustomAttributes(attributeMap);
		scmService.saveCustomAttributesForVersionable(vhandles[i],
				attributeList, null);
	}
}

As shown in the post Setting Access Control Permissions for SCM Versionables it is easy to create the required array if only one versionable handle is available using this code.

IVersionableHandle[] vhandles = new IVersionableHandle[] { versionableHandle };

Similar, it is easy to use the code here if the available data is a change set, by using the same technique as shown in the post Setting Access Control Permissions for SCM Versionables.

In both case, it is possible to create the array with all elements that need the change and then run the operation for all. This is also the most efficient way.

Removing Custom Attributes

Custom attributes can be removed by removing an attribute entry from the map or creating a map that does not contain this attribute. It is possible to erase all custom attributes by setting an empty map like below:

ICustomAttributeList[] versionableAttributesList = scmService
		.fetchCustomAttributesForVersionable(vhandles, null);

for (int i = 0; i < versionableAttributesList.length; i++) {
	ICustomAttributeList attributeList = versionableAttributesList[i];
	attributeList.setCustomAttributes(new HashMap<String, Object>());
	scmService.saveCustomAttributesForVersionable(vhandles[i],
			attributeList, null);
}

I have not tested this, but I assume that attributes that are defined to have a default value and are automatically applied, will be recreated with the default value when deleting them from the map.

Getting Custom Attributes

The next code snippet shows how to get or accesses the custom attributes and how to print them. It basically gets the map and then iterates the contained keys to access the attributes:

/**
 * Print the attributes for an array of versionable handles
 * 
 * @param vhandles
 * @param scmService
 * @throws TeamRepositoryException
 */
public static void printAttributes(IVersionableHandle[] vhandles, IScmService scmService,String message)
		throws TeamRepositoryException {
	System.out.println(message);
	ICustomAttributeList[] versionableAttributesList = scmService
			.fetchCustomAttributesForVersionable(vhandles, null);

	for (int i = 0; i < versionableAttributesList.length; i++) {
		ICustomAttributeList attributeList = versionableAttributesList[i];
		Map<String, Object> attributeMap = attributeList
				.getCustomAttributes();
		printAttributes("Attributes: ",attributeMap);
	}
}


/**
 * @param message
 * @param attributeMap
 */
private static void printAttributes(String message, Map<String, Object> attributeMap) {
	System.out.print(message + " - ");
	Set keys = attributeMap.keySet();
	if(keys.isEmpty()){
		System.out.print("No");
	}
	System.out.println(" attributes found:");
	for (String key : keys) {
		Object value = attributeMap.get(key);
		printAttributeValue(message, key, value);			
	}	
}

/**
 * @param message
 * @param key
 * @param value
 */
private static void printAttributeValue(String message, String key, Object value) {
	if (value != null) {
		System.out.println(message + ": " + key
				+ " value: " + ((String) value));
	} else {
		System.out.println("Version Attribute: " + key
				+ " no value");
	}
}

Custom Attributes for Other SCM Elements

The API to get or set custom attributes for other objects, is similar to the API for versionables. Since they are unique objects and don’t have different versions, there is only one set of custom attributes available for them.

Please note, the full functionality for these objects only became available in 6.0.1

Custom Attributes for Streams

To set custom attributes for streams, since 6.0.1 the common API provides the interface

com.ibm.team.scm.service.internal.ScmService.setWorkspaceCustomAttributes(IWorkspaceHandle, IGenericAttributes, String[], ISynchronizationTimes[], IRepositoryProgressMonitorHandle)

to set custom attributes.

The interface com.ibm.team.scm.common.IWorkspace provides the method

com.ibm.team.scm.common.IWorkspace.getCustomAttributes()

to get the custom attributes of the stream.

Please note, that the data is cached, if you want accurate information refresh the object e.g. using com.ibm.team.scm.client.IWorkspaceConnection.refresh(IProgressMonitor).
The code to set and get the custom attributes would look like below:

IWorkspaceManager wm = SCMPlatform.getWorkspaceManager(teamRepository);
IWorkspaceSearchCriteria criteria = IWorkspaceSearchCriteria.FACTORY.newInstance().setKind(IWorkspaceSearchCriteria.STREAMS);
criteria.setExactName("JKE Banking Integration Stream");
List connection = wm.findWorkspaces(criteria, Integer.MAX_VALUE, monitor);
IWorkspaceHandle streamHandle = connection.get(0);
IWorkspaceConnection wcStream = wm.getWorkspaceConnection(streamHandle, monitor);
IWorkspace streamConnection = wcStream.getResolvedWorkspace();
IScmService scmService = ScmServiceClient.getSCMService(teamRepository);
		
Map<String,Object> customAttributes=new HashMap<String,Object>();
customAttributes.put(CUSTOM_ATTRIBUTE, "Test");
String[] attributesToClear = new String[] { CUSTOM_ATTRIBUTE };

wcStream.refresh(monitor);
printAttributes("Stream AttributesInitial", streamConnection.getCustomAttributes());
		
// Set the custom attributes
IGenericAttributes streamAttributes = IGenericAttributes.FACTORY.newInstance(customAttributes);
scmService.setWorkspaceCustomAttributes(streamHandle, streamAttributes, null, null, IRepositoryProgressMonitor.ITEM_FACTORY.createItem(monitor));

wcStream.refresh(monitor);
printAttributes("Stream Attributes", streamConnection.getCustomAttributes());

// Clear the custom attributes
scmService.setWorkspaceCustomAttributes(streamHandle, null, attributesToClear, null, IRepositoryProgressMonitor.ITEM_FACTORY.createItem(monitor));

wcStream.refresh(monitor);
printAttributes("Stream AttributesAfterClear", streamConnection.getCustomAttributes());

Custom Attributes for Snapshots

To set custom attributes for snapshots, since 6.0.1 the common API provides the interface

com.ibm.team.scm.service.internal.ScmService.setBaselineSetCustomAttributes(IBaselineSetHandle, IGenericAttributes, String[], ISynchronizationTimes[], IRepositoryProgressMonitorHandle)

to set custom attributes.

In addition, in 6.0.1, the interface com.ibm.team.scm.common.IBaselineSet provides the method

com.ibm.team.scm.common.IBaselineSet.getCustomAttributes()

to get the custom attributes of the snapshot.

Please note, that the data is cached, if you want accurate information refresh the object e.g. using the IItemManager and the IItemManager.REFRESH flag to get the latest information.
The code to set and get the custom attributes would look like below:

IBaselineSetSearchCriteria bScriteria = IBaselineSetSearchCriteria.FACTORY.newInstance();
bScriteria.setExactName("TestSnapShot");
List baselineSetHandles = SCMPlatform.getWorkspaceManager(teamRepository).findBaselineSets(bScriteria, 100, monitor);
BaselineSetHandle snapShotHandle = (BaselineSetHandle) baselineSetHandles.get(0);
IBaselineSet snapShot = (IBaselineSet) teamRepository.itemManager().fetchCompleteItem(snapShotHandle,IItemManager.REFRESH,monitor);
	
printAttributes("Snapshots AttributesInitial", snapShot.getCustomAttributes());

scmService.setBaselineSetCustomAttributes(snapShotHandle, custAttributes, null, null, IRepositoryProgressMonitor.ITEM_FACTORY.createItem(monitor));
snapShot = (IBaselineSet) teamRepository.itemManager().fetchCompleteItem(snapShotHandle,IItemManager.REFRESH,monitor);
printAttributes("Snapshots Attributes", snapShot.getCustomAttributes());

scmService.setBaselineSetCustomAttributes(snapShotHandle, null, attributesToClear, null, IRepositoryProgressMonitor.ITEM_FACTORY.createItem(monitor));
snapShot = (IBaselineSet) teamRepository.itemManager().fetchCompleteItem(snapShotHandle,IItemManager.REFRESH,monitor);
printAttributes("Snapshots AttributesAfterClear", snapShot.getCustomAttributes());

Custom Attributes for Baselines

To set custom attributes for streams, since 6.0.1 the common API provides the interface

com.ibm.team.scm.service.internal.ScmService.setBaselineCustomAttributes(IBaselineHandle, IGenericAttributes, String[], ISynchronizationTimes[], IRepositoryProgressMonitorHandle)

to set custom attributes for snapshots.
In addition, in 6.0.1, the interface com.ibm.team.scm.common.IBaseline provides the method

com.ibm.team.scm.common.IBaseline.getCustomAttributes()

to get the custom attributes of the baseline.

Please note, that the data is cached, if you want accurate information refresh the object e.g. using the IItemManager and the IItemManager.REFRESH flag to get the latest information.
The code to set and get the custom attributes would look like below:

IBaselineHandle baseLineHandle = buildComponent.getInitialBaseline();
IBaseline baseLine = (IBaseline) teamRepository.itemManager().fetchCompleteItem(baseLineHandle,IItemManager.REFRESH,monitor);
		
printAttributes("Baseline AttributesInitial", baseLine.getCustomAttributes());

scmService.setBaselineCustomAttributes(baseLineHandle, custAttributes, null, null, IRepositoryProgressMonitor.ITEM_FACTORY.createItem(monitor));
baseLine = (IBaseline) teamRepository.itemManager().fetchCompleteItem(baseLineHandle,IItemManager.REFRESH,monitor);
printAttributes("Baseline Attributes", baseLine.getCustomAttributes());

scmService.setBaselineCustomAttributes(baseLineHandle, null, attributesToClear, null, IRepositoryProgressMonitor.ITEM_FACTORY.createItem(monitor));
baseLine = (IBaseline) teamRepository.itemManager().fetchCompleteItem(baseLineHandle,IItemManager.REFRESH,monitor);
printAttributes("Baseline AttributesAfterClear", baseLine.getCustomAttributes());

Custom Attributes for Components

To set custom attributes for components, since 6.0.1 the common API provides the interface

com.ibm.team.scm.service.internal.ScmService.setComponentCustomAttributes(IComponentHandle, IGenericAttributes, String[], ISynchronizationTimes[], IRepositoryProgressMonitorHandle)

In addition, in 6.0.1, the interface com.ibm.team.scm.common.IComponent provides the method

com.ibm.team.scm.common.IComponent.getCustomAttributes()

to get the custom attributes of the component.

Please note, that the data is cached, if you want accurate information refresh the object e.g. using the IItemManager and the IItemManager.REFRESH flag to get the latest information.
The code to set and get the custom attributes would look like below:

printAttributes("Component AttributesInitial", buildComponent.getCustomAttributes());

scmService.setComponentCustomAttributes(buildComponent, custAttributes, null, null, IRepositoryProgressMonitor.ITEM_FACTORY.createItem(monitor));
buildComponent = (IComponent) teamRepository.itemManager().fetchCompleteItem(buildComponent,IItemManager.REFRESH,monitor);
printAttributes("Component Attributes", buildComponent.getCustomAttributes());

scmService.setComponentCustomAttributes(buildComponent, null, attributesToClear, null, IRepositoryProgressMonitor.ITEM_FACTORY.createItem(monitor));
buildComponent = (IComponent) teamRepository.itemManager().fetchCompleteItem(buildComponent,IItemManager.REFRESH,monitor);
printAttributes("Component AttributesAfterClear", buildComponent.getCustomAttributes());

Summary

This post explains how to set custom attributes for SCM elements. As always, I hope this is useful to someone out there.

Posted in Jazz, RTC Automation, RTC Extensibility | Tagged , , , , , | Leave a comment