You are on page 1of 14

E-Business Suite and APEX Extending or Integrating?

Since returning from KScope14, I have been spending a great deal of time and effort examining any method of
truly integrating E-Business Suite 12.2.3 (EBS) and APEX 4.2.5 (APEX). I have read the Oracle white paper,
Extending Oracle E-Business Suite Release 12 using Oracle Application Express, and I realize this is the only
supported method. But, it feels incomplete to me...
Currently our users are logged in to APEX automatically when they choose an APEX app in EBS (version 11).
From a usability standpoint I do not want my users to have to re-login to APEX after logging in to EBS (version
12).
In the following series of posts, I will post the steps we took and the issues we ran into while developing our
solution.

Custom EBS 12.2.3 to APEX 4.2.5 Integration Part 1: The obligatory listing of caveats,
gotchas, and mumbo jumbo

This part is to introduce you to what we used and why we did it this
way.
Software Versions:
Oracle E-Business Suite 12.2.3
Oracle Application Express: 4.2.5.00.08
Glassfish Server: 4.0
Oracle REST Data Services: 2.0.8.163.10.40
General Approach:
Requirements:

Users cannot log directly into APEX for EBS integrating applications

Users MUST log into Oracle EBS first

APEX applications must be assigned to Responsibilities for inclusion in Menus for those responsibilities
not to individual users or a custom APEX Responsibility. For example, an HR APEX application should
be accessible from HR specific responsibilities only.

APEX access must work in a mix of environments SSL and non-SSL. For instance, EBS uses SSL but
APEX (being a non-externally facing application) is non-SSL

EBS to APEX must not pass anything user identifiable in the URL, including responsibility IDs

Each Responsibility group must not be able to access the other responsibilities applications. In other
words, HR should not be able to access Sales applications in APEX nor see any menu items for Sales
APEX applications

Caveats:

Our code is minimal in both commenting and error handling. This is done on purpose to make it easier
to understand and for quick adaptability into your environment (should you choose to use it).

Yes we use a customized jsp based on the GWY.jsp. In order to accomplish the requirement for working
in mixed SSL and non-SSL environments, we had to make a non-secure copy of the EBS session cookie
that could be read in non-SSL APEX pages. We know, we know... we really should be full SSL
everywhere, even if it's non-externally facing.

We also realize that this solution is not supported by Oracle and any function call we make today may
not work in the future. But how is this different from any other customization we have to make in
house? Every organization is different and has different needs. We make do with what we have.

We host several APEX instances on a single Glassfish server so urls contexts may seem a little strange.
I will post how we accomplished this at a later date.

The LAST and MOST IMPORTANT thing we have to mention. Using cookies means both servers
MUST BE ON THE SAME DOMAIN. This is a strict cookie and session management requirement set
in stone many, many years ago. So if your EBS server is at abc.def.com and APEX is at ghi.jkl.com, this
method will not work. Both servers must be on the .def.com or both on the .jkl.com domain. However,
that doesn't mean all is lost. My next project is to... well that's for another post ;)

Custom EBS 12.2.3 to APEX 4.2.5 Integration Part 2: LaunchApex.jsp


We didn't alter any of the original GWY.jsp code. Instead we added a piece to capture the value of
the current EBS session cookie and rewrite it to another cookie that APEX will expect. By using
the GWY.jsp, in the case where someone has bookmarked the urls within EBS to launch APEX, we
can lean on the session checking already included. Anyone without a valid session will be sent to
the Oracle login page.

Where does LaunchApex.jsp go on the server?


$OA_HTML should point to the running file system.
For example:
<some path>/fs1/FMW_Home/Oracle_EBS-app1/applications/oacore/html

For production you would only place in the non-running or Patch file system, then compile and
wait for a patch cycle to commit to the running file system. But in our test environment we place
in both file systems

For example:
<some path>/fs1/FMW_Home/Oracle_EBS-app1/applications/oacore/html
<some path>/fs2/FMW_Home/Oracle_EBS-app1/applications/oacore/html

How is LaunchApex.jsp used?


LaunchApex.jsp will be set in the function call within EBS and we will see this in another post.
But first we have to compile the jsp and restart Weblogic so the new jsps are ready for use.

For Example:
cd <some path>/fs1/FMW_Home/Oracle_EBS-app1/applications/oacore/html
$FND_TOP/patch/115/bin/ojspCompile.pl --compile -s 'ZEUS_LaunchApex.jsp' flush
cd <some path>/fs2/FMW_Home/Oracle_EBS-app1/applications/oacore/html
$FND_TOP/patch/115/bin/ojspCompile.pl --compile -s 'ZEUS_LaunchApex.jsp' --flush
Restarting Weblogic Server
admanagedsrvctl.sh stop oacore_server1
admanagedsrvctl.sh start oacore_server1
The Cookie Variables explained:
String ebsCookieName = "VIS"; - this is the name of the EBS cookie, there are several
articles on the internet that show you how to locate this value either in your browser or in your
database.

