Friday, September 14, 2012

UMD ie Unitask Migration Director

"Unitask" is third party tool which operates with Oracle EBS to download code components as package.
Its known as UMD ( Unitask Migration Director )


More details are at http://www.unitask.com

Follow below steps to generate package and upload:

1 Navigate to Responsibility : Unitask Object Migration Manager Developer
2 Create New Package
3 Select objects needed for package
4 It will submit two concurrent programs
    UMD: Create Download Script
    Unitask Object Migration Manager: Download Package (UMD: Download Package)
5 Output report shows details of what package is made of. Output file is in tar format.
6 Once programs are completed, package can be viewed/saved by clicking view link in menu of same responsibility.
7 Download package on local machine
8 Move package file to different instance and upload using same responsibility


Notes : 
  • For modifying already created package unfreeze it and change
  • Control files or application server files can be picked up as "Application Server File" , source path can contain dynamic variables like $XBOL_TOP
  • I could not find option for migrating table along with data. May be not feasible ?
  • It creates shell script to install objects 
  • Menu/ Responsibilities can be migrated
Its simple approach to get code downloaded from one instance and migrate to other.
It covers concurrent program definition, executable, lookups , pl/sql packages, table, view definitions and many more objects.. simple r i g h t?

Thursday, September 13, 2012

XML Response file not parsing

We faced big issue on UAT days due to hidden error caused by XMLPARSER

    response_parser := xmlparser.newparser;
    xmlparser.parseclob(response_parser, response_clob);
    resp_dom_doc := xmlparser.getdocument(response_parser);


This caused SOAP UI response XML parsing error and aborting
supportable search , presenting incomplete results.

Exception: ORA-31011: XML parsing failed ORA-19202: Error
occurred
in
XML processing LPX-00217: invalid character 26 (U+001A) Error at
line 1 Stack: ORA-06512: at "XDB.DBMS_XMLPARSER", line 191
ORA-06512: at "APPS.XXRH_SUPX_USER_SVC_PKG", line 759
 
After lot of search on net and Oracle SR, I found below simple solution to replace control characters from XML clob
 
pout_response_clob:= regexp_replace(pout_response_clob, '['||chr(1)||'-'||chr(13)||chr(14)||'-'||chr(31)||chr(127)||']','');
 
What this does is replaces all the control chars and gives back clob which can be parsed by XMLPARSER
 
More details - https://forums.oracle.com/forums/thread.jspa?messageID=10265001
 
There are other related functions like DBMS_XMLGEN.CONVERT , DBMS_LOB.CONVERTCLOB etc 
 
This finding helped us to save big go-live!!!
 
"Dhundane pe khuda bhi milta hain! "

Tuesday, August 28, 2012

Oracle Apps - changing user responsibilities programmatically

This code gives idea about API's available and usage to assign new responsibility or revoke existing responsibility. Also one can find how to end date responsibility itself.

/* Formatted on 2012/08/28 10:59 (Formatter Plus v4.8.8) */
CREATE OR REPLACE PACKAGE BODY apps.xxrh_decommission_11i_pkg
AS
/* $Header: /home/appprdas/new/xxrh/fnd/install/XXRH_DECOMMISSION_11I_PKG.sql,v 1.9 2005/01/27 18:38:58 appprdas Exp $ */

   -- Modification History
