Using Build Options in the deployment of APEX applications

Lately there have been some interesting changes in APEX regarding development and deployment of applications. Working Copies have been introduced, YAML exports, and of course we are looking forward to APEXLang. But one tool that has been around since the beginning of APEX, and is often overlooked, is Build Options, which in the latest versions of APEX also have got some improvements. In this blog post I will show how Build Options can be a valuable tool in development and deployment, and are powerful where Working Copies still fall short.

An example

Let me start with an example. I am working on an application, and I’m implementing user story SRY-001, which involves a large change in some package procedures, and also a signature change, so the calling Page Process in the APEX application also needs to be changed. When I’m finished, I install the new versions of the package and the APEX application into the Test environment. It’s a complicated change, so testing will take a while. Then I start working on a new user story SRY-002, implementing a new button, which invokes a new procedure. When finished, I also install it on Test. Now the business tests the second story really quick, and really wants to have that new functionality, so they ask me to put it to production as soon as possible. But now I have a problem, because SRY-001 has not been tested yet, and I cannot bring the APEX application to production without the changes made for SRY-001. Working Copies would not have helped me either, because I would have merged the changes into the main application before deploying it to the Test environment. But, as you would have guessed, Build Options come to the rescue here.

Build Options explained

Let me first explain the concept of Build Options. Actually a Build Option is like a switch, it can be On or Off. And that switch can be linked to almost all kinds of APEX components. When we create a Build Option, we get the following attributes:

  • Build Option: a name for the new Build Option.

  • Status: Include means that the components linked to this Build Option will be active in the current application, Exclude means they are not active.

  • Default On Export: whether the Status in the exported application will be Include, Exclude, or the same as in the current application.

  • On Upgrade Keep Status: when this is Off the Status of the Build Option will be overwritten on a new import of the application, with the value in the import file. When it is On the Status is kept the same on import (the value in the import file is ignored).

  • Comments: optional further explanation of the use of this Build Option.

Almost every component can be linked to a Build Option. This can be done in the Configuration section of the component properties.

A simple use for Build Options is to mark components only to be available in the Development environment (e.g. for debugging purposes). The Build Option would have a name like “Development only“, Status is Include and Default On Export is Exclude. Any components linked to this Build Option would be available in the Development environment, but not in the exported application, and therefore not in other environments. Another use is the “Commented Out” Build option, used to hide components without permanently deleting them.

💡
TIP: since APEX version 23.2 there is the possibility to Comment or Uncomment objects by a left mouse click on a component in the Page Designer. This will link or unlink a Build Option with the name “Commented Out“. In newly created applications this Build Option is standard available, but in applications created in older releases it is not, and the possibility to Comment and Uncomment does not exist. By adding the Build Option “Commented Out“ (with this exact case), with Status = Exclude and Default On Export = Same as Current Status, the possibility to Comment Out is made available to older applications.

Build Option API functions

The APEX_APPLICATION_ADMIN package (before 23.1 the APEX_UTIL package) has a function GET_BUILD_OPTION_STATUS and a procedure SET_BUILD_OPTION_STATUS. They provide a way to get or set the Build Option status from outside of the Application Builder.

The function GET_BUILD_OPTION_STATUS (which exists in two signatures) has two input parameters, the application id, and either the id (signature 1) or the name (signature 2) of the Build Option. It returns a varchar2 with the value of the status, INCLUDE or EXCLUDE.

The procedure SET_BUILD_OPTION_STATUS has only one signature. It takes three input parameters, the application id, the Build Option id, and the status to set, INCLUDE or EXCLUDE. Unfortunately it doesn’t take the Build Option name as a parameter, but we can easily write a custom procedure that does, see my example at Github.

The function and procedure are very useful in deployment, in combination with the On Upgrade Keep Status attribute, as we will see later.

Using Build Options in deployment

Key to the use of Build Options in deploying new features, is that a separate Build Option is created for every feature. That Build Option is then linked to all the new, changed or deleted components in developing that feature. Let’s clarify that in an example, starting with the SRY-002 story described above.

For that story, we create a new Build Option called SRY-002. The status is set to Include, so we have the new functionality in our development application, and the Default On Export is set to Exclude. This way we ensure that when someone else (or we for that matter) exports the application to deploy another feature to Test, our unfinished feature is not active yet. The On Upgrade Keep Status is set to On.

This feature only implements one new button, so on this button we now change the Build Option (in the properties under “Configuration“) to SRY-002.

The only thing we have to do now is to add a line to the install script. When we export the application, and install it into the Test environment, the status of the Build Option will be Exclude (that was the Default On Export that we have set). To make the functionality available, we have to call the SET_BUILD_OPTION_STATUS procedure to set it to Include. So our install-SRY-002.sql will look something like this:

