Skip navigation

Oracle Documents Cloud Service  provides “Conversations” – which is a great way for to share information with each other in an enterprise.  This can reap great benefits by extending to the developer teams in your enterprise by integrating with the Developer Cloud Service to automatically provide updates about the latest status of a project.  Furthermore, conversations can be accessed by any user on the go, using the Android/iPhone mobile app for Documents Cloud Service (for downloads refer to this page) and ensure that everybody is on the same page always with regards to what is happening in the project.

 

Do note that conversations are actually a feature of Oracle Social Network Cloud (OSN) which is bundled along with a Documents Cloud Service instance and I will be using these interchangeably in this blog.

 

This blog post will demonstrate how to achieve this via Webhooks provided by the Developer Cloud Service (version 16.3.5) and the Documents Cloud Service (version 16.3.5). Webhooks are a callback mechanism for a producer application to provide updates about itself to other consumer applications in real time.  This eliminates the need for polling for the destination applications and improves efficiency for both.

 

So any activities in the project, like issue updates, commits, branch creation etc, will be automatically published into Documents Cloud Service (or Oracle Social Network Cloud) as posts to a conversation.  This way the entire team (which has access to the conversation) can be aware about the latest updates to the project, and can collaborate with each other to clear impediments during development like failed builds, merge conflicts etc.

 

In the case of Documents Cloud Service and Developer Cloud Service, this can be accomplished without any code using an incoming webhook at the Documents Cloud Service side and an outgoing webhook at the Developer Cloud Service as illustrated in the below figure.

 

Webhooks system.png

An outgoing webhook is used to push data out of the system, i.e. convert the event data into the required payload and post the same to the target URL, in this case the URL for the DOCS/OSN incoming webhook.  An incoming webhook is used at the destination system as a service listening for these post events and converts the payload into the meaningful destination data – in this case, conversations.

 

Below are the steps for achieving this setup:

 

Step 1 – Create a conversation in Documents Cloud Service

First, we need to create the conversation to which all the Developer Cloud Service updates would be automatically posted.  Go to the Documents Cloud Service console, click on “Conversations” on the left-hand menu and create a conversation.  I am going to name this conversation – “Webhooks 2016”

 

incoming webhook - 1.png

incoming webhook - 2.png

 

Step 2 – create a DCS (Developer Cloud Service) incoming hook in Documents Cloud Service

In the Documents Cloud Service, click on your user name on the top right hand corner, and select “Administration” from the menu.  This will take you to the Documents Cloud Service Administration console.  Select “Webhooks” from the administration menu as shown:

 

incoming webhook - 3.png

 

You would see 3 options –

  • DCS Incoming Webhook – handles incoming updates from a Developer Cloud Service Instance
  • Generic Incoming Webhook – handles incoming updates from any application
  • JIRA Incoming Webhook – handles incoming updates from a JIRA application

 

 

incoming webhook - 4.png

 

We will create a DCS Incoming Webhook as our source is a Developer Cloud Service project.  Click on New Instance and provide the various parameters to create the webhook.

 

incoming webhook - 5.png

 

For the fields:

Webhook Name – a relevant name to identify the webhook

Webhook enabled – tick this to enable the webhook

Target conversation – select the conversation created in Step 1

Message template - would be populated by default and contain two variables data.projectId and data.message.  The structure of the data object is as follows:

data {

message : ‘test’

projectId : ‘projectId’

}

 

Once you save this webhook, there will be a webhook URL that is generated along with the token.

 

incoming webhook - 6.png

 

Here the webhook URL is a relative URL.  The full webhook URL would be the following:

https://<OSN instance URL>/osn-public/hooks/webhooks

 

And the token here would be ‘6361690deedf10aad6147533636dfd49’

 

To find out the OSN (Oracle Social Network) instance URL attached to the Documents Cloud Service, open the following endpoint in your browser (note that you have to be logged in to the documents cloud service to access this)

https://<documents instance URL>/documents/web?IdcService=GET_SERVER_INFO

This will return a JSON payload containing a lot of server side information.  Look for an attribute called OSNServiceURL

[

"OSNServiceURL",

"https://instancexyz-test.socialnetwork.us.oraclecloud.com:443/osn"

],

 

Replace the osn with osn-public, this becomes your webhook base URL.

So in this example, the webhook URL will be

https://instancexyz-test.socialnetwork.us.oraclecloud.com:443/osn-public/hooks/webhooks

 

And the token will be 6361690deedf10aad6147533636dfd49

 

Step 3 – create an Outgoing webhook in Developer Cloud Service

The next step is to create an outgoing webhook in Developer cloud service to post updates to the Documents Cloud Service incoming webhook.  Note that you have to be the administrator for the project for which you want to configure the webhook to achieve this.

 

Here for demonstration purposes, I have created an empty GIT project called “test” for which I am the administrator.  Select the project and go to the administration tab, and click on Webhooks.

 

outgoing webhook - 1.png

 

Select New Webhook, which will take you to the ‘Create Webhook’ form

 

outgoing webhook - 2.png

 

In the “Create Webhook” form, use the following

Type = Oracle Social Network

Name = any description, I am using “test webhook” in this example

Active = Yes

URL = give the OSN webhook URL i.e. https://instancexyz-test.socialnetwork.us.oraclecloud.com:443/osn-public/hooks/webhooks

Authentication token – give the token value - 6361690deedf10aad6147533636dfd49

Event groups – You can select specific events, or Failed Builds.  For the purpose of this example, I am going to select “All events”

Click on Done when all the details are complete.  This will create a new Webhook ready to be used.

 

outgoing webhook - 3.png

 

Step 4 – Test the outgoing webhook


Developer Cloud Service provides a way to test the webhook by simply clicking on the “Test” button.  You can also go to Logs and see the full details of the webhook interactions including the message payload.  If the test is successful, it will show up in green as below.

 

outgoing webhook - 4.png

 

This should show up in our “Webhooks 2016” conversation in Documents Cloud Service.

 

conversation.png

 

If the test is successful, try performing some activity in the Developer Cloud Service project, like commit or create a wiki, and check whether the same is being populated in the conversation.

 

You can track this conversation from the mobile client for Documents Cloud Service as well (available for iPhone and Android).  An effortless way of increasing developer collaboration and keeping track of project activities!  Consult the official documentation of Developer Cloud Service and Documents Cloud Service for more on Webhooks.

 

**The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

In this blog post, we demonstrate adding a social context (conversations) to an Oracle JET based application hosted on Java Cloud Service – SaaS Extension using the embedding features of Document Cloud Service.

