Skip to content

Dynamic Dependency

IFS Application is a component-based soultion that provides organizations with the flexibility to select and integrate specific components according to their requirements. The combination of these chosen components forms a tailored solution set. There are more than 250 components, and when it comes to a solution set, each of these component would have static or dynamic dependencies on one another. If an IFS Client page needs to refer to an element located inside a dynamic component, the element should be annotated as a dependent element of a dynamic component.

Purpose of this document is to provide you with necessary tips and tricks on how to use Conditional Compilation to declare dynamic dependencies between components.

Solution Sets and Dynamic Dependency

Solution Set is a concept introduced in IFS Cloud being a simple configuration which defines what components should be enabled or disabled from the whole IFS component suite.

Being integrated with Developers Studio and Code Generation, any active Solution Set configuration will simply act as a filter and, show and/or Code Generate the enabled components and remove and/or not Code Generate the disabled components

The whole impact of a Solution Set definition is seen first when we start to code generate IFS Cloud. Components that are disabled (false) will not be shown in the Projects Navigator and therefore not being possible to code generate. For components that are enabled (true), there will also be a noticeable change during the code generation as the model files containing items marked with the DynamicComponentDependency attribute will check the component availability using the Solution Set definition. If the dependent component is disabled (or not listed in the SolutionSet), the result will be same as if the mentioned component was not physically available on disk. That means that the entire section below each DynamicComponentDependency annotation will be removed, not being part of the code generation.

Refer to Working with Solution Sets to get more information on deployment and installation properties of a component.

Components and Their Static or Dynamic Dependency

Components serve as containers that group entities, utilities, and enumerations into installable units, creating a logical framework for development. The interaction between these components occurs through 'Public' interfaces. In simpler terms, components act as holders, owning specific entities, enumerations, and utilities. This ownership role makes components a crucial foundation in the development process.

The Deploy.ini file is used to specify dependencies among components. These dependencies can be either static or dynamic

Static Dependency

When there is a Static Dependency between two components

Example: Component 1 has a Static Dependency with Component 2.

Then Component 1 cannot function without the purchasing / installation of Component 2.

Dynamic Dependency

When there is a Dynamic Dependency between two components

Example: Component 1 has a dynamic dependency with component 2.

Component 1 can function without Component 2, but the features in Component 1 that has dynamic dependencies with Component 2 will not work until Component 2 is purchased / installed.

Example: Dependency in a Deploy.ini file.

[Connections]  
Invoic=STATIC  
Apppay=DYNAMIC  
Conmgt=DYNAMIC  
Docman=DYNAMIC

Note: Refer to Component Deployment Profile File (deploy.ini) to get more information on deployment and installation properties of a component.

There are two recommended methodologies for articulating dynamic dependencies within the code of a component:

  • Dynamic Component Dependency Annotation

and

  • Conditional Compilation statements

While there are alternative approaches, such as:

these options should be approached with caution and generally avoided. The preferred and most efficient method is to leverage "Conditional Compilation."

Defining a Dynamic Dependency

A dynamic dependency has to be defined in two locations of a projection or client file. Namely:

  1. At the point of the element declaration or definition
  2. At the point where the element is referred.

The examples below show how these dependencies are created for each IFS Cloud Web model.

Example 1 - Dynamic component dependency in the projection model

At the point of declaration:

@Override  
@DynamicComponentDependency PROJ  
entity Activity {  
    crud = Read;  
}  

At the point of Reference:

@Override  
entity Movie {  
    attribute Year Integer {  
        fetch = "Extract(year from RELEASE_DATE)";  
    }  
    array Cast(MovieId) to MovieActor(MovieId);  
    @DynamicComponentDependency PROJ  
    reference Movie(MovieId) to Activity(ActivityId);  
}  

Example 2 - Dynamic component dependency in the client model

At the point of Definition:

@DynamicComponentDependency PROJ  
group MovieGroupWithProjectInfo for MovieWithProjQry {  
    label = "Movie";  
    field MovieId;  
    field Title;  
    field Genre;  
    field ReleaseDate;  
    field Rating {  
        rating {  
            maxrating = 10;  
            showlabel = true;  
        }  
    }  
    field Country;  
}  

At the point of Reference:

page MovieDetail using Movies {  
    label = "${TitleYear}";  
    stateindicator MovieStateIndicator;  
    selector MovieSelector;  
    @DynamicComponentDependency PROJ  
    group MovieGroupWithProjectInfo;  
    list MovieCast(Cast) bind MovieSelector;  
}  

Example 3 - Using a Dynamic Fragment

If you are using a dynamic fragment, annotate it with @DynamicComponentDependency when you include it in the projection or client file.

@DynamicComponentDependency ORDER  
include fragment SomeFragmentFromOrder;  

NOTE: When you are referring items in the dynamic fragment always remember to annotate them as well.

What is Conditional Compilation

