Project: User-Added Function Implemented by Action Block (Part2)

I mentioned about launching a new incubator project. The primary goal was to build a tool helping in the development of so-called user-added functions for the CA Gen. It was couple weeks ago. The first experimental version of the Eclipse project delivering such tool you can find here published on the GitHub for the public viewing. You will be able to download the standalone UAF utility from here. I would like to remain you that all software downloaded from this website is experimental and you should not use it in the production environment until tested adequately.

This post provides a detailed information how to install and use the UAF utility by creating a simple user-added function in the CA Gen Model, later referred to as a function.

Installing software

Step 1. Download and expand zip file

The utility consists of the executable jar file and directory with the number of jar files required to run the UAF utility. Your installation directory will look as follows.

Step 2. Copying CA Gen jar files

The utility is using a number CA Gen jar files which you can find in the CA Gen installation directory. You need to copy them into the subdirectoryuad_lib. They are:

com.ca.gen.jmmi_8.5.0.00333.jar, abrt.jar, csu.jar, odc.jar, vwrt.jar

Above jar files containing JMMI API allowing access a CA Gen model located on the workstation and some runtime classes allowing run mockup software required to do unit-testing of your newly developed functions.

Step 3. Starting utility

You need to run the utility from the command line. Here is how to display help information.

Utility  User-Added Function (UAF), Version 0.5
Usage:  java  -jar uaf.jar  modelpath cagenpath [ -forceall | -testonly  | -sourcesonly]
     where:
        -forceall   force clean up entire generation frastructure
        -testonly   generate test classes only
        -sourcesonly   regenerate implementation classes only

You will learn more about parameters and options later.

Defining user-added function

We are going to use the CA Gen Toolset to develop a library of functions. This is very easy and straightforward process.

Step 1. Create a new CA Gen model

Best practice is to start creating a new dedicated empty model and use it to define all functions in your library. Additionally, you can use such model later to implement some of your functions using some purpose written action blocks created in this model.

Step 2. Set environment for generation

You will notice that your model has one Business System having a name like your model. Select Environment under Construction and select our business system by double-clicking on the name. You will see the following window pane opens allowing set some properties for the selected business system.

The utility can generate only for the Java environment at present. Therefore, be sure that selected operating system is JVM, language is  Java and you set correct name for the package.

Step 3. Create action block

You are defining a function by creating your action block. Not all action block can serve as a template. Qualifying action block should have some attribute views defined in the import section and single attribute in the export section.

We are going to create a rather simple function first whose whole purpose will be to add two numbers and return a sum of them as a result. We expect that our new function will take two parameters of type number and return a single number.

 
Model : TSTUAF1                                       10 Sept. 2017  22:24
Subset: (complete model)                                         
                                                                           
                          BSD Action Block:  FAB01
___________________________________________________________________________

Action Block Description:
#meta {
import eu.jgen.notes.uaf.proc.Function;
@Function (CGName="XFAB01", useselec=false, impl=true)
// Adds two numbers and returns sum of those numbers.
}

 +- FAB01
 |    IMPORTS: 
 |      Work View   imp1 ief_supplied (optional,transient,import only)
 |        count (optional)
 |      Work View   imp2 ief_supplied (mandatory,transient,import only)
 |        count (mandatory)
 |    EXPORTS: 
 |      Work View   exp ief_supplied (transient,export only)
 |        count 
 |    LOCALS: 
 |    ENTITY ACTIONS: 
 |  
 |  USE ab02
 |      WHICH IMPORTS: Work View   imp1 ief_supplied  TO Work View   imp1 ief_supplied 
 |                     Work View   imp2 ief_supplied  TO Work View   imp2 ief_supplied 
 |      WHICH EXPORTS: Work View   exp ief_supplied  FROM Work View   exp ief_supplied 
 +--

The above action block qualifies as a template for the function and we will use it to create such function. Also, please notice that action block has one statement. The statement is USE statement and invokes another action block. This is an unnecessary complication, but it demonstrates that function’s implementation can invoke a number other action blocks if necessary.

 
Model : TSTUAF1                                       10 Sept. 2017  22:28
Subset: (complete model)                                         
                                                                           
                           BSD Action Block:  AB03
___________________________________________________________________________

Action Block Description:

 +- AB03
 |    IMPORTS: 
 |      Work View   imp1 ief_supplied (optional,transient,import only)
 |        count (optional)
 |      Work View   imp2 ief_supplied (mandatory,transient,import only)
 |        count (mandatory)
 |    EXPORTS: 
 |      Work View   exp ief_supplied (transient,export only)
 |        count 
 |    LOCALS: 
 |      Work View   loc ief_supplied 
 |        command 
 |    ENTITY ACTIONS: 
 |  
 |  SET exp ief_supplied count TO imp1 ief_supplied count + imp2 ief_supplied count 
 +--

