Tuesday, 22 September 2015

Tracking web services calls in WebCenter logs

When invoking web services from WebCenter applications, it may be useful to track all the requests and responses generated in the application. In order to achieve this, some configuration in WebLogic console must be done:

1. Log in to WebLogic console as administrator user.

2. Navigate to WebCenter Portal managed server.

3. Select Configuration -> Server Start tab.



4. In the Arguments box, paste the following commands:


  -Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true  -Dweblogic.security.SSL.verbose=true -Dcom.sun.net.ssl.checkRevocation=false



5. Save and restart the managed server.

After that, in the out log file there will be traces with all the requests to web services, as well as their responses.

For instance:

---[HTTP request - http://<WS_Host>:6073/Service/CustomerManagement/Endpoint]---
Content-type: text/xml; charset=utf-8
Soapaction: "/Service/CustomerManagement.serviceagent/CustomerManagementEndpoint/GetServiceBillingAccounts"
Accept: text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
<?xml version='1.0' encoding='UTF-8'?>


[..]

---[HTTP response - http://<WS_Host>:6073/Service/CustomerManagement/Endpoint - 200]---
null: HTTP/1.1 200 OK
Content-type: text/xml; charset="utf-8"
Content-length: 32026
Connection: keep-alive
Server: Jakarta-HttpComponents-NIO/1.1
Date: Thu, 17 Sep 2015 17:44:42 GMT
<?xml version="1.0" encoding="UTF-8"?>


It is important to note that this configuration is not recommended in Production environments, as it negatively affects the performance of the WebCenter platform.

Acknowledgement: Thanks to Roberto Fuertes Peña for his help.

Friday, 7 August 2015

Data source drivers for ADF applications

Recently I found an error in an ADF 12c application in Production which was prompting error popups to users all the time. In the managed server log files, the following trace was registered:

oracle.jbo.SQLStmtException: JBO-29114 ADFContext is not setup to process messages for this exception.
[..]
Caused By: java.sql.SQLException: Statement cancelled, probably by transaction timing out

Firstly, I checked data source connectivity from WebLogic console, but the result was successful.



Then I found this post and this one, where the source of the problem was attributed to the data source driver. Despite the common practice of assigning JDBC XA drivers to data sources connections, this should not be used with Oracle Fusion applications, as it is documented here, because they are not compatible, "XA data sources close all cursors upon commit" and that produces errors. As that data source was using that type of thin XA driver (oracle.jdbc.xa.client.OracleXADataSource), I decided to change it.

As the list of driver types is only displayed when creating a new one, nd I did not know the exact name, I decide to create a new mock data source, just to get that value, which was:

Description: Oracle's Driver (Thin) for Instance connections; Versions:Any
Name: oracle.jdbc.OracleDriver



Once I knew the name, I edited the current data source with that driver name. However, I could not activate changes, because an error was received, it was related to not been able to update de data source configuration file.



The workaround consists in changing manually that configuration file. Navigate to the following folder in the domain server:

<adf_domain_dir>/config/jdbc 

Create a backup copy of the file with the data source name and edit the original one. Just update the parameter related to driver-name:

<driver-name>oracle.jdbc.OracleDriver</driver-name>

After this, the error disappeared from the production environment.


References


Don't Use Oracle's Driver (Thin XA) to Define WebLogic Data Source for ADF Applications
ADF: Resolving random JBO-27122 and closed statement errors
What You May Need to Know About JDBC Data Source for Oracle WebLogic Server

Friday, 31 July 2015

Invoking Web Services from WebCenter Portal

It is very common to find clients relying on web services to perform actions across different platforms, such as Siebel, data warehourse or content repositories. When implementing an Oracle WebCenter Portal installation, those web services must be integrated via WebCenter applications. This post explains how to achieve it.

Creating Web Service Proxy 

 

Firstly, a WebCenter Portal application  needs to be created in jDeveloper. In this case I used jDeveloper 11.1.1.7.0 with WebCenter extensions. Once it is created, the following steps must be performed:

1. Create a Project for the new web service proxy. I recommend to mantain one project for web service, because there could be conflicts between them.

2. Add a Web Service Proxy Client. In this case I am using JAX-WS style.







3. Introduce URL to web service. It is recommended to select the option "Copy WSDL intro project".




4. Define packages for this client. In this step there could be an error regarding classes conflict, if this is the case, I recommend to leave the packages blank.



5. Select default settings in methods.






6. No policies are usually needed.

 


7. Continue with default values until the last window, where the actions are summarised.




Once the client is created, it should be tested by inserting code in the main method of the endpoint class (<WS_Name>EndpointClient.java) and executing it with the Run option. This quick check will determine if the connection is fine.





Implementing Web Service Methods

 

The next step is to create the methods that will invoke web service for the WebCenter application.

1. Create a new java class named Invoker<WS_Name>.java. This should be created in the root package of the proxy and will invoke operations generated by the client. In this class the input parameters of the service are sent and the output objects are created.



2. In this new class, an invoke function is created per service, where the input parameters are inserted in the input object, then it is sent to a function in the Enpoint class. Example:

    public static WSOutputQueryMobileTransactions invokeMobileTransactions(String mobileNumber, String queryType, String startDate, String correlationID  ){
       
        MobileBalanceQueriesEndpointClient mobileTransaction = new  MobileBalanceQueriesEndpointClient();
        InputQueryMobileTransactions input = new InputQueryMobileTransactions();
        input.setMobileNumber(mobileNumber);
        input.setQueryType(queryType);
        input.setStartDate(startDate);
       
        return mobileTransaction.invokeMobileTransactions(input,correlationID);
       
    }



3. Once the invokers are defined, in the Endpoint class functions are created where the request is built, putting together the input object from the Invoker class and other header parameters. Finally, the request is sent to the Soap.java class which communicate with the web service and return its response. Example:

        public static WSOutputQueryMobileTransactions invokeMobileTransactions (  InputQueryMobileTransactions input,String correlationID){
              mobileBalanceQueriesServiceagent = new MobileBalanceQueriesServiceagent();
              Soap soap = mobileBalanceQueriesServiceagent.getMobileBalanceQueriesEndpoint();
              ((BindingProvider)soap).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY , Properties.getInstance().getValues().get("URL_ENDPOINT_MOBILE") + "/Service/MobileBalanceQueries.serviceagent/MobileBalanceQueriesEndpoint/QueryInvoiceValue"); 
             
              // General Request
              WSInputQueryMobileTransactions request = new WSInputQueryMobileTransactions();
             
              // Header parameters are created and added
              WSRequestHeader cabecera = new WSRequestHeader();
              WSRequestHeader.System system = new WSRequestHeader.System();
              system.setCorrelationID(correlationID);
              system.setValue("Portal");
              system.setProcessingServer("Test");
              cabecera.setSystem(system);
             
              // Header and input parameters are put together
              request.setWSRequestHeader(cabecera);
              request.setInputQueryMobileTransactions(input);
             
              //Web Service is invoked with the request
              return soap.queryMobileTransactions(request);

          }



4. The main method in the Endpoint can be used to test the functions. Example:

        public static void main(String[] args)
        {
            try
            {
            WSOutputQueryInvoiceValue resp = new MobileBalanceQueriesEndpointClient().invokeInvoiceValue("3057000973", "1");
              
            System.out.println(resp.getWSResponseHeader().getService().getStatus());
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }




Eventually, a JAR library needs to be generated from the project and it will be added to the WebCenter Portal application, where web services will be invoked via the Invoker class.

References


Tutorial: Creating a Web Service Proxy 
Creating Web Services Proxy in JDeveloper


Friday, 26 June 2015

Forcing browsers to clear cache

When updating Production environments, there is usually an issue with browser cache. Some styles (css) are modified and you need to manually clear cache in your browser to check the result. This is fine for developers, but what about users? Are you going to tell all the users of a public website to manually clear browser cache?

This problem could be solved by disabling caching of the pages, in the page header or even in the template header, the following line can be added and browsers would not cache anything:

<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">

However, an Oracle WebCenter application, as many others nowadays, relies heavily on cache to speed up loading processes, so this approach does not seem to be the best one.

My recommendation is to add a version parameter to the css file reference. Navigate to the place where the css include is located, usually in the page template, and add the following text: ?ver=1.1 The version value could be any of your choice.

For instance, in the WebCenter template file, the following line would force the client browsers to clear cache with the new modifications:

   <af:resource type="css" source="/../shared/css/portal/main.css?ver=1.1"/>

Next time the page is loaded in browser, it will load a new version of the style classes. This may checked using Firebug.



The best part is that you will not need to update the name of the css files, just ensure that include statements are updated when css are changed: 1.1, 1.2, 1.3, etc. It could also be applied to javascript files.

References



Monday, 25 May 2015

Oracle Access Manager Error page customised

WebCenter Portal is usually integrated with Oracle Access Manager (OAM) to manage its authentication. This integration has several advantages such as enabling Single Sign On (SSO) across all Oracle products, but it may cause some problems to end users.

Issue


Recently, a client with a private users area received complaints regarding an unexpected error page been displayed in Portal. Even a user tweeted that page tagging the company, so the problem was considered critical to the top management. The page was the following standard unfriendly OAM error page:



The URL was: /oam/server/auth_cred_submit.

Firstly, we tried to reproduce the issue, which was not easy because users did not remember the actions they performed. After some testing, the issue was reproduced:

  1. Access protected URL.
  2. Portal application login page is displayed.
  3. Introduce valid credentials.
  4. Portal home page is accessed.
  5. Click browser Back button.
  6. OAM error page appears.
We tried to map that URL (auth_cred_submit) as an error by web server configuration, but that was not a solution because it was actually the URL that performs login too.

The explanation of this error is:
  • The login page submits the "request_id" or the "OAM_REQ" value sent by OAM when redirecting to the external login page. 
  • When user introduces credentials and click login, a value for request_id is set into the HTTP Header.
  • The back button does not reset the values already set via cookie or Header information into the browser. 
  • The second time "auth_cred_submit" is accessed, the values from the previous login are sent to the server, which interprets them as invalid because are from a different session. 

So Oracle Support was contacted about this problem. If that page could not be avoided, at least we wanted to have it customised.

Solution

 

Apparently, that OAM page cannot be customised, but the engineer managed to reproduce the issue and built an effective workaround. It involves deploying a custom pages application in OAM application server.
  1. Copy oamcustompages.war file in a local machine. This file is located in the following path: $IDM_HOME/oam/server/tools/custompages/
  2. Unpack this war file.
  3. Navigate to the "pages" folder inside the uncompressed war and create a page named: Error.html. That page would contain the HTML code to be displayed in the reproduced scenario, so it should include the cient look&feel.
  4. Other pages in that folder may be deleted.
  5. Compress the folders back to oamcustompages.war. Then rename that file, i.e. oamcustompages1.war.
  6. Deploy the war in the application server where OAM is running. For information about deploying an application to WebLogic Server, check this link.
  7. OAM Custom Pages must be updated using WLST:
    7.1 Start WebLogic Scripting Tool (WLST) in OAM Oracle home, located under the installation folder: /Oracle_IDM1/common/bin).

    7.2. Connect to the Weblogic AdminServer as the Weblogic Administration User.
    For instance:
    wls:/offline> connect();
    Please enter your username [weblogic] :weblogic
    Please enter your password [welcome1] :Oracle
    Please enter your server URL [t3://localhost:7001] :t3://oamadminserver.oracle.com:7001


    7.3. Execute the following WLST command:
    updateCustomPages(pageExtension ="html", context="/oamcustompages1");

    Where context is the name assigned to the war file in step 5.
    You should receive the following message: "Custom page configuration updated successfully"

    8. Test the scenario. A new error message should be displayed, defined in Error.html file.
This solution works perfectly for our scenario, but we also wanted to avoid displaying an error page to the final users. So Error.html was modified to add a javascript redirect to OAM logout page:

<meta http-equiv="refresh" content="0;url=/../oam/server/logout?end_url=/myApp">

As this content is in the page header, as soon as it starts loading, user is redirected to logout page, where session cookie (OAMAuthnCookie_) is removed. Eventually, the login page is displayed to the user, this is specified by the URL parameter end_url. So customers would not even see the error page.

References


Oracle Service Request: SR 3-10186096271 : OAM how to avoid auth_cred_submit page to be displayed to users
Installing and Configuring OAM with WebCenter Portal
Benefits of Oracle Access Manager
Deploying Applications to WebLogic Server
WebLogic Scripting Tool Command Reference 
Enabling Error Page Customization
Using meta refresh to create an instant client-side redirect
Configuring Centralized Logout for OAM 11g