Selasa, 29 Oktober 2013

Implementasi jsTree dalam APEX

Jika anda telah mengimplementasikan APEX tree dan kurang sreg dengan style-nya. Maka kita bisa mencoba dengan mengimplementasikan jsTree ke dalam APEX.

Sebenarnya APEX tree telah memakai jsTree yang dimodifikasi dan dibundle dalam library js APEX. Namun yang dipakai masih versi lama. Librari jsTree ada di folder #IMAGE_PREFIX#libraries/jquery-jstree.

Anda sekarang bisa memakai jsTree versi stabil dari jstree v.1.0pre yang dapat di download dari sini.
Berikut referensi yang bisa anda pakai dalam membangun jstree kedalam apex.
 Oke tanpa banyak nyengnyong lagi kita coba construct jsTree dalam APEX :
  1. Buatlah konstruksi pl/sql AJAX callback dengan nama GET_NODE_DATA dengan return xml data:
  2. declare
          l_xml         VARCHAR2(32767):='';
          l_loop_counter NUMBER(5);
    BEGIN
          FOR i IN (SELECT m.id,m.STATUS,
                           m.menu_id parent_id,
                           m.description name,
           case when .. then 
    --- define your dynamic icon for node here
           end   tree_image,
                          case   when
    --- define your dynamic style for node here e.g : color,font
                          end tree_style,                      
                          m.TOOLTIP as tooltip, 
                          null as link,                      
                          m.STATUS type_menu,m.alias
                      FROM your_table m
                     START WITH m.menu_id is null
                    CONNECT BY PRIOR m.id = m.menu_id 
                    order siblings by m.seq
                    )
          LOOP
             l_xml := l_xml || ''||
             '<![CDATA['||i.name||']]>';
          END LOOP;
             l_xml := l_xml || '';
          htp.prn(l_xml);
    EXCEPTION
          WHEN OTHERS THEN
             RAISE;
    END;
    
  3. Buatlah js function untuk membangun tree yang dipanggil saat windows on load.
  4. function loadDataTree() {
        apex.server.process("GET_NODE_DATA", null,
                                {
                                    dataType: 'text',
                                    success: function (pData) {
                                        constructTree(pData);
                                    }
                                }
                           )
    }
    
    function constructTree(pData) {
        $(function () {
            var treeCon = $("#treeContainer").jstree({
                "plugins": ["themes", "xml_data", "ui", "cookies"],
                "ui": {
                    "select_limit": 2,
                    "select_multiple_modifier": "alt"
                },
                "core": {
                    "animation": 700,
                    "initially_open": [1,3], "load_open": true
                },
                "xml_data": {
                    "data": pData
                },
                "themes": {
                    "theme": "classic",
                    "dots": false,
                    "icons": true
                },
               "cookies": { prefix: "tree1", opts: { path: '/' } }
            });
     $("#treeContainer").on("dblclick", "a", function (e, data) {
        document.location.href = $(e.target).attr('href');
          });
        });
    };
    
  5. Buatlah sebuah region dengan region source :
  6. Demo bisa dilihat disini untuk implementasi jstree on apex.oracle.
  7. Preview image 

Kamis, 26 September 2013

Implementasi jQuery Sortable pada APEX Classic Report (AJAX)

Sebelumnya silahkan pelajari UI dokumentasi disini dan demonya disini.
Contoh kasus kita terapkan pada tabel EMP.
Kita bisa lakukan dengan memakai konsep AJAX atau Dynamic Action.