Document Cloud Service is an enterprise grade content sharing and collaboration platform with inbuilt social features like real-time conversations and detailed analytics.  It can also be combined with other PaaS services and easily extend these features to those services.

 

Documents Cloud Service integration via UI

I have already discussed about the Service-to-Service integration between JCS-SX and DCS in the earlier blog.  Another way of integrating with Documents Cloud Service is to use its versatile UI and ‘embed’ in your application to make available its collaboration features.

 

This integration mechanism is very simple and can be used when all the services are federated by the Shared Identity Management (SIM) with the user having access to all of these services. The Documents Cloud Service has an embeddable UI that can be shown in an iframe of the application hosted in JCS-SX. When the browser first requests this embeddable resource, SSO will kick in, and the user, behind the scenes will get seamlessly authenticated to the Document Cloud Service/Social Network Cloud Service via the Shared Identity Management.  For the subsequent requests to Document Cloud Service/Social Network Cloud Service, the SSO cookie will serve as the valid identifier that the user has logged in.

 

Since 16.3.x, Documents Cloud Service also offers conversations as embeddable content.  In this example, we will embed Conversations from Document Cloud Service in the JET application.

Step 1 - Setting up conversations in the Document cloud Service

First, login to Documents Cloud Service and create a folder using Conversations -> Create option.  If the same conversation is to be shown to multiple users, add ‘Members’ to the conversation

 

Create conversation.png

 

The created conversation would have a unique URL that identifies it – e.g.

https://docs1-<id-domain>.documents.<dc>.oraclecloud.com/documents/conversations/16014

 

 

Note that the 16014 is the Id of the conversation that is created and the conversation displays like below:

Conversation - non embed.png

 

Step 2 - Embedding the Document Cloud Service Web UI Using an IFrame

 

The Document Cloud Service provides an embeddable URL for its folders, files and conversations.  Let us implement an iframe in the home.html module that will display the embeddable URL for a particular conversation.  The embeddable URL will have ‘embed’ after the documents.  In our case :

https://docs1-<id-domain>.documents.<dc>.oraclecloud.com/documents/embed/conversations/16014

 

would display the document in an embeddable iframe as below:

Conversation - embed.png

 

Notice this doesn’t have the search and the navigation bar.

Further, the embedded Document Cloud Service content can be customized by adding parameters to the URL which will enable hidng certain UI elements, or changing layout.

E.g.https://docs1-<id-domain>.documents.<dc>.oraclecloud.com/documents/embed/conversations/16014?noopen

will display the conversations without means to open a conversation, i.e. you can only see a list of conversations

 

To see the full list of options, please consult the configuration parameters documentation

 

For the purpose of this example, I will use the basic Quick Start Oracle JET project developed in earlier blog post.  Add the iframe to the home.html module at the end

 

<iframe src='https://docs1-<id-domain>.documents.<dc>.oraclecloud.com/documents/embed/conversations/16014/' style="overflow : auto ; height : 400px ; width :  100% "> </iframe>

 

Step 3 – Configuring Document Cloud Service to allow embedding content on other domains

To allow the content to be embeddable, go to Administration -> Documents (available from the actions on the left hand pull down menu next to the profile photo) and do the following:

In the Embedded Content section, Select “Enabled".  Add your domain into the list of allowable domains in the format xyz.com:port_number

 

Without this you would get a X-Frame-Options DENY in your application and the content will not be loaded. You can see this error in the console of the browser

embed error.png

Note:

If your application and Oracle Documents Cloud Service are in different domains and SSO is not enabled, the IFrame will display a login screen and the users will have to manually provide their authentication credentials.

 

Conclusion

That is it!  Deploy to JCS-SX and run your JCS-SX JET application and you should see the output as below.

working-app.png

 

Do make sure popups are allowed for this site from the browser, since the Document Cloud Service will open a popup that allows the user to login seamlessly.

 

You can do all sorts of operations on the conversations i.e. Post/Upload Document/Close etc that you would be able to do in the full Documents Cloud Service UI.  Another feature is that if the conversation is updated by another person the same would be updated in the embedded UI automatically!

 

**The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

Oracle JET is the new open source JavaScript library from Oracle which is great for building Single Page Applications.  In this blog post, I discuss the various steps to create an Oracle JET web application hosted on Java Cloud Service – SaaS Extension that can hold a logged in user Context.  For implementing this, we will leverage the out-of-box capabilities of the Shared Identity Management (SIM) to achieve Single Sign on and Single Log off and integrate with a JAX-RS REST Service that provides User Context.

 

Here is the list of softwares/services I am using:

  • IDE – Netbeans 8.1
  • Oracle JET Quick Start template (version 2.1.0).
  • Oracle Weblogic Server 10.3.6 (for testing locally)
  • Oracle Java Cloud Service – SaaS Extension 16.3.x

 

Pre-requisites

  1. Register the Oracle Weblogic Server in your Netbeans IDE (Tools -> Servers -> Add Server – add the Oracle Home for the Oracle Weblogic Server in the location).  More details can be found in the Netbeans documentation
  2. Make sure you have the Jersey 1.x library for compilation purposes.    If not create a new library in Netbeans  via Tools -> Libraries -> New Library, give it a name of Jersey 1.x and add the following jars under it:

jersey-bundle-1.18.1.jar

jersey-core-1.18.1.jar

jersey-json-1.18.1.jar

jersey-multipart-1.18.1.jar

jersey-server-1.18.1.jar

jersey-servlet-1.18.1.jar

 

You can download these jars from the maven central repository or from the Jersey downloads page.

 

Step 1 – Create a Web Application in Netbeans 8.1

 

Go to File -> New Project -> Java Web.  Choose Web Application as the project type as shown below:

 

NetbeansSetup - create project.png

NetbeansSetup - create project 2.png

 

Give the information required by the New Project Wizard like project name, runtime server environment (Oracle Weblogic) etc.  This will create an empty Web Application with the name you chose with a web.xml, weblogic.xml and an index.jsp

 

Step 2 - Download and Unzip the Quick Start template.

There are multiple ways to scaffold an Oracle JET (web) application as given in the JET documentation.  The technique given here is my preferred one in Netbeans.

 

Download the Oracle JET Quick Start template from here into any directory.  This contains the skeleton of a working Oracle JET project, which you can then change according to your needs.  This is great if you are starting out with Oracle JET.

 

Next unzip the Oracle JET Quick Start template.  This is what the structure looks like:

NetbeansSetup - Quick Start structure.png

 

