X

Best Practices from Oracle Development's A‑Team

Troubleshooting Techniques for a JCS-SX ADF Application Embedded in SalesCloud

Introduction

I have been playing around with embedding an external ADF application (running on Oracle Java Cloud Service - SaaS Extension) within Oracle SalesCloud to demonstrate the trusted association (SSO) between SalesCloud and JCS-SX and ran into a couple of issues. I would like to share my experience of troubleshooting those issues and provide a few tips for fellow developer comrades that may experience similar problems.

Technology Versions

SalesCloud 11.1.9.2+, 11.1.10+
JCS-SX 15.2+
ADF 11.1.1.7.1

Main Article

Before I get into discussing techniques used for troubleshooting, let me provide a brief overview of what I am trying to do in the first place. I have created a very simple ADF application called AccountDetails that will be deployed on JCS-SX and accesses data from the co-located DbCS Schema instance (which will be available as a Sample soon). My goal is to make the ADF application, which is just a single page for now, appear as a part of the SalesCloud content. The ADF content will be displayed within a tab on the Account Details screen displaying additional information stored in DbCS related to the given account.
TT4AJAAEISC_fig00

Note: This code will be uploaded as a Sample Application soon, and I will post the link here once it is live. At this link you will also find a step-by-step readme to run this sample along with necessary documentation if you want to build your own version of this sample.

In this article, I'll focus on the issues that I hit during the development and deployment of that sample - which may be useful to troubleshoot issues when you are building an implementation similar to this sample.
Below is where I hit problems while developing this sample. I had installed the ADF application in JCS-SX, performed the customizations in SalesCloud’s AppComposer to embed the ADF application in the sub-tab, and initially the content did not appear. The following is a summary of the issues I faced while getting the content to load properly. Following the summary will be details about each issue, including the technique I used to diagnose it, the cause, and how I fixed or worked around the issue (but keep in mind the solutions are not the ultimate focus of this article).
At this point, I am able to open the ADF application (via a direct link to the application hosted on JCS-SX) in a full browser tab and am able to pass in an Account Number via the URL. This is what the application looks like when loaded directly into a browser tab:
TT4AJAAEISC_fig01


Issues Summary

Issue 1: Although the ADF page renders in the browser, nothing is displaying view viewing this page within the SalesCloud sub-tab. Diagnostic technique: View Frame Source.
Issue 2: After addressing the first issue, still nothing is displaying within tab. Diagnostic technique: Browser’s built-in Developer Tools.
Issue 3: After addressing the second issue, a 500 error is displaying within tab. Diagnostic technique: SalesCloud and JCS-SX logging.

Issues Details

Issue 1: Nothing is displaying within the SalesCloud sub-tab

Description

Although I can access the ADF application if I open it in a full screen (i.e. place the URL directly in its own browser tab), it doesn’t display correctly when embedded in the SalesCloud Account Details tab. All I see is:
TT4AJAAEISC_fig02

Diagnostic Technique

By right-clicking the tab content area and selecting View Frame Source, Chrome will open another tab with “view-source:” prepended to the URL and this may give us some insight as to what the problem might be.
TT4AJAAEISC_fig03

Cause

In this case, rather than seeing the page’s source, I get a screen telling me that Chrome has blocked access to unsafe content. This happens because the development server I’m working with is using a self-signed certificate and the browser expects it to be signed by a proper Certificate Authority.

Solution

Ultimately, to appease the browser, we’d need to get the certificate signed by a CA, but since this is only a development machine and we don’t want to bother with the expense of doing so, the workaround is to instruct the browser to proceed regardless.
TT4AJAAEISC_fig04

Note: You may not require this if you are developing using Oracle Public Cloud JCS-SX instances. If you are using your development server in conjunction with Oracle Sales Cloud, you may face this issue.

Issue 2: After addressing the first issue, still nothing is displaying within tab.

Description

Although I bypassed the certificate issue, I’m still not seeing any content in the tab. This time View Frame Source is not helpful, because all it has is the “about: blank” page, which is the browser’s placeholder for empty content.
TT4AJAAEISC_fig05

Diagnostic Technique

By viewing the JavaScript Console available in Chrome’s Developer Tools, we may be able to see what the problem is. Show the Console by clicking View > Developer > JavaScript Console.
TT4AJAAEISC_fig06

