Skip navigation.

Angelo Santagata

Syndicate content
Fusion Middleware / Cloud Integration Architect - If its middleware, or PaaS for SaaS, then I'm interested!
Updated: 8 hours 41 min ago

Using SalesCloud RESTFacade with Custom Fields & CORS support

Fri, 2014-06-13 12:38

Some of you may be using my RESTFacade which I wrote and Oracle recently released as sample code on OTN (link).

There has been a couple of requests, or more "how to"s which I thought Id post here.

  1. How to add CORS support (Cross Origin Resource Sharing) support
  2. How to use the facade with custom fields defined in AppComposer

How to add CORS support (Cross Origin Resource Sharing) support

 Adding CORs support is quite straightforward, simply open the web.xml file in the FusionRESTService project and add the following <init-param>

<init-param>
 <paramname>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
<param-value>oracle.fusion.pts.ResponseCorsFilter</param-value>
</init-param>

Simples :-)

How to use the facade with CustomFields

This one is a little trickier. The facade uses a collection of static proxies and although I am planning to rewrite the proxies as "dynamic" proxies we're not there yet (and I need to do some reading first).

The only way to use custom fields with the facade today is to regenerate the proxies against your Sales Cloud instance. Here I will go through the steps you will need to do, however in the near future I will release some "scripts" which will do it all for you.

1. Identify the correct package name

The Facade has all its proxies in projects called "FusionProxy_<Object>Service. Within this project you will find the java classes are split between two packages

  • com.oracle.xmlns : This contains all the standard generated types
  • oracle.demo.pts.fusionproxy.<objectName> : This one contains the proxy itself

Identify the full package name of the proxy for the object you are going to regenerate. In my example here, im going to regenerate the Opportunity object and as you can see the package name is oracle.demo.pts.fusionproxy.opportunities


 2. Delete the contents of the proxy directory.

Shutdown JDeveloper, navigate to the source directory of the proxy project and delete both the src and classes



Startup JDeveloper, navigate to the FusionProxys project , in our case FusionProxy_OpportunityService, you should notice it is now "empty". If it is not the press the refresh button


4.  Regenerate the proxy from scratch

  • Select the project, right mouse click and select new...
  • Select "Web Service proxy" from the Web Services Categories.. If it doesnt show try typing it in the search  dialog
  • Enter the appropriate WSDL Document. This is the Hostname of your service + Endpoint URL. You can get this information from the fusionconfig.properties file.
    E.g. For opportunities it is https://<hostname>/opptyMgmtOpportunities/OpportunityService?wsdl

    Hint: Check it works in a webbrowser first!


  • Next, Wait a bit....
  • For the package name, use the name you identified in step 1, for the Root Package leave it blank
    • Un-Select "Generate As Async"
  • Next
  • Next
  • Select "Don't generate any asynchronous methods"

  • Next 
  • Select "Oracle/wss_username_token_over_ssl_client_policy"
  • Next, then Finish

This will generate the proxy from scratch , just note the generation of the proxy may take some time. 

5. Go to the XJS_Beans project

Within here edit the generateClasses script and modify dummy.oracle.com with your hostname for all rows.

open a shell prompt, navigate to this directory using your shell and execute this script. This regenerates all the JAXB objects..

6. Finally do a Build/Clean All followed by a Build/Make and deploy as normal

Any questions do ask! and yes as I mentioned earlier I plan to create a script to automate all of this. 

Common usecases and techniques when integrating a 3rd party application with Oracle Sales Cloud

Tue, 2014-06-10 09:24

Over the last year or so I've see a lot of partners migrating and integrate their applications with Oracle Sales Cloud. Interestingly I'd say 60% of the partners use the same set of design patterns over and over again. Most of the time I see that they want to embed their application into Oracle Sales Cloud, within a tab usually, perhaps click on a link to their application (passing some piece of data + credentials) and then within their application update sales cloud again using webservices.

Here are some examples of the different use-cases I've seen , and how partners are embedding their applications into Sales Cloud,
NB : The following examples use the "Desktop" User Interface rather than the Newer "Simplified User Interface", I'll update the sample application soon but the integration patterns are precisely the same

Use Case 1 :  Navigator "Link out" to third party application


This is an example of where the developer has added a link to the global navigator and this links out to the 3rd Party Application. Typically one doesn't pass any contextual data with the exception of perhaps user credentials, or better still JWT Token.

