Monday 30 December 2013

Adding “remember me” functionality to Oracle ADF login

 

The following example based on Jdeveloper 11g R2 (11.1.2.3)

There are many ways to implement login page in Oracle ADF. One can create custom login logic or use build in security mechanism. This is covered in many blogs and also in official Oracle documentation and I am not going to touch it in this post.

  I do want to explain how to add a functionality for “remember me”, so if user already logged in and checked “remember me” option, next time he logs into the application he will not be asked to enter the credentials again

I started by creating some login form with “remember” check box

image

Definition of the check box button

image 

When I press the login button I check that the check box is checked and if it checked I save the credentials in the cookies

image

I created some other  dummy page that I expect to see if user logged in with Cookies

Here my adfc-config.xml file

image

“AfterLogin” page contains only text “some other page”

Now I want my cookies to be checked when user enters the login page (“LoginTest” page in my application)

I will do it with JavaScript that will check the cookies after the page is loaded

Note!!! I tried to do it with all other methods like “afterPhase” or by using “router” in the Task-Flow. It didn’t work

image

When the page is loaded eventually I call “goToDashBoard” method in my backing bean

public void goToDashBoard(ClientEvent clientEvent) {
   checkCookies();
}

 

public String checkCookies() {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExternalContext externalContext = facesContext.getExternalContext();
    Map<String, Object> cookies = externalContext.getRequestCookieMap();
    Cookie user= (Cookie)cookies.get("nam.user.cookie");
    Cookie pass= (Cookie)cookies.get("nam.pass.cookie");
    Cookie domain = (Cookie)cookies.get("nam.domain.cookie");
    if (user!=null &&

         pass!=null &&

         domain!=null &&  

         user.getValue()!=null &&

         pass.getValue()!=null &&

         domain.getValue()!=null)

      {
        this._username=user.getValue();
        this._password =  pass.getValue();
        this._domain = domain.getValue();
        NavigationHandler  nvHndlr = FacesContext.getCurrentInstance().getApplication().getNavigationHandler();
        nvHndlr.handleNavigation(FacesContext.getCurrentInstance(), null, "AfterLogin");

     }

}

All I do here is reading the information from Cookies and if credentials are found to be stored in the Cookies I programmatically execute “AfterLogin” control case (see the print screen of adfc-config.xml)

Wednesday 27 November 2013

ADF - Using selectOneChoice in af:iterator

 

The following example replated to Jdeveloper 11g R3

af:iterator is a grate component when you need to with collections, but also design by yourself the UI for each row in the collection.

Here I will explain how can you put a selectOneChoice (combo box) with dynamic values in each row UI.

For this I will create 2 tables

create table XX_SAMPLE_DATA
(
ID number,
TITLE varchar2(100),
STATUS varchar2(100)
)

create table XX_STATUSES
(
CODE varchar2(100),
MEANING varchar2(100)
)



The “status” column in the XX_SAMPLE_DATA will be based on the values from XX_STATUSES table


I am not going to explain how to create the “Model” for this 2 tables, assuming that you are well recognized with this part. Eventually we will have the following structure


image


Now. Do not attempt to set XxStatusesView as LOV for “Status” attribute . It will give you nothing.


Ok, lets create our page .


Create whatever page you want (jsf or jspx) and go to page defintion


image


We need to add both View Objects to the binding


In the “binding” section, click plus sign and choose tree


image


Click on the “Add” and choose “XxSampleDataView1”


image


 


Add new rule (you will have only one option)


image


And pass all attributes to the “Display Attributes”


image


Create also “tree” binding for the second View Object “XxStatusesView1”.


This is how your binding should look at the end


image


Drop iterator component on the page


image


Set the following properties on the iterator


image


We will also put “output text” element inside iterator to display “Title” attribute


Add the following script as iterator child

 <af:selectOneChoice label="Status" id="soc1" value="#{row.Status}">
<af:forEach items="#{bindings.XxStatusesView1.children}"
var="status">
<af:selectItem value="#{status.Code}"
label="#{status.Meaning}"
id="si1"/>
</af:forEach>
</af:selectOneChoice>




Explanation about this part. The value that will be displayed is the current value in the row of XX_SAMPLE_DATA status column. But it will be displayed as a combo box with values based on the data from XX_STATUSES table


image


 


We are ready to run. We only need to put some dummy data into our tables

