Dimensions CM 2019 CABs Announced

Micro Focus is very happy to announce that we have secured the venues and dates for next years Software Change and Configuration Management Customer Advisory Boards. This is a free event that we are hosting for our SCCM customers of Dimensions, StarTeam, and AccuRev.

For 2019 we are very pleased to announce that we will be holding two events, one in the UK and one on North America.

Full details are noted below and please let myself and Jimmy know if you want to secure your place and we will follow up with full logistics.

London

Micro Focus Wood street office

2 day event on 5th and 6 of March 2019

 

Las Vegas

ARIA Resort and Casino 

2 day event on 15th and 16th May 2019

 

To secure your place at these events please contact myself clifford.hunter-gammon@microfocus.com and James.ORourke@microfocus.com.

If you have not attended an SCCM CAB before let me provide further details:

What is a CAB?:

CAB is Short for Customer Advisory Board.

A meeting between Micro Focus Customers and various departments within Micro Focus. This usually consists of the support team, product manager, R&D team and other customer advocates.

The meetings are usually 2 days long but recently we have added a 3rd optional day to facilitate one to one personal meetings.

The CABs are highly interactive collaboration between Micro Focus and it’s customers to help drive the future of the product, build a more personal relationship and also to provide additional value on the maintenance plans paid to Miro Focus.

Why have a CAB?

To often product decisions can be made in a bubble and without clear customer direction, Micro Focus wants clear customer direction on product strategy.

Benefit of meeting with many customers vs individual trips. Plus, customers love hearing from other customers as opposed to the product vendor.

CABs allows for PM, Dev, Support and CAM’s to interact in a more intimate setting rather than over email or web meetings.

Better insight and understanding about how your products are being used in the market place.

Relationship building.

Customers get to present their deployment of the product and the benefits it brings to their org.

Plus a host of other benefits including swag bags of branded merchandise, offsite dinners and Micro Focus exectives (VP level) will be in attendance. 

Hoping to see you at the 2019 CABs!

Cliff and Jimmy

 

Continue reading
18 Hits
0 Comments

SBM MODSCRIPT, PART 15 - Singletons

As a common programming pattern, singletons are very helpful with data that needs to be read once and then reused throughout the program. This may not be required for simple scripts, but for long running, complicated scripts, this can help with keeping the script running with high performance. Since scripts often run as parts of transitions that users are clicking through, performance can affect user confidence and contentment.

To create a singleton in ModScript, follow the following pattern:

def GetConfiguration() {
  global g_appconfiguration;
  if ( g_appconfiguration.is_var_undef() ) {
    g_appconfiguration = Map();
    // read various configuration settings from DB or file system and inject into the map
  }
  return g_appconfiguration;
}

Create a function. Inside the function, declare a global (but do not initialize it). Check if the global is undef, if so, initialize it and set it up. Finally, return the global. The global variable should have a very unique name, as it is global and we do not want it to interfere with other scoped variables. Since it is global, this means it will have the lifetime of the script, meaning the check for is_var_undef() will only be true the first time. As such, you can be confident that the time taken to read configuration data will only occur once, and can be accessed as often as needed throughout the script lifetime. 

 

SBM ModScript - Table of Contents

Continue reading
84 Hits
0 Comments

SBM MODSCRIPT, PART 14 - Checking the Type of a Variable

When interacting with a variable, it is sometimes useful to know what type it has been initialized as. This can be especially useful when working with the results of a from_json() call, where the scripting engine has parsed a blob of JSON and then you need to figure out how to interact with it. The following utility function can be invoked on any var.

  • type_name() -> string: returns a string value denoting the underlying type of the variable, such as "Vector", "Map", "int", "Variant", etc.
  • is_var_undef() -> bool: returns true if the variable has not yet been assigned a type (uninitialized).
  • is_var_null() -> bool: returns true if the variable was initialized by a null, which occurs when from_json() encounters a null.

Example:

def processJSONObj( r ) {
  if ( r.is_var_null() ) {
    Ext.WriteStream( "null\n" );
    continue;
  }
  switch ( r.type_name() ) {
    case( "Vector" ) {
      Ext.WriteStream( "[ " );
      for ( v : r ) {
        processJSONObj( v );
      }
      Ext.WriteStream( " ]\n" );
      break;
    }
    case( "Map" ) {
      Ext.WriteStream( "{ " );
      for ( prop : r ) {
        Ext.WriteStream( prop.first + ": " );
        processJSONObj( prop.second );
      }
      Ext.WriteStream( " }\n" );
      break;
    }
    case( "String" ) {
      Ext.WriteStream( "\"" + r + "\"\n" );
      break;
    }
    default {
      Ext.WriteStream( r + "\n" );
      break;
    }
  }
}

var result = "{
    \"array\": [1,2,3,\"textData\",{ \"a\": 1, \"b\": 2 }],
    \"intData\": 5,
    \"doubleData\": 4.5,
    \"stringData\": \"Welcome to ModScript\"
}".from_json();

processJSONObj( result );

 

SBM ModScript - Table of Contents

Continue reading
80 Hits
0 Comments

SBM ModScript, Part 13 - Base64Encode

Someone recently asked me if it is possible to base64 encode a string in ModScript... so I did.

