SAP 3D Visual Enterprise Generator is a very customizable solution. However, unlike SAP ERP, there is no transport mechanism to automatically migrate content from one environment to another. The method for moving Processes through the different environments like Dev, QA, Prod, is a very manual one.
Along with this, there is not an easy way to deal with environment specific configuration properties. For instance, let’s say there’s another database that has some business data that needs to be merged into the 3D data as metadata. Also, that database has a Dev, QA, and Prod environment also. That means, your VEG process needs to know which database it needs to access based on which environment VEG is running in.
One option is to have a variable in the VEG process. However, when the process is migrated to QA, someone would need to update that variable to point at the QA database. This is ok the first time but if there is a change to the process in Dev and it gets migrated to QA, the variable needs to be modified again. This is the issue in a nutshell.
To resolve this, the SAP 3D Visual Enterprise Services team has come up with a best practice that allows for a configuration file that is outside the VEG Process but can easily be loaded in at runtime.
For this type of configuration file, YAML files tend to work the best. They’re much easier to read than XML and much, much easier to edit. JSON could be used but that one is still not as easy to edit but it is easier to read.
Here’s a good example of the difference between XML, JSON and YAML if you’re interested:
Before getting the YAML module, you’ll need somewhere on the VEG server to put it. The best place for this is the VEG_SHARE\Workspace\PythonLibraries folder.
NOTE: Replace VEG_SHARE with the actual path to the VEG Share directory.
NOTE: If the PythonLibraries folder doesn’t exist, please create it spelled that exact way so VEG can find it.
The next thing that needs to happen is VEG needs to know how to load YAML files by adding a Python library. PyYaml will be what is used here as it’s pretty well maintained.
Once there, click on the green Code button and select “Download ZIP”
Once PyYaml is downloaded, extract it and grab the pyyaml-master\lib\yaml directory itself.
Place the yaml folder in the PythonLibraries folder created previously.
The yaml folder should look something like this:
The YAML module allows Python to load YAML files but there’s no YAML configuration file on our Dev environment. Creating the config file is easy as YAML is a nice text file to create.
The best location for configuration files like this is somewhere in the VEG_SHARE\Workspace directory as this is an easy path to determine in a VEG Process that you will see shortly.
Create a new text file in the VEG_SHARE\Workspace directory called blog.yaml and edit it in a text editor like Notepad or Notepad++.
Use the following values for testing (including the — as that’s a header for yaml files):
--- database: someServer user: someUser pass: somePa$$
Save the file and that part’s all done.
Now that the YAML module is set up and the configuration file has been created, a VEG Process needs to be created to load it.
Using the VEG Administrator application, log in, go to the Server Configuration area, and create a new Process.
For this example, we will use:
Display Name: _TEST – Blog Example
The first operation is a Trigger so drag Trigger / filetrigger onto the workspace and press OK:
Then add a General / serverproperties_getall and press OK
The next step is to connect those two together by dragging from the bottom of the filetrigger to the top of the serverproperties_getall:
Now we need a new Scriptable Operation so we can add some custom Python code to load the YAML file and convert it to an XML output.
To do this, select the menu Operations -> New Scriptable Operation…
Set the Operation Name to py_yaml_load and Display Name to py_yaml_load
Then drag a filename parameter from the list on the right and drop it on the Input panel on the left.
Double click on the filename parameter that’s in the Input panel and specify the Name and Display Name to be yamlFile
Then, drag an xml parameter (you’ll need to scroll down a little) from the parameter list and drop it into the Output panel in the middle.
Double click on the xml parameter that’s in the Output panel and specify the Name and Display Name to be config.
The window should look like this:
Once you have that done, press OK.
Then, drag the new py_yaml_load operation onto the workspace and connect it after the serverproperties_getall operation:
The black lines just show the flow of execution but to connect properties together, we need to use the properties windows.
Double click on the serverproperties_getall operation and the py_yaml_load operation to open their properties windows.
Since our blog.yaml configuration file is in the VEG_Share\Workspace directory, we can use the GlobalWorkspace property for our yamlFile\directoryname property. To link these, expand the yamlFile parameter by clicking on the + next to the name. Then, drag the GlobalWorkspace property from serverproperties_getall to the py_yaml_load\yamlFile\directoryname parameter:
Then, put blog.yaml in the name parameter:
NOTE: Make sure the directoryname property is grey as that denotes that it’s an XPath statement that will be evaluated at runtime. However, the name property is black and editable because it’s a hard coded value.
Now, we need to set up the Python code to load the YAML file and put the output into the config parameter.
To do this, expand the script parameter and then select the code line and press the … button that appears.
Here’s the code we want to use to load the config file and put the output into the config output parameter:
def yaml2xml(yamlFile): import yaml from xml.sax.saxutils import escape data = yaml.safe_load(open(yamlFile)) def _parseValues(rslt, item): if isinstance(item, dict): for key in item: if str(item[key]) == "None": item[key] = "" rslt += "<" + key + ">" if isinstance(item[key], dict): rslt = _parseValues(rslt, item[key]) elif isinstance(item[key], list): rslt = _parseValues(rslt, item[key]) else: rslt += escape(str(item[key])) rslt += "</" + key + ">" elif isinstance(item, list): for idx in range(len(item)): val = item[idx] rslt += "<val>" if isinstance(val, dict): rslt = _parseValues(rslt, val) elif isinstance(val, list): rslt = _parseValues(rslt, val) else: rslt += escape(str(val)) rslt += "</val>" return rslt rslt = "<data>" rslt = _parseValues(rslt, data) rslt += "</data>" return rslt sap.output_parameters["config"] = yaml2xml(sap.input_parameters["yamlFile"])
Copy that and paste it into the Edit Script Code window and press OK.
To test the process, use the menu Debug -> Run. When the red box disappears from the py_yaml_load operation, you’ll know it’s done. Then use the menu Debug -> View Results Document.
Scroll down to the bottom and you should see the blog.yaml content converted into XML and inserted into VEG process log:
The final step would be to use one of these config properties in the Process. An example of this would be to use a General / log_message operation.
Drag one of them onto the workspace and connect it after the py_yaml_load operation.
Open the log_message properties by double-clicking on the log_message operation.
To create an XPath link, you’ll need to drag the py_yaml_load/config parameter to the log_message/message parameter.
However, that is not the correct XPath statement as we want to just log the database parameter. So, click the message property and select the … button that appears at the end of the line to open the XPath editor.
Then, edit the XPath Statement field so it specifies:
Then press OK.
Now, when you use the menu item Debug -> Run, you should see this in the Results window:
That means you can access the information from your configuration file easily from your VEG Process.
Now that this is working, you can safely migrate your VEG Process to QA and Prod and set up the blog.yaml config files in each server’s Workspace directory. That way, the VEG Process is disconnected from the configuration file and will just load it at run time.
I hope this has been a helpful blog post for those trying to make it easier to migrate VEG Processes through the development landscape.