Enable Oracle JCS to access External REST API

Enable Oracle JCS to access External REST API

For a training I’m preparing I had to implement a POC on how to access an external REST API and to make it available in an ADF application running in the Oracle Java Could Service.

This task sounds pretty easy, nevertheless it’s best to see this working before starting a training which in the end will not work.

I decided to use Spotify public available REST API at https://api.spotify.com for this task. I started by creating a simple Fusion Web Application using JDev version 12.2.1.2.0. To this project I added a custom model Project which I later used to add the REST DataControl pointing to the Spotify track search API.

As this post isn’t about how to create such a project and use it in your normal ADF application, I spare the details here and write this up in another blog post.

Implementing a REST DataControl is pretty straight forward and the sample application was set up quickly. The first problem you might run into, even on the local development machine is this

null

error you get when you try to access the public API from inside the WebLogicServer. To make this error searchable for other users here is a part of the stack trace

javax.net.ssl.SSLKeyException: Hostname verification failed: HostnameVerifier=weblogic.security.utils.SSLWLSHostnameVerifier, hostname=api.spotify.com.
at weblogic.security.SSL.jsseadapter.JaSSLEngine.doPostHandshake(JaSSLEngine.java:686)
at weblogic.security.SSL.jsseadapter.JaSSLEngine.doAction(JaSSLEngine.java:757)
at weblogic.security.SSL.jsseadapter.JaSSLEngine.unwrap(JaSSLEngine.java:133)
at weblogic.socket.JSSEFilterImpl.unwrap(JSSEFilterImpl.java:644)
at weblogic.socket.JSSEFilterImpl.unwrapAndHandleResults(JSSEFilterImpl.java:541)
at weblogic.socket.JSSEFilterImpl.doHandshake(JSSEFilterImpl.java:99)
at weblogic.socket.JSSEFilterImpl.doHandshake(JSSEFilterImpl.java:78)
at weblogic.socket.JSSESocket.startHandshake(JSSESocket.java:240)
at weblogic.net.http.HttpsClient.New(HttpsClient.java:574)
at weblogic.net.http.HttpsClient.New(HttpsClient.java:545)
at weblogic.net.http.HttpsURLConnection.connect(HttpsURLConnection.java:236)
at weblogic.net.http.HttpURLConnection.getInputStream(HttpURLConnection.java:685)
at weblogic.net.http.SOAPHttpsURLConnection.getInputStream(SOAPHttpsURLConnection.java:41)
at weblogic.net.http.HttpURLConnection.getResponseCode(HttpURLConnection.java:1545)
...

This problem can easily sorted out by changing the ‘Hostname Verification’ to custom and to specify ‘weblogic.security.utils.SSLWLSWildcardHostnameVerifier’ as ‘Custom Hostname Verifier’. Here are the detailed steps:

  1. Go to the WebLogic admin console -> Environment -> Servers -> Server -> Configuration -> SSL
  2. Under advanced options , change “Hostname Verification” from “BEA Hostname Verifier” to “Custom Hostname Verifier”.
  3. Set “Custom Hostname Verifier” to weblogic.security.utils.SSLWLSWildcardHostnameVerifier
  4. Click “Save” and then “Activate Changes”
  5. Restart your server.

After this the sample application will run on the local development machine or an stand alone webLogic Server.

Now the fun part begins, making the application run in the Oracle JCS. Here I started with setting up a new Java Cloud Service with a WebLogic Server of version 12.2.1.2 and deployed my local running application to this new JCS.

The application did start OK, but when I came to the point where the application tried to call the external REST API all I got is: NOTHING

I only saw a spinning cursor, no error message on the UI regardless of my exception handler. It turned out, that I did not wait long enough for the error message to come up. The REST call timed out eventually providing more info in the servers log file

Exception in invoking HTTP method GET from Rest data control. Cause: javax.ws.rs.ProcessingException: java.net.ConnectException: Tried all: 3 addresses, but could not connect over HTTPS to server: api.spotify.com port: 443

It looks like the external REST call is not allowed. Here is the REST call

https://api.spotify.com/v1/search?q=sorry&type=track

If you write this into your browser you’ll get a JSON string in return, something like