Conditional compilation in PL/SQL is a feature that allows you to selectively include or exclude sections within a component code during compilation based on certain conditions. This is particularly useful for writing code that can be customized or adapted for different environments or scenarios

Below is an example of PL/SQL code with Conditional Compilation:

$IF boolean_static_expression $THEN  
   some pl/sql code  
$ELSE  
   other pl/sql code  
$END

Additional information regarding Conditional Compilation can be found in the Oracle documentation.

How to format Conditional Compilation

Conditional Compilation code can be used anywhere within a PL/SQL code and it always comes in between

  • $IF (at the start)

and

  • $END(at the end)

keywords.

WHILE (Client_SYS.Get_Next_From_Attr(attr_, ptr_, name_, value_)) LOOP  
   IF (name_ = 'ITEM_ID') THEN  
      newrec_.item_id := value_;  
      Todo_Item_API.Exist(newrec_.item_id);  
   ELSIF (name_ = 'PERSON_ID') THEN  
      newrec_.person_id := value_;  
$IF Component_Enterp_SYS.INSTALLED $THEN   
      Person_Info_API.Exist(newrec_.person_id);  
$ELSE  
      NULL;  
$END  
   ELSE  
      Error_SYS.Item_Not_Exist(lu_name_, name_, value_);  
   END IF;  
END LOOP;

Using Conditional Compilation in Views

It is not possible to use Conditional Compilation when creating views in Oracle, but sometimes dynamically built views are needed while developing IFS Applications.  The framework has therefore added support for having Conditional Compilation in views.

When views with a conditional compilation are generated from .views files into deployable code, it is done in both. apv files and the method Post_Installation_View in the .apy file. In the .apv, it is deployed with Conditional Compilation, meaning only parts of the view that are available at deployment time will be included in the dynamic statement. The Post_Installation_View methods are executed after all components are deployed in the database, meaning that the parts of the view that are available in the database will be included. This means that the view must have the exact same interface no matter of the dynamic statements are true or false.

Installation Process and Component Management in IFS Application Framework

When the IFS Application installed to clients local server:

  • IFS Application Framework creates packages named as: Component_<component name>_SYS (Ex: Component_Enterp_SYS)

for all the components related to client installation.

  • Each package consists of information related to a component such as, whether the component is installed in the database or not.

  • In addition to the packages created for related components, Framework also create packages for dynamically used components.

  • In the beginning of an installation, all component constants are set to FALSE

(Note: Except for the components that has already being installed and are not part of the delivery)

  • At the end of the installation process, constants are transitioned to TRUE for the installed components, while the remaining components retain a status of FALSE. This transition of constants has implications for the status of database objects. Subsequently, all the invalid database objects undergo recompilation.

Note: Please be aware that it is possible for a component to have a conditional compilation set to itself. This can be useful if an object used in a package is created as a Post Installation Object. Normally its views, that are defined differently depending on which other components are installed, that are created as Post Installation Objects.

  • Information related to installed or not-installed components are stored in Module entity. Dynamic dependencies are retrieved from the deploy.ini files and stored in ModuleDependency entity. Therefor it is crucial to mention all the Conditional Compilation Component packages in the code of deploy.ini as Dynamic.
  • This means that all usages of the Conditional Compilation component packages in the code must be reflected as a DYNAMIC connection in the deploy.ini. This is also the case when a component refers to itself.

Example : deploy.ini

[Connections]  
Invoic=STATIC  
Apppay=DYNAMIC  
Conmgt=DYNAMIC  
Docman=DYNAMIC  

Example: Generated code in Install.tem

-- The CompRegAndDep.sql is generated automatically in the build process  
START CompRegAndDep.sql  
EXEC Installation_SYS.Create_Component_Package(FALSE);  
...  
[installing components]  
...  
EXEC Installation_SYS.Create_Component_Package(TRUE);  
EXEC Database_SYS.Compile_All_Invalid_Objects;  
...

Example : Generated Package (Component_<component name>_SYS)

CREATE OR REPLACE PACKAGE Component_Enterp_SYS IS  

module_ CONSTANT VARCHAR2(25) := 'FNDBAS';  
lu_name_ CONSTANT VARCHAR2(25) := 'ComponentEnterp';  
lu_type_ CONSTANT VARCHAR2(14) := 'System Service';  

-------------------------------------------------------------------------  
-------------------- LU SPECIFIC GLOBAL VARIABLES -----------------------  
-------------------------------------------------------------------------  

-------------------------------------------------------------------------  
-------------------- INSTALLED COMPONENTS -------------------------------  
-------------------------------------------------------------------------  

INSTALLED CONSTANT BOOLEAN := TRUE;  

END Component_Enterp_SYS;  

Through the utilization of conditional compilation statements, a package (Component_<component name>_SYS) and its global constants can be used to execute specific code depending on whether the component is installed or not. In other words the compilation code varies depending on the Boolean value of the component constant (TRUE / FALSE), which generates more efficient code compiled into the database.