Step 3 – Copy the contents of the QuickStart to the Netbeans Web Application

Delete the index.jsp that was created by default in the Netbeans Web Application, because we will be using the index.html that is provided with the Oracle JET Quick Start.

NetbeansSetup - index.png

 

Select all the contents in the Quick Start template as shown in Figure 3 and copy them to the Netbeans Web application Web Pages folder.

NetbeansSetup - copyall.png

 

Step 4 – Modify the WEB-INF/web.xml and WEB-INF/weblogic.xml

Add security-constraint and login-config entries to the web.xml.  This will make the application protected by delegating authentication to the SIM which will require a user to log in before he can access index.html

 

The login-config entry has a value of CLIENT-CERT as the auth-method which is Oracle's recommended mode of authentication, as it enables the tenant-specific SSO authentication mode for an application.

 

web.xml

 

<?xml version = '1.0' encoding = 'windows-1252'?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">
    <security-constraint>
        <display-name>name</display-name>
        <web-resource-collection>
            <web-resource-name>name</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
    </security-constraint>
    <login-config>
        <auth-method>CLIENT-CERT</auth-method>
        <realm-name>default</realm-name>
    </login-config>
</web-app>

 

 

weblogic.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd">
    <container-descriptor>
        <prefer-web-inf-classes>true</prefer-web-inf-classes>
    </container-descriptor>
    <context-root>/QuickStartProject</context-root>
</weblogic-web-app>

 

Now you have a basic Oracle JET web application that is restricted to only tenants having access to JCS-SX.  You can further restrict this to a certain role in web.xml.  For more details consult JCS-SX documentation for securing applications

 

Tip – You can add this skeleton project in Netbeans as a sample project, so that you don’t need to carry out the same steps again.  Here is the tutorial that helps to make this a sample project in NetBeans.

 

 

Running it locally using the Netbeans platform (Project -> Run) will yield the following screen

JET QuickStart - running application.png

 

Not Bad!  But the logged in user is hardcoded (on the top right hand corner) and the ‘Sign Out’ menu (on expanding the user name menu dropdown) doesn’t do anything.  Let us correct that.

 

Tip – If you want to use the minified version of oracle JET JavaScript and not the debug version, change the path in main.js to use the minified JS.

 

'ojs': 'libs/oj/v2.1.0/debug',  

 

to

 

'ojs': 'libs/oj/v2.1.0/min',

 

You can now delete the debug folder  (js/libs/oj/v2.1.0/debug) if you wish, which will make the application smaller in size.

 

Step 5 - To get the logged in User

Let us develop a JAX-RS REST service to get the logged in User.  You can create this in the same project or any other project that will be deployed on the same server.  I am going to do this in the same project.

 

Add the Jersey 1.x library to the project by clicking on Project -> Properties -> Libraries -> Add Library.  If you only see the Jersey 2.x library, click Create and add a custom library called Jersey 1.x as given in prerequisites.

 

The Jersey 1.x is only required for compilation purposes – so make sure the library is not packaged (by unticking the Package checkbox)

 

NetbeansSetup - add Jersey Library.png

 

We need to develop a JAX-RS REST API that the JET application can call which would give the logged in user name.

 

UserApplication.java – This is the JAX-RS Application that is the entry point for the REST Service

 

package com.oracle.rest;

import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;

public class UserApplication extends Application {
    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> classes = new HashSet<Class<?>>();
        classes.add(UserService.class);
        return classes;
    }
}

 

UserService.java – This is the JAX-RS resource which contains the logic for getting the logged in user

 

package com.oracle.rest;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;

@Path("rest")
public class UserService {
    public UserService() {
        super();
    }
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("userinfo")
    public String getLoggedInUser(@Context SecurityContext sc) {
        String userName = "No user";
        if (sc.getUserPrincipal() != null) {
            userName = sc.getUserPrincipal().getName();
        }
        return userName;
    }
}

 