--  Date        Author      Changes
--  08/21/2012  ypatil     initial draft

   -- Declaration of Constants

   --
   PROCEDURE modify_access (
      errbuf              OUT      VARCHAR2,
      retcode             OUT      NUMBER,
      p_tower             IN       VARCHAR2,
      p_app_code          IN       VARCHAR2,
      p_user_type         IN       VARCHAR2,
      p_processing_mode   IN       VARCHAR2
   )
   AS
      CURSOR cur_revoke_resp
      IS
         SELECT usr.user_name, fr.responsibility_key,
                frt.responsibility_name, fa.application_short_name app,
                fnds.security_group_key, frt.description, usr.user_id,
                fr.responsibility_id,
                fr.application_id responsibility_application_id,
                furg.start_date,
                DECODE (p_user_type,
                        'ASSOCIATE', xd.inactive_date_assoc,
                        'MANAGER', xd.inactive_date_manager,
                        'SUPER USER', xd.inactive_date_super_user
                       ) user_type_inactive_date,
                fa_c.application_short_name inq_app_name,
                fr_c.responsibility_key inq_resp_key,
                fnds.security_group_key inq_sec_grp,
                frt_c.description inq_resp_desc, fr.data_group_id,
                fr.data_group_application_id, fr.menu_id,
                fr.start_date resp_start_date, fr.group_application_id,
                fr.request_group_id, fr.VERSION, fr.web_host_name,
                fr.web_agent_name, xd.*
           FROM fnd_user usr,
                fnd_responsibility_tl frt,
                fnd_application fa,
                fnd_responsibility fr,
                fnd_security_groups fnds,
                fnd_user_resp_groups_all furg,
                bolinf.xxrh_decommission_11i xd,
                bolinf.xxrh_decommission_user_type xua,
                fnd_responsibility_tl frt_c,
                fnd_application fa_c,
                fnd_responsibility fr_c
          WHERE usr.user_id = furg.user_id
            AND furg.responsibility_id = fr.responsibility_id
            AND fr.responsibility_id = frt.responsibility_id
            AND fr.application_id = fa.application_id
            AND furg.security_group_id = fnds.security_group_id
            AND usr.user_name = xua.user_name
            AND NVL (furg.end_date, SYSDATE + 1) > SYSDATE
            AND xd.resp_name = frt.responsibility_name
            AND xua.user_type =
                       DECODE (p_user_type,
                               'ALL', xua.user_type,
                               p_user_type
                              )
            AND xd.tower = p_tower
            AND fa.application_short_name = p_app_code
            AND fr_c.responsibility_id = frt_c.responsibility_id
            AND fr_c.application_id = fa_c.application_id
            AND DECODE (xd.corr_inq_resp,
                        'Not Required', xd.resp_name,
                        xd.corr_inq_resp
                       ) = frt_c.responsibility_name
            ORDER BY frt.responsibility_name           ;

      l_inactive_date             DATE;
      l_user_type_inactive_date   DATE;
      l_resp_name                 VARCHAR2 (500);
      l_resp_name_all             VARCHAR2 (500);
      l_raise_excp                EXCEPTION;
   BEGIN
      fnd_file.put_line
              (fnd_file.LOG,
               '~~~~~~~~~~~~~~~~~~~~~PARAMETERS~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
              );
      fnd_file.put_line (fnd_file.LOG, ' Tower           ' || p_tower);
      fnd_file.put_line (fnd_file.LOG, ' Application   ' || p_app_code);
      fnd_file.put_line (fnd_file.LOG, ' User Type     ' || p_user_type);
      fnd_file.put_line (fnd_file.LOG,
                         ' Processing Mode ' || p_processing_mode
                        );
      fnd_file.put_line
               (fnd_file.LOG,
                '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
               );
              
       fnd_file.new_line(fnd_file.LOG,2);          

      FOR rec_revoke_resp IN cur_revoke_resp
      LOOP
         IF p_user_type = 'ALL'
         THEN
            BEGIN
               l_resp_name_all := rec_revoke_resp.responsibility_name;

               SELECT DISTINCT inactive_date
                          INTO l_user_type_inactive_date
                          FROM (SELECT inactive_date_assoc inactive_date
                                  FROM bolinf.xxrh_decommission_11i xda
                                 WHERE xda.resp_name = l_resp_name_all
                                UNION
                                SELECT inactive_date_manager inactive_date
                                  FROM bolinf.xxrh_decommission_11i xdm
                                 WHERE xdm.resp_name = l_resp_name_all
                                UNION
                                SELECT inactive_date_super_user inactive_date
                                  FROM bolinf.xxrh_decommission_11i xds
                                 WHERE xds.resp_name = l_resp_name_all) a;
            EXCEPTION
               WHEN TOO_MANY_ROWS
               THEN
                  fnd_file.put_line
                     (fnd_file.LOG,
                         ' Different inactive dates for User type ALL resp name '
                      || rec_revoke_resp.responsibility_name
                     );
                  retcode := 2;
                  errbuf :=
                        'Different inactive dates for User type ALL for '
                     || rec_revoke_resp.responsibility_name;
                  RAISE l_raise_excp;
               WHEN OTHERS
               THEN
                  fnd_file.put_line
                     (fnd_file.LOG,
                         ' Different inactive dates for User type ALL resp name '
                      || rec_revoke_resp.responsibility_name
                     );
                  retcode := 2;
                  errbuf :=
                        'Different inactive dates for User type ALL for '
                     || rec_revoke_resp.responsibility_name;
                  RAISE l_raise_excp;
            END;
         ELSE
            l_user_type_inactive_date :=
                                      rec_revoke_resp.user_type_inactive_date;
         END IF;                                            -- user type check

         IF p_processing_mode IN ('DISABLE', 'BOTH')
         THEN
           
            l_inactive_date := SYSDATE;

            IF l_inactive_date >= rec_revoke_resp.user_type_inactive_date
            THEN
               fnd_user_resp_groups_api.update_assignment
                  (user_id                            => rec_revoke_resp.user_id,
                   responsibility_id                  => rec_revoke_resp.responsibility_id,
                   responsibility_application_id      => rec_revoke_resp.responsibility_application_id,
                   start_date                         => rec_revoke_resp.start_date,
                   end_date                           => l_inactive_date,
                   description                        => NULL
                  );
               fnd_file.put_line (fnd_file.LOG,
                                     'Inactivated  Resp '
                                  || rec_revoke_resp.responsibility_name
                                  || ' for '
                                  || rec_revoke_resp.user_name
                                  || ' with end date '
                                  || rec_revoke_resp.user_type_inactive_date
                                 );
               -- disable responsibility only if user access is disabled first                                    
                IF NVL (l_resp_name, 'N/A') <>
                                          rec_revoke_resp.responsibility_name
            THEN
               -- API call to end date responsibility
               fnd_responsibility_pkg.update_row
                  (x_responsibility_id              => rec_revoke_resp.responsibility_id,
                   x_application_id                 => rec_revoke_resp.responsibility_application_id,
                   x_web_host_name                  => rec_revoke_resp.web_host_name,
                   x_web_agent_name                 => rec_revoke_resp.web_agent_name,
                   x_data_group_application_id      => rec_revoke_resp.data_group_application_id,
                   x_data_group_id                  => rec_revoke_resp.data_group_id,
                   x_menu_id                        => rec_revoke_resp.menu_id,
                   x_start_date                     => rec_revoke_resp.resp_start_date,
                   x_end_date                       => SYSDATE,
                   x_group_application_id           => rec_revoke_resp.group_application_id,
                   x_request_group_id               => rec_revoke_resp.request_group_id,
                   x_version                        => rec_revoke_resp.VERSION,
                   x_responsibility_key             => rec_revoke_resp.responsibility_key,
                   x_responsibility_name            => rec_revoke_resp.responsibility_name,
                   x_description                    => rec_revoke_resp.description,
                   x_last_update_date               => SYSDATE,
                   x_last_updated_by                => fnd_global.user_id,
                   x_last_update_login              => fnd_global.login_id
                  );
               fnd_file.new_line (fnd_file.LOG,3)  ;
               fnd_file.put_line (fnd_file.LOG,
                                     ' Inactivated Responsiibility - '
                                  || rec_revoke_resp.responsibility_name
                                 );
               fnd_file.new_line (fnd_file.LOG,3)  ;                   
               l_resp_name := rec_revoke_resp.responsibility_name;
            END IF;                                  -- disable responsibility
               
            ELSE
              --  Inactive date is not yet arrived , pre-mature run of process
               fnd_file.put_line
                              (fnd_file.LOG,
                                  ' Pre-mature run of process for resp '
                               || rec_revoke_resp.responsibility_name
                               || ' - Proposed inactive date '
                               || rec_revoke_resp.user_type_inactive_date
                               || ' Current system date for the timezone is '
                               || l_inactive_date
                              );
            END IF;                                         -- date comparison
         END IF;                                          -- processing mode 1

         IF p_processing_mode IN ('ENABLE', 'BOTH') AND rec_revoke_resp.corr_inq_resp <>'Not Required'
         THEN
            -- Add responsibility
            fnd_user_pkg.addresp
                              (username            => UPPER
                                                         (rec_revoke_resp.user_name
                                                         ),
                               resp_app            => rec_revoke_resp.inq_app_name,
                               resp_key            => rec_revoke_resp.inq_resp_key,
                               security_group      => rec_revoke_resp.inq_sec_grp,
                               description         => rec_revoke_resp.inq_resp_desc,
                               start_date          => SYSDATE,
                               end_date            => NULL
                              );
            fnd_file.put_line (fnd_file.LOG,
                                  ' Activated  Resp '
                               || rec_revoke_resp.inq_resp_desc
                               || ' for '
                               || rec_revoke_resp.user_name
                              );
         -- end add resp
         END IF;                                          -- processing mode 2
      END LOOP;

      COMMIT;
   EXCEPTION
      WHEN l_raise_excp
      THEN
         fnd_file.put_line (fnd_file.LOG, ' l_raise_excp Raised ');
         retcode := 2;
      WHEN OTHERS
      THEN
         ROLLBACK;
         errbuf := 'Other Error ' || SQLERRM;
         fnd_file.put_line (fnd_file.LOG, ' Error Occured ' || errbuf);
   END modify_access;