Example: Conditional Compilation Statement

$IF Component_Enterp_SYS.INSTALLED $THEN  
      Person_Info_API.Exist(newrec_.person_id);  
$ELSE  
      NULL;  
$END

This gives the opportunity to get rid of old dynamic PL/SQL code which executes at a considerably slower rate than the compiled code.

If a package (Component_<component name>_SYS) is missing from a development environment, there is a shortcut to temporary add it until the next build is executed.

First you must insert the dependency, then call the procedure that generates the package.

INSERT INTO module_dependency_tab  
(module, dependent_module, dependency, rowversion)  
VALUES  
('<my component>', '<dynamic component>', 'DYNAMIC', SYSDATE);  

COMMIT;  

BEGIN  
   Installation_SYS.Create_Component_Package(TRUE);  
END;  
/

Developer Studio usages of Conditional Compilation

If you want an entire PL/SQL method to be excluded or included depending on another component, use the @DynamicComponentDependency annotation.

But it is strongly recommended to limit the usage of this annotation exclusively to implementation methods.

Placing it within methods published in the package specification may result in deployment errors and significantly impede build time. Alternatively, a similar outcome can be accomplished by utilizing a static Boolean expression of your own with the @DynamicDependency annotation.

Dynamic elements can exist in both the projection and client model as well as in fragments.

Dynamic Elements in Client Dynamic Elements in Projection
1. Navigator entries 1. Entity Sets
2. Sub-Menus 2. Entities
3. Pages 3. Queries
4. Groups 4. Summaries
5. Lists 5. References
6. Tabs 6. Functions
7. Pages 7. Actions
8. Commands
9. Fields
10. List of Values
11. Selectors
12. List of Value Lists

Static Code Analyzer Tool and Dynamic Dependency

Static Code Analyzer (SCA) examines source code before the code is generated and deployed. This is done by analyzing a set of code against a set of coding rules. With Static Code Analysis, developers get to know early on if there are any problems in their code. One of the rules available in Static Code Analyzer is "DependencyAnnotation", which checks the dependency among components. DependencyAnnotation annotation helps to analyze whether to access the code in optional components or not. If the annotation is missing in the code where the optional code is used, SCA tool warns developers about the missing annotation and it helps to avoid runtime and deployment issues.

When conditional compilation statement is added, but if the Static or Dynamic entry is missing in depoly.ini file, SCA will raise an error about missing declaration in deploy.ini file.

Refer to Static Code Analyzer to get more information on deployment and installation properties of a component.

Developer Studio and Conditional Compilation

Static Code Analyzer (SCA) is capable to identifying missing conditional compilation statements in the code, as missing such statements would lead to runtime and deployment issues.

Detection of conditional compilation errors is often deferred until central builds, as only the "true" code undergoes deployment and testing during development. Typically, the $IF block is examined while the $ELSIF or $ELSE blocks are overlooked, resulting in compilation errors during customer configurations. Early identification of such issues during development is highly advantageous, providing valuable feedback and minimizing the likelihood of complications during subsequent stages.

The newly introduced Test Conditional Compilation context menu item lets you compile the $ELSIF and $ELSE blocks, which otherwise would not be compiled during the usual deployment. You will find this context menu item by right-clicking in the editor of *plsql*/*plsvc*/views files.

img

Benefits of Conditional Compilation

Conditional Compilation presents advantages compared to alternative solutions that require a different implementation approach. Some examples of these benefits are as follows:

  • Better performance (compared to Using Dynamic PL/SQL through DBMS_SQL)
    Compiled code always performs better than dynamic code.
  • Easier implementation (compared to a solution with stub packages, with or without any implementation)
    Just add a simple Conditional Compilation piece of code and you have finished your solution. Also there are no maintenance problems in the future.
  • Easier testing
    By amending a Boolean value in a package then you can test both of your cases very easily without the need to deploy/uninstall a component.

Drawback

  • Code needs to be recompiled when a Boolean constant is changed.

Important: It is important to manage changes to Boolean constants carefully. Sometimes it is necessary to recompile the code, but in the majority of cases, the code will automatically recompile when needed. In a production environment at a customer's site, it is advisable to modify the Boolean package constants only during installation or upgrade procedures to avoid potential disruptions.

Applications of Conditional Compilation Across Other Domains

In addition to checking whether a component is installed or not, there are many other places where Conditional compilation can be very useful. Below you can see some of these examples:

  • Tracing
    You can add trace texts that are only visible if you set a flag in a specific package. Alternatively you can insert specific data into tables so you can see what happened during the execution of your code. This avoids performance impacts on the code within a production environment.
  • Oracle Versions
    You can add code that behaves differently depending on which version of Oracle you are running. The package Dbms_Db_Versionholds information about which version you are running on.
  • Oracle Features
    If you have a specific Oracle feature installed you could compile the code so it becomes optional as to whether this feature is used or not.