The statement in the last invoked action block has our implementation logic and simply adds two numbers. On this occasion, we are going to use newly created action block to implement the logic of our function as well. Please notice that only first action block has the annotation.

Step 4. Annotate action block

We are using Java style annotations to mark action block as a template creating function. You find the following annotation added to the description of our action block.

 

The @Funtionannotation allows providing additional information required for creating a function in the CA Gen model. The CGName parameter specifies the generated function internal name. It should be unique among already existing functions including those provided by the CA Gen. The useselecparameter indicates whether the function will take part in a database SELECT statement as selection criteria. The parameterimpl indicates whether the action block should be used as implementation. You may decide to implement function entirely outside of the CA Gen or only partially using also dedicated action blocks.

This step completes a process of defining the function. Rest of processing is generating artifacts using our UAF utility.

Step 5. Running utility

You will need Java 1.8 to run, but you can regenerate project with another version of Java. Version 1.7 should be fine. Utility takes two parameters. The first parameter points to the location of the CA Gen model with templates created in the previous step. The second parameter points to the location of the CA Gen itself. Here is sample output produced when running the utility.

Utility  User-Added Function (UAF), Version 0.5
Starting...
Connected to local model: TSTUAF1
WARNING: All subdirectories were forced to be emptied.
INFO: Adding subdirectory. 
INFO: Adding java functions subdirectory. 
INFO: Adding meta-inf subdirectory. 
INFO: Generation directory used: C:\jgen.notes.models.test\tstuaf1.ief\notes
INFO: Project file with Java nature created. 
INFO: Classpath file with CA Gen libraries created. 
INFO: Found 1 function(s).
INFO: XML file for 1 function(s) created.
INFO: Creating  package sub-directories for functions: C:\jgen.notes.models.test\tstuaf1.ief\notes\src\com\ca\gen\abrt\functions
INFO: Function com.ca.gen.abrt.functions.XFAB01 generated.
INFO: Creating  package sub-directories for functions: C:\jgen.notes.models.test\tstuaf1.ief\notes\src\com\ca\gen\abrt\functions\test
INFO: Function Test Classcom.ca.gen.abrt.functions.XFAB01Tests generated.
WARNING: Test class was regenerated. All previous modifications were lost.
INFO: Implementation action block AB03 generated.
INFO: Implementation action block AB02 generated.
INFO: Implementation action block FAB01 generated.
INFO: MANIFEST.MF file created. 
Processing completed.

Utility produces some messages as progress thru the generation process. The utility does not modify your model and is accessing model in the read-only mode.

Step 5. Reviewing generated artifacts

You will find that your local model directory’s structure has changed and you have a new subdirectory notes and its internal structure is as follows.

The utility creates Eclipse plug-in project structure that you can import into the Eclipse as a new project. The project has Java nature, and all Java artifacts will be compiled as soon import completes.

Step 6. Import project into Eclipse

You need to start Import wizard, select Existing Projects into Workspace and press Next.

You need select root directory and our new project will show up on the list of projects. Select project and press Finish.

 

You will notice that you have a new project in your workspace. The project is instantly built.  You can expand folders to see what has been generated for you.

 

Starting from the top, the folderjava has sources of all action blocks marked by annotation and all other action blocks that may be used by the annotated action block. Next, the foldersrc contains the source of the function and testing harness for the unit testing. On the bottom, you will find XML userfunctions.xmlfile with the definition of the function. The CA Gen Toolset will use this file to create the function inside the CA Gen model.

Testing user-added function

Your functions can be relatively straightforward and tested easily, but in some cases, you will need to ensure a proper test cycle. This includes unit test done in a separation of other software components. The UAF utility can help generating for you some testing classes invoking the function with your choice of input parameters and checking if result matches expected value. The proposed testing framework provides mock-up setting simulating real runtime environment. You do not need to run the web server and deploy test application to the server to conduct such tests.

Here is generated code for our sample function.

/**
* Code generated by UserAddedFunctionProcessor
*/
package com.ca.gen.abrt.functions.test;

import static org.junit.Assert.assertTrue;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import com.ca.gen.abrt.functions.XFAB01;
import com.ca.gen.vwrt.types.IntAttr;
import com.google.inject.Guice;
import com.google.inject.Injector;

import eu.jgen.notes.ab.direct.mgr.ActionBlockModule;
import eu.jgen.notes.ab.direct.mgr.DBMSType;
import eu.jgen.notes.ab.direct.mgr.DirectException;
import eu.jgen.notes.ab.direct.mgr.SessionContext;
import eu.jgen.notes.ab.direct.mgr.SessionManager;
import eu.jgen.notes.ab.direct.mgr.TransactionManagerType;