-------------------------------------------
END xxrh_decommission_11i_pkg;
/

Making Read-Only responsibilities OKS

For decommissioning work one may require to change transactional responsibilities to Read-Only or Inquiry
Below are steps that can be followed for Order Contracts module i.e OKS

_______________________________________________
MAKING existing OKS responsibility to read-only
_______________________________________________

Using "Service Contracts XX Manager" responsibility

    1)Navigate > Setup > Contract  > Categories and Sources > Define Categories
    2)Enter Query (F11)  and category "Warranty and Extended Warranty"
    3)Crtl - F11 (This will query the Warranty and Extended Warranty categories)
    4) Click on the Responsibilities Tab
    5) Click on the Access Level Dropdown for "OKS XX Manager" responsibility
    6) Update the level to "Read Only"
    7) Save the Record.

Using "System Administrator" responsibility
       1) Navigation Responsibility > Define > Query "OKS XX Manager"
       2) Add Menu Exclusion for function "Update Online" 
       3)Save the changes


Sunday, June 17, 2012

Query Performance

Do you know columns in selection list affect use of index on table..??

I couldn't  believe this..I was always under impression that query plan is decided based on from and where clause and select clause has no impact on index usage. I was proved wrong in the Smoke Test for INT2 at midnight yesterday..

See how...