insert into XX_SAMPLE_DATA values (1,'First','OPEN')
/
insert into XX_SAMPLE_DATA values (2,'Second','CLOSED')
/
insert into XX_STATUSES values ('OPEN','Open')
/
insert into XX_STATUSES values ('CLOSED','Closed')
/
insert into XX_STATUSES values ('N_A','Not Available')
/



image


You can download the workspace from here Download Workspace

Wednesday 16 October 2013

Oracle ADF - How to center the popup to the center of the page?

 

Jdeveloper 11g R2.

To center the popup ,just don’t provide “align” and “alignId” attributes in “Show Popup Behavior” component

<af:showPopupBehavior popupId="confirm" triggerType="click"/>

Wednesday 7 August 2013

OAF Populate View Object with a data from DB2 database

 

The problem is the following. I have a view object that displays item+lot information from EBS.

Part of the data is located on the remote DB2 server. The goal is somehow to join the data from DB2 with a data in local EBS database.

The idea is the following . We will create global temporary table that will be populated with a data from DB2 when the OAF page is loaded.

Here is the table

create global temporary table XX_OM_LOT_ALLOC_FROM_DB2

  FACILITY                                        VARCHAR2(1000),
  ITEM_ID                                         NUMBER,
  LOT_NUMBER                                VARCHAR2(1000),
  BOX_QUANTITY                              NUMBER,
  ONHAND_QUANTITY                      NUMBER,
  ALLOCATED_ONHAND_QUANTITY NUMBER,
  EXPIRY_DAYS                               NUMBER,
  UNITS_INNER_PACK                     NUMBER,
  NBR_OF_INNER_IN_OUTER           NUMBER
)
on commit delete rows
/

 

The View Object will be based on the following SQL.

select *

from  XX_OM_LOT_ALLOC_FROM_DB2 db2,

        ic_item_mst_b  items

where db2.item_id = items.item_id

 

So all we have to do is to populate the temporary table with a data

To connect connect to DB2 we will use open source jt400.jar file.

Bellow is the java class that connects to the DB2 , reads the data and populates the temporary table. Explanation about the code are found in the code comment

import java.sql.CallableStatement;
import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.ResultSet; 
import java.sql.PreparedStatement; 
import java.sql.SQLException;
import java.util.Properties;
import com.ibm.as400.access.*;
import java.sql.*;

public class LotConnector
{