Techniques Used  

Use Case 2 : Application Embedded within the Sales Cloud Dashboard

Within the Oracle Sales Cloud application there is a tab called "Sales", within this tab its possible to embed a SubTab and embed a iFrame pointing to your application. To do this the developer simply needs to edit the page in customization mode, add the tab and then add the iFrame, simples! The developer can pass credentials/JWT Token and some other pieces of data but not object data (ie the current OpportunityID etc)

 Techniques Used

 Use Case 3 : Embedding a Tab and Context Linking out from a Sales Cloud object to the 3rd party application

In this usecase the developer embeds two components into Oracle Sales Cloud. The first is a SubTab showing summary data to the user (a quote in our case) and then secondly a hyperlink, (although it could be a button) which when clicked navigates the user to the 3rd party application. In this case the developer almost always passes context specific data (i.e. the opportunityId) and a security token (username password combo or JWT Token). The third party application usually takes the data, perhaps queries more data using the Sales Cloud SOAP/WebService interface and then displays the resulting mashup to the user for further processing. When the user has finished their work in the 3rd party application they normally navigate back to Oracle Sales Cloud using what's called a "DeepLink", ie taking them back to the object [opportunity in our case] they came from.

This image visually shows a "Happy Path" a user may follow, and combines linking out to an application , webservice calls and deep linking back to Sales Cloud.

Techniques Used


Use-Case 4 :  Server Side processing/synchronization

This usecase focuses on the Server Side processing of data, in this case synchronizing data. Here the 3rd party application is running on a "timer", e.g. cron or similar, and when triggered it queries data from Oracle Sales Cloud, then it queries data from the 3rd party application, determines the deltas and then inserts the data where required. Specifically here we are calling Oracle Sales Cloud using SOAP/WebServices and the 3rd party application is being communicated to using the REST API, for Oracle Sales Cloud one would use standard JAX-WS WebService calls and for REST one would use the JAX-RS api and perhap the Jackson api for managing JSON objects.. This is a very common use case and one which specifically lends itself to using the Oracle Java Cloud Service as the ideal application server where to host the mediator between the two applications.

 Techniques Used


General Resources

The above is just a small set of techniques and use-cases which are used today. There are plenty of other sources of documentation and resources available on the internet but to get you started here are a few of my favourite places 

JWT Token Security with Fusion Sales Cloud

Tue, 2014-06-10 04:38

When integrating SalesCloud with a 3rd party application you often need to pass the users identity to the 3rd party application so that 

  • The 3rd party application knows who the user is
  • The 3rd party application needs to be able to do WebService callbacks to Sales Cloud as that user. 

Until recently without using SAML, this wasn't easily possible and one workaround was to pass the username, potentially even the password, from Sales Cloud to the 3rd party application using URL parameters..

With Oracle Fusion R8 we now have a proper solution and that is called "JWT Token support". This is based on the industry JSON Web Token standard , for more information see here

JWT Works by allowing the user the ability to generate a token (lasts a short period of time) for a specific application. This token is then passed to the 3rd party application as a GET parameter.  The 3rd party application can then call into SalesCloud and use this token for all webservice calls, the calls will be executed as the user who generated the token in the first place, or they can call a special HR WebService (UserService-findSelfUserDetails() ) with the token and Fusion will respond with the users details.



Some more details 

The following will go through the scenario that you want to embed a 3rd party application within a WebContent frame (iFrame) within the opportunity screen. 

1. Define your application using the topology manager in setup and maintenance

2. From within your groovy script which defines the iFrame you wish to embed, write some code which looks like this :

def thirdpartyapplicationurl = oracle.topologyManager.client.deployedInfo.DeployedInfoProvider.getEndPoint("My3rdPartyApplication" )
def crmkey= (new oracle.apps.fnd.applcore.common.SecuredTokenBean().getTrustToken())
def url = thirdpartyapplicationurl +"param1="+OptyId+"&jwt ="+crmkey
return (url) 


This snippet generates a URL which contains

  • The Hostname/endpoint of the 3rd party application
  • Two Parameters
    • The opportunityId stored in parameter "param1"
    • The JWT Token store in  parameter "jwt"