Langkah implementasi dalam APEX untuk AJAX sbb:

  • Tambahkan kolom ORDER_BY number(3);
  • Buatlah report dengan memakai collection contoh nama collection : 'R_SORT'
    1. Buat process pl/sql before header
    2. declare
       l_col_name varchar2(100):='R_SORT';
       l_query varchar2(4000);
      begin
        l_query:='select a.EMPNO,a.ENAME,a.JOB,a.MGR,a.HIREDATE,a.SAL,a.COMM,a.DEPTNO,a.ORDER_BY from emp a order by a.ORDER_BY';
       if not APEX_COLLECTION.COLLECTION_EXISTS(p_collection_name => l_col_name) then
        APEX_COLLECTION.CREATE_COLLECTION_FROM_QUERY_B(
                p_collection_name => l_col_name
              , p_query => l_query
            );
       end if;
      end;
            
    3. Buat calssic report dengan query
    4. SELECT coll.seq_id No
           , coll.c001 empno
           , coll.c002 ename
           , coll.c003 job
           , coll.c004 mgr
           , coll.c005 hiredate
           , coll.c006 comm
           , coll.c007 sal
           , coll.c008 deptno
      FROM APEX_collections coll
      WHERE coll.collection_name = 'R_SORT'
      ORDER BY to_number(coll.seq_id)
          
  • Buatlah Application Process : REORDER dengan process point : on demand
  • declare
      -- ajax call to move a seq_id collection
     l_seq     number(5);
     l_seq_id     number(5); 
     l_old        number(5); 
     l_new        number(5); 
     l_counter    number(5);
     l_abscounter    number(5);
    begin
     l_seq_id    := to_number(wwv_flow.g_x01);
     l_counter   := to_number(wwv_flow.g_x02);
     l_abscounter  :=abs(l_counter);
          if l_counter < 0 then
          -- Move UP
            for i in 1 .. l_abscounter loop
            apex_collection.move_member_down(
                p_collection_name => 'R_SORT'
              , p_seq             => l_seq_id
            );     
              l_seq_id := l_seq_id - 1;
            end loop;
          elsif l_counter > 0 then
          -- Move DOWN
            for i in 1 .. l_abscounter loop
              apex_collection.move_member_up(
                  p_collection_name => 'R_SORT'
                , p_seq             => l_seq_id
              );        
              l_seq_id := l_seq_id + 1;        
            end loop;      
          end if;    
    htp.prn('success');
    end;
      
  • Buatlah sebuah function jQuery untuk setup preparation Sortable dan AJAX memanggil application process REORDER:
  • function setSortable() {
        var vStart = 0;
        var vEnd = 0;
        var vCounter = 0;
        var vSeqId = 0;
        var sortRegion = '#report_RSORT_1 .report-standard tbody:first'; // selector tergantung report yg anda pakai
        $(sortRegion).sortable({
           cursor      : 'wait',
           distance    : 15,
           revert      : 500,
           start       : function (event, ui) {
            vStart = Number(ui.item.index()) + 1;
            vSeqId = Number($(this).find('td[headers="NO"]')[ui.item.index()].innerHTML);},
           stop        : function (event, ui) {
            vEnd = Number(ui.item.index()) + 1;
            vCounter = vEnd - vStart;
            apex.server.process("REORDER"
                  , { x01: vSeqId, x02: vCounter }
                  , {
                      dataType: 'text'
                      , success: function (pData) {
                      if (pData != 'success') {
                               alert(pData);
                       }
                      else {
                         // refresh report id tergantung report yg anda pakai
                        $('#report_28558823308938595811_catch').trigger('apexrefresh');
                      }
            }
           }
        );
        }
       });
       $(sortRegion).disableSelection();
    }
    
  • tambahkan function setup preparation Sortable pada  bagian on load : setSortable();
  • Buatlah DA after refresh pada report sortable execute javascript : setSortable();
Liat demo hasilnya disini.

Rabu, 05 Juni 2013

Beberapa hal yang harus diperhatikan saat memakai apex_mail

Salah satu API yang disediakan oleh APEX adalah send email melalui APEX_MAIL. Dari contoh API kita bisa mengirimkan email baik text atau format html. Contoh :
DECLARE
 l_body CLOB;
 l_body_html CLOB;