    /* All parameters to the fucntion are ment to be used
       to connect to DB2. Except "localConn", which is used to
       connect to local database (EBS database)
    */
   public static String getItemOnHandQuantity(String env,
                                               String item,
                                               String serverHost,
                                               java.lang.Integer  serverPort,
                                               String serverUser,
                                               String serverPwd,
                                               String serverDb,
                                               String serverLib,
                                               Connection localConn)
    {

       //insert statement to populate the temporary table
      final String insertSql = "insert into XX_OM_LOT_ALLOC_FROM_DB2 values (?,?,?,?,?,?,?,?,?)";
        String PkEnv = env;
        String Item_id = item;
        String server = serverHost;
        int port = serverPort.intValue();
        String username = serverUser;
        String password = serverPwd;
        String dbName = serverDb;
        String LibraryName = serverLib;
        Connection connection = null; 
        CallableStatement proc_stmt = null;
        ResultSet rs = null;

         boolean isResultSetExists = false;
       //do something only if connection details to DB2 exist
        try
            if(PkEnv!=null  && server!=null && port!=0 && username!=null && password!=null && dbName!=null && LibraryName!=null)
            {   
                // load the driver and set properties for connection
                // to db2
                DriverManager.registerDriver( new AS400JDBCDriver());
                Properties props = new Properties();
                props.setProperty("user",username);
                props.setProperty("password",password);
                props.setProperty("naming","system");
                props.setProperty("date_format","iso");
                props.setProperty("transaction_isolation","none");

                connection = DriverManager.getConnection("jdbc:as400://"+server+":"+port+"/"+dbName+"", props);
               //note the format of the call
                // in Oracle it is MY_PACKAGE.MY_FUNCTION
                // but for DB2 we specify MY_LIBRARY/MYFUNCTION
                proc_stmt = connection.prepareCall("{call "+LibraryName+"/TV38U0RP(?,?)}"); //IN Parameter
                proc_stmt.setString(1, PkEnv);
                proc_stmt.setString(2,Item_id);
                proc_stmt.execute();
                rs = proc_stmt.getResultSet();
                Connection localConnection = localConn;

               //insert to local table
                PreparedStatement ps = localConnection.prepareStatement(insertSql);
                while (rs.next())
                {
                   //indication that something found
                    isResultSetExists = true;
                   //record data from DB2
                    String facility =  rs.getString(1);
                    String ITEM_ID  = rs.getString(2);
                    String lot = rs.getString(3);
                    String InnerPackQuantity = rs.getString(4);
                    String OnHandQuantity = rs.getString(5);
                    String AllocatedOnHandQuantity  = rs.getString(6);
                    String ExpiryDays = rs.getString(7);
                    String UnitsInnerPack = rs.getString(8);
                    String NbrOfInnerInouter = rs.getString(9);

                    //local insert
                      ps.setString(1,facility);
                      ps.setInt(2,Integer.parseInt(ITEM_ID.trim()));

                      if (lot!=null && !lot.equals(""))
                         ps.setString(3,lot);
                      else
                         ps.setNull(3,Types.NULL);
                      if (InnerPackQuantity!=null && !InnerPackQuantity.equals(""))
                         ps.setString(4,InnerPackQuantity);
                      else
                         ps.setNull(4,Types.NULL);

                       if (OnHandQuantity!=null && !OnHandQuantity.equals(""))
                         ps.setString(5,OnHandQuantity);
                       else
                         ps.setNull(5,Types.NULL);

                       if (AllocatedOnHandQuantity!=null && !AllocatedOnHandQuantity.equals(""))
                         ps.setString(6,AllocatedOnHandQuantity);
                       else
                         ps.setNull(6,Types.NULL); 

                       if (ExpiryDays!=null && !ExpiryDays.equals(""))
                         ps.setString(7,ExpiryDays);
                       else
                         ps.setNull(7,Types.NULL);

                       if (UnitsInnerPack!=null && !UnitsInnerPack.equals(""))
                         ps.setString(8,UnitsInnerPack);
                       else
                         ps.setNull(8,Types.NULL); 

                       if (NbrOfInnerInouter!=null && !NbrOfInnerInouter.equals(""))
                         ps.setString(9,NbrOfInnerInouter);
                       else
                         ps.setNull(9,Types.NULL);
                   //use batch insert to improve the performance                        
                    ps.addBatch();
                } //end while

            if (isResultSetExists)
            {
              ps.executeBatch();
              ps.close();
            }
            }
            else
            {
                return ("Parameter missing.");
            }
        }
       // handle exceptions and connections
        catch (SQLException sqle)
        {
            sqle.printStackTrace();
            return ("SQLException: " + sqle.getMessage());
        }
        catch (Exception e) { 
            e.printStackTrace();
            return ("SQLException: " + e.getMessage());           
        }
        finally
        {
            if (proc_stmt != null) {
                try {
                    proc_stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                    return ("SQLException: " + e.getMessage());
                }
            }
            if (rs!= null){
                try {
                    rs.close();
                }catch (Exception expre) {
                    expre.printStackTrace();
                    return ("Exception : " + expre.getMessage());
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException exp) {
                    exp.printStackTrace();
                    return ("SQLException: " + exp.getMessage());
                }
            }
        }
        return "OK";
    }
}

We will define in application module the following function

public class LotAllocationAMImpl extends OAApplicationModuleImpl
{

  public String pullDataFromDb2(String env,
                                               String itemId,
                                               String server,
                                               String port,
                                               String user,
                                               String pwd,
                                               String name,
                                               String library)
  {
    Connection conn = getOADBTransaction().getJdbcConnection();

   //call the class we defined above
    return LotConnector.getItemOnHandQuantity(env,
                                               itemId,
                                               server,
                                               new Integer(port),
                                               user,
                                               pwd,
                                               name,
                                               library,
                                               conn);
    }

}

All we need to do now is to call this code when the page is loaded , before VO is executed.

As every OAF developer knows the way to do it , is to call this function from processRequest functon in the page controller

public void processRequest(OAPageContext pageContext, OAWebBean webBean)
  {
    super.processRequest(pageContext, webBean);

// for obvious reasons I don’t publish the connection details

    String db2Env = "dummy";
    String itemId = "dummy";
    String db2Server = "dummy";
    String db2Port = "dummy";
    String db2User = "dummy";
    String db2Pwd = "dummy";
    String db2Name = "dummy";
    String db2Lib = "dummy";

    Serializable[] db2Params = { db2Env, itemId,db2Server,db2Port,db2User,db2Pwd,db2Name,db2Lib};
    String result =  (String)pageContext.getRootApplicationModule().invokeMethod("pullDataFromDb2",db2Params);
   }

 