3. From your 3rd Party Application you now have two options

  • Execute a webservice call by first setting the header parameter "Authentication" to the JWT token. The webservice call will be executed against Fusion Applications "As" the user who execute the process
  • To find out "Who you are" , set the header parameter to "Authentication" and execute the special webservice call findSelfUserDetails(), in the UserDetailsService

For more information 


Deploying JAXWS to JCS?? Getting "java.lang.ClassNotFoundException: org.apache.xalan.processor.TransformerFactoryImpl" error

Thu, 2014-04-17 06:21

Hey all,

  • Problem
  • The issue
    • Its a bug on Java Cloud Server (bug#18241690), basically JCS is picking up the wrong XSL transformer
  •  Solution
    • In your code simply put the following piece of java code to execute when your application starts up

System.setProperty("javax.xml.transform.TransformerFactory",
        "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");

 And all should be fine :-)


How to restrict data coming back from a SOAP Call

Thu, 2014-04-10 09:51

In sales cloud a big positive of the SOAP interface is that lots of related data is returned by issuing a single query, including master-detail data (ie multiple email addresses in contacts) however these payloads can be very very large, e.g. In my system querying single person you get 305 Lines(!), whereas I only want the firstName,LastName and partyId which is 3 lines per record..

Solution

For each findCriteria element you can add multiple <findAttribute> element indicating what elements you want to return. By default if you provide <findAttribute> entries then only those attributes are returned, and this functionality can be reversed by setting the <excludeAttributes> to true.


Example 1 :  only retrieving PersonLastName,PersonFirstName,PartyId

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="http://xmlns.oracle.com/apps/cdm/foundation/parties/personService/applicationModule/types/" xmlns:typ1="http://xmlns.oracle.com/adf/svc/types/">

   <soapenv:Header/>

   <soapenv:Body>

      <typ:findPerson>

         <typ:findCriteria xsi:type="typ1:FindCriteria" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

                <typ1:fetchStart>0</typ1:fetchStart>

                <typ1:fetchSize>100</typ1:fetchSize>

<typ1:findAttribute>PersonLastName</typ1:findAttribute>

                <typ1:findAttribute>PersonFirstName</typ1:findAttribute>

                <typ1:findAttribute>PartyId</typ1:findAttribute>

            <typ1:excludeAttribute>false</typ1:excludeAttribute>

         </typ:findCriteria>

      </typ:findPerson>

   </soapenv:Body>

</soapenv:Envelope>

Notes

findAttributes work on the level1 attributes of that findCriteria, the value can be a attribute or an element

If you want to restrict SubElements you can use childFindCriterias for that subelement and then add findAttributes within that

Example 2 :  Only Retrieving PartyId, and within Email element only EmailAddress     

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="http://xmlns.oracle.com/apps/cdm/foundation/parties/personService/applicationModule/types/" xmlns:typ1="http://xmlns.oracle.com/adf/svc/types/">

   <soapenv:Header/>

   <soapenv:Body>

      <typ:findPerson>

         <typ:findControl>

            <typ1:retrieveAllTranslations/>

         </typ:findControl>

         <typ:findCriteria xsi:type="typ1:FindCriteria" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

            <typ1:fetchStart>0</typ1:fetchStart>

            <typ1:fetchSize>100</typ1:fetchSize>

<typ1:findAttribute>PartyId</typ1:findAttribute>

            <typ1:findAttribute>Email</typ1:findAttribute>

            <typ1:excludeAttribute>false</typ1:excludeAttribute>

<typ1:childFindCriteria>

               <typ1:fetchStart>0</typ1:fetchStart>

               <typ1:fetchSize>10</typ1:fetchSize>

<typ1:findAttribute>EmailAddress</typ1:findAttribute>

               <typ1:excludeAttribute>false</typ1:excludeAttribute>

               <typ1:childAttrName>Email</typ1:childAttrName>

</typ1:childFindCriteria>

         </typ:findCriteria>

      </typ:findPerson>

   </soapenv:Body>

</soapenv:Envelope>

Notes

For a childFindCriteria to work you must query it in the parent, which is why “Email” is referenced in a findAttribute on line 14

Passing data between apps using URL Query parameters???

Thu, 2014-03-27 05:12

If so then you need to be careful about private data.. It can be secure but remember security is only as good as the weakest link.. This article is a nice summary of what's possible , whats secure and what isnt....

https://blog.httpwatch.com/2009/02/20/how-secure-are-query-strings-over-https/