select trx_number, org_id, interface_header_attribute1      
          from ra_customer_trx_all
          where org_id = 112 
         
Plan
SELECT STATEMENT  ALL_ROWSCost: 1,947  Bytes: 219,538  Cardinality: 9,979     
    1 TABLE ACCESS FULL TABLE AR.RA_CUSTOMER_TRX_ALL Cost: 1,947  Bytes: 219,538  Cardinality: 9,979 



select trx_number, org_id      
          from ra_customer_trx_all
          where org_id = 112
         
Plan
SELECT STATEMENT  ALL_ROWSCost: 551  Bytes: 129,727  Cardinality: 9,979     
    1 INDEX SKIP SCAN INDEX AR.RA_CUSTOMER_TRX_N1 Cost: 551  Bytes: 129,727  Cardinality: 9,979 
        
Ultimately the solution to this performance issue was add one more table to query... Interesting huh?

bad query
select trx_number
          from ra_customer_trx_all
          where 1=1
          and interface_header_attribute1 = to_char(pin_order_number)
          and org_id = v_Header_Rec_Type.org_id
          and rownum = 1;

Good query

select trx_number      
          from apps.ra_customer_trx_all rct, apps.ra_customer_trx_lines_all rctl
          where rct.customer_trx_id = rctl.customer_trX_id
            and rctl.sales_order = to_char(66000120)
            and rct.org_id = 112
            and rownum < 2;

Wednesday, June 13, 2012

Materialized View with Fast Refresh idea

Complete refresh for materialized views may not be time effective in all cases. Moreover if the changes to data are minimal Fast refresh should be used and scheduled frequently using cron job or dbms_job.

I faced issue as there was no primary key on underlying table to create materialized view. I was under impression that there must be primary key. However there is an idea to beat this..

We can create materialized view based on rowid column as well

Below are the scripts

---------------- on Web DB  -------------------

create materialized view log on subscription.xxrh_subscription with rowid excluding new values;

grant select on subscription.MLOG$_xxrh_subscription to web;



----------------- On R12EBS environment in Web Schema  ---------------

CREATE MATERIALIZED VIEW web.xxrh_subscription_mv tablespace web_data
    REFRESH FAST ON DEMAND WITH ROWID AS
    SELECT *
    FROM subscription.xxrh_subscription@WEB_LINK;

CREATE INDEX web.XXRH_SUBSCRIPTION_MV_IDX1 ON web.XXRH_SUBSCRIPTION_MV(ORACLE_ACCOUNT_NUMBER) tablespace web_indx;

ThanksAnil Prodduturi for this knowledge!

Tuesday, June 12, 2012

ORA-04021 Timeout when compiling package

Sometimes we face timeout error ORA-04021 when trying to compile existing package.

Following steps can help to get rid of the error.
1) Find who is accessing the object using below sql
     SELECT * FROM v$access WHERE object = 'XXRH_SUPX_ORCL_PKG';

2) Check session details using below query. SID will be from the result of above query
    SELECT * FROM V$SESSION WHERE SID IN (1040,1529,1016)

3) Kill the session which is accessing the package . Ensure that you inform osuser of these session before you kill them!
   ALTER SYSTEM KILL SESSION '1016,58335'

Go ahead with package compilation!