Enjoy…

Thursday 27 June 2013

OAF CacheComponent not registered

 

When developing a custom Oracle Framework Page for Oracle EBS I run to the following error when running the page from JDeveloper.

image

 

I don’t know what is the cause of the error but I found the resolution on OTN and wanted to share it .

First of all you need to add “Functional Developer” responsibility to your user in EBS

Now, switch responsibility to “Functional Developer” and you will see a new web page is being opened immediately.

Click on core services

image .

Click on the “Cache Components”

image

Click on the “Create Component”

image

Enter the following information:

Name -- FLEXFIELD_METADATA_CACHE

Code -- FLEXFIELD_METADATA_CACHE

Application Name -- Application Object Library

Description -- Stores descriptive flexfield, key flexfield, and value set metadata

Loader Class Name -- oracle.apps.fnd.flexj.FlexfieldCacheLoader

Time Out Type --Time To Live

Time Out After --Global Idle Time

image

And click “Apply”.

Next time you will run your project from Jdeveloper the error will be gone

Sunday 2 June 2013

Manually install SOA DbAdapter into Weblogic 10.3.6.0

 

What is SOA DbAdapter and why do we need it is a separate question which you can cover by reading the following post. The point of concern in my port is to explain that you don’t need to download 3 GB of data in order to install it.

Oracle SOA suite a big piece of software and if you want to use only dbAdapter you will find that you need to download about 3GB of data from the following web site

Actually you need only several megabytes of data.

Download only second disk of installation from here download link (Oracle account required)

image

 

Open downloaded file. The name of the file I downloladed is ofm_soa_generic_11.1.1.7.0_disk1_2of2.zip

Inside this file you need to extract the following path:

Disk4\stage\Components\oracle.soa.common.adapters\11.1.1.7.0\1\DataFiles

Inside this path you will find a JAR file filegroup1.jar.

From this file you need to extract:

1. soa\connectors\DbAdapter.rar

2. soa\modules\oracle.soa.adapter_11.1.1\jca-binding-api.jar

From DbAdapter.rar extract DbAdapter.jar file.

All jar files you extracted put into <YOUR_DOMAIN>/lib directory.

“DbAdapter.rar” upload as web application through Web Logic “Deployment” intefrace.

So to make it work you only need 3 files. I would post them here, but I am not sure about licensing issues that may arise.

Sunday 12 May 2013

Infinite “Fetching Data” in ADF treeTable

 

In Jdeveloper 11g R2 there is a wonderful option to easily create hierarchical data presentation as tree or table tree.

All you need to do is to define View Link between two View Objects.

This is what I did, and this is how my table tree looks like

image

However when I expend the row, I see endless “Fetching Data” message and the component is stacked and the process is never ends

image

The resolution is simple. You need to define “Key Attribute” on the child View Object

image

After this , tree components works like a charm

image

Wednesday 17 April 2013

Oracle ADF - programmatically expand row in RichTable to show detailsTamp

 

One of the cool features of Oracle ADF is the ability to have inline components in RichTable (or tree) UI component. This post is based on the following "ADF Code Corner" example however in the example , they use binding layer . In my example – I don’t

Basically it looks like this

image

And alter you click on the small arrow icon , the row is expanded and you can see an inline data.

image

To get this feature is very easy, you only need to define a facet after column definition. In my case my inline data is just some text

 

<af:table value="#{bindings.customers.collectionModel}" var="row"
rows
="#{bindings.customers.rangeSize}"
emptyText
="#{bindings.customers.viewable ? 'No data to display.' : 'Access Denied.'}"
fetchSize
="#{bindings.customers.rangeSize}" rowBandingInterval="0"
selectedRowKeys
="#{bindings.customers.collectionModel.selectedRow}"
selectionListener
="#{bindings.customers.collectionModel.makeCurrent}"
rowSelection
="single" id="t1" binding="#{backingBeanScope.backing_untitled1.t1}">
<af:column sortProperty="#{bindings.customers.hints.customerName.name}" sortable="false"
headerText
="#{bindings.customers.hints.customerName.label}" id="c1">
<af:outputText value="#{row.customerName}" id="ot1"/>
</af:column>
<af:column sortProperty="#{bindings.customers.hints.customerId.name}" sortable="false"
headerText
="#{bindings.customers.hints.customerId.label}" id="c2">
<af:outputText value="#{row.customerId}" id="ot2"/>
</af:column>