Cause

The console shows that the requested content refused to be displayed within a frame. Content can instruct the browser to prevent it from being rendered within a frame by setting its “X-Frame-Options” header set to “DENY,” which is what happened here. This URL is actually the SSO login page. The ADF application I created is protected, so it is only accessible by someone who has been authenticated with the Authentication Provider for JCS-SX. Because we are connecting to a JCS-SX instance that is associated with this SalesCloud instance, we can use the SSO sign in to authenticate with either SalesCloud or JCS-SX and either partner will accept the authentication token. At this point, I have only logged into SalesCloud directly and not into the SSO provided by OAM.

Solution

Access the JCS-SX console (which will prompt with the SSO login) before attempting to access the sub-tab in SalesCloud. An alternative solution is to set the "org.apache.myfaces.trinidad.security.FRAME_BUSTING" parameter to "never" in the web.xml of your ADF application, but be aware that this disables framebusting and can leave your application vulnerable to Clickjacking (a.k.a UI Redress).

Issue 3: After addressing the second issue, a 500 error is displaying within the tab.

Description

I am getting closer. At least the 500 is a response from the JCX-SX server, but obviously this is not the correct content.
TT4AJAAEISC_fig07

Diagnostic Technique

Using a combination of view source, Run Time Messages in SalesCloud’s ApplicationComposer, and the log messages in the JCS-SX console, I can get a better idea of what’s going on.

Cause

Using View Frame Source, I see that the browser is trying to load what looks like the correct URL (I have removed some of the ADF params that clutter it, e.g. jsessionid, _afr*, for clarity):
https://jcssx-host/AccountDetails/faces/adf.task-flow?adf.tfDoc=/WEB-INF/main/tf-main.xml&adf.tfId=tf-main&accountNumber=300000000845217
This doesn’t tell me a whole lot, unless I know exactly what it should be, but if I check the log messages using the JCS-SX console, I can see there are some errors having to do with the ADF task-flow controller being unable to parse a task-flow Id from the URL.
TT4AJAAEISC_fig08
Upon further inspection of the URL revealed by View Frame Source, I notice the query parameters are not quite correct. Notice the “&” before “adf.tfId” is followed by “amp;”. Same for “accountNumber.” Apparently, something is encoding the ampersands in the URL, and doing so incorrectly. If an “&” is going to be encoded in a URL, it should be “%26”, not “&”. In this case, “amp;" is becoming part of the “adf.tfId" parameter name, so the query param “adf.tfId” is not present, because it is now actually “amp;adf.tfId”.
To help me understand where this is occurring, I employ some logging in the Groovy script that is generating the URL for the SalesCloud Web Content:
TT4AJAAEISC_fig09
 I can then check the Run Time Messages (SalesCloud > Navigator > More … > Application Composer > Run Time Messages) to see how the URL is coming out of the Groovy script (*note: be sure to enable Application Script Logging before accessing the Account Details embedded content tab so the messages will appear in the message log), and in this case it is correct, there are no extra “amp;” appended to the ampersands:
