Best practices for developing applications in BMC Helix Innovation Studio
Access to applications
- Always create the bundle in Best Practice Customization Mode with overlay group ID 1. For more information, see Customization-layer.
- Leverage the BMC permission system to give end users and personas different permissions. For more information, see Managing-user-access-and-permissions.
- Do not create and use AR System groups as the permission system for the following reasons:
- Group IDs are global to a server and not to an application. Group IDs might conflict with groups from another application.
- Group IDs are not bundled with a bundle install, update, or content package because they are not scoped to a bundle.
- Do not use groups for permissions other than those provided by BMC because the groups are not specific to an application, which could cause potential conflicts.
- Instead of assigning Administrator privileges to users, use roles and functional roles.
Roles and functional roles are scoped to a bundle, and it is possible to assign functional roles to BMC Helix ITSM People data. For more information, see Creating-and-assigning-functional-roles. - Verify that the objects, accessible to end users, implement the appropriate permission system.
For example, verify that Views use the relevant roles and record definitions use the relevant roles, groups, and security labels. - Test the application with non-admin users.
- If permissions are not adequate, use security labels.
For example, use security labels to ensure that data from one company remains inaccessible to users from another company. For more information, see Enabling-row-level-security-by-defining-security-labels. - Don't use the BMC Reserved Group IDs range when you use groups. For more information, see Special-groups-in-AR-System.
General recommendations for developing applications
Review these recommendations when you develop applications.
Naming convention for code-based applications and libraries
- Do not use com.example which should only be used to create test applications or libraries.
- Avoid using bmc, com.bmc, com.bmc.arsys, bmc.arsys.com, com.bmc.dsm, helix, rx, ux, or ax in your application name, short name, and group ID to prevent confusion with BMC bundles.
- Use only lowercase characters for the application's short name and group ID.
- Use the customer company in the group ID.
For example, if the customer name is Apex Global, use com.apexglobal.pizzza-ordering. After creating an application, it is difficult to change its name.
Third-party libraries
Use libraries that BMC provides as much as possible. For example, use BMC Adapt icons for UI elements and Lodash.
To make the BMC ADAPT icons and graphics library accessible via a web server, perform the following steps:- Download the adapt-docs-14.46.0.zip file.
- Unzip the file.
Run a local web server and set its root directory to the same folder.
This can be done using different options. For more information, see the tutorials,Python SimpleHTTPServer - Python HTTP ServerandHow To Create a Web Server in Node.js with the HTTP Module.
Read the BMC Cloud Services Master Agreement prior to utilizing any open-source software. This agreement pertains to SaaS customers, and it is also important for on-premises customers to acquaint themselves with its contents. For example, GNU General Public License (GPL) and GNU Lesser General Public License (LGPL) licenses are not allowed. For more information, seeBMC Cloud Services Master Agreement.
AR System objects
Leverage BMC Helix Innovation Studio objects and workflow as much as possible. If you use AR System objects, make sure the AR System objects, workflows, and data are bundled as a D2P package. For more information, see Defining-a-package.
Records
- Use custom record definition s with caution because they are union-based and retrieve data from multiple AR forms or record definitions, which might affect the performance. For more information, see Creating-or-modifying-custom-record-definitions.
- It is not recommended to use an external record definition because AR forms can be directly accessed in a process or a view.
- It is not recommended to use a Web API record definition because it does not support operations such as sorting, pagination, and searching.
- If you create a join, make it public and customizable to avoid issues when the base AR forms or record definitions are overlaid. For more information, see Creating-join-record-definitions.
Processes
Avoid using objects from other BMC applications or libraries, such as BMC Helix Business Workflows because they might not be designed for use by a third-party application or library. Instead, raise an enhancement request at Innovation Studio Ideas .
The behavior of these objects might change from one version to another and might impact your application. If an object is not Public and customizable, it is not designed for use by a third-party developer or a non-BMC developer. You may use the object in the Base mode, but it will be overridden during the next upgrade.- They can still use the object in Base mode, but it will be overridden during the next upgrade.
- Do not use deprecated process activities.
You can identify such activities by the information icon and the text in their properties.
Codeless objects
Codeless objects consist of only definitions and data and do not include any Java or JavaScript code. Review the following best practices when you develop codeless objects.
Naming convention
Avoid using BMC, helix, rx, ux, or ax in object names to prevent user confusion.
Permission
For codeless objects, enforce the permission system where applicable, for example, in record definitions, views, processes, and configurations. For more information, see Managing-user-access-and-permissions.
Row-level security
- Use security labels to add, view, and edit restrictions to record instances and fields and provide more granular access control. For more information, see Enabling-row-level-security-by-defining-security-labels .
- In a process or a rule, add users, groups, and roles to a security label to make sure only users matching this combination can access the data.
For example, if you add the company Apex Global to the security label, users of Centari would not have access to the data. For more information, see Providing-access-to-record-instances-by-defining-security-labels.
Records
- Use reserved field IDs only when necessary, like when adding a new password field. For more information, see Reserved-field-ranges.
- It is not recommended to set the field length to 0 for a text field as it can affect performance.
For example, you might do that when storing very long data like an image encoded in base64. Developers often don't know what length to input, so they might set the length to 0 to make sure they have enough space rather than determine the necessary data size. For example, you might do it when when storing very long data like an image encoded in base64. - Enforce permissions by ensuring that record definitions use the relevant roles, groups, and security labels.
- Add relevant indexes in the database to improve performance.
Views
- Make sure to apply permissions wherever they are applicable.
- Avoid using CSS classes from a BMC bundle, such as those from BMC Helix Business Workflows. Such classes are not designed to be publicly available and might be changed or removed without notice.
- Avoid using view components or actions from a BMC bundle if they are not Public and documented in the documentation. Such components and actions might be changed or removed without notice. For more information about object definition scope, see Object-definition-scope .
- Refer to these BMC Community posts for more information about CSS classes in Views:
Rules
- Enforce a qualification to a rule to avoid the following issues:
- Infinite loops: If a rule is triggered On Update of a record instance and changes data on the same record instance, it could trigger the same rule again. To avoid such a scenario, use a flag field that is set to PROCESSING and verify the flag value in the qualification (flag = PROCESSING). The rule will change the field value to PROCESSED.
- Traversing too much data: For example, a time-based rule is supposed to check all lunch orders to verify their status. Without a qualification, all lunch orders would be verified, including those in Delivered status. To avoid this scenario, set a qualification on orders with the status Pending. For more information about the lunch-order application, see the Tutorial.
For more information about qualifications, see Defining-a-trigger-for-a-rule .
- Do not use the Get Records By Query process activity in a rule. It is not designed to return data and would be limited to the first record found.
Processes
- Add error handling for areas that might fail or trigger an exception. These areas could be web API calls, connector action calls, custom action calls, and so on. For more information, see Handling-errors-in-a-process. See also Handling-exceptions.
- When performing a multi-instance loop, check whether the collection is empty or contains too many elements.
- When using process activities that return data, such as a Get Records By Query, make sure you do the following:
- Use a qualification to return the required data and only select the fields necessary for your process. Otherwise, all fields would be fetched.
- Select the fields you are interested in instead of none, in which case all fields will be returned.
- Determine whether to retrieve all matching records or just the first one.
- When a process contains too many objects, note the following points:
- The process can be very hard to read and maintain.
- Split the logic into multiple processes and call those processes in your main process.
For example, if a process has multiple branches in an exclusive gateway and the process activities in each branch are very similar, create a new process with those activities. Call the new process in your main process.
- When you add alert codes in processes and rules:
For more information, see Configuring-processes-to-send-notifications-to-users.- Define a message ID when you use the Show Alert process activity.
- Make sure the alert code is unique to each message for better maintenance and debugging.
Associations
- It is not recommended to use many-to-many relationships unless they are absolutely necessary. For more information, see Associations-overview.
Use many-to-many relationships when both the record instances can be tied to other record instances instead of one-to-many or one-to-one. For example, multiple restaurants can use the same delivery service. It would not be accurate to say that one restaurant has many delivery services or that one restaurant has only one delivery service. - Add indexes in record definitions, if necessary, to improve performance. For more information, see Creating-or-modifying-regular-record-definitions.
- Use associations instead of join record definitions because associations have more capabilities.
Associations offer the following benefits:- You can follow an association in a Process Designer process or a grid in the View Designer.
For more information, see Enhancing-our-New-Order-view-to-use-associations. - You can leverage out-of-the-box UI and process activities to associate data.
For more information, see the following documentation:
- You can follow an association in a Process Designer process or a grid in the View Designer.
Named lists
- Use a qualification or a record grid in a view if the source record definition contains too much data or data irrelevant to the task at hand.
For example, listing companies that are not operating or listing all restaurants rather than those that are not closed. - Add indexes in record definitions if necessary to improve performance.
For more information about named lists, see Facilitating-data-entry-through-named-lists.
Code-based objects created by using Javascript
For information about developing code-based objects, see Developing-and-deploying-code-based-applications.
- Do not override BMC methods unless specifically allowed in the BMC Helix Innovation Suite documentation.
Do not create a component or action that BMC already provides; instead, consider creating an enhancement request (Idea) for the existing component at Innovation Studio Ideas.
Note the following considerations:
- The following types of objects are allowed: Actions, view components, record field view components.
- Use Global CSS classes in View Designer elements only if they don't conflict with BMC functionalities. As a web developer, you will see if a CSS class is overridden.
- The following operations are not allowed:
- Global Javascript method, cookie, or persistent storage
- Keylogger or monitoring solution
- Pure Javascript objects to access objects in the DOM. Instead, use the Angular or the BMC framework equivalent where available. For example, do not use document or window. Instead, use the exposed property of ViewChild() from Angular.
For more information, see the following documentation: - Storing of API keys or credentials in code because it’s a bad practice, and these keys can be easily accessed by reading the code using web browser tools.
- Dead code
Dead code refers to code that is never used or executed or code that is commented out.
Naming convention
For naming guidelines, refer to Coding and naming guidelines.
- Object names and file names must contain the bundle's fully qualified name to avoid naming conflict with BMC or other customer objects.
For example, if the application is com.mycompany.lunchorder, some object names could begin with comMycompanyLunchorder and the HTML templates could begin with com-mycompany-lunchorder. Use BMC SDK schematics because it will correctly generate the view action or view component name.
For more information, see Introduction-to-view-components-and-view-actions. See alsoSource code examples.- Do not use bmc, rx, ux, or ax to prevent conflict with BMC objects.
Data sanitization
Make sure you sanitize the data when you display it in HTML templates. Follow Angular guidelines to sanitize the data. For more information, seeAngular guidelines.
If you want to display HTML data in a view component, do not use bypassSecurityTrustHtml() to trust unsafe HTML code. Instead, sanitize the HTML by using Angular DomSanitizer or leverage the default Angular sanitization.
- When opening a URL by using window.open(), verify that the URL is safe by using Angular DomSanitizer.
Third-party libraries
Read the BMC Cloud Services Master Agreement prior to utilizing any open-source software. This agreement pertains to SaaS customers, and it is also important for on-premises customers to acquaint themselves with its contents.
- Third-party libraries are allowed but are subjected to review based on the following aspects:
- License
- Security assessment
- Necessary permissions or behavior
- Consider leveraging an NPM package if available.
- Avoid using PrimeNG components or styling because they might conflict with the versions that BMC provides.
- Do not use additional CKEditor plug-ins because they might require additional licenses, and BMC might decide to change the editor version for security reasons.
- Do not use the JointJs+ or Rappid third-party library provided in the SDK unless you have a license.
Logging
- Use the BMC logging services for logging.
- Avoid console.() methods. Instead, use the RxLogService service.
For more information, see Enabling-browser-logging-for-a-BMC-Helix-Innovation-Studio-application.
Error handling
- Catch exceptions in your code and log them accordingly.
Avoid silent error trapping. If you catch errors without logging them, they are difficult to track and fix.
Design time experience
Make sure view components, record editor field components, or action inputs are validated at design time. For more information, see validation .
- Use the right inspector and Tooltip to help the user in entering data.
For example, if it is possible to provide a list of values, use a list instead of free text. - When using additional UI elements, use the BMC Adapt library instead of importing a third-party library.
Enable lazy loading for code-based UI elements. For more information, see Lazy loading.
View actions
Before creating view components, record editor field view components, and view actions, see the Tutorial. See also Introduction-to-view-components-and-view-actions, Creating a View Action, and Coded view components .
Make sure the action name contains the bundle's fully qualified name.
For example, if the action is Notification, its name defined in this.rxViewActionRegistryService.register should be comExampleTest210500ActionNotification. The bundleId is the current code-based Application or Library bundleId.
For example,this.rxViewActionRegistryService.register({
// The best practice to avoid collision is to use in the action name
// the fully qualified bundle name, for example:
// <bundleId>Action<actionName>
name: 'comExampleTest210500ActionNotification',For more information, see Notification action.
View components and record field view components
Before creating view components, record editor field view components, and view actions, review the tutorial, Introduction-to-view-components-and-view-actions. See also Creating a View Actionand Coded view components.
Use BMC-provided schematics. The schematics automatically create the file structure, ensuring that the object names, such as the view component type and selector, are unique and tied to the bundle. They also ensure that view components are standalone. For information about standalone components, see standalone components.
- In the following example, the view component foo type and selector begin with the bundle name. com-example-myapp
registration module
type: 'com-example-myapp-foo',
view component selection
selector: 'com-example-myapp-foo-design',
- Use the ChangeDetectorRef to detach the change detector, which can help prevent memory leaks.
Services, pipes, design model managers, and constants
- If you implement services and pipes, make sure the name contains the fully qualified bundle name.
Inject the service in root to avoid dependency injection issues:
The following code is an example of a service calling a REST API:@Injectable({
providedIn: 'root'
})
export class ComCalbroPizzaOrdering {
- Pipes must be stand-alone components to be imported in a stand-alone view component:
Pipe
@Pipe({
name: 'iconFilter',
standalone: true
})
export class IconPipe implements PipeTransform {Pipe imported in a standalone view component
import { IconPipe } from './list-icons.pipe';
// ...
@Component({
selector: 'com-example-test210500-com-example-test210500-list-icons',
styleUrls: ['./list-icons.scss'],
templateUrl: './list-icons.component.html',
standalone: true,
imports: [CommonModule, AdaptRxSearchModule, FormsModule, AdaptAlertModule, IconPipe]
})
For more information about pipes, seepipe.
- If you create a constant file, make sure that the constant name contains the bundle's fully qualified name; for example, export const COM_CALBRO_PIZZA_INGREDIENTS
CSS classes for actions or view components
There is no real naming convention if the CSS is applied to a component because it will be scoped to that component. If you import the default CSS variables provided by the SDK, make sure not to use "~" in the path because it is deprecated in Angular 14 and later. For more information, see View component.
- The CSS is only applicable to that specific view component. Angular makes sure that the CSS classes and properties are contained and do not affect other components by using Shadow DOM or dynamically modifying the CSS class name during the build. Use the provided CSS variables rather than hardcoded values, such as $text-primary . This approach makes sure that if the tenant administrator changes the value in BMC Helix Innovation Studio skinning and branding, the value is reflected in the UI element:
- @import "styles/variables";
img {
cursor: pointer;
} - @Component({
selector: 'com-example-test210500-image-click',
styleUrls: ['./image-click.scss'],
templateUrl: './image-click.component.html',
standalone: true,
imports: [CommonModule]
})
@RxViewComponent({
name: 'com-example-test210500-image-click',
})
export class ImageClickComponent extends BaseViewComponent implements OnInit, IViewComponent {For information about skinning and customizing the appearance of your applications, see Tailoring-the-application-skin-and-brand.
Global CSS classes
- Do not override BMC CSS classes unless specifically allowed in the BMC Helix Innovation Studio documentation.
Do not change an HTML tag or a third-party component CSS class globally because it might affect other customers, applications, or libraries.
For example, this CSS class would override all HTML tables:table {
border: solid red 1px;
}
Do not change an HTML tag or a third-party component CSS class, even in the scope of a specific view component, because it might change the component behavior. If you decide to do so, make sure you test it thoroughly:
.com-mycompany-lunchorder-meal-order {
table {
border: solid red 1px;
}
}
- Do not import CSS files already leveraged by BMC.
For example, PrimeNG components might override CSS properties such as colors or styles, affecting the behavior of some BMC objects. - Do not use PrimeNG.
Most PrimeNG elements have equivalents provided in the BMC Adapt graphical library. Leveraging those Adapt components will ensure that they integrate seamlessly with other out-of-the-box (OOTB) elements and match the appearance of other elements used in BMC Helix Innovation Studio.
Refer to the examples and guidelines provided in the following documents:
Make sure the CSS class name contains the bundle's fully qualified name to prevent conflict with BMC or other customer CSS class names.
For example, if you want to add a red border for a container object, the class name must be: .<bundleName>-<className> ..com-mycompany-lunchorder-red-border {
border: solid red 1px;
}
Code-based objects created by using Java
For information about developing code-based objects, see Developing-and-deploying-code-based-applications.
- Do not override BMC methods unless it is specifically allowed in the BMC Helix Innovation Studio documentation.
- Avoid using bmc, rx, or ax because they might conflict with BMC objects.
- Avoid using process activity names that could be mistaken for a BMC product. For example, Assign Case could be confused with Case Management from BMC Helix Business Workflows.
- Do not create a process activity, datapage, REST API, or command already provided by BMC.
Naming convention
- The Java objects are scoped to their bundle, so there is no real limitation except in the earlier cases.
Object types allowed
The following object types are allowed:
- REST APIs, commands, process or rule activities, datapage queries, or other allowed object types as specified in the BMC Helix Innovation Studio documentation. Review the specific recommendations:
- Rest API : We recommend that you output JSON instead of text or HTML because the BMC Javascript SDK expects a JSON output.
- Commands: A command usually does not return values and is usually only used to trigger an action. If your command needs to return a value, it's better to create a REST API instead.
- Process or rule activities:
If an activity can be leveraged by processes or rules from a different bundle, make sure that the scope is Public:
For example:@Action(name = "getListValueByIndex", scope = Scope.PUBLIC)
public Object getListValueByIndex(@ActionParameter(name = "list") List<Object> list,
@ActionParameter(name = "index") int index) {
- Necessary support classes or utilities. For example, Incident and Workorder classes with a datetime conversion class.
Operations
- The following operations are not allowed:
- Leveraging AR System APIs that are not provided in the SDK
- Direct database SQL calls
- Static variable or object
- Keylogger or data storage
- Storage or access to files on the OS system layer
- Call to the OS system layer
- External script execution by the OS system layer
- Multithreading (you may use a time-based rule or a rule or process)
- Thread injection or thread data sharing
- User elevation, unless stated in the documentation.
- Dead code
Dead code refers to code that is never used or executed or code that is commented out.
Different objects, such as the REST APIs, actions, and others, must enforce user authentication and transactional behavior.
@RxDefinitionTransactional(readOnly = true, isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
@AccessControlledMethod(authorization = AccessControlledMethod.AuthorizationLevel.SubAdministrator, licensing = AccessControlledMethod.LicensingLevel.Application, checkSchemaForSpecialAccess = true, promoteStructAdmin = true)
Logging
Use the BMC log object as described in the documentation and the examples listed in Debugging and logging .
- Do not create separate log files on the OS file system.
Error handling
- Handle exceptions in your code gracefully and log them accordingly.
- Avoid silent error trapping or trying to catch errors without logging them.
Third-party libraries
- Third-party libraries are generally allowed but are subject to review.
A review process is necessary in SaaS deployments. There is no specific review process for on-premises deployments; however, it is important to determine whether you want to include unlicensed third-party software. If you plan to sell your BMC Helix Innovation Studio applications to your clients, you may need to consider licensing requirements. - The libraries must be cleared of vulnerabilities.
Do not use a different version of a library that BMC provides unless you confirm it does not conflict with the version bundled by BMC. Use the version BMC provides. Read the BMC Cloud Services Master Agreement prior to utilizing any open-source software. This agreement pertains to SaaS customers, and it is also important for on-premises customers to acquaint themselves with its contents.
Performance
- If a REST API call, a connector call, or process execution takes too long, release the call and create another one that will check its status instead of waiting for the execution to finish. For example, if a connector action triggers an environment deployment on Kubernetes that usually takes several minutes, it is recommended to create the following:
- An action, create environment, that will trigger the environment deployment and immediately return that the request has been acknowledged with the request ID.
- An action, request status, that will return the status of this specific request.
- A time-based rule or process that will periodically verify the status of the request and send a notification to the end user.
- If record definition data is fetched in a process, in the UI, or custom code by using a specific field, such as Customer ID, make sure to index that field in the record definition.
- Avoid any commands that would imply a pause in a Javascript or Java code:
- Any command that would imply a sleep in the main thread or Java code
- Javascript Synchronous calls
- Synchronous Timeouts
- In a process, implement a Timer object on the User Task or Receive Task to prevent the process from stalling indefinitely.
Installation and upgrade
This section provides best practices and recommendations to install and upgrade your applications.
Deployment
Consider the deployment strategy and the relevant bundles, reports, data, and AR System objects used for the upgrade and a timeframe if there is a dependency with a third-party system, such as Jira. For example, in SaaS deployments, if one Library has a dependency on Jira that requires a new field, notify BMC Support to deploy the bundles when the new Jira system is ready or it could trigger errors consuming a Jira Rest API with the new field on an older Jira system. In on-premises deployments, you need to plan it yourself.
Deployment format
Prepare a deployment document that lists the different elements to deploy, the deployment order, and the steps to follow before and after deployment. For example:
<bundle-1>.zip
<bundle-2>.zip
...
<bundle-n>.zip
If you need to import AR Systems objects, bundle them in D2P packages. In SaaS deployments, provide the necessary documentation and the correct import order. In on-premises deployments, prepare the documentation and the correct import order. For information about packages, see Defining-a-package.
D2P uninstall workflow 22.1.zip
D2P install workflow 23.1.zip
<bundle-1>.zip
<bundle-2>.zip
...
<bundle-n>.zip
Compatibility, Pre- and Post-upgrade steps, and Zero downtime (ZDT)
- Design your application so the upgrade does not impair the ZDT capability to avoid downtime.
- Check the following points:
- Does a script need to run?
- Does a process need to run that would require modification on most data (for example, to apply a new permission model)?
- Are there some required configuration changes?
- Would it require end users to log out of the application or clear their web browser cache?
- We recommend that the n+1 version of an Application or Library be fully backward compatible with a current system version. This approach would ensure a smooth upgrade experience for the end users. In the earlier example, the new version of the Bundle Library could detect the Jira version and handle both the old and new versions of Jira. We recommend that you ensure a patch or upgrade supports ZDT to avoid any service interruption.
Maintain and upgrade code-based bundles
- When upgrading to a major version, rebuild the code-based bundle using the latest SDK version. For more information, see Upgrading-to-the-latest-BMC-Helix-Innovation-Studio-SDK.
- We recommend that you upgrade and rebuild the bundle even if it only contains Java code and no custom UI elements such as view components, record editor field components, and view action.
- When creating a code-based bundle, consider the effort of upgrading it from a major version to another version. If the bundle is not rebuilt, the UI elements might not function properly.