<!-- This part will be an inline data -->
<f:facet name="detailStamp">
<af:outputText value="I am inner data" id="ot3"></af:outputText>
</f:facet>

</af:table>
Now the demand is the following . One of the table column actually displays the tracking number of the FedEx, so when user clicks on this column inline data will show the delivery status in FedEx web page.


You can access your delivery directly by providing tracking number inside GET parameter


https://www.fedex.com/fedextrack/?tracknumbers=AAAAAA. So it is not a problem to concatenate instead of the AAAAA the real tracking number. But user don’t want to click on the arrow icon at the beginning of the the row, but directly on the column data.


So first of all we need to convert the text in the column from plain text to clickable link


We do it by replacing


 


<af:column sortProperty="#{bindings.customers.hints.customerId.name}" sortable="false"
headerText
="Tracking number" id="c2">
<af:outputText value="#{row.customerId}" id="ot2"/>
</af:column>

By


 


 



<af:column sortProperty="#{bindings.customers.hints.customerId.name}" sortable="false"
headerText
="Tracking number" id="c2">

<af:commandLink text="#{row.customerId}" id="cl2"
partialSubmit
="true"
action
="#{viewScope.managedBean1.onButtonCLick}">
</af:commandLink>
</af:column>


Note that the command link will perform partial submit and is bound to some viewscope bean.


We will define this bean immediately inside adfc-config.xml file.


 


image


 


We need to understand also how does table knows which row to expand and with to collapse.


It is also easy . Each table has a property called “DisclosedRowKeys”


image


 


This object holds the keys of the rows in the table. Row which has her key inside this object will be expanded , the rest of the rows will stay collapsed.


So lets define this object inside our bean and bind the table “DisclosedRowKeys” property to it


 

public class HelperBean
{

private RowKeySetImpl disclosedKeys = null;

public HelperBean()
{
super();
}




adf by default makes first row selected which means , it will be expanded. We don’t want this , so we delete “SelectedRowKeys” property


image


We also want our table to refresh after user clicks on the link by using PPP so we define table partialTrigger property to be the ID of the command link (which is cl2)


image


 


So our goal is by clicking on the link to add row’s key to discloser object.


As you saw above our command link is bound to a method inside the bean

    public String onButtonCLick()
{
FacesContext fctx = FacesContext.getCurrentInstance();
UIViewRoot root = fctx.getViewRoot();
AdfFacesContext adfFacesContext =
AdfFacesContext.getCurrentInstance();
//clear disclosed RowKeys
disclosedKeys =null;
//PPR tree table
RichTable treeTable =
(RichTable)root.findComponent("t1");
getDisclosedKeys();
adfFacesContext.addPartialTarget(treeTable);
return null;
}


We find the table , call getDisclosedKeys(); method and refresh the table. The key here is

getDisclosedKeys();  method.


In the original article (I posted the link at the beginning of this article), they use binding layer to find which row to expand. Since I always want to expand only current row, I don’t need an access to the binding


 


Here it is

    public RowKeySetImpl getDisclosedKeys()
{

FacesContext fctx = FacesContext.getCurrentInstance();
UIViewRoot root = fctx.getViewRoot();

RichTable tree = (RichTable)root.findComponent("t1");
RowKeySet rks = tree.getSelectedRowKeys();
Key currentKey = null;

Iterator rksIter = rks.iterator();

while (rksIter.hasNext())
{
List l = (List) rksIter.next();
currentKey = (Key)l.get(0);

}

if (rks.size()>0) {
disclosedKeys = new RowKeySetImpl();

//if tree is found .... ADF CODE CORNER

if (tree != null) {

ArrayList newKeys = new ArrayList();
ArrayList temp = new ArrayList();
temp.add(0,currentKey);
                     newKeys.add(temp); 
disclosedKeys.addAll(newKeys);
}
}

else
{
disclosedKeys = new RowKeySetImpl();
}

return disclosedKeys;
}



What it does?


1. Find the table


2. Get selected row (for this your table has to be set to enable selection)


3. Get the key of the row


4. Add the key to disclosure object. (There are a lot of ArrayLists, I know)


Now we will do some cosmetic changes.


Lets stretch the last column , so the table will occupy the whole page width


image


 


And also our facet will hold an iframe element instead of just output text


<f:facet name="detailStamp">
<af:inlineFrame source="https://www.fedex.com/fedextrack/?tracknumbers=#{row.trackingId}"
id
="if1"></af:inlineFrame>
</f:facet>



I concatenate the binding of the tracking number to FedEx tracking link. This is what we get


 


image


User clicks on the tracking number link and see his delivery state immediately as an inline compoment

Wednesday 10 April 2013

Popup External Web Content in a Siebel View in Full Screen

 

There is an option to embed external web content into Siebel Client. I am not going to explain how , it is explained very well here. I am going to talk about symbolic URL which is “IFRAME” . You can open it as part of your page or as a popup window.