{
 "tracks" : {
 "href" : "https://api.spotify.com/v1/search?query=sorry&type=track&offset=0&limit=20",
 "items" : [ {
 "album" : {
 "album_type" : "album",
 "artists" : [ {
 "external_urls" : {
 "spotify" : "https://open.spotify.com/artist/1uNFoZAHBGtllmz…

telling me that the problem is somewhere with the JCS. I ask for help in the OTN Java Cloud Service space and got an answer that there must be a rule missing. This is true to some point as I tried to access the REST API with curl from the JCS command shell

null

which did not work either. The interesting part is that you can do the same from the DBCS command shell and get the right answer.

I tried to add a rule to allow the access but looking at the possible source and destinations lists this did not work. Only

  • OTD — The Oracle Traffic Director load balancer VMs
  • WLS_ADMIN_SERVER — The WebLogic Server Administration Server VM
  • WLS_MANAGED_SERVER — The WebLogic Server Managed Server VMs

are allowed as destinations and my rule should allow the managed server (source) to access the PUBLIC_INTERNET or allow access to https protocol port 443.

After some more reading and testing I found a solution, however I’m not sure if this is the best way to handle this. Anyway, for others users who run into the same problem here it is:

First you have to create a ‘Security List’ Which you name e.g. outbound_wlsms_https_traffic which denies incoming packages and allows outgoing packages

null

Next a ‘Security Rule’ can be created like

null

with source set as the managed server and destination the new security list. After that the access to the external REST API works.

Developer Cloud Service: Continuous Integration with JDeveloper 12.2.1

The last blog showed that the Oracle Developer Cloud Service is now available for JDeveloper and ADF 12.2.1 (Developer Cloud Service with JDeveloper 12.2.1 available). The missing part is the connection of the DCS to the newly created JCS for version 12.2.1. This we show in the blog.

The ground work, how to set up a build system for the DCS has been shown in Fasten your seat belts: Flying the Oracle Development Cloud Service (3 – Take Off – ROTATE). We now have to find out which environment variable to use for the 12.2.1 installation. At the time I wrote the mentioned blog there where only environment variables for 11.1.1.7.1 and 12.1.3.0 available. Looking at the documentation Using Hudson Environment Variables we find that the variables

  • ORACLE_HOME_SOA_12_2_1=/opt/Oracle/MiddlewareSOA_12.2.1/jdeveloper
  • MIDDLEWARE_HOME_SOA_12_2_1=/opt/Oracle/MiddlewareSOA_12.2.1
  • WLS_HOME_SOA_12_2_1=/opt/Oracle/MiddlewareSOA_12.2.1/wlserver

Are the right ones (and the only ones which point to 12.2.1). In the application.properties file (from the ‘… Take Off…’ blog) we exchange

# Don't change anything below!
 oracle.home=${env.ORACLE_HOME_12C3}
oracle.commons=${env.MIDDLEWARE_HOME_12C3}/oracle_common
middleware.home=${env.MIDDLEWARE_HOME_12C3}
install.dir=${env.ORACLE_HOME_12C3} 

with

# Don't change anything below!
oracle.home=${env.ORACLE_HOME_SOA_12_2_1}
oracle.commons=${env.MIDDLEWARE_HOME_SOA_12_2_1}/oracle_common
middleware.home=${env.MIDDLEWARE_HOME_SOA_12_2_1}
install.dir=${env.ORACLE_HOME_SOA_12_2_1} 

This change will use the JDeveloper 12.2.1 to run ojdeploy and configure the application to run on a WebLogic Server 12.2.1. This should do the trick and we can use the DCS build system to create application using ADF 12.2.1. As the application I used for the ‘Fasten your seat belts…’ blog series was pretty simple I like to show the result using the application I used for a presentation at the DOAG DevCamp2016, named AppsClouUIKit. You can read all about this application in a blog I wrote here DOAG DevCamp2016.

The application was build using JDeveloper 11.1.1.9.0 and has been migrated during the DevCamp to 12.1.3. This was the DCS version which was available at the time of the DevCamp. The first task is to migrate the source to 12.2.1 by creating a new branch in the GIT repository for the new 12.2.1 version.

We Clone the repository and create a new branch 12_2_1 which we use to build the AppsCloudUIKit for 12.2.1. As we are now running JDeveloper 12.2.1 we can use the Team-Server to get the sources from the DCS GIT repository

But we can use any other GIT client to get it. As this is covers in other blogs I’ll skip the details here. In the end we have this branch tree

Where the green marked local branch 12_2_1 is the one we are working on.

After changing the application.properies as shown above we can run the build using ant on the local machine

By selecting the ‘deploy’ target.

The result is an EAR file in the deploy folder

Setting up the build job

Let’s check-in the changes and setup the build in the DCS. Here are the steps for the build job

With this we can build the application to get the result

Setting up the Deployment

The final task is to set up the deploy task to deploy the application on the JCS_12_2_1. When we select the ‘Deploy’ tab we see the existing deployment configuration for the 12.1.3 JCS.

For the JCS 12.2.1 we created a new JCS instance with a different IP (public). Before we can create a new configuration for the 12.2.1 JCS instance we have to allow the Hudson user access to the JCS. This process is described in detail at Deploying an Application from Oracle Developer Cloud Service to Oracle Java Cloud Service

It’s absolutely necessary to get the Oracle Developer Cloud Service SSH public key and add this key to the JSC 12.2.1 instance as authorized key. Please follow the instructions given in the link above to do so.

After this is done we can create a new deployment configuration

Start filling in the dialog by giving the configuration a name. Next we create a new ‘Deployment Target’

In the dialog fill in the public IP address from the new JC 12.2.1 and select SSH Tunnel. The user name and password is the one you selected when you created the JCD instance. Test the connection and close the dialog by clicking ‘Use Connection’

Finally we can complete the Deployment dialog

We choose ‘On Demand’ here which let us specify which job/Build and artifact to use. A click to ‘Save and Deploy’ closes the dialog and the artifact will be deployed to the JCS 12.2.1. The URL to open the application is AppsCloudUIKit 12.2.1

And we should see