String apexCookieName = "VISAPEX"; - this is the name of the cookie for which APEX
will be looking in the browser. In the APEX application this is a substitution string setting (don't
forget to set it)

String apexDomain = ".YOURDOMAIN.com"; - the SHARED domain between apex and


ebs. Not setting this could cause an issue if you have any custom code that uses a default
domain that isn't correct. Maybe a bad clone from another instance kept an older value or
something to that effect.The leading "." isn't strictly required but some browsers may forget to
add it, so explicitly setting is a good idea.

String apexPath = "/"; - another parameter that isn't required but could be set to an
undesirable value by your webserver due to any number of ways defaults/non set values are
handled, so explicitly setting is a good idea.

boolean isCookieSecure = false; - If both servers are using SSL, change this to true.
Otherwise leave alone.
Full listing for our LaunchApex.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%-/*===========================================================================+
|

Copyright (c) 2009 Oracle Corporation, Redwood Shores, CA, USA

All rights reserved.

|
|

+===========================================================================+
|
|

FILENAME

GWY.jsp

|
|

|
DESCRIPTION

GWY.jsp handles external application URL embedding within

E-Business Suite. GWY expects to be invoked only from RF as

standard function invocation.

|
|

|
DEPENDENCIES

|
|

HISTORY
01-AUG-2009

|
raghosh

created

+===========================================================================*/
--%>
<%@ page contentType="text/html;charset=windows-1252"%>
<%@ page import="java.util.Map"%>
<%@ page import="java.util.HashMap"%>

<%@ page import="java.util.Enumeration"%>


<%@ page import="java.util.Iterator"%>
<%@ page import="oracle.apps.fnd.common.VersionInfo"%>
<%@ page import="oracle.apps.fnd.services.gwy.ExternalAppManager"%>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Oracle Applications External Gateway - Custom Launch Apex 20140801 - 5</title>
</head>
<body>

<%! public static final String RCS_ID =


05:28:11 appldev ship $"; %>

"$Header: GWY.jsp 120.3.12020000.1 2012/06/30

<%! public static final boolean RCS_ID_RECORDED =


VersionInfo.recordClassVersion(RCS_ID,"oa_html"); %>

<%

Enumeration<String> paramNames = request.getParameterNames();

Map<String, String> params = new HashMap<String, String>();

while(paramNames.hasMoreElements()) {
String param = paramNames.nextElement();
String paramVal = request.getParameter(param);
if (!(paramVal == null || "".equals(paramVal)))
paramVal = paramVal.trim();
params.put(param, paramVal);
}

//boolean debugMode = "Y".equalsIgnoreCase(params.get("debug")) ? true : false;

//if (debugMode) {
//

Iterator iter = params.entrySet().iterator();

//