TT4AJAAEISC_fig10
The URL from the Groovy script looks good, so let’s try adding some logging in the ADF application to see if that will help us determine where the URL is getting mis-encoded. Since ADF is a J2EE compliant architecture, I can add a filter to the web.xml that logs the request URLs (there are other options for logging the URL, but this is what I was able to come up with quickly). I created the following Filter:
package oracle.cloud.sampleapps.accountdetails.view;   import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import oracle.adf.share.logging.ADFLogger;   public class AccountDetailsFilter implements Filter {       private static ADFLogger LOG = ADFLogger.createADFLogger(AccountDetailsFilter.class.toString());         public AccountDetailsFilter() {         super();     }     public void destroy() {     }     public void init(FilterConfig filterConfig) { }     public void doFilter(ServletRequest servletRequest,                          ServletResponse servletResponse,                          FilterChain filterChain) throws IOException, ServletException {         HttpServletRequest request = (HttpServletRequest)servletRequest;         final String queryString = request.getQueryString();         LOG.severe("[AccountDetailsFilter] Incoming URL: "+request.getRequestURI() +"?" + queryString);         filterChain.doFilter(servletRequest, servletResponse);     } }
 And in the web.xml, I added the following filter and filter-mapping entries:
  <filter>     <filter-name>AccountDetailsPreFilter</filter-name>     <filter-class>oracle.cloud.sampleapps.accountdetails.view.AccountDetailsFilter</filter-class>   </filter>   <filter-mapping>     <filter-name>AccountDetailsPreFilter</filter-name>     <url-pattern>/*</url-pattern>     <dispatcher>REQUEST</dispatcher>   </filter-mapping>
After deploying the ADF application to an EAR and redeploying it to JCS-SX, I can now see logging statements from the AccountDetailsPreFilter that I created. They show that the URL is coming in with the ampersands in an encoded format.
TT4AJAAEISC_fig11
Unfortunately, I think this means the issue is somewhere between the Groovy script and the ADF application, which means it likely somewhere in SalesCloud’s handling of the URL returned by Groovy for display in the tab's WebContent, especially since I can close the AccountDetails dialog, reopen, access the tab, and the content will display correctly. And the logs show the URL coming into ADF properly at that point. So, the issue only occurs the very first time I access the tab. I will need to check with the SalesCloud team to see about digging into this further, but that I will leave for another article. In the mean time, I’ll just code a quick work around to keep me moving forward.

Solution

If any aberrant ampersands exist in the requested URL, correct them and redirect the response to the correct URL. Here’s the code update for the AccountDetailsPreFilter (*note: I also reduced the pattern scope on the filter in the web.xml to “/faces/*” instead of “/*" ):
package oracle.cloud.sampleapps.accountdetails.view;   import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import oracle.adf.share.logging.ADFLogger;   public class AccountDetailsFilter implements Filter {       private static ADFLogger LOG = ADFLogger.createADFLogger(AccountDetailsFilter.class.toString());       private static final String ENCODED_AMP = "&amp;";     private static final String PLAIN_AMP = "&";       public AccountDetailsFilter() {         super();     }       public void destroy() {     }       public void init(FilterConfig filterConfig) {     }       public void doFilter(ServletRequest servletRequest,                          ServletResponse servletResponse,                          FilterChain filterChain) throws IOException,                                                          ServletException {         HttpServletRequest request = (HttpServletRequest)servletRequest;         HttpServletResponse response = (HttpServletResponse)servletResponse;           final String queryString = request.getQueryString();         LOG.fine("[AccountDetailsFilter] Original URL: "+request.getRequestURI() +"?" + queryString);           //A query String should never contain an ampersand encoded as "&amp;", the         // proper URL encoding would be "%26" if one wanted to include "&" as part         // of parameter value. So, we should be able to safely replace all occurrences         // of "&amp;" with just "&".         if(queryString != null && queryString.contains(ENCODED_AMP)){             LOG.severe("[AccountDetailsFilter] URL Contains poorly encoded Ampersands: "+request.getRequestURI() +"?" + queryString);             final String newUrl = request.getRequestURI() +"?" + queryString.replaceAll(ENCODED_AMP, PLAIN_AMP);             response.sendRedirect(newUrl);             LOG.severe("[AccountDetailsFilter] Redirecting to: "+newUrl);         }else{             filterChain.doFilter(servletRequest, servletResponse);         }     } }

Summary

In this article, I covered several issues that I faced while trying to embed into SalesCloud an ADF application that is hosted on JCS-SX. The symptoms of all the issues were basically that the ADF content was not displaying in the tab even though the ADF application was working properly when directly accessed in a browser tab. I demonstrated how to use browser features, such as View Frame Source and JavaScript Console, how to add logging to Groovy script used to customize SalesCloud and view those messages in the Run Time Messages section of Application Composer, as well as how to add logging to a filter in the ADF application and view those messages via the JCS-SX console. There are many more techniques that can be used to troubleshoot issues in SalesCloud and JCS-SX, but these should be a good start to help make you successful in customizing SalesCloud.
 

p.s. Other common issues faced while deploying the ADF application to Sales Cloud are solved by:
- Using the correct version of JDeveloper (11.1.1.7.1 - Cloud Version).
- Using the correct version of JSF by setting the deployment profile target to type "Oracle Cloud."

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha

Recent Content