def Base64Encode( string input ) {
  add_global_const("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "CONST_BASE64TABLE");
  
  var sOut = "";
  
  var buf = [uint8_t(),uint8_t(), uint8_t()];
  var idx = -1;

  for ( c : input ) {
    buf[++idx] = c;
    if (idx == 2) {
      // Output the 4 encoded bytes
      sOut += CONST_BASE64TABLE[buf[0] >> 2];                              // first 6-bits of byte 0
      sOut += CONST_BASE64TABLE[(((buf[0] & 0x03) << 4)) | (buf[1] >> 4)]; // last 2-bits of byte 0 + first 4-bits of byte 1
      sOut += CONST_BASE64TABLE[(((buf[1] & 0x0f) << 2)) | (buf[2] >> 6)]; // last 4-bits of byte 1 + first 2-bits of byte 2
      sOut += CONST_BASE64TABLE[buf[2] & 0x3f];                            // last 6-bits of byte 2

      idx = -1;
    }
  }

  // Special case handling of last 1 or 2 characters
  if ( idx != -1 ) {
    sOut += CONST_BASE64TABLE[buf[0] >> 2];             // first 6-bits of byte 0
    
    if (idx == 0) {
      sOut += CONST_BASE64TABLE[((buf[0] & 0x03) << 4)];  // last 2-bits of byte 0
      sOut += '=';                                  // pad
    }
    else if (idx == 1) {
      sOut += CONST_BASE64TABLE[(((buf[0] & 0x03) << 4)) | (buf[1] >> 4)]; // last 2-bits of byte 0 + first 4-bits of byte 1
      sOut += CONST_BASE64TABLE[((buf[1] & 0x0f) << 2)];                   // last 4-bits of byte 1
    }
    
    sOut += '=';                                  // pad
  }
  
  sOut; // return
}

 

The function above iterates the string contents and uses base64 to create an encoded output string. Notice that the "buf" variable is a Vector of 3 unsigned, 8 bit integers. As we are going to use bit shifting in order to encode the data, it is important to use unsigned byte data to ensure the expected bit-shift result. We then use the bit-shifted value to index into CONST_BASE64TABLE to find the data-representation we are looking for. The result is a base64 encoding of the string data. 

A likely use-case for this would be when adding custom headers to a RESTDataSource call-out.

 

SBM ModScript - Table of Contents

Continue reading
160 Hits
0 Comments

NEW COURSE: 3166 – ZENWORKS 2017 MOBILE MANAGEMENT ADMINISTRATION

NEW COURSE: 3166 – ZENWORKS 2017 MOBILE MANAGEMENT ADMINISTRATION

This course provides instruction on how to set up ZENworks Mobile Management for enrolling and managing corporate mobile devices in your ZENworks zone.

Further Information: https://www.microfocus.com/ondemand/courses/zenworks-2017-mobile-management-administration-3166/

Continue reading
218 Hits
0 Comments

New Course: Silk Test Workbench Essentials (SLK430)

New Course: Silk Test Workbench Essentials (SLK430)

 

Featuring a brand-new Instructor Led Training Course aimed at testers who wish to harness the power of the Silk Test Workbench Client.

 

The following modules are covered:

 

·         Module 1: Course introduction

·         Module 2: Introduction to Silk Test Workbench

·         Module 3: Creating a Silk Test Workbench project

·         Module 4: Configure Project, manage Project Assets & record Visual Test

·         Module 5: Test playback 

·         Module 6: Object recognition

·         Module 7: Adding verification

·         Module 8: Play back tests and analyze results

·         Module 9: Testing Web applications on mobile browsers

·         Module 10: Example: Cross-browser testing

·         Module 11: Wrap-up Exercises and wrap-up Assessment

 

See more information on the Course and the Course Outline for more information.

Continue reading
267 Hits
0 Comments

Using Araxis Merge in a simple parallel development scenario

Using Araxis Merge in a simple parallel development scenario

The following document describes the steps used that cover a standard parallel development scenario across two streams.

 

 

The attached document describes a practical 6 step scenario working on both the mainline and patch development and how Araxis Merge can be used to help assist the merge conflicts.

 

Step 1: Main Line Development (Version 1.0)   
Step 2: Work on a Branch Patch Release (Version 1.1)   
Step 3: Make a patch modification (Version 1.1)   
Step 4: Main Line Development (Version 2.0)   
Step 5: Merge the branch modifications into the mainline   
Step 6: Review the merge   

Please see the attached document for further details.

Continue reading
468 Hits
0 Comments

COMING SOON: Silk Test Workbench Essentials (SLK430)

COMING SOON: Silk Test Workbench Essentials (SLK430)

This new 1-day course has been developed as a fully-fledged Instructor Led Training course (ILT). The course includes progressive learning modules, including a hands-on lab experience to accelerate learning.

As well as developing a fully featured test scenario, learning is further enhanced and re-enforced through participation in a fully featured and expanded wrap up lab exercise and assessment.

Lab exercises are systematically themed, providing fully annotated instruction. Each module allows the student to build out live test scenarios that harness the major technologies employed in automated functional testing offered by Silk Test Work Bench using user friendly interfaces, designed to get your team building smooth, efficient automated tests, without the need for in-depth scripting knowledge.

For more information on the course, see the following course outline.

 

The following modules are covered:

• Module 1: Course introduction
• Module 2: Introduction to Silk Test Workbench
• Module 3: Creating a Silk Test Workbench project
• Module 4: Managing Application Configurations
• Module 5: Recording a test 
• Module 6: Object recognition
• Module 7: Adding verification
• Module 8: Play back tests and analyze results
• Module 9: Testing Web applications on mobile browsers
• Module 10: Example: Cross-browser testing
• Module 11: Wrap-up Exercises
• Wrap-up Assessment

Recent Comments
Paul Caruana
You are welcome Raj
Monday, 15 October 2018 8:08 AM
Raj Khanna J
Great post paul keep up the good work and cheers.
Saturday, 13 October 2018 10:10 AM
Continue reading
374 Hits
2 Comments

New Course: Silk4J Scripting Essentials (SLK420)

New Course: Silk4J Scripting Essentials (SLK420)

Featuring a brand-new Instructor Led Training Course aimed for developers who wish to harness the power of Java in Eclipse, using the Silk4J plugin.

The following modules are covered:

• Module 1: Course introduction
• Module 2: Introduction to Silk4J
• Module 3: Creating a Silk4J project
• Module 4: Managing Application Configurations
• Module 5: Recording a test 
• Module 6: Object recognition
• Module 7: Adding verification
• Module 8: Play back tests and analyze results
• Module 9: Testing Web applications on mobile browsers
• Module 10: Example: Cross-browser testing
• Module 11: Wrap-up Exercises
• Wrap-up Assessment

See more information on the Course and the Course Outline for more information.

Continue reading
377 Hits
0 Comments

COMING SOON: SILK4J Scripting Essentials (SLK420)

COMING SOON: SILK4J Scripting Essentials (SLK420)

This new 1-day course has been developed as a fully-fledged Instructor Led Training course (ILT). The course includes progressive learning modules, including a hands-on lab experience to accelerate learning.

As well as developing a fully featured test scenario, learning is further enhanced and re-enforced through participation in a fully featured and expanded wrap up lab exercise and assessment.

Lab exercises are systematically themed, providing fully annotated instruction. Each module allows the student to build out live test scenarios that harness the major technologies employed in automated functional testing offered by Silk Test leveraged with the programming power of Java using the Eclipse IDE.

For more information on the course, see the following course outline.

Continue reading
432 Hits
0 Comments

New Course: Silk4Net C# Scripting Essentials (SLK410)

New Course: Silk4Net C# Scripting Essentials (SLK410)

Featuring a brand new Instructor Led Training Course aimed for developers who wish to harness the power of Visual Studio (C#), using the Silk4Net plugin.

 

The following modules are covered:

 

• Module 1: Course introduction
• Module 2: Introduction to Silk4NET
• Module 3: Creating a Silk4NET project
• Module 4: Managing Application Configurations
• Module 5: Recording a test 
• Module 6: Object recognition
• Module 7: Adding verification
• Module 8: Play back tests and analyze results
• Module 9: Testing Web applications on mobile browsers
• Module 10: Example: Cross-browser testing
• Module 11: Wrap-up Exercises
• Wrap-up Assessment

 

See more information on the Course and the Course Outline for more information.

 

Continue reading
375 Hits
0 Comments

New Course: Silk4Net Scripting Essentials (SLK400)

New Course: Silk4Net Scripting Essentials (SLK400)

Featuring a brand new Instructor Led Training Course aimed for developers who wish to harness the power of both Test Director and Visual Studio (VB.net), using the Silk4Net plugin.

The following modules are covered:

• Module 1: Course introduction
• Module 2: Introduction to Silk4NET
• Module 3: Creating a Silk4NET project
• Module 4: Managing Application Configurations
• Module 5: Recording a test 
• Module 6: Object recognition
• Module 7: Adding verification
• Module 8: Play back tests and analyze results
• Module 9: Testing Web applications on mobile browsers
• Module 10: Example: Cross-browser testing
• Module 11: Wrap-up Exercises
• Wrap-up Assessment

See more information on the Course and the Course Outline for more information.

Continue reading
495 Hits
0 Comments

Reporting with Complex Systems

“A little conflict can create a lot of activity.” –Richie Norton

The conflict we’re addressing today is that more and more systems, especially modern SaaS systems, are moving to different authorization protocols.

  • Authorization Micro Services: “I need to generate a token automatically and pass that token into all of my subsequent RESTful web service calls. It’s not necessarily a proper protocol, but that’s how you work with our APIs.”
  • Data Abstraction: We use this in SBM as TS-IDS. The item identifier that might come back from a web service call may not actually be the human-readable identifier for an item ID. We have internal identifiers that come back, and the actual values are stored in a different table.
  • Lack of Data Consistency: Depending on the system that you’re querying, you might get back an all-lowercase new value, a camel-case new value, or all caps. Every system stores these items a little differently.

And there are several other conflicts or challenges that we have with external systems when we bring all of these together. So how do we handle these types of challenges?

We can do direct database reporting: Within SBM, we provide several different methods of reporting against systems:

  • With the Data Service, we can actually connect directly to a database and add a web services layer on top of these databases that may not actually have web services exposed.
  • We can do the same thing with Advanced Reporting—we actually pull these and you’re able to use our reporting engine to get back the actual data with a SQL query.
  • We can also use ModScript and RESTful Web Services. This is an interesting option, because most people don’t think about the ModScript engine in terms of being able to actually query other systems and use it to report all of that data coming back. How can we actually do that?

Let’s start by diving into what ModScript is. ModScript was first introduced in SBM 11.2 or 11.3. With every SBM release, we’ve been improving ModScript and adding more features and functionality.


ModScript is based on a scripting language called ChaiScript, which is based on ECMAScript, which is the basis of JavaScript. It executes on the server side, so when you think of client/server execution, it doesn’t take up any resources on the browser side—all of those requests are done from the server itself.

ModScript has contextual awareness, so it knows things like whether you’re trying to execute the script in the context of a transition, if you’re directly invoking the script, or if it’s being invoked by a URL. Since we can invoke these scripts via a URL , we can return back HTML, but we can also return back JSON—and JSON is the de facto standard for web service calls when you’re using the REST protocol.

There are several uses for Modscript:

  • We can do server-side integrations and processing data
  • We can utilize external DLLs
  • We can perform database-level integrations with SBM
  • We can execute external Command Line commands
  • We can also insert dynamic HTML and JavaScript as well as generate JSON

This works when we use ModScript as a proxy, so everything is as-a-service. As shown in the diagram below, ModScript can be invoked by an SBM URL. The script then executes, and that script is written so that we request the authorization token. The destination system would then send back our authorization token, and we would perform the RESTful web service call to retrieve the dataset with that token in place in the payload. The destination system would send back the dataset that we need, and our script would process that data. Finally, ModScript returns the data to the user.

When we say “The script processes the data,” this processing can happen a few different ways. If the service sends back everything exactly the way we need it and we just need to be able to handle that authorization – great! In some cases, we may want to format the data, or we have any of those data consistency issues that we mentioned above. For example, you might want to change a lowercase “low priority” field title to a camel case to match your other data. Or you may want to trim off some system value that’s appended to the end. In our demo, we go through how we would do that within the ModScript itself.

Check out our webinar recording for Reporting with Complex Systems here, which includes a great demo of ModScript used as a proxy integrated with Micro Focus Service Management Automation X (SMA-X). We’ll generate an authentication token and normalize some data being returned to what we would see out of SBM. We’ll also show you how we return JSON from an already existing report.

See our Discovering SBM page for all of our webinars covering a range of SBM features and functionality. And, as always, we want to hear from you! Tell us what you want to hear more about or anything you’d like to see addressed in an upcoming session.

Recent Comments
Raj Khanna J
Great article very helpful
Saturday, 13 October 2018 10:10 AM
Paul Caruana
Good article
Wednesday, 29 August 2018 9:09 AM
shiney bratt
great!
Wednesday, 05 September 2018 10:10 AM
Continue reading
695 Hits
4 Comments

COMING SOON: Silk4Net Scripting Essentials

COMING SOON: Silk4Net Scripting Essentials

Coming soon, a new fully featured course for Silk Test.

 

This new 1-day course has been developed as a fully-fledged Instructor Led Training course (ILT). The course includes progressive learning modules, including a hands-on lab experience to accelerate learning.

As well as developing a fully featured test scenario, learning is further enhanced and re-enforced through participation in a fully featured and expanded wrap up lab exercise and assessment.

Lab exercises are systematically themed, providing fully annotated instruction. Each module allows the student to build out live test scenarios that harness the major technologies employed in automated functional testing offered by Silk Test.

 

 

Recent Comments
Daniel Nolan
x
Wednesday, 25 July 2018 10:10 AM
Denis Bill
Great
Wednesday, 29 August 2018 5:05 AM
Canon Printer Support Number
Fantastic
Wednesday, 19 September 2018 12:12 PM
Continue reading
1345 Hits
3 Comments

UPDATED COURSE: 200 DA FOR RELEASE ENGINEERS

UPDATED COURSE: 200 DA FOR RELEASE ENGINEERS

Following the release of DA 6.2, 200 DA for Release Engineers  has been updated.

This course update contains the following additions and benefits:

 

  • New 6.2 features covered:
    • UI updates including Process Designer

    • Deployment Packages

  • End of module quiz assessments added:

    • Re-inforce learning

    • Provide additional group interaction

  • Additional lab exercise content covering:

    • Fail and Debug scenario  added

    • Improved UI navigation to harness UI improvements

    • Added Application Gates informationally and as a practical exercise

    • Added Pipelines informationally and as a practical exercise

    • Improved diagnostic checks

    • Limited step repeat scenarios – allow complex exercises to be completed more efficiently

    • Introduced systematic 15 point method for a new and fully functioning DA Application creation module

    • Deployment technology update including DA and CM Deployment comparison

       

  • Exercise improvements: more real life role-play work scenarios, simplified procedures

  • Content improvements: reformatting, improved layout and additional visual aids to understanding.

     


More information on the DA200 course can be found in the Course Outline.


More information on DA courses can be found in the:  Courseware Catalogue

 

 

 

 

 

 

 

 

 

Continue reading
984 Hits
0 Comments

Release Train for Solution Business Manager

Recently, we've formalized the release train for Solutions Business Manager (SBM) to be as predictable and agile as possible. By holding to a predictable release schedule, our hope is that customers will be better able to plan resources and schedule upgrades in a repeatable and standardized way. In addition, by releasing new versions often, new customer innovation and corrections to non-critical customer reported defects can be distributed more quickly.

Quarterly Releases

Our goal is to release a new version of SBM once a quarter. To achieve this cadence, we expect to generally alternate between minor and maintenance (update) versions. For each minor release (e.g. 11.3) we expect to release an update release in the following quarter (e.g. 11.3.1). This will then be following by a minor release the next quarter (e.g. 11.4) and the cycle repeats.

A minor release is defined as a release that may introduce new features or deprecate legacy features, but will not introduce significant architectural changes to the product. An update version may introduce enhancements to existing features but typically will not include completely new features. As needed, we may release a major release instead of a minor release which would include architectural changes, but this is not expected to happen often.

Codenames for releases

Generally, SBM uses code names for releases prior to achieving code complete. To make it easy to understand the cadence of SBM, code names are in alphabetical order and follow a theme. The theme for SBM is "cities in the United States". So, for example, we've had releases codenamed "Aurora", "Babylon", "Chattanooga", "Dillsburg" and "Eugene". Because the releases are in alphabetical order, you can always tell if a release comes before or after another - i.e. Dillsburg came after Chattanooga and before Eugene.

Upgrading has become routine

Improvements since the SBM 11.0 release have made upgrades efficient and quick to perform. For example, over the last 6 releases (releases from 11.0 to 11.4), Micro Focus has upgraded our internal production version of SBM in under 2 hours including both the upgrade and post-upgrade testing. Because it is much easier to upgrade than in the 10.x series, it is our hope that customers will stay current on the latest release and be able to participate in the quarterly release cadence.

 

We hope that this new predictable release train, coupled with easy identification and efficient upgrades, will enable customers to take full advantage of every release and the new capabilities provided in each version.

Continue reading
622 Hits
0 Comments

What's new in SBM 11.4?

Solutions Business Manager 11.4 released on May 24th, 2018. This minor release is intended to augment orchestration options, ease administration, improve navigation, enhance developer flexibility, and address customer ideas and defects. Here are some of the highlights from the release. 

New Application Administrator Interface

  What it is: The SBM Application Administrator user interface now leverages HTML5 functionality that results in an improved user experience for administrators including enhanced navigation, direct access to analytics and statistics, a tree view for projects, fewer clicks to view project or user details, and a modern look and feel.

  Why we did it: As has been widely communicated, Flash based technology is no longer considered secure enough for today's product offerings. By moving from Flash to HTML5, these security concerns are addressed. In addition, since all of the facets of Application Administrator had to be converted, we took the time to review navigation and launch points within SBM to improve how administrators use SBM. Finally, there's a trend today toward flat, monochromatic interfaces being driven primarily in the mobile marketplace, so we took this opportunity to embrace this trend so that Application Administrator feels in line with other parts of SBM.

New Scheduler Feature

What it is: The new Scheduler feature enables administrators to define and schedule jobs to perform tasks like run scripts, execute Web services, send email, call REST services, or raise orchestration events at a specific date and time or on a recurring basis.

Why we did it: Adding a native scheduler to SBM dramatically broadens the options available to a process designer by allowing asynchronous actions to be taken on a consistent basis. Rather than waiting for an event to be raised or external source to connect with SBM, SBM can now initiate such polling actions. For example, SBM can check with another solution to determine if unexpected changes have occurred and then notify stakeholders of the situation - even using the E-mail transition feature within SBM to allow a transaction to be performed remotely.

 

 Improved Runtime Statistics 

  What it is: Several new report types have been added to Runtime Statistics that provide usage statistics for Applications, Orchestrations, and Reports for a given time period including access counts, execution counts and run counts.

  Why we did it: There are two primary drivers for these enhancements. First off, statistics can be used to better understand how not only SBM as a whole is being used but also how an individual process app or report is being utilized. Rarely used items can be identified for sunsetting, or updating of commonly used items can be business justified. Secondly, administrators need to have tools to monitor unexpected resource use of the SBM system. By either watching real-time statistics or by setting thresholds, an administrator can be proactive about ensuring that SBM runs efficiently. If thresholds are set, SBM will even notify the administrator of an exceeded threshold and attach a link to a screenshot which will show a graph of the affected resource when the threshold was exceeded.

 Work Center navigation improvement

What it is: Administrators can now specify which categories to display or hide in the Work Center side menu for users.

Why we did it: For users not taking full advantage of all the views, reports, folders and dashboards available through SBM, we heard feedback that it was preferred to hide unused categories. By enabling these categories to be hidden per application group, administrators can ensure that the available categories will grow as the capabilities become required.

 

Other enhancements

Many new enhancements were first suggested on Serena Central. Those introduced in SBM 11.4 have now been marked as Delivered.

  • Work Center Search Improvements: Users can now select which work item fields are displayed in Work Center search results and search for archived items from Work Center.
  • Report Name Used for Exported Report: When you export a report to Microsoft Excel, the default file name is now the report name instead of tmtrack.xlsx.
  • SBM ModScript Improvements:  Several new functions and usability improvements have been added to SBM ModScript. The SBM ModScript documentation has been improved and expanded with new examples, detailed usage notes, and consistent formatting. In addition, a new blog series that provides background and training has been posted to Serena Central.
  • Command line orchestrations: Orchestrations can now be invoked via the command line - either at a command prompt or via a script.
  • "Where used" improvement: In Composer, the "Where Used" capability that shows where any design element is used in a process app and in referenced applications now searches workflow and transition overrides.

 In addition, Over 240 Customer-Reported Issues were fixed. A list of defects fixed in this version can be found in the Knowledge Base.

Important notice about User WorkSpace

In SBM version 10.1.3, Serena introduced a new paradigm in user experience with the SBM Work Center.  SBM User Workspace remained available in the product to enable organizations to transition from SBM User Workspace to SBM Work Center over a period of several releases. However, SBM 11.4 will be the final minor release to include the User Workspace shell. Customers are encouraged to adopt Work Center to interact with SBM in future releases.

Obtaining the New Version

You can download Micro Focus SBM 11.4 from Micro Focus SupportLine.

Learn More

You can view the recording for the What’s New in SBM 11.4 webcast that happend on May 30th. A demo of many of the above features was part of the presentation.

Continue reading
965 Hits
0 Comments

SBM ModScript, Part 12 - Class Inheritance

After looking into ChaiScript classes, I discovered that ChaiScript does not currently support class inheritance. This is common for scripting languages. However, as ChaiScript is such a powerful language, I was wondering how hard it would be to implement it. I came up with the following two options.

Option 1

Option 1 was updated on June 11, 2018 to introduce the "this.This" object, which allows for methods in the base class to invoke overrides on the child class.

def _getBaseVarName( obj ) {
  return "_${obj.get_type_name()}_base";
}

def _getBase( obj ) {
  return eval("obj.${_getBaseVarName(obj)}");
}

def _setThis( obj, ancestor ) {
  ancestor.This := obj;
  if ( eval( "!ancestor.${_getBaseVarName(ancestor)}.is_var_undef()" ) ) {
    _setThis( obj, ancestor._getBase() );
  }
}

def _addMethod( obj, funcname, containedFunc ) {
  var pts = containedFunc.get_param_types();
  
  // since we checked arity above, we know there will be at least 2 entries, so this is safe
  if ( pts[1].is_type_undef() || pts[1].name() == "Dynamic_Object" ) { // if parameter is for a Dynamic_Object class, this is true
    // ensure there are no guards on the parameters (pts[0] is return, pts[1] is "this"
    if ( pts.size() > 2 ) {
      for( var ii = 2; ii < pts.size(); ++ii ) {
        if ( pts[ii].name() != "Object" ) {
          return false;
        }
      }
    }
    
    var paramStr = ""
    for ( var ii = 1; ii < containedFunc.get_arity(); ++ii ) {
      if ( ii != 1 ) {
        paramStr += ',';
      }
      paramStr += "v${ii}";
    }
    eval( "def ${obj.get_type_name()}::${funcname}(${paramStr}){ this._getBase().${funcname}(${paramStr}); }" );
    return true;
  }
  return false;
}

def _verifyAndAddMethod( obj, base, funcname, func ) {
  var sParamVals = "";
  for ( var x = 1; x < func.get_arity(); ++x ) {
    sParamVals += ",0";
  }
  
  if ( eval("call_exists( func, base ${sParamVals} );") && // method exists on base object
       !eval("call_exists( func, obj ${sParamVals} );") && // method does not exist on this object (override)
       !func.has_guard() &&                                // method may not have guards
       !func.get_contained_functions()[0].has_guard() &&   // method may not have guards
       funcname != "This" &&                               // ignore "This" attribute
       !_addMethod( obj, funcname, func ) ) {
    for ( containedFunc : func.get_contained_functions() ){
      if ( !containedFunc.get_contained_functions().empty() && _addMethod( obj, funcname, containedFunc ) ) {
        break;
      }
    }
  }
}

def _setup( obj ) {
  _setThis( obj, obj );
}

def _inherit( obj, base ) {
  obj._getBase() = base;
  _setup( obj );
  
  global _inheritance;
  if ( _inheritance.is_var_undef() ) {
    _inheritance = Map();
  }
  
  // only set up this class inheritance once
  if ( _inheritance.count( obj.get_type_name() ) == 0 ) {
    _inheritance[obj.get_type_name()] = base.get_type_name();
    
    // must invoke get_functions every time, cannot filter and save list, as class definitions might occur after we 
    // hit this for the first time
    for ( func : get_functions() ) {
      if ( func.second.get_arity() == -1 ) {
        for ( inner : func.second.get_contained_functions() ) {
          if ( inner.get_arity() > 0 && !inner.get_contained_functions().empty() ) {
            _verifyAndAddMethod( obj, base, func.first, inner );
          }
        }
      }
      else if ( func.second.get_arity() > 0 && !func.second.get_contained_functions().empty() ) {
        _verifyAndAddMethod( obj, base, func.first, func.second );
      }
    }
  }
}
Usage:
class Base {
  attr id;
  def Base() { _setup( this ); }
  def Base( ID ) { _setup( this ); this.id = ID; }
  def go( x ){ print("go(x) | dynamicType: ${this.This.get_type_name()} | x: ${x} | id: ${this.This.id}"); }
  def go2( x ){ print( "go2(x) | hardcodedType: Base | x: ${x} | id: ${this.This.id}" ); }
  def go3( x, y ){ print( "go3(x,y) | hardcodedType: Base | x: ${x} | x: ${y} | id: ${this.This.id}" ); }
};

class Child {
  def Child() { 
    _inherit( this, Base() );
  }
  
  def Child( ID ) {
    _inherit( this, Base( ID ) );
  }
  
  // override that (optionally) invokes base
  def go2( x ){ print( "Child: ${x}: ${this.This.id}" ); this._getBase().go2( x ); }
};

class GrandChild {
  def GrandChild() { 
    _inherit( this, Child() );
  }
  
  def GrandChild( ID ) {
    _inherit( this, Child( ID ) );
  }
  
  // override that (optionally) invokes _base
  def go3( x, y ){ print( "go3(x,y) | dynamicType: ${this.get_type_name()} | x: ${x} | x: ${y}" );  this._getBase().go3( x,y ); }
};
What Does It Do?
  • In any given base class (class which does not inherit from another class, but will be inherited from), invoke "_setup(this);".
    • This will set up a "this.This" attribute on the object.
  • In the constructors of child classes, invoke "_inherit( this, )".
    • The class of the base object is used to determine the parent class of this object. It is important to use the same base class for every constructor for the child class. 
    • You can invoke any of the parent's constructors, allowing you to initialize the parent object as desired.
  • Behind the scenes of the _inherit() function
    • It will look at all the attributes and methods of the parent class and, if it doesn't find an override in the child class, it will define a method in the child class that invokes the method from the parent class. As such, any given child class object will have access to all the attributes and methods of the parent object.
    • The base object passed to _inherit is stored as a member on the child object. It is accessible via the "this._getBase()" method. This allows you to invoke the parent class method directly if desired.
    • Each object of type GrandChild will look like this (simplified):
      • GrandChild class
        • this = theGrandChildObj
        • this.This = theGrandChildObj
        • this._getBase() = theChildObj (Child class)
          • this = theChildObj
          • this.This = theGrandChildObj
          • this._getBase() = theBaseObj (Base class)
            • this = theBaseObj
            • this.This = theGrandChildObj
            • this._getBase() = undefinedObj
    • As you can see, in the GrandChild constructor, we create an object of type Child (which gets stored in the "this._getBase()" location). The Child constructor creates an object of type Base which gets stored in the Child object's "this._getBase()" location. Therefore, in any given method, you can call the parent object's version of the method by invoking this._getBase().method().
    • Each object will point to itself via the "this" attribute. Be careful when you use "this", as it is safer to use "this.This" to ensure polymorphic overrides are invoked.
    • Each object will point to the actual object via the "this.This" attribute. As such, any given method can polymorphically invoke the methods of the child object.
      • Do NOT use "this.This" when invoking "this._getBase()".
  • Watch out for guards on methods or parameters. It is just too complex to support class method overrides with guards, so they are not supported in this implementation. Also, each class is still separate as far as the ChaiScript class engine is concerned, so a function like "foo( Base bar )" will not recognize an object of type "Child". As long as you leave the guards out, all objects should act polymorphically correct.
Notes
  • Make sure to invoke _inherit() in every constructor on the child class, and pass in an object from the parent class.
  • Make sure to invoke _setup() in every class intended for usage as a base class. This will set up the "this.This" pointer, which allows the base class methods to invoke the overridden methods in the child class.
  • Attributes and Methods added to the parent class after a child class object has been created will never be visible to objects of the child class.
  • No classes in the class hierarchy may have methods with guards on the parameters or on the functions.
  • Objects of the child class will not convert to the base class, do not try to pass an object of type Child to a function like foo( Base bar ).
  • When invoking a method from the base class, code inside the base class method will treat the "this" object as if it is of the base class. Calls in the base method to other methods that have overrides in the child will not invoke the child override if you use the "this" object. To get the child methods to invoke from base methods, use the "this.This" object.
  • Classes built in to ModScript cannot be inherited from.

 

Option 2

There is another option, which has different benefits and drawbacks. The biggest drawback is that you cannot use the ChaiScript "class" syntax.

global _classInheritence_ = ["VirtualClass" : ""];
global _vtable_ = Map();

// All "classes" will be instances of VirtualClass, but with a different
// value for _classname_. It knows how to look up the stuff for the
// fake "class".
class VirtualClass{
  attr _classname_;
  def VirtualClass( sClass ) { this._classname_ = sClass; }
  
  // a method for invoking the function in the parent class
  def _callBase( classname, funcName, params ) {
    // verify "classname" is base of "this"
    var classnameSearch = this._classname_;
    while ( !classnameSearch.empty() ) {
      if ( classnameSearch == classname ) {
        break;
      }
      classnameSearch = _classInheritence_[classnameSearch];
    }
    if ( classnameSearch.empty() ) {
      Ext.LogErrorMsg( __FILE__ + ":" + __LINE__ + ": could not find base class ${classname} for ${this._classname_}");
      throw(0);
    }
    var f = _findVMethod( "${funcName}:${params.size()+1}", classname );
    var p2 = [this];
    params.for_each( back_inserter( p2 ) );
    return call( f, p2 );
  }
}

def _findVMethod( sFuncWithArrity, classname ) {
  var virtFuncArrity = _vtable_.at( sFuncWithArrity );
  var classnameSearch = classname;
  while ( !classnameSearch.empty() ) {
    if ( virtFuncArrity.count( classnameSearch ) == 1 ) {
      return virtFuncArrity[ classnameSearch ];
    }
    classnameSearch = _classInheritence_[classnameSearch];
  }
  Ext.LogErrorMsg( __FILE__ + ":" + __LINE__ + ": could not find function ${sFuncWithArrity} for class ${classname}" );
  throw(0);
}

def VClass( sClass, sParentClass ) {
  if ( _classInheritence_.count(sClass) == 0 ) {
    //eval( "global ${sClass} = fun(){ return VirtualClass( \"${sClass}\" ); };" );
    eval( "def ${sClass}(){ return VirtualClass( \"${sClass}\" ); }" );
    _classInheritence_[sClass] = sParentClass;
  }
}

def VClass( sClass ) {
  VClass( sClass, "VirtualClass" );
}

def VMethod( sClass, sFunc, f ) {
  if ( f.get_arity() < 1 ) {
    return;
  }
  else if ( f.has_guard() ) {
    Ext.LogErrorMsg( __FILE__ + ":" + __LINE__ + ": registerVirtual failed for function ${sFunc}, virtual function cannot have guard" );
    throw(0);
  }
  else {
    // check the params of f, reject if any params have a guard
    for ( p : f.get_param_types() ){
      if ( p.name() != "Object" ) {
        Ext.LogErrorMsg( __FILE__ + ":" + __LINE__ + ": registerVirtual failed for function ${sFunc}, virtual function cannot have guard on parameter" );
        throw(0);
      }
    }
  }
  
  var sFuncWithArrity = "${sFunc}:${f.get_arity()}";
  
  if ( _vtable_.count( sFuncWithArrity ) == 0 ) {
    _vtable_[sFuncWithArrity] = Map();
    var sParams = "";
    for ( var v = 1; v < f.get_arity(); ++v ) {
      if ( v != 1 ) {
        sParams += ',';
      }
      sParams += "v${v}";
    }
    
    // add a method to the VirtualClass that will look up the method for this "class"
    eval( 
"def VirtualClass::${sFunc}(${sParams}){ 
  /* _findVMethod throws if not found */
  var f = _findVMethod( \"${sFuncWithArrity}\", this._classname_ );
  return f( this ${sParams.empty() ? "" : ","} ${sParams} );
}" );
  }
  
  _vtable_[sFuncWithArrity][sClass] = f;
}

def VClassAttr( sClass, sMember ) {
  VMethod( sClass, sMember, eval( "fun(this){ return this._${sClass}_${sMember}; }" ) );
}
Usage:
VClass( "Base" );
VMethod( "Base", "go", fun(this, x){ print( "${this._classname_}: ${x}" ); } );
VMethod( "Base", "go2", fun(this, x){ print( "Base: ${x}" ); } );
VClassAttr( "Base", "id" );

VClass( "Child", "Base" );
VMethod( "Child", "go2", fun(this, x){ 

// optional call to base
this._callBase( "Base", "go2", [x] );
} ); VClass( "GrandChild", "Child" ); VMethod( "GrandChild", "go2", fun(this, x){ this._callBase( "Base", "go2", [x] ); } );

 

Notes
  • All objects are instances of the VirtualBase class
    • All methods and attributes for each class are added to the _vtable_ Map.
    • Each object has an attribute that tells it which class it is.
    • Function calls will look up the method for the current class, and if no override is found, will search up the class tree to find the method or attribute.
    • As opposed to Option 1, when invoking a method from the base class, code inside the base class method will treat the object as if it is of the child class. Calls in the base method to other methods that have overrides in the child will invoke the child override. As such, there is no need for a "this.This" attribute.
  • No virtual methods may have methods with guards on the parameters or on the functions.
  • All objects are of type VirtualBase, do not try to pass an object of type Child to a function like foo( Base bar ), but you can pass any objects from this hierarchy to a function like  foo( VirtualBase bar ).
  • Classes built in to ModScript cannot be inherited from.
  • Option 2 is faster than Option 1.
  • this._callBase() requires that you tell it the name of the base class, and it checks to ensure that the base class you select is an ancestor of the current class.

 

SBM ModScript Blog Series

Continue reading
848 Hits
0 Comments

DA 6.2: Evaluation Tutorial - Deployment Packages

DA 6.2: Evaluation Tutorial - Deployment Packages

A new feature in Deployment Automation 6.2. Deployment Packages allow you to orchestrate a series of Application or Component Deployments within a single Deployment Package process.

 

The attached Evaluation Guide allows you to create a deployment package from scratch using some simple JSON Applications.

 

Step 1: Create the first application 
Step 2: Create the second application 
Step 3: Create a Deployment Package 
Step 4: Test and run the Deployment Package

 

See the Evaluation Guide for more details.

 

Please check out the related video.

 

 

 

Tags:
Continue reading
505 Hits
0 Comments

SBM ModScript, Part 11 - Transitions

In ModScript, you can create objects based on Primary and Auxiliary tables. These objects can be used to Submit new items into those tables. Also, you can read items from the tables and then transition them. In Part 2, we used ProjectBasedRecord.QuickTransition() to transition a master item when all related items were closed.

 

To submit, first create an object for the desired table. When submitting, the current user must have privilege to submit into the desired aux table or project. The following methods are available for submitting:

  • VarRecord.StartSubmitToAux()
    • Start the submission process for the aux table. Fields will be initialized to default values.
  • VarRecord.FinishSubmitToAux()
    • After a call to VarRecord.StartSubmitToAux(), populate field values as desired, then invoke VarRecord.FinishSubmitToAux() to complete the submission process.
  • VarRecord.QuickSubmitToAux()
    • If no fields need to be set by the script, you can just run the submit directly.
  • ProjectBasedRecord.StartSubmitToProject()
    • Start the submission process for the project, project can be specified by project TS_ID, project internal name, or project UUID. Fields will be initialized to default values.
  • ProjectBasedRecord.FinishSubmitToProject()
    • After a call to ProjectBasedRecord.StartSubmitToProject(), populate field values as desired, then invoke ProjectBasedRecord.FinishSubmitToProject() to complete the submission process.
  • ProjectBasedRecord.QuickSubmitToProject()
    • If no fields need to be set by the script, you can just run the submit directly.

 

To execute a transition on an item, the object must first be created and then read.  ModScript can only invoke Regular, Update, and Delete transitions (not Post, Subtask, etc). The current user must have the privilege to execute the selected transition. The following methods are available for executing transitions:

  • VarRecord.GetTransitions()
    • Allows the script to get a list of the transitions that are currently available on the item. Only Regular, Update, and Delete transitions will be listed.
  • VarRecord.StartTransition()
    • Starts a transition on the item. The transition can be specified by transition TS_ID, internal name, or UUID. The default Update transition can be specified by sending 0. The default values will be set for fields. 
  • VarRecord.StartTransitionWithLock()
    • This method is the same as VarRecord.StartTransition() except that it assumes you have already established a record lock by invoking AppRecord.Lock() on this item.
  • VarRecord.FinishTransition()
    • After invoking VarRecord.StartTransition(), set the field values as desired, then complete the transition by invoking this method.
  • VarRecord.QuickTransition()
    • If no field values need to be set, the item can be transitioned in a single command. The transition can be specified by transition TS_ID, internal name, or UUID.

 

Notes
  • Each of these functions returns bool.  If false is returned, check Shell.GetLastErrorMessage() for more information.
  • It is possible for the transition commands to throw an exception. This will exit the script unless you wrap the call in a try/catch block.
  • AppRecord.Add(), AppRecord.Update(), AppRecord.UpdateWithLock(), and AppRecord.Delete() can be used to modify Primary/Aux items, but they will not invoke the workflow transitions.

 

SBM ModScript Blog Series

Continue reading
797 Hits
0 Comments

Recent Tweets