  My Customer wanted another page to be opened as a popup. I choose IFrame option and basically it is all I need to do.

image

However IFrame didn’t open as a full screen and customer was complaining that he need to click on the “maximize” button (yeahh… such a big efford).

Any way the solution is very simple. I took an advantage over IFrame “onload” function and just wrote simple javascript function to maximize the popup window.

image

 

Now popup windows opens in a full screen mode (maximized)

Monday 4 February 2013

Tomcat support for UTF-8 encoded parameter

 

So here is the deal. My JSP file should get a parameter that  contain Russian text , which is encoded in UTF-8

Это тест

%D0%AD%D1%82%D0%BE%20%D1%82%D0%B5%D1%81%D1%82

Later this parameter is passed into Siebel CRM system which is defined as UTF-8. How it does it and why is not really important . What is important that instead of the Russian text I see ????????????? . Nice ,haa?

image

I spend about 3 hours searching forums ,tutorials and so on and so on, but none of the proposed solution did the work. However the COMBINATION of proposed solutions did the work.

   Could be that some of the steps are not necessary to achieve the goal. You are most welcome to try to eliminate some of them.

Here a list of configurations that eventually caused my Tomcat to handle the parameter properly

1. I save the JSP page in UTF-8 format. For this I used “Notepad++” (If you don’t know that is “Notepad++” you are probably still leave in 20th century)

image

2. Put a UTF-8 declaration at the top on the JSP page

image

3. Set character encoding to UTF-8*

image

* Some examples proposed to create a filter. See no reason to do it in my case

4. Configure Tomcat’s “Connector” (in server.xml file) to handle requests as UTF-8

image

5. Define Java JVM paramter “file.encoding” as UTF-8

a. If you start Tomcat from command line (on Windows), use:

   set CATALINA_OPTS=”-Dfile.encoding=UTF-8”

b. If you run Tomcat as a service (on Windows), inside Tomcat’s bin directory execute “tomcat7w.exe” file . and it “Java” tab, add to Java Options “-Dfile.encoding=UTF-8”

image

 

Just for the reference . My Tomcat version is 7.0.21, but probably Tomcat 6 and 5 have the same or very similar configuration.

After applying the changes above everything worked like a charm

Technorati Tags: ,,,

Thursday 31 January 2013

Connect to Oracle EBS apps schema without password by using JDBC connection

 

The following post is not a hack. It just describes the method which is used by Oracle EBS to connect to APPS schema without providing username and password.

  The method will work only with Oracle Application EBS environment. Standalone Oracle databases have nothing to do with it. Also you need to understand that this method is for obtaining JDBC Connection object only

Lets start straight with a code, because it is very simple.

import oracle.apps.fnd.common.AppsContext;
import java.sql.*;

public class ConnectionToApps
{
public static void main(String[] args)
{
String dbcFile
= "Enter Here The Path To Dbc File";
Connection _conn
=null;
AppsContext ac
= new AppsContext(dbcFile);
_conn
= ac.getJDBCConnection();
}
}

Only 4 lines of code.


But the trick is to get the path to DBC file.


It is also simple. DBC files are located under $FND_SECURE directory (if connected to the server with application owner OS user)


Bellow is the shell example


/home/applDVIS12>cd $FND_SECURE
/space2/DVIS12/inst/apps/DVIS12_cow/appl/fnd/12.0.0/secure>ls
DVIS12.dbc
/space2/DVIS12/inst/apps/DVIS12_cow/appl/fnd/12.0.0/secure>


Obviously the correct file is DVIS12.dbc. But many times there are a lot of files in this directory. So how do you know the correct one.


It is also not a problem. The file name (without .dbc) always can be found by looking into “Applications Database ID” profile in EBS or by just running the following query



select fnd_profile.VALUE('APPS_DATABASE_ID') from dual
So now you have everything to assemble the PATH to DBC file


To summarize it , the path is $FND_SECURE/ + select fnd_profile.VALUE('APPS_DATABASE_ID') from dual +/.dbc