/**
 * @author
 *
 */
public class XFAB01Tests {

	static Injector injector;
	private static SessionManager sessionManager;

	/**
	 * @throws java.lang.Exception
	 */
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		try {
			injector = Guice.createInjector(new ActionBlockModule());
			sessionManager = injector.getInstance(SessionManager.class);
			sessionManager.initialize(TransactionManagerType.None, DBMSType.None).begin();
		} catch (DirectException e) {
			e.printStackTrace();
		}
	}

	/**
	 * @throws java.lang.Exception
	 */
	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	@Test
	public void sampleTest() {
		IntAttr result = IntAttr.getInstance();
		XFAB01.XFAB01(new Object(), new SessionContext(sessionManager.getGlobData()), sessionManager.getGlobData(), 2,
				2, result);
		assertTrue(result.get() == 4);
	}

}

The only change to the generated code was to modify method assertTrue and set values for two input parameters.

The test classes are not always generated. You need to run the utility with the-testonly parameter to have them generated.

Delivering user-added functions

The CA Gen does not know about your new function at this point. You need CA Gen Toolset to find user-added function and create relevant changes in the Gen model. One of the generated artifacts is the XML file.userfunctions.xml You will find file having the same name in one of the directories created after CA Gen was installed. The directory name isC:\ProgramData\CA\Toolset. This file contains some user-added functions provided by the CA Gen. You need to merge those files or, for time being, rename original file and copy in your one generated by our UAF utility. Once you start the CA Gen Toolset our function will be visible and available for use.

You will find more about user-added function here on the CA Gen Documentation website.

Developing application using functions

Here a snapshot of the procedure step developed in the another model that uses the newly developed function.

Model : USEUAF1                                       10 Sept. 2017  23:10
Subset: (complete model)                                         
                                                                           
                          Procedure Step:  USRUAF1
___________________________________________________________________________

Procedure Step Description:

Action Block Description:

 +- USRUAF1
 |    IMPORTS: 
 |      Work View   imp1 ief_supplied (optional,transient,import only)
 |        count (optional)
 |      Work View   imp2 ief_supplied (optional,transient,import only)
 |        count (optional)
 |    EXPORTS: 
 |      Work View   result ief_supplied (transient,export only)
 |        count 
 |      Work View   exp1 ief_supplied (transient,export only)
 |        count 
 |      Work View   exp2 ief_supplied (transient,export only)
 |        count 
 |    LOCALS: 
 |    ENTITY ACTIONS: 
 |  
 +--
 +- EVENT ACTION usruaf1_pb_add_click
 |  SET result ief_supplied count TO fab01(imp1 ief_supplied count, imp2 ief_supplied count) 
 +--

Deploying application

There is no difference to the standard way of building and deploying an application with user-added functions. However, you need to remember to build a jar file with some classes from the model you are using to develop your functions.

You need to make your jar visible to the Build Tool so application consuming your function can successfully compile your application. You jar file needs also to be included in the application ear file by the Assembly process.

You can see the sample application running after deploying to the Weblogic server.

Java Wrapping for CA Gen Encyclopedia API

Historically first officially published CA Gen API was the Encyclopedia and Workstation Application Program Interface (API) software for CA Gen. It supports the Host Encyclopedia and the Client Server Encyclopedia (CSE) for all available API platforms and databases. It also supports local access to workstation models, Host Encyclopedia, and the CSE for all available API platforms and databases.

The Encyclopedia API is a set of C functions, include files, and libraries. You must be familiar with the C programming language and the software development tools for the platform on which you are working in order to use the Encyclopedia API. You must also be familiar with the CA Gen meta-model.

Today we have CA Gen JMMI API written in Java. The JMMI was introduced when CA Technologies announced the CA Gen Studio built on the Eclipse platform. The JMMI is frontend written in Java, but most of their methods are native methods written in C++. The JMMI does not offer access to the models stored in one of the supported encyclopedias (HE and CSE). Therefore, the Encyclopedia API is the only way to access models stored in the HE and CSE.

The JGen Notes Core Java project is offering Java wrapping for the models located on the workstation only (limitations of the CA Gen Free Gen), but those interfaces can be easily extending to the model located in the remote places like Client Server Encyclopedia (CSE) or Host Encylopedia (HE).

You can find sources of the implementation here and here.

 

Developing plug-ins in Java for Gen Toolset

Overview

CA Gen allows applications to access the currently opened model through a mechanism that is known as a plug-in. The application should register itself in the Windows registry, and from there the CA Gen toolset knows how to call it. Toolset adds a menu item to the CA Gen “Plug-in” menu. The developer starts plugin from the toolset after Toolset opens model for processing.

You will find more information about CA Gen Toolset Automation here.

