Introduction
HCM Atom feeds provide notifications of Oracle Fusion Human Capital Management (HCM) events and are tightly integrated with REST services. When an event occurs in Oracle Fusion HCM, the corresponding Atom feed is delivered automatically to the Atom server. The feed contains details of the REST resource on which the event occurred. Subscribers who consume these Atom feeds use the REST resources to retrieve additional information about the resource.
For more information on Atom, please refer to this.
This post focuses on consuming and processing HCM Atom feeds using Oracle Service Oriented Architecture (SOA) Cloud Service. Oracle SOA Cloud Service provides a PaaS computing platform solution for running Oracle SOA Suite, Oracle Service Bus, and Oracle API Manager in the cloud. For more information on SOA Cloud Service, please refer this.
Oracle SOA is the industry’s most complete and unified application integration and SOA solution. It transforms complex application integration into agile and re-usable service-based connectivity to speed time to market, respond faster to business requirements, and lower costs.. SOA facilitates the development of enterprise applications as modular business web services that can be easily integrated and reused, creating a truly flexible, adaptable IT infrastructure.
For more information on getting started with Oracle SOA, please refer this. For developing SOA applications using SOA Suite, please refer this.
Main Article
Atom feeds enable you to keep track of any changes made to feed-enabled resources in Oracle HCM Cloud. For any updates that may be of interest for downstream applications, such as new hire, terminations, employee transfers and promotions, Oracle HCM Cloud publishes Atom feeds. Your application will be able to read these feeds and take appropriate action.
Atom Publishing Protocol (AtomPub) allows software applications to subscribe to changes that occur on REST resources through published feeds. Updates are published when changes occur to feed-enabled resources in Oracle HCM Cloud. These are the following primary Atom feeds:
Employee Feeds
New hire
Termination
Employee update
Assignment creation, update, and end date
Work Structures Feeds (Creation, update, and end date)
Organizations
Jobs
Positions
Grades
Locations
The above feeds can be consumed programmatically. In this post, Node.js is implemented as one of the solutions consuming “Employee New Hire” feeds, but design and development is similar for all the supported objects in HCM.
HCM Atom Introduction
For Atom “security, roles and privileges”, please refer my blog HCM Atom Feed Subscriber using Node.js.
Atom Feed Response Template
SOA Cloud Service Implementation
Refer my blog on how to invoke secured REST services using SOA. The following diagram shows the patterns to subscribe to HCM Atom feeds and process it to downstream applications that may have either web services or file based interfaces. Optionally, all entries from the feeds could be staged either in database or messaging cloud before processing it during events such as downstream application is not available or throwing system errors. This provides the ability to consume the feeds, but hold the processing until downstream applications are available. Enterprise Scheduler Service (ESS), a component of SOA Suite, is leveraged to invoke the subscriber composite periodically.
The following diagram shows the implementation of the above pattern for Employee New Hire:
Feed Invocation from SOA
HCM cloud feed though in XML representation, the media type of the payload response is “application/atom+xml”. This media type is not supported at this time, but use the following java embedded activity in your BPEL component:
Once the built-in REST Adapter supports the Atom media type, java embedded activity will be replaced and further simplify the solution.
try { String url = "https://mycompany.oraclecloud.com"; String lastEntryTS = (String)getVariableData("LastEntryTS"); String uri = "/hcmCoreApi/atomservlet/employee/newhire"; //Generate URI based on last entry timestamp from previous invocation if (!(lastEntryTS.isEmpty())) { uri = uri + "?updated-min=" + lastEntryTS; } java.net.URL obj = new URL(null,url+uri, new sun.net.www.protocol.https.Handler()); javax.net.ssl.HttpsURLConnection conn = (HttpsURLConnection) obj.openConnection(); conn.setRequestProperty("Content-Type", "application/vnd.oracle.adf.resource+json"); conn.setDoOutput(true); conn.setRequestMethod("GET"); String userpass = "username" + ":" + "password"; String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(userpass.getBytes("UTF-8")); conn.setRequestProperty ("Authorization", basicAuth); String response=""; int responseCode=conn.getResponseCode(); System.out.println("Response Code is: " + responseCode); if (responseCode == HttpsURLConnection.HTTP_OK) { BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line; String contents = ""; while ((line = reader.readLine()) != null) { contents += line; } setVariableData("outputVariable", "payload", "/client:processResponse/client:result", contents); reader.close(); } } catch (Exception e) { e.printStackTrace(); }
These are the following things to consider when consuming feeds:
Initial Consumption
When you subscribe first time, you can invoke the resource with the query parameters to get all the published feeds or use updated-min or updated-max arguments to filter entries in a feed to begin with.
For example the invocation path could be /hcmCoreApi/Atomservlet/employee/newhire or /hcmCoreApi/Atomservlet/employee/newhire?updated-min=<some-timestamp>
After the first consumption, the “updated” element of the first entry must be persisted to use it in next call to avoid duplication. In this prototype, the “/entry/updated” timestamp value is persisted in a database cloud (DbaaS).
This is the sample database table
create table atomsub ( id number, feed_ts varchar2(100) );
For initial consumption, keep the table empty or add a row with the value of feed_ts to consume initial feeds. For example, the feed_ts value could be “2015-09-16T09:16:00.000Z” to get all the feeds after this timestamp.
In SOA composite, you will update the above table to persist the “/entry/updated” timestamp in the feed_ts column of the “atomsub” table.
Next Call
In next call, read the updated timestamp value from the database and generate the URI path as follows:
String uri = "/hcmCoreApi/atomservlet/employee/newhire"; String lastEntryTS = (String)getVariableData("LastEntryTS"); if (!(lastEntryTS.isEmpty())) { uri = uri + "?updated-min=" + lastEntryTS; }
The above step is done in java embedded activity, but it could be done in SOA using <assign> expressions.
Parsing Atom Feed Response
The Atom feed response is in XML format as shown previously in the diagram. In this prototype, the feed response is stored in output variable as a string. The following expression in <assign> activity will convert it to XML
oraext:parseXML($outputVariable.payload/client:result)
Parsing Each Atom Entry for Downstream Processing
Each entry has two major elements as mentioned in Atom response payload structure.
Resource Link
This contains the REST employee resource link to get Employee object. This is a typical REST invocation from SOA using REST Adapter. For more information on invoking REST services from SOA, please refer my blog.
Content Type
This contains selected resource data in JSON format. For example: “{ “Context” : [ { "EmployeeNumber" : "212", "PersonId" : "300000006013981", "EffectiveStartDate" : "2015-10-08", "EffectiveDate" : "2015-10-08", "WorkEmail" : "phil.davey@mycompany.com", "EmployeeName" : "Davey, Phillip" } ]}”.
In order to use above data, it must be converted to XML. The BPEL component provides a Translator activity to transform JSON to XML. Please refer the SOA Development document, section B1.8 – doTranslateFromNative.
The <Translate> activity syntax to convert above JSON string from <content> is as follows:
<assign name="TranslateJSON"> <bpelx:annotation> <bpelx:pattern>translate</bpelx:pattern> </bpelx:annotation> <copy> <from>ora:doTranslateFromNative(string($FeedVariable.payload/ns1:entry/ns1:content), 'Schemas/JsonToXml.xsd', 'Root-Element', 'DOM')</from> <to>$JsonToXml_OutputVar_1</to> </copy> </assign>
This is the output:
The following provides detailed steps on how to use Native Format Builder in JDeveloper:
In native format builder, select JSON format and use above <content> as a sample to generate a schema. Please see the following diagrams:
One and Only One Entry
Each entry in an Atom feed has a unique ID. For example: <id>Atomservlet:newhire:EMP300000005960615</id>
In target applications, this ID can be used as one of the keys or lookups to prevent reprocessing. The logic can be implemented in your downstream applications or in the integration space to avoid duplication.
Scheduler and Downstream Processing
Oracle Enterprise Scheduler Service (ESS) is configured to invoke the above composite periodically. At present, SOA cloud service is not provisioned with ESS, but refer this to extend your domain. Once the feed response message is parsed, you can process it to downstream applications based on your requirements or use cases. For guaranteed transactions, each feed entry can be published in Messaging cloud or Oracle Database to stage all the feeds. This will provide global transaction and recovery when downstream applications are not available or throws error.
The following diagram shows how to create job definition for a SOA composite. For more information on ESS, please refer this.
SOA Cloud Service Instance Flows
First invocation without updated-min argument to get all the feeds
Atom Feed Response from above instance
Next invocation with updated-min argument based on last entry timestamp
Conclusion
This post demonstrates how to consume HCM Atom feeds and process it for downstream applications. It provides details on how to consume new feeds (avoid duplication) since last polled. Finally it provides an enterprise integration pattern from consuming feeds to downstream applications processing.
Sample Prototype Code
The sample prototype code is available here.
All content listed on this page is the property of Oracle Corp. Redistribution not allowed without written permission