Skip to main content

In IFS Developer Studio, I’ve got one module with a few entities and a couple utilities in it. The utilities depend on the entities, but when I try to create a topic environment, it’s not deploying in the correct order. The utility’s package fails because it’s created before the dependent entity’s view.

!!!Error deploying database object
!!!PACKAGE C_MY_UTILITY_API created with compilation errors at 28-MAY-25 22:07:16
PLS-00201: identifier 'C_MY_OTHER_ENTITY' must be declared error at line no :12
PL/SQL: Compilation unit analysis terminated error at line no :0

I’ve been trying to play with the deploy.ini file to force the order the files are deployed, but this isn’t working. I’ve tried putting the files under CapMergeFiles and under CapMergeFilesLast, and they don’t seem to be honored.

rCapMergeFiles]
...
File6=CMyOtherEntity.api
File7=CMyOtherEntity.apy
...

rCapMergeFilesLast]
File1=CMyUtility.api
File2=CMyUtility.apy
...

What do you think I’m doing wrong? (Is this an issue with 24.2.0?) How can I force an entity inside a module to get deployed before the utilities inside that same module that depend on it?

It’s failing when deploying the API for my utility entity because it contains a reference to the other entity’s view in a TYPE declaration.

TYPE table_of_stuff IS
TABLE OF c_other_entity_view%ROWTYPE
INDEX BY VARCHAR2(40);

It’s the API that’s failing, not the APY, so the usual strategy of assuming the APIs are all safe to deploy doesn’t work.

WORST CASE, I should be able to work around this by defining an explicit row type, but I don’t like how inflexible that would be.

Is there a different filename or syntax I should expect to use if I want to force the deployment order under CapMergeFiles in deploy.ini?


hi ​@Stefan Dj  can you take a look on this

 


Hi,
I don’t think you are allowed to point to a view definition in your api file, because the deployment order is api,apv,apy…

The TCapMergeFiles] and aCapMergeFilesLast] defined files will only change to order for the extension deployed.


So you should be able to solve this by adding the .apv file to the deploy.ini, just like in STD:

 


So you should be able to solve this by adding the .apv file to the deploy.ini, just like in STD:

 

I tried putting both the .apv file and the -Cust.views file in the CapMergeFiles section of deploy.ini (separately, as two attempts), and neither is getting honored. Do you have any ideas to figure out why?


Hi,
As I answered above, you can only change the order of an specific extension.
As you your example above OrderRmAcc.apv will be the first .apv that will be deployed, first .apv of the rest of the .apv files.
You can not change in which order files with different extension should be deployed.

 


Hi,
As I answered above, you can only change the order of an specific extension.
As you your example above OrderRmAcc.apv will be the first .apv that will be deployed, first .apv of the rest of the .apv files.
You can not change in which order files with different extension should be deployed.

 

That’s a shame. What do you think of this proposal, then?
Improve developer productivity with automatic dependency discovery | IFS Community


I developed a workaround for my particular problem:

 

-- I don't want to lose the expressive power and deduplication of the %ROWTYPE
-- directive in the utilities' APIs.
-- https://en.wikipedia.org/wiki/Don%27t_repeat_yourself

-- This is what I'd do if I could:

/*
TYPE table_of_c_my_view IS
TABLE OF c_my_view%ROWTYPE
INDEX BY VARCHAR2(40);

TYPE table_of_c_my_view_line IS
TABLE OF c_my_view_line%ROWTYPE
INDEX BY PLS_INTEGER;
*/

-- However, using %ROWTYPE requires us to deploy the dependency's APV before the
-- utility's API, and that's not currently possible. The CapMergeFiles section
-- of the deploy.ini file is limited to only changing the deployment order of
-- files with the SAME extension and can't force an APV before an API.
-- https://community.ifs.com/framework-experience-infrastructure-cloud-integration-dev-tools-50/ifs-developer-studio-change-the-order-entities-are-deployed-59297

-- Here's a workaround to semi-automatically create a manual definition here.
-- Re-run this whenever the view definition changes to pick up those changes.
/*
SELECT
'TYPE record_of_' || LOWER(table_name) || ' IS RECORD (' || CHR(10)
|| LISTAGG(
' ' || RPAD(LOWER(column_name), 30)
|| ' '
|| CASE WHEN data_type LIKE '%CHAR%'
THEN data_type || '(' || char_col_decl_length || ')'
WHEN data_type = 'NUMBER' AND data_precision IS NULL
THEN 'NUMBER'
WHEN data_type = 'NUMBER' AND data_scale = 0
THEN 'NUMBER(' || data_precision || ')'
WHEN data_type = 'NUMBER'
THEN 'NUMBER(' || data_precision || ', ' || data_scale || ')'
WHEN data_type LIKE 'TIMESTAMP%' AND data_scale IS NOT NULL
THEN data_type || '(' || data_scale || ')'
ELSE data_type
END,
',' || CHR(10)) WITHIN GROUP (ORDER BY column_id ASC)
|| ');' || CHR(10)
|| CHR(10)
|| 'TYPE table_of_' || LOWER(table_name)
|| ' IS TABLE OF record_of_' || LOWER(table_name) || ';' AS plsql_code
FROM user_tab_columns
WHERE table_name IN ('C_MY_VIEW', 'C_MY_VIEW_LINE')
GROUP BY table_name;
*/

TYPE record_of_c_my_view IS RECORD (
c_order_type VARCHAR2(4000),
c_order_type_db VARCHAR2(80),
-- ...
objkey VARCHAR2(200),
objversion VARCHAR2(56),
objid ROWID);

TYPE table_of_c_my_view IS TABLE OF record_of_c_my_view;

TYPE record_of_c_my_view_line IS RECORD (
c_order_type VARCHAR2(4000),
c_order_type_db VARCHAR2(80),
-- ...
objkey VARCHAR2(200),
objversion VARCHAR2(56),
objid ROWID);

TYPE table_of_c_my_view_line IS TABLE OF record_of_c_my_view_line;

 


Removing %TYPE and %ROWTYPE references from the package spec solved the problem, but I’m disappointed that such deduplication and self-documenting techniques are actively discouraged by the tooling. For example, which one of these is more meaningful? Which one helps the next developer understand what’s going on and helps them avoid misunderstandings?

DECLARE
info_ VARCHAR2(32767);
objid_ ROWID;
objversion_ VARCHAR2(32767);
attr_ VARCHAR2(32767);
DECLARE
info_ VARCHAR2(32767);
objid_ customer_order.objid%TYPE;
objversion_ customer_order.objversion%TYPE;
attr_ VARCHAR2(32767);

 


Yeah it’s unfortunate you can’t do that ​@durette .

 

Not sure what your current use case is, but if the view is based on an underlying table, you probably could get away with using the rowtype of the table instead, and then if any elements determined by the view are needed in your business logic with the method, (such as getting decoded versions of db values), reproduce that logic within the method itself?

 

Of course if you’re wanting the rowtype of a view that’s a compound view with multiple tables etc, then you probably can’t do that.


Reply