-- install application 123
@f123.sql
-- set build option status
execute apex_api_extensions.set_build_option_status(p_application_id    => 123
                                                   ,p_build_option_name => 'SRY-002'
                                                   ,p_build_status      => 'INCLUDE');

When after our install, a new install of the application is done, the On Upgrade Keep Status setting will make sure that the Build Option status remains Include, so the functionality will continue to work in the Test environment. And of course this will also hold for subsequent installs in Acceptance and Production.

For the SRY-001 story we have to do the same. First create a Build Option like above, this time called SRY-001. As this story involves a change of a component (a Page Process) things get a little more complicated. In the resulting application both the old and the new functionality will have to be present. The trick is to make a copy of the component (easily done using ”Duplicate” in the right mouse menu), change the name of the copy to the original name with something like “v2“ added (as two page processes cannot have the same name), and make the changes for story SRY-001 in the copy. Then attach the Build Option SRY-001 to the copy, and attach the negated Build option {Not SRY-001} (which is also in the drop-down list) to the original. And add a call to SET_BUILD_OPTION_STATUS in the install script, to set the status of Build Option SRY-001 to Include. When exporting the application, and importing it into the Test environment, the status of Build Option SRY-001 is set to Include in the install script. The status of Build Option SRY-002 remains Include (although the newly imported file contains Exclude), because the On Upgrade Keep Status is On.

With all this in place, it is now possible to bring only feature SRY-002 to Production. The install script in Production will set the status of Build Option SRY-002 to Include, but will leave the status of SRY-001 on Exclude. Therefore the copy of the Page Process that we have changed for story SRY-001 will not be executed, but the original (with the negated Build Option {Not SRY-001}) will.

Cleaning up afterwards

After a feature has been brought to Production, the associated Build Option is no longer necessary and can be deleted. All components with the negated Build Option will also have to be deleted. This cleaning up is necessary, because a component can only have one Build Option, so without cleaning up you will run into problems when the same component will have to be changed again in a new feature.

When you open the Build Option in the Application Builder, at the bottom you will see the Associated Components. The Build Option will have to be removed from these components, and the components which have the negated Build Option must be removed altogether. There is even the option Remove Components, but unfortunately this will do exactly the opposite: it will remove all components having the Build Option, and remove the Build Option from the components having the negated Build Option. While this is useful for a story that in the end won’t make it to Production, in general this will not help us for our goals. So for now removing the Build Option will remain a manual task (but there is a workaround, keep reading).

🐛
As I would like to have the opposite of Remove Components, i.e. remove components with the negated Build Option and remove the Build option from components having the normal Build Option, I created an idea in the APEX Ideas app: APEX Idea FR-4518. It is closed, because it apparently relates to a bug. I hope this will be fixed in a future release.
If there are still associated components, you must not delete the Build Option! The reference to the Build option will be removed from all the components, so it is no longer clear which components had the negated Build Option. In older versions of APEX the reference to the Build option was not be updated in the components, so all components remained with an invalid Build Option id. Safest is to first remove the Build Option from all components, and then delete the Build option.

The ideal solution

Because the Remove Components option does exactly the opposite from what is helpful in our situation, we can turn this around from the beginning:

When we start a story SRY-002, we create a Build Option with the name pre-SRY-002, with Status is Exclude and Default On Export is Include, i.e. exactly the opposite from before.

Any new component created in story SRY-002 is now linked to the negated Build Option {Not pre-SRY-002} (i.e. after SRY-002). For changed components the old version is linked to pre-SRY-002, the new version to {Not pre-SRY-002}. Deleted components are linked to pre-SRY-002. Also the SET_BUILD_OPTION_STATUS call in the install file will have to updated, to now set the Build Option Status to Exclude.

-- install application 123
@f123.sql
-- set build option status
execute apex_api_extensions.set_build_option_status(p_application_id    => 123
                                                   ,p_build_option_name => 'pre-SRY-002'
                                                   ,p_build_status      => 'EXCLUDE');

In terms of functionality now everything works the same as described before, only the Remove Components option does exactly what we want when we are ready to clean things up, removing the old components and leaving the new components, without the Build Option.

This is conceptually somewhat more difficult to grasp, but it helps us in doing exactly what we want with minimal effort.

Conclusion

Build options can help in differentiating between features in APEX applications, when some features need to deployed independently of others. A Build Option needs to be created per feature, and attached to each new, changed or deleted component. With a smart choice of configuring, the Remove Components option in the Build Option can be used to cleanup afterwards, avoiding the need of tedious manual removal of the Build Option configuration of components.

1
Subscribe to my newsletter

Read articles from André van der Put directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

André van der Put
André van der Put