while (iter.hasNext()) {

//

Map.Entry aPair = (Map.Entry) iter.next();

//
out.println(String.valueOf(aPair.getKey()) + "=" +
String.valueOf(aPair.getValue()) + "<br>");
//

//}

String targetType = params.get(ExternalAppManager.EXTERNAL_APP_TYPE_PARAM);


if (targetType == null || "".equals(targetType))
targetType = (String)
request.getAttribute(ExternalAppManager.EXTERNAL_APP_TYPE_PARAM);

String handlerClass = params.get(ExternalAppManager.EXTERNAL_APP_HANDLER_PARAM);


if (handlerClass == null || "".equals(handlerClass))
handlerClass = (String)
request.getAttribute(ExternalAppManager.EXTERNAL_APP_HANDLER_PARAM);
//String authFunction = params.get(ExternalAppManager.EXTERNAL_APP_AUTH_FUNCTION);
ExternalAppManager manager = new ExternalAppManager(request, response, targetType,
handlerClass);
manager.logParams(params);

/** COOKIE REWRITE BEGIN **/

// COOKIE VARIABLES
String ebsCookieName = "VIS";
String apexCookieName = "VISAPEX";
String apexDomain = ".YOURDOMAIN.com";
String apexPath = "/";
boolean isCookieSecure = false;

// RETRIEVE EBS COOKIE


Cookie[] cookies = request.getCookies();
Cookie ebsCookie = null;
if (cookies != null) {
for (int i = 0; i < cookies.length; i++) {
if (cookies [i].getName().equals (ebsCookieName)) {
ebsCookie = cookies[i];
break;
}
}
}

// CREATE APEX COOKIE USING EBS COOKIE VALUE


Cookie apexCookie = new Cookie(apexCookieName, ebsCookie.getValue());
apexCookie.setDomain(apexDomain);
apexCookie.setPath(apexPath);
apexCookie.setSecure(isCookieSecure);

// ADD COOKIE INTO RESPONSE


response.addCookie(apexCookie);

/** COOKIE REWRITE END **/

manager.doForward(params, false);
manager.releaseResources();

%>
</body>
</html>

Custom EBS 12.2.3 to APEX 4.2.5 Integration Part 3: EBS Function and Menu Setup

The following steps were done while logged into EBS with the System Administrator responsibility.
note: The System Administrator menus are used as references. The same techniques can be used to create menu
entries under other responsibilities as well.

Set APEX Function path


System Administrator -> Profile -> System
In the Find System Profile Values -> Profile field enter FND: APEX URL and press the Find button

Change the Site value to your appropriate path and save.


For example: http://yourserver.yourdomain.com:8080/ords

Create Form Function


Application -> Function
Description Tab:

Function Name

User Function Name

Description

Properties Tab - Type: SSWA jsp function

Web HTML Tab - HTML Call: LaunchApex.jsp?targetAppType=APEX&p=900:1


(using application id 900 and page 1, make sure the application ID matches what you are using for your APEX
app. )
Notice we are not sending anything else in the call. Therefore, no other information will be sent in the calling
URL!

Adding Menu Prompt


Application -> Menu
Create a new entry(see bottom entry in image below):

Prompt - whatever you wish the user to see

Submenu - depends on your setup

Function - the function we created above

Description - optional

Notes:

You can set up multiple Form Functions. We use one for each application. For example, HR and Sales
each have different Form Functions and menu entries.

On the APEX side we have completely separate applications for each group. Therefore we can
completely separate responsibilities and groups that are affected with changes in any applications.

Multiple APEX listeners, one Application Server using Oracle REST Data Services (ORDS)
Oracle REST Data Services (ORDS) gives us the capability us to deploy multiple versions of the APEX
listeners to a single Glassfish instance. This is great for centralizing resources on a single server in our nonproduction environments. This short post will show you how quick and painless it is to setup.

Setting up 2 instances (apptest & appdev)


Using ords.2.0.8.163.10.40.zip
Set up 2 directories and unzip into both directories
for example:

<some path>/apptest

<some path>/appdev

Rename the ords.war files in both


for example:

<some path>/apptest/ords_apptest.war

<some path>/appdev/ords_appdev.war

Run the war config process on each war using your specific setup info for each app

cd <some path>/apptest

java -jar ords_apptest.war

note: we use app and date specific configurations file locations


<some path>/apptest/ords_apptest_<today's date>_cfg

cd <some path>/appdev

java -jar ords_appdev.war

note: we use app and date specific configurations file locations


<some path>/appdev/ords_appdev_<today's date>_cfg

Configure the "Listener Administrator" user with your specific setup info for each app

cd <some path>/apptest

java -jar ords_apptest.war user username "Listener Administrator"

enter password

confirm password

cd <some path>/appdev

java -jar ords_appdev.war user username "Listener Administrator"

enter password

confirm password

Configure images war files with

cd <some path>/apptest

java -jar ords_apptest.war static --context-path /i_apptest <glassfish install


path>/glassfish/domains/domain1/docroot/i_apptest

cd <some path>/appdev

java -jar ords_appdev.war static --context-path /i_appdev <glassfish install


path>/glassfish/domains/domain1/docroot/i_appdev

Copy images from each APEX instance to glassfish as needed

<glassfish install path>/glassfish/domains/domain1/docroot/i_apptest

<glassfish install path>/glassfish/domains/domain1/docroot/i_appdev

Deploy war files to glassfish

ords_apptest.war

i_apptest.war

ords_appdev.war

i_appdev.war

Note: if you have already chosen /i/ as the images context during setup (instead of specifying /i_apptest/ or
/i_appdev/), run the reset_image_prefix.sql in <apex installation folder>/utilities and specify the correct context
for your image files. This might take some time to finish so be patient.

Conclusion
There you have it, a down and dirty, quick and easy setup of multiple listeners for your different APEX
installations on a single Glassfish install.

E-Business Suite and APEX integration using Views


Create a view on top of the EBS views and use some naming conventions so it's easy to recognise which
objects you created and are not native EBS ones.
create view apex_per_people_vw as select * from per_people_x
Grant access on that view to the schema that is linked to your APEX workspace and application
grant select on apex_per_people_vw to apex_ebs

Create a view in your own schema that selects everything from the view in the apps schema.
We do that so that the views are a one-on-one mapping between schema's, but they show up in the APEX
wizards.
create view apex_per_people_vw as select * from apps.apex_per_people_vw
Create an Interactive Report on top of the view

This first examples shows how you can view data from EBS in your own APEX application. We can now create
a calendar, charts etc. in APEX based on the data coming from EBS. In the next post I will show how you can
edit this data.

You might also like