BEGIN
 l_body := 'To view the content of this message, please use an HTML enabled mail client.'||utl_tcp.crlf;
 l_body_html := '<html>
                 <head>
                 <style type="text/css">
                 body{font-family: Arial, Helvetica, sans-serif;
                 font-size:10pt;
                 margin:30px;
                 background-color:#ffffff;}
                 span.sig{font-style:italic;
                 font-weight:bold;
                 color:#811919;}
                 </style>
                 </head>
                 <body>'||utl_tcp.crlf;
 l_body_html := l_body_html ||'<p>Thank you for your interest in the <strong>APEX_MAIL</strong> package.</p>'||utl_tcp.crlf;
 l_body_html := l_body_html ||' Sincerely,<br />'||utl_tcp.crlf;
 l_body_html := l_body_html ||' <span class="sig">The APEX Dev Team</span><br/>'||utl_tcp.crlf;
 l_body_html := l_body_html ||'</body></html>';
 apex_mail.send( p_to => 'some_user@somewhere.com', -- change to your email address
                 p_from => 'some_sender@somewhere.com', -- change to a real senders email address
                 p_body => l_body,
                 p_body_html => l_body_html,
                 p_subj => 'APEX_MAIL Package - HTML formatted message');
END;
/

Beberapa error yang muncul seperti :

  • PLS-00307: too many declarations of 'SEND'
  • Hal ini terjadi jika type yang tidak sama anda berikan pada value p_body dan p_body_html pastikan jika memakai varchar2 semua atau clob semua

  • ORA-06502: PL/SQL: numeric or value error
  • Hal ini terjadi kita memakai clob dengan data memakai concate '||'yang melebihi kapasitas varchar2(32767)

    Solusinya kita dapat mengganti dengan tipe data CLOB dengan memakai DBMS_LOB.APPEND, pada contoh diatas dapat dimodifikasi dengan cara

    DECLARE
     l_body CLOB;
     l_body_html CLOB;
    BEGIN
     l_body := 'To view the content of this message, please use an HTML enabled mail client.'||utl_tcp.crlf;
     dbms_lob.createtemporary (l_body_html,true);
     DBMS_LOB.append (l_body_html,'<html>
                     <head>
                     <style type="text/css">
                     body{font-family: Arial, Helvetica, sans-serif;
                     font-size:10pt;
                     margin:30px;
                     background-color:#ffffff;}
                     span.sig{font-style:italic;
                     font-weight:bold;
                     color:#811919;}
                     </style>
                     </head>
                     <body>');
     DBMS_LOB.append (l_body_html,'<p>Thank you for your interest in the <strong>APEX_MAIL</strong> package.</p>');
     DBMS_LOB.append (l_body_html,' Sincerely,<br />');
     DBMS_LOB.append (l_body_html,' <span class="sig">The APEX Dev Team</span><br/>');
     DBMS_LOB.append (l_body_html,'</body></html>');
     apex_mail.send(p_to => 'some_user@somewhere.com', -- change to your email address
                    p_from => 'some_sender@somewhere.com', -- change to a real senders email address
                    p_body => l_body,
                    p_body_html => l_body_html,
                    p_subj => 'APEX_MAIL Package - HTML formatted message');
     dbms_lob.freetemporary (l_body_html);  
    END;
    /
    

Selasa, 14 Mei 2013

Multiple Interactive Report with Synchronize Link

Beberapa pertanyaan tentang bagaimana memanipulasi interactive report (IR) dalam satu page sambil menunggu APEX 5. kita bisa lakukan dengan cara berikut.
Contoh kasus kita akan membuat sebuah 3 IR dalam satu page.

  • Page 27 adalah IR1 (DEMO_CUSTOMERS).
  • Page 29 adalah IR2 (DEMO_ORDERS).
  • Page 30 adalah IR3 (DEMO_ORDERS).

Pada page 27 buatlah 3 region seperti gambar berikut :

  • Region IR 1 : IR report dengan link: redirect ke page 27 dengan ngisi item P27_CUSTOMER_ID dengan value #CUSTOMER_ID# dengan request REDIR
  • Region IR 2 : dengan subregion Frame 2.
    • Bagian header
    • <iframe src="f?p=&APP_ID.:29:&SESSION."
            style="width:500px;height:500px"
            name="details"
            scrolling="no" marginwidth="0" marginheight="0"
            frameborder="0" vspace="0" hspace="0" >
      
    • Bagian footer
    • </iframe>
      
  • Region IR 3 : dengan subregion Frame 3.
    • Bagian header
    • <iframe src="f?p=&APP_ID.:30:&SESSION."
            style="width:500px;height:500px"
            name="details1"
            scrolling="no" marginwidth="0" marginheight="0"
            frameborder="0" vspace="0" hspace="0" >
      
    • Bagian footer
    • </iframe>
      

Lalu pada page 29 dan 30 buatlah IR dengan hidden item P29_CUSTOMER_ID dan P30_CUSTOMER_ID dengan query report:
select ORDER_ID, CUSTOMER_ID, ORDER_TOTAL, ORDER_TIMESTAMP
from DEMO_ORDERS
where customer_id=:P29_CUSTOMER_ID

Lalu langkah terakhir pada page 27 buatlah sebuah dynamic action
  • Event:Page Load
  • Condition: Request=Expression1 dengan Expression 1 =REDIR
  • True Actions : Execute javascript Code
  • code :
  • top.frames['details'].location.href = 'f?p=&APP_ID.:29:&SESSION.::&DEBUG.::P29_CUSTOMER_ID:&P27_CUSTOMER_ID.';top.frames['details1'].location.href = 'f?p=&APP_ID.:30:&SESSION.::&DEBUG.::P30_CUSTOMER_ID:&P27_CUSTOMER_ID.';
    

Demo aplikasi bisa lihat disini.

Rabu, 10 April 2013

Checkbox heading on report for check all / uncheck all

Untuk implementasi checkbox heading seperti layaknya ketika anda membuat tabular form dapat di-implementasikan dalam dua cara yaitu:
  1. Classic Report
  2. <input type="checkbox" onclick="$f_CheckFirstColumn(this);" >
    
  3. Interactive Report
  4. Cara dari Jeffrey Kemp

Jumat, 05 April 2013

The macro cannot be found or has been disabled

Tiba-tiba saja setelah lama gak buka BI publisher word template jadi gak bisa login ke dalam BI Publisher dengan symptom error : "The macro cannot be found or has been disabled".
Untung ada mbah gugel. anda bisa coba resep dari http://damir-vadas.blogspot.com/2011/02/macro-cannot-be-found-or-has-been.html. Terbukti manjur kekeke.

Sabtu, 30 Maret 2013

Merubah cookie APP_USER secara permanen

Cookie APP_USER adalah sebuah penampung yang dibuat APEX untuk menyimpan nama user Aunthenticated. contoh username kita entry lutfi hedir. Lalu cookies tersebut bisa kita ubah didalam aplikasi menjadi lutfi.hedir dengan cara membuat sebuah proses dengan block seperti ini.
begin
--set user menjadi nama tertentu cara 1
apex_custom_auth.set_user('lutfi.hedir');
--set user menjadi nama tertentu cara 2
wwv_flow.g_user := 'lutfi.hedir';
end;

Yang harus diperhatikan adalah dimana akan dijalankan code tersebut. Jika anda tidak ingin secara permanen maka dapat dilakukan di proses page on load before header atau tempat lain sesuai keinginan. Namun jika ingin merubah secara permanen maka satu-satunya cara harus di lakukan pada Post-Authentication Procedure Name. Karena jika dilakukan diluar itu maka APP_USER akan tetap seperti USERNAME dimana kita entry pada saat login. meskipun kita lakukan proses di application proses on load before header, tetap APP_USER tidak berubah yang berubah disaat proses render saja, tapi jika digunakan dalam proses authorization APP_USER kembali seperti semula, atau jika digunakan dalam database trigger dengan memanggil v('APP_USER') maka kembali APP_USER akan dikenali sebagai lutfi hedir bukan lutfi.hedir.
Jadi anda harus buat sebuah procedure dalam database contoh my_post_login dengan code sbb:
create or replace procedure my_post_login is 
 begin 
   apex_custom_auth.set_user('lutfi.hedir'); 
 end my_post_login;

lalu gunakan my_post_login dalam Post-Authentication Procedure Name. Selamat mencoba
Sumber : Oracle APEX Forum

Rabu, 27 Maret 2013

Delete multiple file on APEX metadata

Untuk keperluan delete file yang ada di aplikasi APEX, APEX telah menyediakan tool untuk melakukan delete file, cuma masih harus satu persatu. jadi kalau kita ingin melakukan banyak file itu yang jadi masalah.

Namun di dalam apex sendiri telah diberikan script untuk melakukan delete metadata tsb contoh saat kita ingin menghapus image "xxx.jpg" maka scriptnya adalah
begin
    wwv_flow_api.create_or_remove_file( 
        p_location => 'APPLICATION',
        p_name     => 'xxx.jpg',
        p_mode     => 'REMOVE',
        p_type     => 'IMAGE');
end;
/

Yang perlu diperhatikan adalah p_type bisa 'IMAGE','CSS'atau 'STATIC'. jadi untuk hapus secara banyak contoh satu WS maka kita harus modifikasi seperti ini. contoh dibawah adalah saya ingin menghapus seluruh image yang tersimpan dalam WS='TEST'.

declare
 v_id number;
 v_ws varchar2(100):='TEST';
begin
--- cari workspace ID
select workspace_id into v_id
from apex_workspaces
where WORKSPACE=upper(v_ws);
---set security supaya bisa di exsekusi diluar apex 
wwv_flow_api.set_security_group_id(v_id);
---cursor 
FOR x IN (select *
from APEX_WORKSPACE_FILES
where MIME_TYPE like 'image/%') LOOP
    wwv_flow_api.create_or_remove_file( 
        p_location => 'WORKSPACE',
        p_name     => x.FILE_NAME,
        p_mode     => 'REMOVE',
        p_type     => 'IMAGE');
END LOOP;
commit;
end;
/

Minggu, 17 Maret 2013

Otentifikasi memakai custom LDAP

Kita jarang sekali memakai LDAP sebagai direktori yang menyimpan profile untuk aplikasi tertentu, hampir dipastikan profile dan akses ke dalam aplikasi di setup tersendiri didalam aplikasi itu sendiri.

Jadi untuk memakai otentifikasi LDAP kita tidak mungkin secara polos memakainya tanpa mengkombinasikan dengan data otorisasi yang telah ada. Karena itu mari kita gunakan logika untuk memakai LDAP kedalam existing apps contoh kasus ini memakai windows server directory.
  1. Buatlah sebuah funsi untuk melakukan test otentifikasi dalam pl/sql dengan return varchar2.
  2. CREATE OR REPLACE function function_ldap_test(
    p_username in varchar2,
    p_password in varchar2)
    return varchar2
    as
    p_dn varchar2(50) := 'your_domain\'||p_username;
    p_ldap_host varchar2(50) := 'ldap_server_host_or_ip';
    p_ldap_port number := 389;
    l_retval pls_integer;
    l_retval2 pls_integer;
    l_session dbms_ldap.session;
    begin
    l_retval := -1;
    dbms_ldap.use_exception := TRUE;
    begin
    l_session := dbms_ldap.init( p_ldap_host, p_ldap_port );
    l_retval := dbms_ldap.simple_bind_s( l_session, p_dn, p_password );
    l_retval2 := dbms_ldap.unbind_s( l_session );
    return 'OK';
    exception when others then
    l_retval2 := dbms_ldap.unbind_s( l_session );
    return null;
    end;
    exception when others then
    return null;
    end function_ldap_test;
    /
    
  3. Gunakan fungsi tersebut dalam custom otentifikasi yang telah kita miliki.
  4. CREATE OR REPLACE function my_auth(
    p_username in varchar2,
    p_password in varchar2)
    return boolean
    as
     l_ldap_test varchar2(200);
    begin
     l_ldap_test:=function_ldap_test(p_username,p_password);
       if l_dap_test is null then
        return false;
       else
        return true;
       end if;
    
    end my_auth;
    /
    
Untuk kasus nyata biasanya kita harus menyimpan sebuah informasi penghubung data user di aplikasi kita dengan data LDAP, yang paling memungkinkan biasanya data email untuk itu kita bisa gunakan fungsi test LDAP seperti ini.
CREATE OR REPLACE function function_ldap_test(
p_username in varchar2,
p_password in varchar2)
return varchar2
as
   l_ldap_host   varchar2(256) := 'ldap_server_host_or_ip';
   l_ldap_port   varchar2(256) := '389';
   l_ldap_user   varchar2(256) := 'my_domain\'||p_username;
   l_ldap_passwd varchar2(256) := p_password;
   l_ldap_base   varchar2(256) := 'dc=my_domain,dc=com';
   l_filter      varchar2(100) := 'sAMAccountName='||p_username;
   l_retval      pls_integer;
   l_retval2    pls_integer;
   l_session     dbms_ldap.session;
   l_attrs       dbms_ldap.string_collection;
   l_message     dbms_ldap.message;
   l_entry       dbms_ldap.message;
   l_attr_name   varchar2(256);
   l_ber_element dbms_ldap.ber_element;
   l_vals        dbms_ldap.string_collection;
   l_raw         dbms_ldap.binval_collection;
   l_result varchar2(100);
  begin
 
        -- Choose to raise exceptions.
       dbms_ldap.use_exception   := true;
       dbms_ldap.utf8_conversion := false;
     
       -- Connect to the LDAP server.
       l_session := dbms_ldap.init(hostname => l_ldap_host, portnum => l_ldap_port);
       l_retval := dbms_ldap.simple_bind_s(ld => l_session, dn => l_ldap_user, passwd => l_ldap_passwd);
     
       -- Get mail attributes
       l_attrs(1) :=nvl( p_attribute,'mail'); 
     
       l_retval := dbms_ldap.search_s(ld       => l_session
                                     ,base     => l_ldap_base
                                     ,scope    => dbms_ldap.scope_subtree
                                     ,filter   => l_filter
                                     ,attrs    => l_attrs
                                     ,attronly => 0
                                     ,res      => l_message);
     
       if dbms_ldap.count_entries(ld => l_session, msg => l_message) > 0
       then
          -- Get all the entries returned by our search.
          l_entry := dbms_ldap.first_entry(ld => l_session, msg => l_message);
       
          while l_entry is not null
          loop
             -- Get all the attributes for this entry.
             l_attr_name := dbms_ldap.first_attribute(ld        => l_session
                                                     ,ldapentry => l_entry
                                                     ,ber_elem  => l_ber_element);
             while l_attr_name is not null
             loop
                -- Get all the values for this attribute.
                l_vals := dbms_ldap.get_values(ld => l_session, ldapentry => l_entry, attr => l_attr_name);
            
                for i in l_vals.first .. l_vals.last
                loop
                   return substr(l_vals(i), 1, 200);
                end loop values_loop;
                l_attr_name := dbms_ldap.next_attribute(ld        => l_session
                                                       ,ldapentry => l_entry
                                                       ,ber_elem  => l_ber_element);
             end loop attibutes_loop;
             l_entry := dbms_ldap.next_entry(ld => l_session, msg => l_entry);
          end loop entry_loop;
       end if;
     
       -- Disconnect from the LDAP server.
       l_retval2 := dbms_ldap.unbind_s(ld => l_session);
      
    exception when others then   
    l_retval2 := dbms_ldap.unbind_s(ld => l_session);
     return null;
end function_ldap_test;
/

Sumber : Oracle APEX Forum

Implementasi APEX SSL dengan OHS 11g (3)

Setelah berhasil membuat wallet CSR dan CA certificate server. langkah selanjutnya adalah setup server OHS dan APEX untuk memakai SSL. OHS 11g adalah component dari weblogic server yang biasanya ssl telah di setup dengan port : 4443 untuk ssl dan 7777 untuk non-ssl, jadi anda sekarang akan merubahnya memakai memakai port ssl:443 dan non-ssl:80

  • Stop proses OPMN dan OHS.
  • Untuk memastikan SSL enable edit file opmn.xml : <data id="start-mode" value="ssl-enabled"/>
  • Ubah port ssl ke 443 di file ss.conf yang ada di <OHS_HOME>\instances\instance1\config\OHS\ohs1
  • Copy file ewallet.pt12 dan cwallet.sso di c:\mywallet ke <OHS_HOME>\instances\instance1\config\OHS\ohs1\keystores\default
  • Edit file konfigurasi hhtpd.conf yang ada di <OHS_HOME>\instances\instance1\config\OHS\ohs1 dengan merubah listen : 7777 menjadi 80 lalu pada bagian terbawah tambahkan.
  • RewriteEngine On
    RewriteCond %{SERVER_PORT} 80 
    RewriteRule ^(.*)$ https://%{HTTP_HOST}:443$1 [R,L]
    
  • Restart proses OPMN dan OHS.
  • Akses aplikasi memakai browser ke https://localhost/pls/apex.
  • Install certificate.server_cacert.crt di browser
  • Akses ke apex melali ws internal
  • Pada bagian manage instance>security : Require HTTPS=Yes
  • Pada bagian manage instance>Instance Settings
  • Wallet Path : C:\mywallet
    Wallet Password : enter your password here
    

Selesai.

Implementasi APEX SSL dengan OHS 11g (1)

Salah satu bagian dari security APEX adalah mengaktifkan mode SSL. dimana dalam proses nya data mengalami enkripsi terlebih dahulu sebelum di proses. untuk lebih jelasnya silahkan baca ini.

Proses merubah dari non ssl menjadi ssl dalam apex lumayan banyak langkah yang harus dilakukan yaitu:

  1. Mempersiapkan oracle wallet untuk membuat certificate request.
  2. Membuat trusted certificate dan user certificate.
  3. Memakai dalam wallet
  4. Mengakatifkan SSL pada OHS.
  5. Mengaktifkan SSL pada instance apex.
Karena banyaknya langkah tersebut maka akan saya bahas prosesnya secara bertahap. pada bagian ini kita akan membuat certificate request dari Wallet dan Membuat trusted certificate dan user certificate dengan OpenSSL.


  • Buatlah directory baru untuk menyimpan certificate contoh C:\mywallet.
  • Bukalah Oracle Wallet Manager.
  • Buatlah New , Standard.
  • Buat certificate request.
  • Save as wallet ke dalam C:\mywallet maka otomatis akan ada 1 file dalam direktori tersebut yaitu ewallet.p12.
  • Exporte certificate request ke dalam C:\mywallet dengan nama contoh : server.req
Oke langkah pertama sudah kita lakukan selanjutnya kita akan membuat CA.

Implementasi APEX SSL dengan OHS 11g (2)

Setelah certificate request (CR) telah terbentuk dalam c:\mywallet maka selanjutnya kita akan membuat certificate authority memakai OpenSSL. untuk versi windows bisa di download disini.
Dalam kasus ini saya sudah terinstall openssl 64 bit di C:\OpenSSL-Win64.
  • Masuk ke working direktory C:\mywallet.
  • Jalankan perintah berikut untuk mengatur configurasi yg dipakai: set OPENSSL_CONF=C:\OpenSSL-Win64\bin\openssl.cfg
  • Jalankan perintah untuk membuka openssl : C:\OpenSSL-Win64\bin\openssl.
  • Buat key : genrsa -out mykey.pem 2048
  • Buat CA : req -new -x509 -key mykey.pem -out server_cacert.crt -days 3650
  • Membuat server certifikate memakai requet dari wallet (server.req) : x509 -req -in server.req -CA server_cacert.crt -CAkey mykey.pem -CAcreateserial -out server.crt 
  • Buka kembali Oracle wallet manager lalu open wallet di direktori c:/mywallet.
  • Gunakan server_cacert.crt sebagai trusted certificate melalui import trusted certificate.
  • Gunakan server.crt sebagai user certificate melalui import user certificate.
  • Simpan kembali wallet jangan lupa auto login di centang.

Disini anda telah berhasil mempersiapkan certifate yang diperlukan dalam proses SSL. selanjutnya anda akan merubah setting OHS dan apex.

Jumat, 01 Maret 2013

Hide Show Region by default is SHOW

Ketika kita memakai sebuah template region "Hide Show" maka secara default ketika page di load maka posisi region dalam keadaan "Hide". Bagaimana jika butuh sebaliknya?.

Lakukan langkah-langkah berikut:

  1. Copy template "Hide and Show Region".
  2. Beri nama baru "Hide and Show Region 2".
  3. Lakukan perubahan berikut :
    • Template Asli :
    • <div class="hide-show-region" id="#REGION_STATIC_ID#" #REGION_ATTRIBUTES#>
        <div class="hide-show-top">
          <div class="hide-show-title"><a href="javascript:hideShow('region#REGION_SEQUENCE_ID#','shIMG#REGION_SEQUENCE_ID#','#IMAGE_PREFIX#themes/theme_21/images/right_arrow.png','#IMAGE_PREFIX#themes/theme_21/images/down_arrow.png');" class="t1HideandShowRegionLink"><img src="#IMAGE_PREFIX#themes/theme_21/images/right_arrow.png" 
        id="shIMG#REGION_SEQUENCE_ID#" alt="" /></a> #TITLE#</div>
          <div class="hide-show-buttons">#CLOSE##PREVIOUS##NEXT##DELETE##EDIT##CHANGE##CREATE##CREATE2##EXPAND##COPY##HELP#</div>
        </div>
      <div class="hide" id="region#REGION_SEQUENCE_ID#" style="float:left;">#BODY#</div>
      </div>
      
    • Template Setelah Perubahan :
    • <div class="hide-show-region" id="#REGION_STATIC_ID#" #REGION_ATTRIBUTES#>
        <div class="hide-show-top">
          <div class="hide-show-title"><a href="javascript:hideShow('region#REGION_SEQUENCE_ID#','shIMG#REGION_SEQUENCE_ID#','#IMAGE_PREFIX#themes/theme_21/images/right_arrow.png','#IMAGE_PREFIX#themes/theme_21/images/down_arrow.png');" class="t1HideandShowRegionLink"><img src="#IMAGE_PREFIX#themes/theme_21/images/down_arrow.png" 
        id="shIMG#REGION_SEQUENCE_ID#" alt="" /></a> #TITLE#</div>
          <div class="hide-show-buttons">#CLOSE##PREVIOUS##NEXT##DELETE##EDIT##CHANGE##CREATE##CREATE2##EXPAND##COPY##HELP#</div>
        </div>
      <div class="show" id="region#REGION_SEQUENCE_ID#" style="clear:both;display:block;">#BODY#</div>
      </div>
      
  4. Gunakan dalam aplikasi contoh disini

Rabu, 30 Januari 2013

Tips Memakai Number Field dengan Format Mask

Memakai item dengan tipe : Number Field dengan format mask memerlukan sebuah trik tersendiri dalam APEX karena pada dasarnya ketika di render item menjadi karakter bukan lagi number seperti asalnya ketika tersimpan dalam database.
Contoh : angka 1000000 ketika memakai format mask 999G999G999G999G999G999G990 ketika di render akan menjadi 1.000.000.

Masalah akan muncul jika kita melakukan sebuah validasi, biasanya akan terjadi error. untuk mengatasi hal ini kita bisa lakukan.
1. Buat sebuah function di Post Calculation Computation di item tersebut.
2. Buatlah fuction tersendiri di database lalu gunakan dalam validasi.

Cara pertama punya kelemahan jika kita masukkan sebuah angka dengan format mask yang salah muncul error yg tidak bisa di handle contoh kita masukkan 1.00.000.

Dengan cara kedua kita bisa handle dalam proses validasi nantinya. oke bagai mana logicnya.
1. Sebelumnya harus dicek apakah item tersebut sudah ter format apa belum
2. Function tersebut akan melakukan konversi Number Field dengan format mask dari char ke number.
3. Gunakan function ter sebut dalam validasi, plus buatlah exception untuk handle format yang salah.

contoh function

CREATE OR REPLACE FUNCTION FORMAT_ANGKA1(P_NUM  VARCHAR2 ) RETURN number
  IS  
 v_jumlah NUMBER;
begin
if instr(P_NUM,'.')=0 then
 v_jumlah:=to_number(nvl(P_NUM,0));
else
 v_jumlah:=to_number(nvl(P_NUM,0),'999G999G999G999G999G999G990');
end if;
    
    RETURN v_jumlah;    
 
  END FORMAT_ANGKA1;
/
Contoh pemakaian dalam validation dengan tipe :Function Returning Error Text

declare
 v_jumlah number;
begin

 v_jumlah:=FORMAT_ANGKA1(:P28_JUMLAH);

if v_jumlah=0 then
 return '#LABEL# tidak boleh null atau 0';
else
 if v_jumlah>:P28_SIMPANAN then
   return '#LABEL# tidak boleh melebihi jumlah Simpanan';
 else
   return null;
 end if;
end if;
exception
 when others then
 return '#LABEL#Format mask tidak valid contoh valid : 999.999.999.999.999.999.990 , atau sama sekali tanpa format mask';
end;

Catatan : pemakaian instr tergantung format mask dan Globalization Apps yang kita pakai.