Change the web.xml as below to add the Jersey servlet

 

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 <servlet>
<servlet-name>jersey</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.oracle.rest.UserApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
<servlet-name>jersey</servlet-name>
<url-pattern>/gateway/*</url-pattern>
</servlet-mapping>

<security-constraint>
<display-name>name</display-name>
 <web-resource-collection>
<web-resource-name>name</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
</security-constraint>
<login-config>
<auth-method>CLIENT-CERT</auth-method>
<realm-name>default</realm-name>
</login-config>
<web-app>

 

 

Deploy the web application on JCS-SX and test the rest service.  For deploying the application on JCS-SX please refer to the documentation.

 

Then test the REST service using

http://<java instance url>/QuickStartProject/gateway/rest/userinfo

 

This should give the logged in user in text/plain format.

 

Now let us call this REST service in our JET application to display the correct user name.  A search for the hardcoded user name (john.hancock@oracle.com) points us to js/appController.js  and sure enough it has the following lines:

 

      self.userLogin = ko.observable("john.hancock@oracle.com");

 

Change this to the following lines

 

                self.userLogin = ko.observable("");
                self.getUserName = function () {
                    return $.ajax({url: "/QuickStartProject/gateway/rest/userinfo",
                        dataType: 'text',
                        type: 'GET'
                    });
                };
               self.getUserName().then(function (result) {
                    self.userLogin(result);
                });

If you deploy and run the application on JCS-SX it will show the logged in user instead of the hardcoded user name.

 

Step 5 - To implement logoff

If you click on the user name, you can see the “Sign Out” button which is not implemented yet.  Let us map it to a LogoutServlet.

 

package com.oracle.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.*;
import javax.servlet.http.*;

public class LogoutServlet extends HttpServlet {

    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getSession().invalidate();
        response.sendRedirect( "/oamsso/logout.html");
    }
}

 

Add the Logout servlet entry in web.xml

 

<servlet>
<servlet-name>LogoutServlet</servlet-name>
<servlet-class>com.oracle.servlet.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LogoutServlet</servlet-name>
<url-pattern>/logout</url-pattern>
</servlet-mapping>

 

In index.html, you can see the menu1 element that has the ‘Sign Out’ menu item.  The selection of any menu item triggers function menuItemSelect.

 

<ul id='menu1' data-bind="ojComponent: {component: 'ojMenu', select: menuItemSelect}" style="display:none">
        <!--<li id="pref"><a href="#">Preferences</a></li>-->
        <li id="help"><a href="#">Help</a></li>
        <li id="about"><a href="#">About</a></li>
        <li id="out"><a href="#">Sign Out</a></li>
</ul>

 

In appController.js, add a case for the sign out event

 

self.menuItemSelect = function (event, ui) {
 switch (ui.item.attr("id")) {
 case "about":
 $("#aboutDialog").ojDialog("open");
 break;
 case "out" :
 window.location.href = "/QuickStartProject/logout";
 default:
       }
};

 

 

Deploy and run the application and clicking on Sign Out redirects to the cloud logout page as below:

JET QuickStart - loggedoff.png

 

If you want to display a particular page and not the cloud logout page, customize the URL in the LogoutServlet.

 

response.sendRedirect( "/oamsso/logout.html?end_url=<landing page>");

 

There you have it – a working JET application deployed on JCS-SX with the logged in user context and Single Sign On and Single Logoff features.

 

**The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

In the previous blog post, we discussed about Identity propagation from Java Cloud Service - SaaS Extension (JCS-SX) to Document Cloud Service (DCS) using SAML token.  Here we will explore achieving Identity Propagation by using OAuth 2.0 tokens.

 

To know more about OAuth 2.0 specification, go here.

 

Broadly the architecture of the interaction between JCS-SX, DCS and SIM is as follows:

architecture_oauth.png

 

There are 4 roles in OAuth 2.0 :

Client - the client application that is requesting resources.  In our use case - this would be the JCS-SX Servlet

Resource Owner - the person/entity on whose behalf the resources are being requested.  This is the end user who is logging in.

Resource Server - the server that hosts the protected resources.  This is the Document Cloud Service.

Authorization (OAuth) Server - the server that authenticates the user and issues tokens to the client - this is the Shared Identity Management (SIM)

 

 

The SIM and OWSM enable OAuth token generation and validation seamlessly in Oracle Public Cloud environment.  The pre-requisites for these are

1) Registering a client with the OAuth server - particularly having the client_id and client_secret

2) Registering what resource do we need to access for this client

3) Importing the OAuth signing certificates into the trust store of the Resource Server

4) Generating a client signing certificate and importing it to the Oauth Server.

 

These steps are automatically done during cloud provisioning for different Cloud Services in the same identity domain.  For e.g. in the identity domain having JCS-SX and Document Cloud Service, if you go to the OAuth administration tab, you can see the following already created.

oauth_tab.png

 

Make sure that the resource is accessible to the JCS SX OAuth Client.  You can check list by clicking on the "Modify OAuth Client" option available and see if the same is ticked as below.

modify_oauth_client.png

 

The next step is to create a CSF key for the map "oracle.wsm.security" with the client_id and client_secret corresponding to the JCS-SX.  For this you need to have the JCS-SX SDK (go here for download ) installed.  Replace the values in angular brackets with the actual values.   The credentials here should be of a user who has the Identity Domain Administrator role.

 

set SDK_LIB={location where JCS-SDK is installed}/lib
java -jar %SDK_LIB%/javacloud.jar -user {user} -password {pass} -identitydomain {id-domain} -serviceinstance {sc-name} -datacenter {dc} -set-credential -map oracle.wsm.security -key myoauth.csf.key -keyuser 01b410bc-3b63-4804-9728-c1c64d493526 -keypassword  aUyQltthbCkBzgTZlWw7

 

Next change the JCS-SX Servlet to use the oracle/http_oauth2_token_over_ssl_client_policy.  This policy mandates that the oracle/oauth2_config_client_policy should also be attached. The full code is given below.  Replace example.documents.us.oraclecloud.com with the documents instance URL and example.identity.us.oraclecloud.com with the SIM URL.

 

package com.oracle.rest;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.client.filter.ClientFilter;
import com.sun.jersey.api.client.filter.LoggingFilter;
import com.sun.jersey.client.urlconnection.HTTPSProperties;

import java.io.IOException;
import java.io.PrintWriter;

import java.security.NoSuchAlgorithmException;

import java.util.Map;

import javax.net.ssl.SSLContext;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import oracle.wsm.agent.handler.jaxrs.RESTClientFilter;
import oracle.wsm.metadata.feature.AbstractPolicyFeature;
import oracle.wsm.metadata.feature.PolicyReferenceFeature;
import oracle.wsm.metadata.feature.PolicySetFeature;
import oracle.wsm.metadata.feature.PropertyFeature;

public class DocsOAuthServlet extends HttpServlet {

    private static final String ENDPOINT_URL =
        "https://example.documents.us.oraclecloud.com/documents/api/1.1/folders/self";
    private static final String CLIENT_CSF_KEY = "myoauth.csf.key";
    private static final String OAUTH_TOKEN_ENDPOINT =
        "https://example.identity.us.oraclecloud.com/oam/oauth2/tokens";


    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }


    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
                                                                                          IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("<html><body>");
        try {
            ClientConfig cc = new DefaultClientConfig();
            Map<String, Object> properties = cc.getProperties();
            SSLContext sslContext = null;
            try {
                sslContext = SSLContext.getInstance("TLS");
            } catch (NoSuchAlgorithmException e) {
                out.println("Exception in setting sslContext is : " + e + " exc messaage is: " + e.getMessage());
            }


            properties.put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(null, sslContext));
            //Adding the policy - starts
            PropertyFeature[] oauthClientPropFeature = new PropertyFeature[1];
            oauthClientPropFeature[0] = new PropertyFeature("oauth2.client.csf.key", CLIENT_CSF_KEY);
            PropertyFeature oauthGeneralPropFeature = new PropertyFeature("token.uri",OAUTH_TOKEN_ENDPOINT);
            
            PolicyReferenceFeature[] oauthPolicyFeature = new PolicyReferenceFeature[] {
                new PolicyReferenceFeature("oracle/oauth2_config_client_policy", oauthGeneralPropFeature ),
                new PolicyReferenceFeature("oracle/http_oauth2_token_over_ssl_client_policy", oauthClientPropFeature)
            };
            properties.put(AbstractPolicyFeature.ABSTRACT_POLICY_FEATURE, new PolicySetFeature(oauthPolicyFeature));
            //Adding the policy - finishes
            
            Client client = Client.create(cc);


            //Adding the client filter - starts
            ClientFilter filter = new RESTClientFilter();
            client.addFilter(new LoggingFilter(System.out));
            client.addFilter(filter);
            //Adding the client filter - finishes
          

            WebResource resource = client.resource(ENDPOINT_URL);
            ClientResponse clientResponse = resource.get(ClientResponse.class);
            String output = clientResponse.getEntity(String.class);
            out.println("\n\n<br>----------Output starts--------------");
            out.println("<br/>Response body from Service is : " + output);
            out.println("<br/>HTTP Status : " + clientResponse.getStatus());
            out.println("<br/>--------------Output ends----------------");
        } catch (Exception e) {
            out.println("Exception is : " + e + " exc messaage is: " + e.getMessage());
        }
        out.println("</body></html>");
    }


    public void destroy() {
        super.destroy();
    }
}

 

In the web.xml we add another servlet entry corresponding to DocsOAuthServlet as below:

<?xml version = '1.0' encoding = 'windows-1252'?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">
    <servlet>
        <servlet-name>Servlet1</servlet-name>
        <servlet-class>com.oracle.rest.DocsServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Servlet1</servlet-name>
        <url-pattern>/saml</url-pattern>
    </servlet-mapping>
    
        <servlet>
        <servlet-name>Servlet2</servlet-name>
        <servlet-class>com.oracle.rest.DocsOAuthServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Servlet2</servlet-name>
        <url-pattern>/oauth</url-pattern>
    </servlet-mapping>
    
    
    <security-constraint>
        <display-name>name</display-name>
        <web-resource-collection>
            <web-resource-name>name</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
    </security-constraint>
    <login-config>
        <auth-method>CLIENT-CERT</auth-method>
        <realm-name>default</realm-name>
    </login-config>
</web-app>

 

Accessing the servlet URL should give an output as below:

oauth_output1.png

The servlet will call the DCS REST API with the authorization header "Bearer <oauth token" and display the result in the servlet response.  The process of getting the token is handled by the OWSM agent on the JCS-SX side.

 

Jersey 1.0 provides a LoggingFilter class that can be used for logging requests.  We have attached this filter in our code:

            client.addFilter(new LoggingFilter(System.out));

 

We can check the output of the LoggingFilter from the system logs provided by JCS-SX.  Go to the JCS-SX Console -> View Log Messages

 

oauth_console_log.png

 

Additional information

In case you dont attach the oracle/oauth2_config_client_policy, you will get an exception like the below

oracle.wsm.common.sdk.WSMException: WSM-07620 : Agent cannot enforce policies due to either failure in retrieving polices or error in validations, detail= "WSM-01797 Attachment of an oauth2 client policy without oauth2 config policy is invalid. Ensure you attach a valid oauth2 config policy either via Direct Policy Attachment or via Global Policy Attachment along with an oauth2 client policy. "

 

 

Note that, there is a mandatory property "token-uri" that needs to be provided to the oauth2_config_client_policy.  This is the OAuth 2.0 token endpoint and will typically be <iddomain>.identity.oracle.com/oam/oauth2/tokens.  For more details refer to the OWSM oauth2_config_client_policy documentation.

 

For the http_oauth2_token_over_ssl_client_policy, there is a mandatory property called oauth2.client.csf.key.  This will hold the key name in the oracle.wsm.security map that will store the client_id and client_secret for the JCS-SX client.  If the required key doesnt exist in the oracle.wsm.security map you will get an exception like the below

 

oracle.wsm.common.sdk.WSMException: WSM-00054 : The password credentials cannot be obtained from the Credential Store Framework (CSF). Unable to retrieve the csfKey "myoauth.csf.key". The csf map "oracle.wsm.security" found in the credential store is being used and the following keys are found in this map :- []

 

 

For more details, refer to the OWSM http_oauth2_token_over_ssl_client_policy documentation

 

The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

To use multiple cloud services as one cohesive unit, it is often needed to propagate identity from one PaaS cloud service to another. For e.g. an application in Java Cloud Service or Mobile Cloud Service that needs to access some RESTful resources in another PaaS service like Documents Cloud Service.    In this blog post I will discuss one such case i.e. identity propagation from Java Cloud Service – SaaS Extension (JCS-SX) to Documents Cloud Service (DCS).  The assumption is that both these services are hosted in the same identity domain.

 

First a note about the two common services that make identity propagation possible.

 

  • In Oracle Cloud, the Shared Identity Management (SIM) provides Identity Management, Single Sign On, Federation and other services out-of-the-box to Oracle PaaS services.  The SIM also acts as the OAuth Server to handle OAuth flows.

 

  • Oracle Web Services Manager (OWSM) provides a policy management and enforcement framework to secure and manage Web Services at design time via code or post deployment from administration consoles.  OWSM can be used to manage both REST and SOAP web services.

 

Our Use Case is based on an application hosted in JCS-SX which has a Servlet (or REST service) accessing a Documents Cloud Service REST API.  Here we have two resources:

  • Resource A in JCS-SX – protected by security-constraint in web.xml, which requires the user to login in order to access the resource.
  • Resource B in Documents Cloud Service – protected by the internal Documents Cloud Service OWSM.

 

The sequence of events that occur when the user requests the URL of the servlet are as follows:

  1. User tries to access Resource A (servlet URL from the browser)
  2. Since Resource is protected, user asked to login
  3. Post Login, User is redirected to the Resource A
  4. Resource A makes a call to Resource B.  Resource B should work in the context of logged in user. E.g. return folders that belong to the logged in user.

 

Here the JCS-SX Servlet acts as the REST client w.r.t the Documents Cloud Service.

 

architecture.png

 

The Document Cloud Service REST APIs are protected by the oracle/multi_token_over_ssl_rest_service_policy (details here) which enforces one of the following authentication policies, based on the token sent by the client:

  • HTTP Basic over SSL—Extracts username and password credentials from the HTTP header.
  • SAML 2.0 Bearer token in the HTTP header over SSL—Extracts SAML 2.0 Bearer assertion in the HTTP header.
  • HTTP OAM security (non-SSL)—Verifies that the OAM agent has authenticated user and establishes identity.
  • JWT token in the HTTP header over SSL—Extracts username from the JWT token in the HTTP header

 

So we could use potentially any of these methods to propagate identity from JCS-SX to DCS (However the first one - HTTP Basic over SSL would require putting in credentials again and is not really a true identity propagation method)  Here I will be using the SAML 2.0 Bearer token as the identity propagation method.

 

The steps to achieve this are as follows:

 

Step 1 – Create JCS-SX Servlet that calls a Documents Cloud Service REST API

Note – replace example.com with the URL for your Documents Cloud Service instance and the API endpoint as any DCS REST API that you need.  The full list of DCS REST APIs are published here.  In this example I have used the ENDPOINT_URL to point to a special folder called "self".

 

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.client.urlconnection.HTTPSProperties;

import java.io.IOException;
import java.io.PrintWriter;

import java.security.NoSuchAlgorithmException;

import java.util.Map;

import javax.net.ssl.SSLContext;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DocsServlet extends HttpServlet {

 private static final String ENDPOINT_URL =
        "https://example.com/documents/api/1.1/folders/self";

 public void init(ServletConfig config) throws ServletException {
        super.init(config);
 }

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
 out.println("<html><body>");
        try {
            ClientConfig cc = new DefaultClientConfig();
            Map<String, Object> properties = cc.getProperties();
            SSLContext sslContext = null;
            try {
                sslContext = SSLContext.getInstance("TLS");
            } catch (NoSuchAlgorithmException e) {
                out.println("Exception in setting sslContext is : " + e + " exc messaage is: " + e.getMessage());
            }

 properties.put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(null, sslContext));

            Client client = Client.create(cc);
            WebResource resource = client.resource(ENDPOINT_URL);
            ClientResponse clientResponse = resource.get(ClientResponse.class);
            String output = clientResponse.getEntity(String.class);
 out.println("\n\n<br>----------Output starts--------------");
 out.println("<br/>Response body from Service is : " + output);
            out.println("<br/>HTTP Status : " + clientResponse.getStatus());
 out.println("<br/>--------------Output ends----------------");
        } catch (Exception e) {
            out.println("Exception is : " + e + " exc messaage is: " + e.getMessage());
        }
 out.println("</body></html>");
 }

 public void destroy() {
 }       super.destroy();
 }

 

I am using maven as a dependency management tool.  Here is the pom.xml

<?xml version="1.0" encoding="UTF-8" ?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.oracle.idprop</groupId>
 <artifactId>idproptodocs</artifactId>
 <version>1.0-SNAPSHOT</version>
 <description>Project for idproptodocs</description>
 <packaging>war</packaging>
 <properties>
 <jersey-version>1.19.1</jersey-version>
 </properties>
 <build>
        <resources>
            <resource>
 <directory>${basedir}</directory>
                <includes>
 <include>*</include>
                </includes>
            </resource>
            <resource>
 <directory>src/main/resources/</directory>
                <includes>
 <include>*</include>
                </includes>
            </resource>
        </resources>
 </build>
 <dependencies>
        <dependency>
 <groupId>javax.servlet</groupId>
 <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <type>jar</type>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.json</groupId>
 <artifactId>json</artifactId>
 <version>20140107</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
        <dependency>
 <groupId>com.sun.jersey</groupId>
 <artifactId>jersey-json</artifactId>
 <version>${jersey-version}</version>
            <type>jar</type>
            <scope>compile</scope>
            <exclusions>
                <exclusion>
 <groupId>com.sun.xml.bind</groupId>
 <artifactId>jaxb-impl</artifactId>
                </exclusion>
                <exclusion>
 <groupId>com.sun.xml.bind</groupId>
                    <artifactId>jaxb-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
 <groupId>com.sun.jersey</groupId>
 <artifactId>jersey-core</artifactId>
            <version>${jersey-version}</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
        <dependency>
 <groupId>com.sun.jersey</groupId>
 <artifactId>jersey-servlet</artifactId>
 <version>${jersey-version}</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
        <dependency>
 <groupId>com.sun.jersey</groupId>
 <artifactId>jersey-bundle</artifactId>
 <version>${jersey-version}</version>
            <type>jar</type>
            <scope>compile</scope>
            <exclusions>
                <exclusion>
 <groupId>com.sun.xml.bind</groupId>
                    <artifactId>jaxb-impl</artifactId>
                </exclusion>
                <exclusion>
 <groupId>com.sun.xml.bind</groupId>
 <artifactId>jaxb-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
 <groupId>com.sun.jersey.contribs</groupId>
 <artifactId>jersey-multipart</artifactId>
 <version>${jersey-version}</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
 </dependencies>
</project>

 

 

And the following is the web.xml entry.  We use a security-constraint and a CLIENT-CERT login-config element in the web.xml to protect the DocsServlet and make it a Tenant Restricted Page

 

<?xml version = '1.0' encoding = 'windows-1252'?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">
 <servlet>
 <servlet-name>Servlet1</servlet-name>
 <servlet-class>com.oracle.rest.DocsServlet</servlet-class>
 </servlet>
 <servlet-mapping>
 <servlet-name>Servlet1</servlet-name>
 <url-pattern>/saml</url-pattern>
 </servlet-mapping>
 <security-constraint>
 <display-name>name</display-name>
        <web-resource-collection>
 <web-resource-name>name</web-resource-name>
 <url-pattern>/*</url-pattern>
        </web-resource-collection>
 </security-constraint>
 <login-config>
 <auth-method>CLIENT-CERT</auth-method>
 <realm-name>default</realm-name>
 </login-config>
</web-app>

 

 

And at last - the weblogic.xml entry

<?xml version = '1.0' encoding = 'windows-1252'?>
<weblogic-web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.7/weblogic-web-app.xsd"
 xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app">
 <container-descriptor>
 <prefer-web-inf-classes>true</prefer-web-inf-classes>
 </container-descriptor>
 <context-root>idproptodocs</context-root>
</weblogic-web-app>

 

Create the WAR for the application and deploy to JCS-SX via the console.  For details on how to deploy to JCS-SX via the Java console, please consult the documentation

 

Post deployment, access the Servlet URL from the browser.  It will first prompt for the user to login.

cloud_sign_in.png

On successful login, it should navigate to the Servlet page, which should give output as below:

output1.png

The 401 indicates that the Document Cloud Service API couldn’t authorize the request made by the JCS-SX Servlet.

Step 2 – Import required libraries for OWSM

The wsm-policy-core and wsm-rest-lib jars are needed for compilation purposes in the IDE.  You can find these jars from the 11g local installation of Weblogic in the following location

MW_HOME/oracle_common/modules/oracle.wsm.common_11.1.1/wsm-policy-core.jar

MW_HOME/oracle_common/modules/oracle.wsm.common_11.1.1/wsm-rest-lib.war

 

Copy these to a specific folder in your local filesystem for use with Maven and then add them in your pom.xml with scope as system.  I have copied the files to C:\temp in my example.  These are referred by Maven only during compilation and are not packaged.

        <!-- owsm -->
        <dependency>
            <groupId>com.oracle.wsm</groupId>
 <artifactId>wsm-rest-lib</artifactId>
            <version>11.1</version>
            <type>jar</type>
            <scope>system</scope>
 <systemPath>C:\temp\wsm-rest-lib.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>com.oracle.wsm</groupId>
 <artifactId>wsm-policy-core</artifactId>
            <version>11.1</version>
            <type>jar</type>
            <scope>system</scope>
 <systemPath>C:\temp\wsm-policy-core.jar</systemPath>
        </dependency>
        <!-- owsm -->

 

The following two libraries are also needed to be deployed to the JCS-SX instance as libraries if they don’t exist there.  The steps for deploying a shared library are given here.

MW_HOME/oracle_common/modules/oracle.webservices_11.1.1/wls-rest-client.war

MW_HOME/oracle_common/modules/oracle.wsm.common_11.1.1/wsm-rest-lib.war

 

libraries.png

Step 3 – Attach required policy to the REST Client

Add properties to the ClientConfig to use the respective client side OWSM policies.  Here we would attach a SAML based client policy.  This means that the OWSM would intercept the REST request, inspect the authenticated subject within JCS-SX, generate a SAML based token from the user assertion, and insert the SAML token as a Bearer token as an Authorization header in the REST request.

For this we would use the “oracle/http_saml20_token_bearer_over_ssl_client_policy”.  The following code illustrates this:

 

          

 //Adding the policy - starts
            PolicyReferenceFeature[] samlfeature = new PolicyReferenceFeature[] {
                new PolicyReferenceFeature("oracle/http_saml20_token_bearer_over_ssl_client_policy",
                                           new PropertyFeature[] { })
            };
 properties.put(AbstractPolicyFeature.ABSTRACT_POLICY_FEATURE, new PolicySetFeature(samlfeature));
            //Adding the policy - finishes
            
            Client client = Client.create(cc);

 

 

To intercept the REST requests and generate and insert the SAML token, attach the OWSM provided out-of-the-box filter for REST Clients called RestClientFilter to the JAX RS Client.

           //Adding the client filter - starts
 ClientFilter filter = new RESTClientFilter();
                 client.addFilter(filter);
//Adding the client filter - finishes

 

Modify the weblogic.xml to refer to the deployed libraries as below

<?xml version = '1.0' encoding = 'windows-1252'?>
<weblogic-web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-web-app
 http://xmlns.oracle.com/weblogic/weblogic-web-app/1.7/weblogic-web-app.xsd"
                  xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app">
    <container-descriptor>
 <prefer-web-inf-classes>true</prefer-web-inf-classes>
    </container-descriptor>
 <context-root>idproptodocs</context-root>
    <library-ref>
        <library-name>wsm-rest-lib</library-name>
    </library-ref>
    <library-ref>
 <library-name>wls-rest-client</library-name>
    </library-ref>
</weblogic-web-app>

Generate the war file and re-deploy to JCS-SX.

 

Now re-run the Servlet - You will see the output as below which indicates that the identity of the logged in user was propagated to the DCS REST API.

output2.png

The output is actually the JSON response of GET request issued to the ENDPOINT_URL of Documents Cloud Service instance - which is the folder information of the "self" folder.

 

The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

Social Objects in Oracle Social Network Cloud are generally used to add Collaboration features to your Business Objects i.e. System of record (for e.g. to carry out a conversation regarding a particular opportunity in Sales Cloud).  Social Objects have their own metadata (attributes), "wall", a documents area where you can upload documents, and provisions to attach other related conversations/objects.

 

You can limit visibility or share a Social Object between other people in your organization by adding individuals or groups.

 

For simple scenarios, where not much relational data is needed, a Social Object can also directly be used as a system-of-record.

 

In this blog post I will explore one such case - using the Social Object API to implement a simple Kanban board with collaboration features.

 

Creating a Social Definition

The first step is to create a Social Definition of a Kanban task.  We will call it "KanbanTask" and have three attributes in it

- Status (TODO, DONE, DOING)

- Title

- Description

- Assigned

 

The definition of a Social Object can be uploaded by an Administrator using the Social Network UI ( Administration -> Social Objects -> Create ).  This can also be done programmatically using REST APIs.  If you have a staging instance, this can also be done via the Social Definiton Builder available at https://<staging-instance>/osndevelopers/ui/integrations/integrations.jsp.  This is a one time activity and I am using the upload option to seed a simple Social Definition. 


<?xml version="1.0" encoding="UTF-8"?>
<Module>
 <ModulePrefs title="KanbanTask" description="A Kanban Task representation" height="175">
 <Require feature="rpc" />
 <Require feature="waggle" />
 <Require feature="jquery" version="1.3.2" />
 <Require feature="jquery-ui" version="1.8.12" />
 <Require feature="osnutils" />
 <Locale country="ALL" lang="all">
            <msg name="osn.group.name">Tools</msg>
            <msg name="osn.group.name.lowercase">tools</msg>
            <msg name="osn.gadget.name">KanbanTask</msg>
            <msg name="osn.gadget.name.lowercase">kanbantask</msg>
            <msg name="osn.gadget.name.plural">KanbanTasks</msg>
            <msg name="osn.gadget.name.plural.lowercase">kanbantasks</msg>
            <msg name="osn.gadget.create.short">New Kanban task</msg>
            <msg name="osn.gadget.create.long">Create a new Kanban Task</msg>
            <msg name="osn.gadget.create.tooltip">Create a new Kanban Task</msg>
            <msg name="osn.field.name.TITLE">Title</msg>
 <msg name="osn.field.name.STATUS">Status</msg>
            <msg name="osn.field.name.ASSIGNED">Assigned</msg>
            <msg name="osn.field.name.DESCRIPTION">Description</msg>
 </Locale>
 <Locale country="ALL" lang="de" />
 <Locale country="ALL" lang="es" />
 <Locale country="ALL" lang="fr" />
 <Locale country="ALL" lang="it" />
 <Locale country="ALL" lang="ja" />
 <Locale country="ALL" lang="ko" />
 <Locale country="BR" lang="pt" />
 <Locale country="CN" lang="zh" />
 <Locale country="TW" lang="zh" />
 </ModulePrefs>
 <ConversationTypePrefs group="Tools" group_order="1" creatable="true" updateable="true" renameable="true" discoverable="false" closeable="true" deletable="false" customizable="true" ui="true" analytics="false" analytics_outcome="false" scoping="false" integration_adapter="none">
 <Field property_key="TITLE" type="STRING" case_sensitive="false" required="false" read_only="false" external="false" analytics="false" display_in_detail="true" display_in_summary="true" display_in_digest="false" filterable="false" sortable="true" units_prefix="false" not_nullable="false" />
 <Field property_key="DESCRIPTION" type="STRING" case_sensitive="false" required="false" read_only="false" external="false" analytics="false" display_in_detail="true" display_in_summary="true" display_in_digest="false" filterable="false" sortable="true" units_prefix="false" not_nullable="false" />
 <Field property_key="STATUS" type="STRING" case_sensitive="false" required="false" read_only="false" external="false" analytics="false" display_in_detail="true" display_in_summary="false" display_in_digest="false" filterable="false" sortable="false" units_prefix="false" not_nullable="false" />
 <Field property_key="ASSIGNED" type="STRING" case_sensitive="false" required="false" read_only="false" external="false" analytics="false" display_in_detail="true" display_in_summary="false" display_in_digest="false" filterable="false" sortable="false" units_prefix="false" not_nullable="false" />

 </ConversationTypePrefs>
 <Content type="html"><![CDATA[ 
<script type="text/javascript"> gadgets.util.registerOnLoadHandler(function() { osnutils.gadget.load(); }); </script>
 ]]></Content>
</Module>













 

Save the XML to the local directory and upload it via the Social Definition screen.

 

SocialDefinition.png

 

Once this XML containing the social Object Definition is uploaded you can see the option to create a new “Kanban Task” from the Navigation menu on the left hand side. Note that the Social Object “KanbanTasks” is  in a Group called Tools, since we specified the same in the XML.

 

social_object_options.png

 

Creating and Updating a Social Object

Navigating to this new menu option will take you to the “Kanban Task” Social Objects page, where you have options to create, update or view the social objects.  You can also see the type of the social object in the URL when you navigate to this page

 

http://<server:port>/osn/web/cList/socialObjects/type/13452

 

Here, 13452 is the type id of the Social Object "KanbanTask"

 

Create a new "KanbanTask" by clicking on the "New" button.  This will open the standard OSN gadget window where you can give a title, and manage membership to the new object that will be created.

 

social_object_create.png

 

The "KanbanTask" will be created with default values of the attributes that we used in the definition.  This is how it will look like in the UI.

social_object_created.png

 

Now you can "Edit" the Social Object to edit these values.  Any changes to the Social Object Data will be visible in the Wall and the members assigned to the Social Objects can collaborate and share documents pertaining to the Social Object.

 

REST interface

The OSN comes with a exhaustive REST API catalog to programmatically perform various tasks and can be referred here. Let us retrieve the Social Object we have just created.

 

The first API to be used for establishing a connection to the Social Network Cloud Service is the connections API.  This API will create a new connection or determine if there is an existing connection and also return a cookie for further communication.

 

POST http://<host-name>/osn/social/api/v1/connections HTTP/1.1

Accept-Encoding: gzip,deflate

Content-Type: application/json

Content-Length: 57

{

                "name" : "tenant.admin",

                "password" : "abc123"

}

 

and the response - a whole bunch of attributes corresponding to the logged

 

HTTP/1.1 200 OK

Date: Tue, 28 Jun 2016 02:02:30 GMT

Set-Cookie: OAMAuthnCookie_<hostname>:443=C3TVf6ypnEzq8RZ9G3wjax6Gq.....;

X-ORACLE-DMS-ECID: 005D^o7XiLt6eLG_IxG7yf0006nT00001R

X-Powered-By: Servlet/2.5 JSP/2.1

X-Content-Type-Options: nosniff

Keep-Alive: timeout=5, max=100

Connection: Keep-Alive

Transfer-Encoding: chunked

Content-Type: application/json;charset=UTF-8

Content-Language: en

 

{

  "user" :

  {

    "id" : "10190",

    "name" : "tenant.admin",

    "displayName" : "tenant.admin",

    "objectType" : "waggle/user",

    "createdByID" : "10041",

    "createdByUserName" : "System",

  ..

  ..

  "apiVersionMinimum" : 6076,

  "apiRandomID" : "b375e527c6e1bbf3b1f2f7fb96184f3e",

   "isTerseMode" : false

}

 

There are two things that need to be passed i the subsequent requests - the cookie and the apiRandomId.  The apiRandomID should be passed in the X-Waggle-RandomID parameter in the header

 

Here are the headers, payload for the request for getting all Social Objects.  You can add a filter query parameter to limit the response to certain variables (e.g. getting all Social Objects that are applicable to a certain user as shown here)

 

GET  /osn/social/api/v1/socialObjects ?filter={"commonMemberID" : "10190"}

HTTP/1.1 Accept-Encoding: gzip,deflate

cookie: OAMAuthnCookie_<hostname>:443=C3TVf6ypnEzq8RZ9G3wjax6Gq.....;

X-Waggle-RandomID: b375e527c6e1bbf3b1f2f7fb96184f3e


Here is the response containing the Social Object just created.

 

{

   "hasMore": false,

   "items":    [

            {

         "id": "13455",

         "name": "UI1 - Coding",

         "objectType": "waggle/conversation",

         "createdByID": "10190",

         "createdByUserName": "tenant.admin",

..

..

         "nFollowups": 0,

         "fields":          [

                        {

               "name": "ASSIGNED",

               "value": "Aparna"

            },

                        {

               "name": "DESCRIPTION",

               "value": "UI coding for task 1"

            },

                        {

               "name": "STATUS",

               "value": "TODO"

            },

                        {

               "name": "TITLE",

               "value": "Task1"

            }

         ],

...

..

      },

   ]

}

 

 

Embeddable UI

The OSN Web UI can be directly displayed in other applications.  This can be done by using the Social Plugins which are UI components embeddable in other applications.

The view to be shown is inserted after the root portion of the URL.  So

https://<hostname:port>/{instance}/web/cList/{view}

Example:

https://tenantname.com:1234/osn/web/cList/conversations/9877

 

displays the view for the conversation id 9877

 

The particular view can be further customized as to not show certain options

E.g.

https://tenantname.com:1234/osn/web/cList/conversations/9877?locale=en&hide=navMenu+sidebar

 

will hide the navigation menu and sidebar from the conversation list displayed.

For full reference please consult the Social Plugin documentation available on https://<hostame>/osn/web/cList/api 

 

Wrapping it all together

 

The output of the REST APIs and the embeddable UI can now be used in the visualization of choice.  For my project, I have created a simple JET application that will be deployed in a Java Cloud Service - SaaS Extension which is in the same identity domain as the Social network Cloud to achieve SSO.  The JET application first retrieves the Social Objects of type KanbanTask for the logged in user and then arranges them on a simple Kanban Board.  The tasks can be dragged and dropped in the To do, Done and In Progress areas. Clicking on any task will load the Social Object page for that particular task in the right hand menu.

 

kanban_board.png

 

The views expressed in this post are my own and do not necessarily reflect the views of Oracle.