However, there is a problem when you are willing to develop something in Java language. The problem is because the plug-in application should instantiate a pointer to the currently opened toolset using the toolset OLE automation interface. Such interface allows the application to access the functionality provided by the interface. Unfortunately,  Java program cannot do it without using some software bridging those two different technologies.

Fortunately, Eclipse is using the SWT GUI framework. SWT does allow to integrated Microsoft application via OLE (Object Linking and Embedding). You can locate jar file org.eclipse.swt.win32.win32.x86_3.3.0.v3346.jar in the subdirectory of your Eclipse installation. Subdirectory name is  plugin.

It has the SWT Win32 OLE implementation classes. Classes provide the public API to the Microsoft Win32 Object Linking and Embedding mechanism that the win32 variant of SWT is capable of using. Referencing any of the classes in this package directly guarantees that the code is platform specific.

You can consult tutorial “Microsoft and Java Integration with Eclipse” written by Lars Vogel here. It helps understand the SWT Win32 OLE implementation classes and shows examples of the use.

Idea developing plugs using Java resulted in the need for some easier ways to access the Gen model and hide the complexity of the SWT Win32 OLE implementation classes. The Toolset Automation Wrapper is a package of Java classes doing just that. The Toolset Automation Wrapper does not cover all functionality offered by the Toolset Automation.

You can download Java documentation and jar file with the wrapper classes here.

You can find Eclipse project on GitHub here.

Sample Application

Sample application connects to the currently opened model in the CA Gen Toolset and lists all business systems defined in the model. The application is a simple Java class with the method main().  You need to run the application from the command line. Yon need be sure that you have two jar files on the classpath. They are jmmi and ToolsetAutomationWrapper.

Here is the source of the application:

package eu.jgen.notes.automation.example;

import com.ca.gen.jmmi.schema.ObjTypeCode;
import com.ca.gen.jmmi.schema.ObjTypeHelper;
import com.ca.gen.jmmi.schema.PrpTypeCode;
import com.ca.gen.jmmi.schema.PrpTypeHelper;

import eu.jgen.notes.automation.wrapper.JGenEncyclopedia;
import eu.jgen.notes.automation.wrapper.JGenFactory;
import eu.jgen.notes.automation.wrapper.JGenModel;
import eu.jgen.notes.automation.wrapper.JGenObject;

public class ListAllBusinessSystems {

	public static void main(String[] args) {
		// create instance of the factory class
		JGenFactory factory = JGenFactory.eINSTANCE;

		// create instance of the encyclopedia
		JGenEncyclopedia ency = factory.createEncyclopedia();

		// connect to the encyclopedia (model needs to be opened in the toolset
		// already)
		ency.connect();

		// select model for processing
		JGenModel genModel = ency.findModels()[0];
		System.out.println(genModel.getName());

		// find all business system in the model
		JGenObject[] bussyss = genModel.findTypeObjects(ObjTypeHelper.getCode(ObjTypeCode.BUSSYS));
		for (JGenObject bussys : bussyss) {
			System.out.println(bussys.findTextProperty(PrpTypeHelper.getCode(PrpTypeCode.NAME)));
		}
	}

}


The application will print the following messages on the console for the sample.ief model which is coming with the standard CA Gen installation on the workstation.

GEN SAMPLE MODEL 8 6
CORPORATE_MANAGEMENT
GUI_CORPORATE_MANAGEMENT
COOP_CORPORATE_MANAGEMENT

Summary

Solution and sample application have been developed using the following software:

  • Windows 10
  • CA Gen 8.6 (Free)
  • Java Version 8 (Update 20)
  • Eclipse Neon.3 Release (4.6.3)

Researching  contents of  local model using JGen Notes Walkency

CA Gen Documentation provides Encyclopedia API Reference which is place providing a lot of information about internal of the CA Gen model and metamodel which describes a structure of the model. Metamodel shows the properties and object associations that are inherited and from which objects they are inherited. The metamodel is the CA Gen Information Model. Additionally, you will find in your CA Gen installation directory file with published Object Decomposition Report presented in a hierarchical format. Name of the file is odrpta. This is the Microsoft’s standard help format (chm).

odr

 You will find here a link to the web page describing utility allowing explore the internal structure of the local model on the workstation easily and comprehensively.  Its name Walkency refers to traditional tools used to display contents of the model stored in the Host Encyclopedia (HE) and Client Server Encyclopedia (CSE). JGen Notes Walkency is the reincarnation of such tool dedicated for the developers using the CA Gen Toolset. JGen Notes Walkency is written entirely in Java and developed as Eclipse Rich Client.

Technically, from the CA Gen Toolset perspective, JGen Notes Walkency is a plug-in registered with the CA Gen Toolset and available for use when selected from the menu system of the CA Gen Toolset.

Zrzut ekranu 2017-06-19 o 20.15.17