Introduction
This document aims at helping to understand how Fusion web services documented in Oracle Enterprise Repository (OER) can be invoked by third party applications from different platforms. Fusion web services are also referred as ADF services because web services are developed in Fusion using ADF business components. OER is accessible at: https://fusionappsoer.oracle.com/oer/index.jsp I assume that readers have gone through the OER cookbook before reading this paper. To find the cookbook in OER, please follow these steps:
- Go to OER http://fusionappsoer.oracle.com (Login will require a Oracle.com account. To access OER guest can be used).
- In left side search enter search term Opportunity, type -> ADF Service
- In the search results select Opportunity Service. This will open opportunity service details and the lower region with few tabs like detail, documentation etc.
- In the documentation tab, select the top link with title ‘Service Invocation Details- Opportunity Service’
Use Case
Fusion web services can be invoked by another 3rd party fusion application, using other integration technologies like Oracle Data Integrator (ODI), a ADF Mobile application etc. This blog post discusses on how to invoke a Fusion Applications web service from a third party ADF or any other Java EE application.Invoking from an ADF/Java EE Application
Any third party ADF application can invoke an ADF web service from various places like the application module impl, entity object impl, from a managed bean code in the UI etc. If it’s a non ADF Java though EE compliant application then a ADF web service can be called from a java code as well.Service Invocation Approaches
A Fusion web service can be invoked as a synchronous service using a service-based entity object and a view object, Java API for XML Web Services (JAX-WS) client, or from SOA. The 3 primary approaches are:- Using web service client proxy
- Using BPEL
- Using connection architecture
Examples for all the 3 approaches are provided in the OER cookbook. This blog post discusses the various aspects of web service invocation using web service client proxy approach. A Fusion Applications web service documented on OER can be invoked by creating a web service proxy client in the JDeveloper by just providing the WSDL URL.
Invoking Services
All ADF business components have synchronous and asynchronous versions for the same method. A service method can be invoked synchronously if all of the following conditions are met:- The invoked method takes a simple payload, such as a single document or a fixed number of documents, (including parent and children).
- The invoked method is expected to be finished in real time and takes no longer than a few seconds.
Security Aspect
Fusion Applications web services are secured using Oracle Web Service Manager (OWSM) using the WS-security 1.1 standard. Web service clients need to send SOAP requests with either the username and password, or a Security Assertion Markup Language (SAML) token for authenticating with Fusion Applications. The web service provider decides what policies can be applied to secure a web service. The method of invocation depends on the policy applied on the service. The applied policies on a service could be find out by looking into the WSDL file. The policies to be applied on a web service are usually decided by the producer team based on the intended usage for the service. In general, more than one policy is applied to a web service to suit different calling mechanisms based on client environment. To use username/password based security, web service clients must use the wss11_username_token_with_message_protection_client_policy policy which provides message protection (integrity and confidentiality) and authentication for outbound SOAP requests. Both plain text and digest mechanisms are supported. The web service consumer inserts username and password credentials, and signs and encrypts the outgoing SOAP message, which is decrypted and verified by the web service provider. To prevent replay attacks, the policy assertion provides the option to include time stamps and verification by the web service provider. The message can be protected with ciphers of different strengths. This policy uses the symmetric key technology for signing and encryption, and the WS-Security’s Basic 128 suite of asymmetric key technology for endorsing signatures. To use SAML based security, web service clients must use the wss11_saml_token_with_message_protection_client_policy policy which enables message protection (integrity and confidentiality) and SAML token population for outbound SOAP requests. A SAML token in the SOAP message provides identity propagation for use in SAML-based authentication. This policy provides message protection (integrity and confidentiality) and uses the symmetric key technology for signing and encryption, and the WS-Security’s Basic 128 suite of asymmetric key technology for endorsing signatures. For more information on the available policies refer to this documentation.
How Policies are Enforced
OWSM policies define how identity is propagated from the client to the service. Based on the policy defined the service authenticates the identity using the token provided by the client. The server side first authenticates the user. ADF Business Components web services will check whether the user is authorized to invoke the service. More information on how authorization is handled is documented here. The client side can invoke the service through a SOAP service invocation, where the client can be a JAX-WS proxy. Before passing the service to the server side, the client side will either propagate the current user credential or switch identity, based on the client side authentication policy. The following example is provided to show how to call a synchronous web service using client proxy method with security policy oracle/wss_username_token_over_ssl_client_policy.
Example
In this example, we are using OpportunityService from OER and using its findOppotunity method to get an opportunity. Steps:
- In your project click on New → Business Tier → Web Services → Web Service Client and Proxy.
- Provide WSDL URL and next. To obtain WSDL url you can login to OER and navigate to required ADF service to invoke. On the bottom of the documentation page the reference WSDL will be available. You will need to replace the host and port name with actual values.
- Leave default in next screen and uncheck “Generate as Async” option. Click next → next.
- Choose “don’t generate asynchronous methods” and next
- Chose oracle/wss_username_token_over_ssl_client_policy and next → next → finish. Please note that this is not the only policy that will work with this case. You may use another policy applicable to the web service.
The above steps will generate required code and files for invoking the OpportunityService web service via client proxy using the selected policy. In this example you will need to open the OpportunityBean class to add the code specific to set parameters for the method being called. The portion of the code that is required to be added is marked in bold. Now, the place where this is required to be invoked use the following code:
package oracle.apps.devrl.demo.ws.view;
import com.oracle.xmlns.adf.svc.types.Conjunction;
import com.oracle.xmlns.adf.svc.types.FindControl;
import com.oracle.xmlns.adf.svc.types.FindCriteria;
import com.oracle.xmlns.adf.svc.types.ViewCriteria;
import com.oracle.xmlns.adf.svc.types.ViewCriteriaItem;
import com.oracle.xmlns.adf.svc.types.ViewCriteriaRow;
import com.oracle.xmlns.apps.sales.opptymgmt.opportunities.opportunityservice.*;import java.util.List;
import java.util.Map;
import javax.faces.event.ActionEvent;
import javax.xml.ws.BindingProvider;
import weblogic.wsee.jws.jaxws.owsm.SecurityPoliciesFeature;
public class OpportunityBean {
//This would be the WSDL url used by removing the ?WSDL part from the urlprivate static String endpointUrl ="https://<server name>/opptyMgmtOpportunities/OpportunityService";public OpportunityBean() { }public void findOpportunity(ActionEvent actionEvent) {ViewCriteriaItem item = new ViewCriteriaItem();item.setUpperCaseCompare(false);item.setAttribute("OptyId");item.setOperator("=");item.getValue().add("300100017410548");ViewCriteriaRow condition = new ViewCriteriaRow();condition.setUpperCaseCompare(false);condition.getItem().add(item);ViewCriteria viewCriteria = new ViewCriteria();viewCriteria.setConjunction(Conjunction.AND);viewCriteria.getGroup().add(condition);int fetchStart = 0;int fetchSize = 100;FindCriteria findCriteria = new FindCriteria();findCriteria.setFetchStart(fetchStart);findCriteria.setFetchSize(fetchSize);findCriteria.setFilter(viewCriteria);FindControl findControl = new FindControl();OpportunityService_Service opportunityService_Service = new OpportunityService_Service();// Configure security featureSecurityPoliciesFeature securityFeatures =new SecurityPoliciesFeature(new String[] { "oracle/wss_username_token_over_ssl_client_policy" });OpportunityService opportunityService =opportunityService_Service.getOpportunityServiceSoapHttpPort(securityFeatures);Map requestContext = ((BindingProvider)opportunityService).getRequestContext();try {setPortCredentialProviderList(requestContext);} catch (Exception e) {e.printStackTrace();}List contacts;try {contacts = opportunityService.findOpportunity(findCriteria, findControl);System.out.println("number of items:" + contacts.size());Opportunity opp = (Opportunity)contacts.get(0);System.out.println("Des:" + opp.getOptyId().longValue());} catch (ServiceException e) {e.printStackTrace();}}public static void setPortCredentialProviderList(Map requestContext) throws Exception {String username = "Sales_Representative";/*Please note that for the sake of simplicity the password is hardcoded. You should always use credential manager to store passwords. More details at http://docs.oracle.com/cd/E29597_01/core.1111/e10043/devcsf.htm#JISEC2139*/String password = "Welcome1";requestContext.put(BindingProvider.USERNAME_PROPERTY, username);requestContext.put(BindingProvider.PASSWORD_PROPERTY, password);requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointUrl);}
}
Considerations while specifying WSDL Location
If you encounter the error on running your app in integrated WLS as: javax.net.ssl.SSLKeyException: [Security:090504]Certificate chain received from <some server name/>- XXXXX –> <another server name> failed hostname verification check. Certificate contained <some server name> but check expected <some server name> Cause: If you use HTTPS to get the Web service from the WSDL, and the hostname definition in the WebLogic Server SSL certificate does not equal the hostname of the peer HTTPS server or is not one of the following, the action fails with a hostname verification error: ■ localhost ■ 127.0.0.1 ■ hostname of localhost ■ IP address of localhost Solution: Turn off the host name verification by weblogic server by adding to the java options in the project properties (run/debug jvm options) as follows:
-Dweblogic.security.SSL.ignoreHostnameVerification=true
Please note that this for local development testing etc. You should not be making such changes to the production server’s setDomain.env. In production scenario this exception should be resolved by adding the required target certificate to the calling server.
Best Practices for Fusion Application Web Services
Below are some tips and best practices for invoking Fusion Applications web services. These are generic best practices and are not specific to any given application web service.
- Guaranteed message delivery: consider use of a messaging infrastructure, such as EDN or native JMS (if the client does not use Fusion Middleware). Using such an infrastructure, with the ability to retry using an exponential back-off, can result in a robust infrastructure resilient to any unplanned downtime.
- Using JDeveloper: Fusion web services are organized in a granular fashion with schema information abstracted from the methods/operations of the Web Service. Instead of manually downloading each XSD file referenced in the WSDL, obtain the WSDL URL for the service from OER and use JDeveloper to import it, which will resolve references to the schema files and download them.
- Managing Large Applications: To effectively manage service metadata (WSDL/XSD/EDL) in large scale integration projects, use the Centralized Asset pattern, in which all integration metadata across all projects are stored in a centralized location for easy access. This centralized location could be a shared network drive, a development Fusion Applications instance (using concrete URL) or its Metadata Services (MDS). The metadata is still accessed via the concrete WSDL obtained from the OER and is referenced using HTTP protocol e.g. http://<host>:<port>/<path_to_asset>. If the integrations are developed using Fusion Middleware, you can also access the metadata directly from MDS of the development Fusion Applications instance using the ORAMDS protocol e.g. oramds://<path_to_asset>. At deployment time, config plans should replace any references to the development instance with the appropriate URLs for the production instance. This is the approach used within Fusion Applications development.