Quantcast
Channel: Oracle SOA / Java blog
Viewing all 142 articles
Browse latest View live

WebLogic Server: Analyzing stuck threads

$
0
0
A while ago I was confronted with a WebLogic server which did not want to start. The log files did not give an indication of what was wrong. I tried the usual suspects such as clearing the tmp and removing lok files but they did solve the issue. How to proceed? In this blog article I'll provide an example of how such an issue can be debugged.

A stuck thread is a thread which takes longer than the configured stuck thread max wait time (600 seconds by default). To simulate a stuck thread issue I created a simple servlet which does a Thread.sleep upon a request. I'll show how to use various tools to detect the servlet causing the problem and even identity the specific request which causes the code to malfunction. A similar mechanism can be used to debug for example JDBC issues and can help in the identification of which connection causes an issue. The tools used do not require the server to be fully started.


Setup

I created a simple HTTP servlet which did a Thread.sleep. After the stuck thread max time has passed, this thread is marked as STUCK. If you want to do your own tests with stuck threads, you can download sample programs doing something similar such as; Stuck thread for free.
 
Get a thread dump

A thread dump indicates which threads have which state and on which thread a thread is waiting. It also provides a stack trace of each thread. There are various ways to obtain a thread dump. If you have this dump, you can use for example ThreadLogic to analyze it. You can create a thread stack dump from the WebLogic console but also by issuing a command in a console.

WebLogic Console

In you have stuck threads but the WebLogic Console is still available, you can go to Environment, Servers and select a server. Now you can go to Monitoring, Threads. Here you can look at threads and identify stuck and hogging threads. Also you can request a dump of the Thread stacks.


Command line

In case the WebLogic Console is not available, you can fall back to the command line. On Windows and Linux/Unix you can use jstack to have the JVM output the thread dump to the console. On Linux/Unix, you can also issue a kill -3 <PID> to ask the JVM to print a thread dump to its standard out. On WebLogic server this thread dump usually ends up in a .out file in the domain log directory.

In order to execute jstack or the kill command, you first have to identify your process. On Windows I recommend Microsoft Sysinternals Process Explorer (GUI). You can also use jps (part of the JDK) which is a command-line tool.


On Linux determining the java process can be done with for example:

ps axw | grep java


Look at the command-line which is executed. This will tell you which process belongs to which WebLogic server.

In my case, the WebLogic server is running as PID 9049. I can now issue a kill -3 9049 giving me in the thread dump in the out log file or a jstack -l 9049 giving me the output directly on the console.

In this article I've described various command line tools in more detail.

Analyze the thread dump

ThreadLogic

To help you analyze thread dumps, the Oracle A-Team has been so kind as to provide us ThreadLogic (introduced here). It is a fork from TDA expanded with several useful features such the option to obtain actual advice and gain some detailed insight. Also it contains some WebLogic specific patterns often found in thread dumps which greatly helps with the analyzis.


In this case requests to my StuckThread servlet are indicated as fatal. Sometimes this provides enough information to solve the issue. However as you have seen, the thread dump contains relatively little information. In order to learn more you can obtain and analyze a heap dump.

Get a heap dump

Of course, knowing which thread causes the issue usually only gives you a general idea of what could be wrong. A JDBC connection is having a problem. Nice, but if you have a lot of JDBC connections configured which connect to different databases. You usually want to know a bit more. You can obtain a heap dump quite easily with jmap;


This generates an output.dmp file which contains the Java heap space (its in a binary hprof format). This file can become quite large so make sure you have enough disk space. For JRockit (a JVM Oracle obtained from BEA Systems) the command is different. See here for some useful JRockit commands. On other JVM's, the commands also differ.

Analyze the heap dump

Once you have obtained a heap dump, you can start analyzing it. A useful tool for this is MAT. A Memory Analyzer Tool. This tool loads the entire heap dump in memory and starts analyzing it. Thus it is recommended to have some memory available to do this. It is not easy to use though and requires some practice to filter the relevant information from a heap dump. Download and start the tool. Load the heap dump you have created. In the dominator_tree (one of the top buttons after you have loaded your heap dump) you can search for a specific string or class. In this case I look for a GET request related to my troublesome servlet. You can also search for the class causing the stuck thread (which you can obtain from the thread dump / ThreadLogic).




I can then list objects with incoming references. By going a bit deeper I can obtain information on the request causing the stuck thread.



GET /StuckThreadServlet/stuckthreadservlet HTTP/1.1..Host: 127.0.0.1:7101..User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0..Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8..Accept-Language: en-US,en;q=0.5..Accept-Encoding: gzip, deflate

Analyzing a heap dump can look difficult at first. You can compare it with looking at SOA Suite debug log files, which can become quite large. At first it is difficult to find what you are looking for (a lot is happening in SOA Suite) but with a bit of experience after a while you start to see patterns and develop your own search methods.

Finally

Getting a heap dump without looking at a thread dump first is not recommended since it will complicate the analysis and ThreadLogic gives you a head start by providing advice on what you should look at.

When not to analyze

Of course if a line like the following in the domain or server log provides you with enough information, you do not require an analysis like this.

####<Nov 22, 2015 10:03:34 AM EST> <Error> <WebLogicServer> <localhost.localdomain> <DefaultServer> <[ACTIVE] ExecuteThread: '73' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <d699ecd1-da0e-4c0a-8674-4fe3a362b5ec-0000022d> <1448204614760> <[severity-value: 8] [rid: 0] [partition-id: 0] [partition-name: DOMAIN] > <BEA-000337> <[STUCK] ExecuteThread: '4' for queue: 'weblogic.kernel.Default (self-tuning)' has been busy for "686" seconds working on the request "Http Request Information: weblogic.servlet.internal.ServletRequestImpl@575083fd[GET /StuckThreadServlet/stuckthreadservlet]
", which is more than the configured time (StuckThreadMaxTime) of "600" seconds in "server-failure-trigger". Stack trace:
        java.lang.Thread.sleep(Native Method)
        nl.amis.smeetsm.StuckThreadServlet.doGet(StuckThreadServlet.java:27)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:790)

Causes

I've not talked about solutions to stuck thread problems. In order to provide suggestions for solutions, you should first look at common causes. Stuck threads can be caused by various issues and there is no single solution which works in every case. Some things I often see are connection problems; a request is send somewhere and a response is expected, but that response never comes and a timeout parameter has not been set (if a timeout has been set, the connection times out). Load balancers, firewalls or bad application programming can cause this. This can occur with most requests which use a connection such as HTTP and JDBC requests. Stuck threads can also be a symptom of memory shortage. If the server starts swapping memory to disk, it can slow down to such an amount that the stuck thread max wait time is reached for actions which can usually be performed within a period before the timeout is reached. Also memory shortage can cause high CPU due to constant garbage collection in a JVM causing a a drop in performance which can lead to stuck threads.

Dealing with stuck threads automatically

Dealing with stuck threads can be done automatically as stated;
I'm not counting 'restarting the server' as dealing with the issue. You're often better off analyzing what is wrong and fixing it instead of configuring automatic stuck thread handling.

JVMD

JVMD, part of Oracle Enterprise Manager Weblogic Management Pack can also be used to analyze stuck threads. Not all customers / operations departments allow developers to access Oracle Enterprise Manager and not everywhere Weblogic Management Pack is available. The tools described in this blog article can be used in such a case.

Java Mission Control

I have not looked at Java Mission Control in this article. Since Oracle JDK 7 Update 40 it is bundled with the JDK. It offers features like 'flight recorder' to do offline trend analyzes (something which JConsole for example does not provide) and allows detection of memory leaks. When analyzing a heap dump, finding memory leaks is far more difficult; you want to look at differences in memory usage over time and not at a fixed moment.

References

Overview monitoring tools Oracle JRockit
http://javaoraclesoa.blogspot.nl/2012/09/overview-monitoring-tools-oracle-jrockit.html

Java Mission Control
http://www.oracle.com/technetwork/java/javaseproducts/mission-control/java-mission-control-1998576.html

JVMD
https://blogs.oracle.com/oem/entry/quickly_diagnose_the_root_cause1

Automatic handling of stuck threads
https://community.oracle.com/thread/1983700

Memory Analyzer Tool
https://eclipse.org/mat/

ThreadLogic
https://java.net/projects/threadlogic

Microsoft Sysinternals Process Explorer
https://technet.microsoft.com/en-us/sysinternals/processexplorer.aspx

A first look at Splunk. Monitor Oracle SOA Suite service response times

$
0
0
Measuring performance of services can be done in various ways. In this blog I will describe a method of measuring Oracle SOA service response times with Splunk a popular monitoring tool. In order to monitor service response times with Splunk, Splunk needs to obtain its data from somewhere. In this example I'll use the HTTP access log which I expand with a time-taken field. Disclaimer; my experience with Splunk is something like 2 hours. This might also be an indication of what can quickly be achieved with Splunk with little knowledge.



Making service response times available

log_policy

At first I thought about using the OWSM policy oracle/log_policy. This policy can be applied to an endpoint. The policy logs request and response messages. There is however not (without alteration of the policy) a way to correlate the request with the response message. See the image below. An ECID is logged, but the ECID can differ for a request and response. The ECID can also be the same for different requests in a call chain. Several HTTP or SOAP headers could potentially be used for this, but they have to be present in the request and in the response. This can require some work, especially if you want to add them in the request, since all consumers need to use these headers.


access.log

The access.log file stores by default some data on HTTP requests such as timestamp, HTTP status code, url and the size of the request. This can easily be expanded with the time which is required to process a request. You can configure this from the WebLogic Console. Go to your server, Logging, HTTP and click the Advanced button. Here you can add time-taken as a field to log in the Extended Logging Format Fields.



Please mind that the access.log file is buffered. See here on how you can change the buffering behavior. Your results will thus not immediately be available in Splunk. A single request will not show up until the access.log has exceeded the buffer size.

Processing the response times in Splunk

In order to make service response times available in Splunk, you first have to tell it how it can obtain the data. Splunk can use a lot of different sources of data. The TCP/UDP and HTTP options open up a port on the local machine, which is then monitored. This port has to be available. Monitoring the WebLogic port is thus not an option since WebLogic has claimed it already.


In this case I have used Files & Directories and pointed it to the location where the access.log file was stored. In my case <DOMAINDIR>\servers\<SERVERDIR>\logs\access.log.


After you have selected your source, you can query the file. In order to allow querying on specific fields, it is useful to extract them from the log line. Splunk makes it easy to create regular expressions for this by simply selecting the fields.



After you have done this, you can use a query like

| eval series=url | search url="/soa-infra/*_ep" | xyseries _time series time_taken | makecontinuous _time

To create a nice visualization, I create a series based on the url. Next I only want specific HTTP requests belonging to interesting services. I create an xyseries based on these values and make the time part continuous. The result of this is visible below;


Based on these results you can of course create alerts to check against SLA's.

A query to trigger an alert can be for example;

| search time_taken > 1 | search url="/soa-infra/services/default/HelloWorld/helloworldprocess_client_ep"



Alerts can be executed once in a while or continuously.

Finally

The method used does not allow you to measure service response times of services using other protocols as HTTP(S). Direct invocations / local optimized / SOA-Direct requests for example will not be logged or JMS request/reply patterns. Alternatives (described below) such as IWS and the DMS Spy servlet do allow you to monitor these services. What does appear in the access.log is if you stay on the same host but tell a composite not to use local invocation on a binding. This can be done by setting two properties in the reference binding in the composite.xml file. These properties are also useful when running on a cluster to allow load balancing of requests.


Alternatives

There are of course many alternatives for monitoring performance and alerting. For (performance) monitoring of service response times you can look at the DMS Spy servlet or use Integration Workload Statistics (IWS). Other Oracle options are RUEI and BTM. For performance testing there are many tools available such as SmartBear SOAP-UI or Apache JMeter. For alerting, there are also several options available. You can use Service Bus default dashboards or for example configure alerts in the Enterprise Manager. It depends on your requirements which solution is the best fit. A more recent solution provided by Oracle is the Application Performance Monitoring Cloud Service which is definitely something worth to take a look at.

Dramatically reduce SOA Suite 11g startup time by cleaning the MDS

$
0
0
SOA Suite can sometimes be a bit slow to start. This is especially the case when there are a lot of composites to load. Customers using different versions of composites can benefit from undeploying non-default revisions of processes which do not have any running instances (see for example here). Undeployment in most cases is an asynchronous process which does not give feedback. It can partially fail without you noticing (apparently not an atomic transaction). This sometimes leaves composite remains; parts of the composite which are still loaded at startup but are not visible from the Enterprise Manager. Removing these can dramatically reduce server startup time. Especially in an environment which has been used for some time and environments with many versions of composites. Reducing the time required to get the soa-infra application fully up and running is of course mostly relevant for 11g SOA installations and less for 12.1.3 (which does some lazy loading) and 12.2.1 (which supports parallel deployments, also during server start-up).

In this article I'll demonstrate how these left-over composite parts can be identified and removed on an 11.1.1.7 SOA environment. First try this procedure on a development or test environment before executing it in production! This method is not supported by Oracle (or me) in any way and using it is entirely at your own risk. If something breaks, tell me so I can update this article. Thanks!

Please mind that these actions, although they help with the start time and memory usage of your SOA environment, have less impact on run-time performance than for example purging of instances and reducing the amount of deployed composites (or tweaking datasources, soa-infra database, JVM, etc).

SOA Suite can be up quickly!

Introduction

What is a composite in the MDS?

WebLogic Server first brings up its Managed SOA server. After this managed server is up and RUNNING, the soa-infra application is started. After the soa-infra application is started, the composites are loaded from the MDS and put in memory.

There is a folder called 'deployed-composites' in the root of the soa-infra MDS. If you are an experienced Oracle SOA developer or administrator, you have probably encountered this folder before. For example when the soa-infra application does not want to start, you can remove an entry in deployed-composites.xml which is in the deployed-composites folder (see here. you can even do this offline (here)). A composite however is not only an entry in the deployed-composites.xml file. There is also a separate folder which contains the files of which the composite consists. These are mostly XML and JAR files.

Cleaning

Entries in the deployed-composites.xml file are visible in the Enterprise Manager. Entries which are not in the deployed-composites.xml file but do have a folder in the MDS, are not visible, but are loaded at server start. This increases startup time and memory usage.

The below procedure can be performed on a running SOA server. Do mind though that the effects will only be visible after a server restart. Please mind to clean the WebLogic cache folder after a server shutdown and before a server start (user_projects/domains/yourdomain/servers/yourserver/tmp) to make sure you start fresh. The first time after cleaning the cache folder, the server start might take a while because it needs to fetch everything again from the MDS. The second time it will be faster.

Deployed-composites

First create an MDS export. This is described here. When you have this export, you can extract it and execute the following Python 2.7 script (don't forget to update the paths for your environment and the SOA server name). What the script does is look at the deployed-composites.xml file and identify all entries in the default partition of the deployed-composites folder which do not have an entry in deployed-composites.xml. Next it creates a WLST script to remove these entries. The WLST script which is created, should have a 'connect' statement at the top and should be executed against your SOA (managed) server. You can also execute it remotely. Make sure you pick the correct wlst.sh or wlst.cmd to start a WLST interpreter which has deleteMetadata available. deleteMetadata was the only WLST command I found which allows deleting documents outside the 'apps' MDS folder.

 import os   
import xml.etree.ElementTree as ET
import xml.dom.minidom as minidom
import sys,re
import argparse

deployed_composites="D:\\tmp\\soa-infra_metadata\\deployed-composites\\deployed-composites.xml"

#read a file and return a ElementTree
def get_tree_from_xmlfile(filename):
if os.path.isfile(filename):
tree = ET.parse(filename)
return tree
else:
raise Exception('Error opening '+filename)

def get_deployedcomposites(deployed_composites):
deployed_composites_root = deployed_composites.getroot()
return deployed_composites_root

deployed_composites_el = get_tree_from_xmlfile(deployed_composites)
deployed_composites_root = deployed_composites_el.getroot()

list = []
for rev in deployed_composites_root.findall('composite-series/composite-revision'):
list.append(rev.attrib.get('dn').replace('!','_rev'))
for dir in os.listdir('D:\\tmp\\soa-infra_metadata\\deployed-composites\\default'):
if 'default/'+dir not in list:
print "deleteMetadata(application='soa-infra',server='soa_server',docs='/deployed-composites/default/"+dir+"/**')"

Directories

I did not find a way to delete directories outside the apps folder by using WLST commands. Luckily the Oracle A-Team also realized this and wrote some custom Java code to address this issue. See here. The blog article offers a project which you can download which contains sample code on how to programatically do interesting things to the MDS. For this specific use-case I updated the code to look for directories which do not contain documents. These directories recursively removed (that's why I have to catch a NullPointerException. the directory could already be gone). Of course first check if this code works for you before actually deleting directories. I only updated the work method in the sample code provided by Oracle which you can download here.

 public static void work()  
{
try
{
MDSInstance mdsInstance = null;
if (true)
{
mdsInstance = MDSUtils.initializeDBStore("soa_mds_user",
"soa_mds_pass",
"jdbc:oracle:thin:@hostname:port/sid",
"soa-infra",
MDS_CONNECTION_NAME);
}

Boolean foundDocument = false;
// Find a resource
if (true)
{
List<ResourceName> list = MDSUtils.findResource(mdsInstance, "/deployed-composites/", false);
List<ResourceName> listinner = null;
List<String> path = new ArrayList<String>();
List<Boolean> type = new ArrayList<Boolean>();
System.out.println("List: (" + list.size() + " element(s))");
for (ResourceName rn : list) {
path.add(rn.getAbsoluteName());
type.add(rn.isPackageName());
}

ResourceName rn = null;

for (int i = 0; i < list.size() ; i++) {
rn = list.get(i);
foundDocument = false;
if (rn.isPackageName()) {
for (int j = 0 ; j<path.size();j++ ) {
if (path.get(j).startsWith(rn.getAbsoluteName())) {
if (!type.get(j)) {
foundDocument = true;
break;
}
}
}
if (!foundDocument) {
try {
MDSUtils.deleteResource(mdsInstance, rn);
} catch (Exception e) {
System.out.print("");
}
System.out.println("Deleted: "+rn.getAbsoluteName());
}
}
}
}
System.out.println("Done");
}
catch (Exception e)
{
e.printStackTrace();
}
}

Be careful with this code if you use other things inside the MDS than documents and packages (folders) such as customizations.

The MDS schema

Everything which was present in the MDS once, but has been deleted, remains in the MDS database. You can confirm this by looking at the SOA_MDS schema and browse for items you thought had been deleted in the MDS_PATHS table. Deleted items can be identified by checking MDS_PATHS for entries which do not have a PATH_HIGH_CN which is null. See here. Deleted documents however are not loaded by the server during startup, but if you once had a lot of stuff in the MDS, the below procedure might be worthwhile since MDS queries will perform faster with less data.

Manually 'fiddling' with the data in the SOA_MDS tables is not recommended and dangerous since there are no foreign key constraints but there are references from other tables! (with column names which do not easily allow you to identify the links between data in the different tables). As a workaround, you can create an MDS export (this only takes the 'not-deleted' documents and folders), backup the SOA_MDS schema, truncate tables containing documents/folders (not the partitions and similarly important stuff!) and re-import the MDS export. You can also recreate the SOA_MDS schema completely with the RCU (Repository Creation Utility) before the import. This should provide you with a clean MDS. As indicated before, do test this procedure to make sure you have identified the correct SOA_MDS tables! There are also several other ways to tweak MDS performance. See here.

Simple IoT security system using Raspberry Pi 2B + Razberry + Fibaro Motion Sensor (FGMS-001)

$
0
0
In this article I'll describe how I created a simple home-brew burglar detection system to send me a mail when someone enters my house (so I can call the police). First my choice for the components is explained. Next how these components combine to achieve the functionality wanted. Based on this article you should be able to avoid certain issues I encountered and have a nice suggestion for a simple relatively cheap burglar detection system.

My purpose was to create a simple security system based on a Raspberry Pi. A Raspberry Pi is a tiny computer which can run a Debian like Linux distribution called Rasbian. I wanted to avoid going to low-level into sensor configuration and programming. That's why I decided early on to use an extension board and not directly attach the sensors to the Raspberry Pi. I decided to go for the Razberry. I also looked at the GrovePi and Arduino. Both are still too low-level for my tastes though. The Razberry is an extension board for the Raspberry which provides a Z-Wave controller chip. Z-Wave is a wireless protocol popular in the area of home automation. This was an attractive option since if in the future I would want to use additional sensors or maybe even use a commercial home automation system, I could very well get compatibility out of the box. For the sensor, I decided on the Fibaro FGMS-001 Motion Sensor. This is a multi-sensor which allows detection of motion, temperature, luminiscence and vibrations. It can even detect tampering and earthquakes (which is relevant since I live in the Dutch city of Groningen).

Z-Wave.Me (the company providing the Razberry), provides software for the Razberry called Z-Way. There are several alternatives. One of the most popular seems to be Domoticz which is provided with OpenZWave. Domoticz allows quite extensive home automation but I was having difficulty getting the sensor to work with OpenZWave so I decided to go with Z-Way. Z-Way supported the sensor out of the box. With the Z-Way server however it was difficult to automate actions based on sensor values. How I solved this is also described in this article.


How to get the environment up

I started out with a Raspberry which had Rasbian pre-installed. Installing Z-Way was easy. After the installation was completed, I went to https://find.z-wave.me and it indicated my Z-Way server. This allowed me to set the admin password and login. I could access the Z-Way web interface from http://192.168.178.10:8083/smarthome. The expert interface was available at http://192.168.178.10:8083/expert and the API at http://192.168.178.10:8083/ZWaveAPI/Run.

Next I had to add the sensor. The Z-Wave controller and the sensor both need to get to know each other. this is called inclusion. The Z-Way software had a handy wizard to install the Fibaro sensor I bought. The sensor could be opened and the button inside pressed three times. the eye of the sensor would turn blue in order to indicate it was ready for inclusion or exclusion. After the sensor was known to the Z-Wave controller and the Z-Way software, I could start looking at sensor data.




So far pretty straightforward and no coding needed (the installation of the Z-Way software does not count). The motion detection sensor worked nicely. Now on to the not so straightforward part

Send me a mail when someone enters the room

Calling JavaScript from Z-Way

Automating actions based on sensor value changes was not straightforward. Under configuration, there are several apps in Z-Way. One of the apps allows you to load a custom JavaScript file. This file has to be present in your automation folder (/opt/z-way-server/automation) on your Raspberry. The JavaScript file is loaded when the server is started.


In order to debug this Javascript, you can look at /var/log/z-way-server.log on the Raspberry. You can also look at the Event log in the smarthome interface. It helps to have debugPrint statements in your JavaScript code.


When the server is starting, the JavaScript file is loaded. The zway specific classes are not always immediately available yet though. You need the 'zway' class to be able to access devices. You need to access the device if you want to act on sensor value changes (bind functions).The solution for this I found here and is as follows:

 this.bindFunc1 = function (zwayName) {  
if (zwayName != "zway")
return; // you want to bind to default zway instance

var devices = global.ZWave[zwayName].zway.devices;

//sensor specific code
};

// process all active bindings
if (global.ZWave) {
global.ZWave().forEach(this.bindFunc1);
}

// and listen for future ones
global.controller.on("ZWave.register", this.bindFunc1);

Call a Python script from JavaScript

Next challenge was calling a Python script from the JavaScript code. Why Python and not JavaScript? Well, I wanted to write files to the file system, send mails and do other things which might be not straightforward in the Google V8 engine which Z-Way uses. Python allows easy independent testing and debugging of a script without having to fiddle with the V8 debugger.

In /opt/z-way-server/automation there is a file called .syscommands. In this files you have to add the commands which are allowed to be executed from JavaScript. In my case I added lines like:

/usr/bin/python /opt/z-way-server/automation/trigger.py
/usr/bin/python /opt/z-way-server/automation/savemeasure.py

The trigger.py script I used for burglar detection and the savemeasure.py I used for temperature, luminescence and battery measures.

In the JavaScript code I could now call these scripts like:

system('/usr/bin/python /opt/z-way-server/automation/trigger.py');

I could also add additional parameters like

system('/usr/bin/python /opt/z-way-server/automation/savemeasure.py' ,'Temperature',this.value);

Find the sensors

It was nice I could start a JavaScript file and execute Python scripts from it. What I wanted however was to do something when something happened. In order to achieve this, I needed to access my devices.

First I needed to get to obtain information on devices. Z-Way provides a nice API. http://192.168.178.10:8083/ZWaveAPI/Run/devices showed me all the devices. I could also browse the expert interface at http://192.168.178.10:8083/expert (it provided me with more information and control than the smarthome interface). The below locations of the sensors are of course environment specific. It does give you some idea though where to look.

Motion sensor

To access the motion sensor value I could go to
http://192.168.178.10:8083/ZWaveAPI/Run.devices[3].instances[0].commandClasses[48].data[1].level.value

Instead of commandClasses[48] you can also go to SensorBinary
http://192.168.178.10:8083/ZWaveAPI/Run.devices[3].instances[0].SensorBinary.data[1].level.value
(which gave 'false' when not triggered)

The available command classes are visible in the expert interface


Battery

The battery was a separate commandClass. The value could be obtained from:
http://192.168.178.10:8083/ZWaveAPI/Run.devices[3].instances[0].Battery.data.last.value

Other sensors

The device contained multiple sensors, the other sensors were available under commandClass 49; sensorMultilevel.


Temperature was available at
http://192.168.178.10:8083/ZWaveAPI/Run.devices[3].instances[0].SensorMultilevel.data[1].val

Luminescence was available at
http://192.168.178.10:8083/ZWaveAPI/Run.devices[3].instances[0].SensorMultilevel.data[3].val

Trigger on change

My JavaScript code ended up looking like:

 this.bindFunc1 = function (zwayName) {  
if (zwayName != "zway")
return; // you want to bind to default zway instance

var devices = global.ZWave[zwayName].zway.devices;

zway.devices[3].instances[0].commandClasses[48].data[1].level.bind(function() {
if (this.value == true)
debugPrint("Executing trigger");
system('/usr/bin/python /opt/z-way-server/automation/trigger.py');
});

zway.devices[3].instances[0].commandClasses[49].data[1].val.bind(function() {
debugPrint("Saving measure");
system('/usr/bin/python /opt/z-way-server/automation/savemeasure.py','Temperature',this.value);
});

zway.devices[3].instances[0].commandClasses[49].data[3].val.bind(function() {
debugPrint("Saving measure");
system('/usr/bin/python /opt/z-way-server/automation/savemeasure.py','Luminescence',this.value);
});

zway.devices[3].instances[0].Battery.data.last.bind(function() {
debugPrint("Saving measure");
system('/usr/bin/python /opt/z-way-server/automation/savemeasure.py','Battery',this.value);
});

};
// process all active bindings
if (global.ZWave) {
global.ZWave().forEach(this.bindFunc1);
}

// and listen for future ones
global.controller.on("ZWave.register", this.bindFunc1);

Send a mail and saving measures

I found that making Z-Way API calls from the Python code via HTTP did not work well. My Z-Way server CPU regularly got to 100% and did not respond anymore. It is better to do the triggering from JavaScript and pass values along to the Python script (see savemeasure.py below) to avoid this issue.

trigger.py

My trigger.py script looked like ('apt-get install python' first of course to get Python on your Raspberry):

 import time  
import datetime

ts = time.time()
st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')

def send_email(user, pwd, recipient, subject, body):
import smtplib

gmail_user = user
gmail_pwd = pwd
FROM = user
TO = recipient if type(recipient) is list else [recipient]
SUBJECT = subject
TEXT = body

# Prepare actual message
message = """\From: %s\nTo: %s\nSubject: %s\n\n%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
try:
server = smtplib.SMTP("smtp.gmail.com", 587)
server.ehlo()
server.starttls()
server.login(gmail_user, gmail_pwd)
server.sendmail(FROM, TO, message)
server.close()
print 'successfully sent the mail'
except:
print "failed to send mail"

send_email('xxx@gmail.com','pass','target@mail.nl','Intrusion detected','Intrusion detected at '+st)

f = open('/opt/z-way-server/automation/intrusions.log', 'a')
f.write(st+"\n")
f.close()

Of course do not forget to allow 'less secure apps' to access to your GMail account if you use one (see here) or implement mail-server authentication in your script which is considered secure by Google. The result was I got a lot of mails so I turned the mails off but will enable them when I'm out on vacation for example. 

savemeasure.py

My save measure.py script looked as followed:

 import time  
import datetime
import sys

ts = time.time()
st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')

f = open('/opt/z-way-server/automation/measure.log', 'a')
f.write(st+"\t"+sys.argv[1]+"\t"+sys.argv[2]+"\n")
f.close()

Thus I end up here with 2 log files. One for intrusions; intrusions.log (motion detector gets triggered) and the other for sensor values; measure.log.

Finally

It took me about 2 days to get everything working. I encountered several issues. With this article I hope you will be able to get started faster and make the right choices in hard- and software for your home automation system. It was fun though to look into this and get it working.

Maybe in the future I'll add a button to turn it on and off (and make it really cool!). I'm using the Z-Wave protocol, it should not be difficult to find something to make this possible. Also it would be nice to do something with the earthquake detection and tamper detection.

The next steps are of course to process the sensor data. Stay tuned!

Service implementation patterns and performance

$
0
0
Performance in service oriented environments is often an issue. This is usually caused by a combination of infrastructure, configuration and service efficiency. In this blog article I provide several suggestions to improve performance by using patterns in service implementations. The patterns are described globally since implementations can differ across specific use cases. Also I provide some suggestions on things to consider when implementing such a pattern. They are technology independent however the technology does of course play a role in the implementation options you have. This blog article was inspired by a session at AMIS by Lucas Jellema and additionally flavored by personal experience.


Patterns

Asynchronous services

Suppose a synchronous call is made and the system takes a while to process the information. In the mean time the end-user might be waiting for the request to be completed while the end-user might not (immediately) be interested in the response. Why not make the process asynchronous?

Making a process asynchronous has some drawbacks. The result of the processing of the request will not be available immediately in the front- and back-end so you cannot use this information yet and often you do not know when (and if) the information will become available. If something goes wrong during processing, who will be informed to take measures? (How) does the back-end inform the front-end when it's done? You can think of server push mechanisms.

Claim-check

This is of course a famous pattern. The claim-check pattern is often used when large objects are used such as large binary files, which you do not want to pull through your entire middleware layer. Often the data is labelled and saved somewhere. The middleware can get a reference to the data. This reference can be send to the place it needs to be and the data can be fetched and processed there.

Set processing

Service calls are expensive since they often traverse several layers of hard- and software. For example I need to fetch data on a lot of persons and I have a service to fetch me person information. I can call this service for every individual person. This can mean a Service Bus instance, a SOA composite instance, a SOA component instance,a database adapter instance, a database connection and fetching of a single item all the way back (not even talking about hard- and software load-balancers). Every instance and connection (e.g. HTTP, database) takes some time. If you can minimize the instances and connections, you obviously can gain a lot of performance. How to do this is more easy than it might seem. Just fetch more than one person in a single request.

Caching

If fetching certain pieces of information takes a lot of time, it might be worthwhile not fetch it every time you need it from the source but to use a cache. Of course you need to think about (among other things) how up to date the data in the cache needs to be, how/when you are going to update it and cache consistency. Also you only want to put stuff in the cache of which you know it is very likely is is going to be retrieved again in the near future. This might require predictive analyses. You can preload a cache or add data the moment it is fetched for the first time.

Caching can be done at different layers, in the front-end, at the service layer or at the database layer. You can even cache service requests in a proxy server.

Often data from different sources needs to be integrated. This can be done efficiently in a database. In such a case you can consider implementing an Operational Data Store. This is also a nice place to do some caching.

Parallel processing

If you are serially processing data and you have cores/threads/connections to spare, you might consider running certain processing steps in parallel. There is often an optimum in the performance when increasing the number of parallel threads (at first processing time decreases, after the optimum has been reached, processing time increases). You should do some measures on this in order to determine this optimum.

If a system has to interface with another system which does not support concurrency, you can use throttling mechanisms (pick up a message from the queue every few seconds) to spread load and avoid parallel requests. Do not forget the effects of having a clustered environment here.

If a service is sometimes unavailable, a retry might solve the issue. If however the system is unstable due to high load, a retry might increase the load further and make the system more unstable, causing more errors. This can cause a snowball effect since all the errors caused might go into retries further increasing the load on the system. If you throttle a queue near the back-end system causing the issue and put the normal requests and the retry requests on the same queue, you can avoid this. This probably requires custom fault-handling though.

Quality of service

You might want to avoid your background processing (e.g. a batch) to interfere with your front-end requests. There are several ways to help achieve this. First you can use queues with priority messages. The batch requests can have a lower priority than front-end requests. You can also split the hardware. Have separate servers to do the batch-processing and other servers doing the front-end serving. Whether this is a viable option depends on the effort required to create new servers to do the batch on.

Service granularity and layering

Usually services in a SOA landscape are layered (e.g. data services, integration services, business services, presentation services, utility services, ...). A service call usually has overhead (e.g. different hardware layers are crossed, cost of instance creation). This layering increases the amount of overhead which is suffered because it increases the amount of service calls which are made. If however you have only a few services which provide a lot of functionality, you suffer in terms of re-use and flexibility. You should take the number of required service calls for a specific piece of functionality into account when thinking about your service granularity and layering. When performance is important, it might help to create a single service to provide the functionality of a couple of services in order to reduce the service instance creation and communication overhead. Also think about where you join your data. A database is quite efficient for those kind of things. You might consider the previously mentioned Operational Data Store and have your services fetch data from there.

Summary

If you want to keep performance in mind when creating services, there are several patterns you can use which can help you. Most are based on;
  • Reduce superfluous data fetching. Think about efficient caching (and cache maintenance). Think about implementing a claim-check pattern.
  • Reduce the number of service calls. Think about service layering, granularity and fetching of data sets instead of single pieces of data.
  • When will the data be needed? Think about asynchronous processing (and how you know when it's done).
  • Optimally use your resources. Think about parallel processing and efficient load-balancing.
  • Keep the user experience in mind. Think about priority of message-processing (batches often have lower priority).
Of course this article does not give you a complete list of patterns. They are however the patterns I suggest you at least consider when performance becomes an issue. This of course next to technical optimizations on infrastructure, configuration and service level.

Asynchronous interaction in Oracle BPEL and BPM. WS-Addressing and Correlation sets

$
0
0
There are different ways to achieve asynchronous interaction in Oracle SOA Suite. In this blog article, I'll explain some differences between WS-Addressing and using correlation sets (in BPEL but also mostly valid for BPM). I'll cover topics like how to put the Service Bus between calls, possible integration patterns and technical challenges.

I will also shortly describe recovery options. You can of course depend on the fault management framework. This framework however does not catch for example a BPEL Assign activity gone wrong or a failed transformation. Developer defined error handling can sometimes leave holes if not thoroughly checked. If a process which should have performed a callback, terminates because of unexpected reasons, you might be able to manually perform recovery actions to achieve the same result as when the process was successful. This usually implies manually executing a callback to a calling service. Depending on your choice of implementation for asynchronous interaction, this callback can be easy or hard.


WS-Addressing

The below part describes a WS-Addressing implementation based on BPEL templates. There are alternatives possible (requiring more manual work) such as using the OWSM WS-Addressing policy and explicitly defining a callback port. This has slightly different characteristics (benefits, drawbacks) which can be abstracted from the below description. BPM has similar characteristics but also slightly different templates.

When creating a BPEL process, you get several choices for templates to base a new process on. The Synchronous BPEL template creates a port which contains a reply (output message) in the WSDL. When you want to reply, you can use the 'Reply' activity in your BPEL process. The activity is present when opening your BPEL process after generation by the template, but you can use it in other locations, such as for example in exception handlers to reply with a SOAP fault. If you want to call a synchronous service, you only need a single 'Invoke' activity.

The output message is not created in the WSDL when using the One Way or Asynchronous templates. Also when sending an asynchronous 'reply', you have to use the Invoke activity in your BPEL process instead of the 'Reply' activity. One Way BPEL process and Asynchronous BPEL process templates are quite similar. The Asynchronous template creates a callback port and message. The 'Invoke' activity to actually do the asynchronous callback is already present in the BPEL process after it has been generated based on the template. The One Way template does not create a callback port in the WSDL and callback invoke in the BPEL process. If you want to call an Asynchronous service and want to do something with an asynchronous callback, you should first use an 'Invoke' activity to call the service and then wait with a 'Receive' activity for the callback.

For all templates, the bindings and service entry in the WSDL (to make it a concrete WSDL for an exposed service) are generated upon deployment of the process based on information from the composite.xml file (<binding. tags).

The callback port of an asynchronous BPEL process is visible in the composite.xml file as followed;


This callback tag however does not expose a service in the normal WSDL, but a WSDL with the callback URL can be obtained. When a request is send to a service, the WS-Addressing headers contain a callback URL in the wsa:ReplyTo/wsa:Address field. This URL can be appended by ?WSDL to obtain a WSDL which contains the actual exposed services.


The SOA infrastructure uses WS-Addressing headers to match the 'Invoke' message from the called service with the Receive activity which should be present in the calling service. These headers are not visible by default. If you want to see them, you can use the JDeveloper HTTP analyzer as a proxy server (the calling process can configure a reference to use a proxy server). You have to mind though to disable local optimization for the calls, else you won't see requests coming through the analyzer. You can do that by adding the below two properties to the reference (see here).

<property name="oracle.webservices.local.optimization">false</property>
<property name="oracle.soa.local.optimization.force">false</property>

Even though WS-Addressing is used, the WS-Addressing OWSM policy is not attached to the service. The WS-Addressing headers can look like for example


Since the callback message send from the called service is not a reference/service, you cannot tell the SOA Infrastructure to send the message through a proxy server (HTTP analyzer). You can however specify in JDeveloper to attach the log_policy to the callback port. This gives you the request and reply of the called service. The messages are stored in DOMAIN_HOME/servers/server_name/logs/owsm/msglogging. Using this log policy also allows you to recover messages later.

Recovery in case the callback does not come

Manual recovery is not straightforward. You need the request headers in order to construct a callback message and it helps if you have a successful callback message as a sample on how to construct the callback headers. Obtaining the request headers can be done in several ways. You can use the log OWSM policy or a Service Bus Log or Alert action. From within BPEL or BPM it is more difficult to obtain the complete set of headers. You can obtain some headers from properties on the Receive (see here for example something to mind when using the wsa.replytoaddress property) but these properties are header specific (not complete) and you can save specific SOAP header fields to variables at a Receive, but these are also specific. The method described by Peter van Nes here seems to allow you control the outgoing WS-Addressing headers and (a similar method) might allow you to also gather the incoming WS-Addressing headers. However, again, this method is per header element. You might be allowed to leave some headers out in order for the callback to still arrive at the correct instance and determine some of the headers from the Enterprise Manager or soainfra database tables but I haven't investigated this further. Once you've obtained the required headers and constructed a suitable reply message, you can use your favorite tool to fire the request at the server.

Service Bus between calls

In case your company uses an architecture pattern which requires requests to go through the Service Bus, you might have a challenge with WS-Addressing. The callback is a direct call based on the callback address in the request. If you want to go through the Service Bus, you have to do some tricks. You can use the SOA-Direct transport (see some tips from Oracle on this here) and use a workaround like described here. Here the callback data is stored somewhere else in the WS-Addressing headers and later overwritten and used by the Service Bus on the way back to perform a proper callback. SOA-Direct however also has some drawbacks. SOA-Direct are blocking RMI calls which do not allow setting a timeout on the request (and thus for example can cause stuck threads). SOA-Direct also provides some challenges when working on a cluster and it causes a direct dependency between caller and called service requiring measures to be taken to achieve a deployment order of your composites (which can cause dependency loops, etc). It can also cause server start-up issues. I have not looked at recovery options for using SOA-Direct. Since it is based on RMI calls, you most likely will have to write Java code to resume a failed process. For plain WS-Addressing correlation I have not found an easy way without using SOA direct to have the callback go through the Service Bus thus you will most likely end up with the second pattern in the below image.


WS addressing in summary

WS Addressing benefits
  • Works out of the box. little implementation effort required.
  • Works in the JDeveloper integrated WebLogic server.
  • Is a generally accepted and widely acknowledged standard (see here). Also allows interoperability with several other web service providers.
WS Addressing drawbacks
  • Possible integration patterns are limited. WS-Addressing is SOAP specific and always one caller and one called service. Multiple callbacks to the same process are not possible and integrating calls from other sources (e.g. a file which has been put on a share) is also not straightforward.
  • It can be hard to propagate WS-Addressing headers through a chain of (e.g. composite) services.
  • The callback when using SOAP over HTTP is always direct (the caller sends a callback port with the request in the WS-A headers). difficult to put a Service Bus in between unless using SOA-Direct (which has other drawbacks).
  • Manual recovery in case a callback does not come, is possible, but requires determining the request headers. With SOA-Direct this becomes harder.
  • The callback cannot arrive before the process which needs to do the callback has been called since the WS-Addressing headers have not been determined yet. if for example you want to respond to events which have arrived before your process has been started, WS-Addressing is not the way to go.
  • Correlation is technical and cannot directly be based on functional data. It is not straightforward (or usual) to let the callback arrive at a different process.
Correlation

Instead of using the out of the box WS-Addressing feature, Oracle SOA Suite offers another mechanism to link messages together in an asynchronous flow, namely correlation. Correlation can be used in BPM and in BPEL. Correlation sets are not so hard and very powerful! You can for example read the following article to gain a better understanding. I borrowed the below image from that blog because it nicely illustrates how the different parts you need to define for correlation to work, link together.


You first create a correlation set. The correlation set contains properties. These properties have property aliases. These aliases usually are XPath expressions on different messages which allow the SOA infrastructure to determine the value for the property for that specific message. If a message arrives which has the same property as the initialized correlation set in a process instance, the message is delivered at that process instance.

For example, the process gets started with a certain id. This id is defined as a property alias for the id property field in a correlation set. When receiving a message, this same correlation set is used but another alias for the property is used, namely an alias describing how the property can be determined from the received message. Because the property value of the process instance (based on the property alias of the message which started the process) and the property value of the received message (based on the property alias of the received message) evaluate to the same value, the message is delivered to that specific instance.

The power in this mechanism becomes more obvious when multiple events from diverse sources need to be orchestrated in a single process. You can think about making the receiving of a file part of your process or do asynchronous processing of items in a set and monitor/combine the results.

Recovery in case the callback does not come

Recovery in case a callback does not come is relatively easy. Correlation usually works based on a functional id and not on message headers so it is usually easier to construct a callback message. The callback message can be constructed based on the original request which could be determined from the audit logs. You can choose a construction such as with WS-Addressing with the implicit callback port defined in the composite, but it is easier to explicitly expose a callback port. This way you can even from the Enterprise Manager see where the callback should go to and use for example the test console to fire a request (this will most likely have preference with the operations department compared to using a separate tool).

Service Bus between calls

The scope of this part is a pattern in which Composite A calls Service Bus B, calls Composite B, calls Service Bus A, calls Composite A (all using SOAP calls).

There is one challenge when implementing such a pattern. Where should the callback go? At first, the callback URL can be present in the headers but when a Composite B calls Service Bus A, it overwrites the WS-Addressing headers and you loose this information unless you forward it in another way. If you hard-code the callback URL in Service Bus A, Composite B can only do callbacks to Composite A and you loose re-usability. If you are implementing a thin layer Service Bus in which the interface of the Service Bus is the same as the interface of the composite, you are not allowed to add extra fields to headers or message (to forward the callback URL in). A solution for this can be to provide a callback URL in the request message and use that callback URL to override the endpoint in the business service in the Service Bus. You can of course also use a custom SOAP header for this but having it in the message is a bit easier to implement and more visible in audit logging.

Obtaining the callback URL can easily be automated. You can use an X-Path expression like for example: concat(substring-before(ora:getCompositeURL(),'!'),'/ServiceCallback'). ServiceCallback of course depends on your specific callback URL. I'll explain a bit more about the ora:getCompositeURL function later.

ora:getCompositeURL obtains (as you can most likely guess) the composite URL. The substring part strips the version part so the callback goes to the default version and you are not dependent on a specific version. Correlation is process based and does not depend on process version for correlation to determine to which instance to go. The below image explains the process on how such a pattern can work.


By using the default version, you are not dependent on a specific version. You can remove them and still have working correlation as long as you have a valid default version which is capable of receiving the callback.

Correlation in summary

Drawbacks
  • Implementation requires some thought. Where do you correlate and how do you correlate?
  • Tight coupling between caller and called service requires effort to avoid. The called service should not explicitly call back to the caller with an hardcoded endpoint in order to allow re-use of the called service. A solution for this can be requiring the calling service to send a callback URL with the request or do integration not with HTTP calls but for example with JMS.
  • The request and callback are required to contain data which allows correlation
  • Correlation does not work on the JDeveloper embedded WebLogic server. You'll receive the below error
    [2015-12-17T07:04:40.500+01:00] [DefaultServer] [ERROR] [] [oracle.integration.platform.blocks.event.jms2.EdnBus12c] [tid: DaemonWorkThread: '1' of WorkManager: 'wm/SOAWorkManager'] [userId: <anonymous>] [ecid: c370fba3-1fcd-480f-8c27-7c4cd6a7a41e-0000010e,0:19] [APP: soa-infra] [partition-name: DOMAIN] [tenant-name: GLOBAL] Error occurred when saving event to JMS mapping to database: java.lang.ClassCastException: weblogic.jdbc.wrapper.PoolConnection_org_apache_derby_client_net_NetConnection cannot be cast to oracle.jdbc.OracleConnection
  • Correlation sets can be used on the SOA infrastructure but is not a generally acknowledged standard method for doing correlation (vendor specific).
Benefits
  • Very flexible. multiple correlation sets can be used in a single process. external events using diverse technologies can be correlated to running processes. complex integration patterns are possible.
  • Correlation does not depend on SOAP headers (technical data) but (most often) on functional data / message content
  • Recovery can be relatively easy (no need to determine request headers, only expected callback message)
  • The correlating events can arrive before the process is listening; they will be processed once the correlation set is initialized
  • SB between request and response can be used (it does not matter from where the callback comes)
Common

For both WS-Addressing and correlation, messages arrive in the soainfra database schema in the DLV_MESSAGE table (when using oneWayDeliveryPolicy async.persist). You can look at the state to determine if the message has been delivered (see here for a handy blog on states). You can also browse the error hospital in the Enterprise Manager to see and recover these messages. For more information on transaction semantics and asynchronous message processing (WS-A based), you can look here. DLV_SUBSCRIPTION is also an important table storing the open Receive activities. You can do many interesting queries on those tables such as demonstrated here to determine stuck processes.

In 11g undelivered messages are not automatically retried. You can schedule retries though. See here. If this is not scheduled, you are dependant on your operations department for monitoring these messages and taking action. Undelivered messages can go to the Exhausted state. When in this state, they are not automatically retried and you should reset them (to state undelivered) or abort them (what is more suitable for the specific case). See here. In 12c retries are scheduled by default.

Clustering

In a clustered environment you have to mind several environment properties to make sure your callback also is load-balanced. The getCompositeURL function and WS-Addressing headers use several properties to determine the callback URL. Some are based on soainfra settings and some on server settings.
  • First the Server URL configuration property value on the SOA Infrastructure Common Properties page is checked. 
  • If not specified, the FrontendHost and FrontendHTTPPort (or FrontendHTTPSPort if SSL is enabled) configuration property values from the cluster MBeans are checked. 
  • If not specified, the FrontendHost and FrontendHTTPPort (or FrontendHTTPSPort if SSL is enabled) configuration property values from the Oracle WebLogic Server MBeans are checked. 
  • If not specified, the DNS-resolved Inet address of localhost is used
If your operations department has followed the Enterprise Deployment Guide (for 11.1.1.6 see here for 12.1.3 see here), you have nothing to worry about though; these settings should already be correct.

Long running instances

As always, you want to avoid large numbers of long running processes. These cause difficulties in service life-cycle management and can cause performance issues and manual recovery can only be done for small numbers onless you want to automate that. It is recommended to put timers in all long running instances and do not wait forever (manual recovery can be time consuming). Also think about options for restarting your process in a new version if new functionality is added. Making long running processes short-running and have an event based architecture might also be a suitable solution.

Oracle Integration Cloud Service (ICS): A developer's first impression

$
0
0
Oracle provides ICS (Integration Cloud Service) as a simple means for citizen developers to do integrations in the cloud and between cloud and on-premises. On the Oracle Fusion Middleware Partner Community Forum I got a chance to get some hand-on experience with this product in one of the workshops. In this blog post I will describe some of my experiences. I'm not the target audience for this product since I am a technical developer and have different requirements compared to a citizen developer. I've not been prejudiced by reading the documentation ;)


I experimented with ICS on two use-cases. I wanted to proxy SOAP and REST requests. For the SOAP request I used a SOA-CS Helloworld web-service and for the REST request I used an Apiary mockservice. I will not go into basics too much such as creating a new Connection and using the Connection in an Integration since you can easily learn about those in other places.

ICS: Calling a SOAP service on SOA-CS

When you want to call a SOAP service which you have exposed on ICS, you require two sets of headers. The WS-Timestamp headers and the WSS-UserName token headers (with the password in plain text).




This is required even when you have not specified a security policy (currently username/password token and basic authentication are supported). When you don't provide them, you get Service Bus errors (as shown in the screenshot below) which indicates ICS is running on the Service Bus (in case you didn't know this yet, it is no secret). This was not required when directly calling the SOA-CS service.


The ICS console also showed me something had gone wrong


However I could not get more details from ICS on the error. SOAP-UI indicated the error was in the response pipeline. SOA-CS did not show any instances or any indication in the log files that the service had been called. Eventually it appeared (trial and error) I was sending basic authentication headers along with the message. I removed them and the request/response worked.


I did find out though that logging can only be done on so-called leaf nodes. I have not seen a way to log the entire message.


Even though in the instance tracking field it said that it would log the payload, I could not find it. Maybe because I was using Chrome? I did not try in IE, Firefox, Edge.


ICS: Calling a REST service on an Apiary Mock

I used Apiary to create a mock REST service which was quite easy.


Apiary allows easy creation and syntax checking of API blueprint and Swagger API descriptions. From these descriptions it creates mocks and generates simple client software in different languages. The mock server logs the request header and response header and body.


Apiary can do much more such as generating tests for your API based on the blueprint. Watch a short movie about it here. Apiary was a good fit to do some testing on ICS and the ICS REST Adapter.

You should mind that the base URL needs to be specified in your Connection and the path of the URL needs to be specified in your Integration.

You can obtain information about your exposed API from the information link next to the Integration.

The provided metadata gives you information on how you can call your API.


If you've done it the right way, you should get a response.


If not, you might get something like:


 Here you can of course see the base URL specified is incorrect.


In the second example I did not send a payload with the request. You will not get a clear message about this.

XPath in ICS

You can use several XPath expressions in ICS to do mappings. In order to access this functionality, you can do the following. First deactivate an Integration so you can edit it. Open the integration and edit your mapping.


Next click the target field in the Mapping column to the right and the following screen will pop up;


Here you have a GUI to allow you to graphically use XPath functions such as translate and concat. You can even do things like for-each and if statements. You can however not look at the generated XSLT or edit it directly. In order to do that you can however export an Integration, extract it with your favorite archiving tool and look at/edit the generated code. XSLTs are under processors, resourcegroup.



This gives you an XSLT like for example:


When you modify this, re-ZIP it and import it:


You can get the following error if the ZIP structure is not correct:


And the following error if an Integration with the same name is still active:


And the following messages if both above requirements are satisfied:



Thus you can edit your transformations outside the ICS web-interface. The process to get the transformation back in though requires some steps, which might not make this process suitable for quick iterative development.

General notes

Editing Connections and Integrations

As a developer I'm used to working quickly in an IDE and have access to everything. ICS feels limiting to me and difficult to debug. For getting the SOAP and REST integrations to work, I needed to look at the back-end and could not get much information from ICS. I even had some cases where the backend indicated a correct request and response, however ICS indicated something had gone wrong. Since ICS did not allow me access to logs or more technical debugging information, this was difficult to fix but I eventually managed by means of the proven 'trial and error' method.

You cannot edit an active Integration. This means that you will have to take measures in order to avoid downtime when a configuration changes. Maybe put something in front of ICS, make a copy of the Integration and route all traffic to the copy. Then bring the Integration down which you want to edit, make your changes, re-activate it and point back to the original endpoint. This is similar when working with a load-balancer and you need to update several nodes. The publish-subscribe pattern which is supported in ICS could also help with this.

When changing the Connection configuration in an Integration, you loose all mappings in the integration and you have to do them again (which will become troublesome when building complex Integrations). When changing a Connection, Integrations need to be reactivated (deactivated and activated) for the changes to become effective. This is of course not strange since a redeployment needs to be executed.

Limiting connectivity

Many of the cloud services have a preconfigured Oracle Traffic Director. You can configure this traffic director (which contains connectivity information) from the Compute cloud service. Below you can see a screenshot from some of the security rules for my SOA-CS database and JCS instance on which SOA-CS runs.


This is not available for ICS. If you want to limit who can access your API's, you should put something in front of it. Also the username/password token which you can put on your service is hardcoded / a single username/password. You might find this also limiting and would want to attach this to a true identity store.


You have the option however to upload certificates.


I noticed some difficulties with the Oracle Cloud SSO functionality when signed in to different identity domains in the same browser on different tabs.

Other things to look at

This is just a first tryout and by no means I completely understand the product yet. The product is quickly improving due to regular new releases. I have not looked at the API's yet or performance. Also I only tried two adapters and the strength of the product probably lies with the many other adapters which are available to integrate SaaS solutions. Also I have not looked at different integration patterns yet such as Publish and Subscribe. They might prove useful to achieve loose coupling in more complex integrations and might help to guarantee up-time, even when changing Integrations. I do think however that more complex integrations will be difficult in ICS due to lack of debugging and error handling functionality and the fact that a little change in a Connection requires you to re-do all mappings in an Integration unless you made an export before and are a bit creative with manually editing the files in the export. I have learned quite a lot about this product in a short time (about 1 day) so it is probably not too difficult to learn for a citizen developer.

My first NodeJS service

$
0
0
Microservices implemented in JavaScript running on NodeJS are becoming quite popular lately. In order to gain some experience with this, I created a little in memory NodeJS cache service. Of course statefulness complicates scalability, but if I would also have implemented a persistent store to avoid this, the scope of this blog article would have become too large. Please mind that my experience with NodeJS is limited to a NodeJS workshop from Lucas Jellema and a day of playing with NodeJS. This indicates it is quite easy to get started. In this blog I'll highlight some of the challenges I encountered and how I solved them. Also I'm shortly describing what Oracle is doing with NodeJS. Because the JavaScript world changes rapidly, you should also take into account the period between when this blog is written and when you are reading it; it will most likely quickly become outdated. You can download the code from GitHub here.


Choosing an IDE

In the Java world there are several popular IDE's such as JDeveloper, Eclipse, Netbeans, IntelliJ. For JavaScript, the IDE's I've heard most about from JavaScript developers (as a newby it helps to talk to people with experience) are Microsoft Visual Studio Code and Jetbrain's WebStorm. Netbeans also has JavaScript support and is the IDE of choice for Oracle JET development. I have not looked into Netbeans yet. I decided on Microsoft Visual Studio Code since WebStorm requires a paid license.


NodeJS package manager

The NodeJS package manager is npm. npm can install modules globally and locally. Supporting tools like 'mocha' for testing and 'typings' for TypeScript support are good candidates to install globally. Do keep track though of your globally installed modules since if you want to reproduce your environment somewhere else, these modules could be dependencies (especially in your build process). You can configure local dependencies in a package.json file. When you do a 'npm install', modules mentioned in that file are installed locally in the node_modules folder of your project. If you want to also update the package.json, you can do 'npm install --save'. This allows you to easily update versions of modules. When your node_modules directory is corrupt because you for example interrupted a module download, you can just remove the node_modules directory and rebuild it from the package.json file.

Code completion

As a spoiled modern developer, I need code completion! This especially helps a lot when you are unfamiliar with a language and want to explore what you can do with a specific object or how to use standard libraries/modules. JavaScript is not strongly typed. You need type information to provide code completion. Microsoft has provided the open source TypeScript to help with that.


TypeScript allows you to write .ts files which can be compiled to JavaScript. These .ts files can also be used to allow Visual Studio Code to provide code completion (even when writing JavaScript and not TypeScript). There is a large library of TypeScript definitions available for JavaScript modules. There are two tools I currently know of to easily import .ts files into your project. TSD and Typings. TSD is end of life (https://github.com/DefinitelyTyped/tsd/issues/269). In order to download .ts files for your modules, you can create a typings.json file which indicates the dependencies on TypeScript files. When you do a 'typings install', it will download these dependencies into your project in the 'typings' directory. When you want to add new dependencies, you can do a command like 'typings install node --save --ambient' to save the dependency to the typings.json file. TSD uses a tsd.json file which can be converted to a typings.json file with 'typings init --upgrade'. You can read more about how to set this up here.

Next to the tsd files, you need to provide Visual Studio Code with compiler options in a jsconfig.json file.


The result looks like:

Testing

I used Mocha to perform tests. Why Mocha? I heard about this from colleagues and found a lot of references to 'mocha' when reading about JavaScript testing.
There are a lot of other modules which help with testing. Mocha is installed globally. When executed in the root of your project, it looks for files in the test directory and executes them.

Below some sample test code


Below what happens when you run Mocha.


For testing as a true outside client, you can use Ready-API or for example Postman, Postman is a Chrome plugin.


Debugging

In order to debug your project and run NodeJS from Visual Studio Code, you need to provide a launch.json file in . vscode directory.


This file indicates which JavaScript file to run and where to attach the debugger. You can read about this in more detail here.

Some general observations

Single threaded

A NodeJS instance uses a single thread. Therefore, you should strife to have all your code non-blocking. Most functions support asynchronous interaction. This allows you to perform an action and wait for an asynchronous callback. While 'waiting' for the callback, other actions can be performed and other callbacks can be received. This event driven / asynchronous way of programming is something you have to get used to. Scalability can be increased by raising more NodeJS instances. In accordance with Microservices architecture, services should be stateless. My example cache process is not stateless and does will not scale well. Instead of using a local variable I should have used a persistent store.

Few generally accepted standards

This is of course my first impression. There are few generally accepted standards in the NodeJS world. For example, for testing there are many frameworks available. This also means that direct IDE support for a testing framework is difficult or requires manual scripting. Also talking to databases has no standard module (not something like JDBC in the Java world). Several modules use similar ideas and principles however. For example, most of them use JSON configuration files as part of the project. Also since the JavaScript language has its limitations (which becomes more apparent in large projects), there are several scripts which offer useful functionality and can be compiled to JavaScript such as TypeScript.

NodeJS and Oracle

Oracle is of course also investing in NodeJS. There is the Application Container Cloud Service which allows you to run NodeJS applications. You can choose the version of NodeJS on which your application should run. This allows Oracle to (relatively easily) stay up to date with the cloud service and users to choose when to run on which version. The cloud service comes integrated with an Oracle database driver to easily access your Oracle persistent store.


Also NodeJS is used in Mobile Cloud Service under the hood.


Oracle is working on several products which go well with NodeJS such as the API Platform and most likely more is coming in this area.

If you want to know how you can access the Oracle database from NodeJS, look here. If you want to create a Docker container with NodeJS and the Oracle database driver integrated, see here.

NodeJS for orchestration

In Oracle SOA Suite and Service Bus we were used to graphical development to do integrations. Languages like BPEL which are XML based to describe flows. Out of the box functionality like security policies, management interfaces and technology adapters/transports. BPEL or ServiceBus 12.2.1 can run JavaScript in the JVM and supports untyped JSON. NodeJS provides a lot of modules but very little out of the box and not much standardization. It is fast, light and scalable though (when stateless). I can imagine that NodeJS would be especially suitable to provide services which are thin and do not require much functionality (≈microservices). An example could be a layer of data services on top of a persistent store. When however you want to validate your messages, provide traceability, advanced error handling, throttling and require features like I previously mentioned, you can do it in NodeJS but it would require quite some coding (which requires maintenance). You might be better of with something which provides these features out of the box (like SOA Suite) in such a case. If however you want a quick stateless solution to easily integrate two REST/JSON services server-side with JavaScript, NodeJS is probably currently the best solution for that.

Software lifecycle

Because of the speed of JavaScript evolution, the turnover rate of code written using specific frameworks/modules will probably be higher since they are quickly outdated. I noticed however that it is quite easy to get started with new modules; not really a steep learning curve. I can imagine in many cases it will be more easy to start over instead of trying to migrate. Large companies and governments might have to get used to such a way of working.

Some things I have not looked at

Code compliancy

I have not looked at code compliancy inspection yet. Especially for a 'sloppy' language like JavaScript, such tooling is important to make larger projects manageable (read here). I heard JSLint for JavaScript and TSLint for TypeScript are popular.



Test coverage

For test coverage reporting you also need specific tools. See here for some example modules. Istanbul seems popular when using Mocha.

Building

Grunt and/or Gulp can help you build your project. You require tools like these to help you compile for example your TypeScript to JavaScript and to perform several other build steps such as automate the release process. Also to orchestrate the tasks mentioned above such as code compliancy checking,  and test coverage checking, these tools can help.



http://gulpjs.com/
Finally

I was surprised how easy it was to get started with NodeJS. The world of JavaScript was new to me and you can see from this blog post what I have learned in just a single day and a workshop. You need very little to get started.

Integration Cloud Service (ICS): Execution Agent proxy issue: NumberFormatException

$
0
0
Integration Cloud Service (ICS) offers an Execution Agent which you can download and install on-premises. This provides a local ICS instance. The Execution Agent is useful in several situations. When you have an ICS trial, it is valid only for a period of 30 days. After initial installation (which does require an ICS subscription), you can use the Execution Agent indefinitely. Secondly, you have full control over the Execution Agent since it is a local installation and not managed by Oracle such as the Oracle Cloud instances. This means you can for example log all requests and replies, install and test a custom Cloud Adapter or browse the Service Bus log files and deployments in case something goes wrong. Currently this is not possible in the Oracle Public Cloud without creating SR's. This blog post is based on the below version of ICS and might not be valid in future versions.


You can download the Execution Agent from the Agents page:


The installation requires Oracle Enterprise Linux 6 UC4 or above. Read the documentation here.

Execution Agent proxy error

When the Execution Agent is installed though, you will most likely encounter the following error sooner or later when accessing remote resources:


When you check the log files you can see the following error:

Caused By: java.lang.NumberFormatException: For input string: "''"         
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:481)
at java.lang.Integer.parseInt(Integer.java:527)
at oracle.cloud.adapter.api.util.NetworkUtil.createConnectionConfig(NetworkUtil.java:309)
at oracle.cloud.adapter.api.util.NetworkUtil.setupConnection(NetworkUtil.java:424)

As you can see from this stack trace, the error originates from NetworkUtil.java:309 when the java.lang.Integer.parseInt method is called. Using JD (Java Decompiler) the error can be traced back to the following line of code;

connConfig.setProxyAddress(new InetSocketAddress(proxyHost, Integer.parseInt(proxyPort)));

Thus the error is caused by an empty proxyPort. During the installation of the Execution Agent, I needed to answer several questions:

Enter your ICS subscription URL for authentication:
Enter ICS subscription Username:
Enter ICS subscription Password:
Enter HTTPS Proxy Server Host Name:
Enter HTTPS Proxy Server Port Number:

I just pressed enter when asked for proxy settings.

How to solve it

There are 2 easy ways to solve this. First disable the proxy and second start using a proxy. After the installation you can change the proxy settings by editing:

ICSOPInstall/ICSOP/data/user_projects/domains/compact_domain/bin/setICSDomainEnv.sh

This file contains the proxy settings:

#!/bin/sh
EXTRA_JAVA_PROPERTIES="${EXTRA_JAVA_PROPERTIES} -Dhttps.proxyHost= -Dhttps.proxyPort= -Dhttp.proxyHost= -Dhttp.proxyPort="
EXTRA_JAVA_PROPERTIES="${EXTRA_JAVA_PROPERTIES} -Dweblogic.security.SSL.minimumProtocolVersion=TLSv1.0"
EXTRA_JAVA_PROPERTIES="${EXTRA_JAVA_PROPERTIES} -DExecutionContext=ICS_ON_PREMISE"
export EXTRA_JAVA_PROPERTIES

Fix 1: Disable the proxy

These proxy settings were interpreted as empty strings which of course cannot be parsed to integers. In the NetworkUtil code, you can see in the NetworkUtil class code that if the proxyHost or proxyPort is not null, that the proxy will be used which causes this error. An empty string is of course not null. When I comment the below line in setICSDomainEnv.sh, the proxy settings are null though.

#EXTRA_JAVA_PROPERTIES="${EXTRA_JAVA_PROPERTIES} -Dhttps.proxyHost= -Dhttps.proxyPort= -Dhttp.proxyHost= -Dhttp.proxyPort="

The result of this is that ICS will not use a proxy server anymore.

Fix 2: Install a proxy server

Sometimes it can be difficult to debug ICS. See also my post here. It can help to have an external proxy server which can log all the incoming and outgoing requests. This way you can see exactly what ICS is sending, including all the headers and the exact response. You can use for example Squid or the JDeveloper HTTP analyser.

Squid

Installing a proxy server on Oracle Enterprise Linux is easy: 'sudo yum install squid' and you are done. By default this proxy server only accepts connections from localhost and runs on port 3128. So now you can supply localhost as proxy server and port 3128 as proxy port. This way ICS will not complain about missing proxy ports and you can use Squid for some additional logging on requests and replies.


JDeveloper HTTP Analyser

An alternative (which does require a bit more memory and diskspace) is to use the JDeveloper HTTP analyzer for this. If you are running a VM and JDeveloper is installed outside of the VM, you could encounter errors like

Caused by: javax.net.ssl.SSLKeyException: Hostname verification failed: HostnameVerifier=weblogic.security.utils.SSLWLSHostnameVerifier, hostname=vmserver.
at weblogic.security.SSL.jsseadapter.JaSSLEngine.doPostHandshake(JaSSLEngine.java:677)
at weblogic.security.SSL.jsseadapter.JaSSLEngine.doAction(JaSSLEngine.java:748)
at weblogic.security.SSL.jsseadapter.JaSSLEngine.unwrap(JaSSLEngine.java:132)
at weblogic.socket.JSSEFilterImpl.unwrap(JSSEFilterImpl.java:603)
at weblogic.socket.JSSEFilterImpl.unwrapAndHandleResults(JSSEFilterImpl.java:507)
at weblogic.socket.JSSEFilterImpl.doHandshake(JSSEFilterImpl.java:96)
at weblogic.socket.JSSEFilterImpl.doHandshake(JSSEFilterImpl.java:75)
at weblogic.socket.JSSESocket.startHandshake(JSSESocket.java:219) 

When you have JDeveloper and the HTTP Analyser installed inside the same VM as the Execution Agent, you will not encounter this issue.


Oracle Database 11g: Virtual database columns

$
0
0
Views in the Oracle database have several uses. You can use them to provide a view of data in different tables as a single object to query. You can use views to achieve a virtualization layer. Also views can be used to provide a user specific view of data. Implementing views however also have some challenges if you want to 'do it right'. You should consider grants to the table and the view. Maybe create synonyms. You should also consider what will happen if someone does access the underlying table since your data can now be queried from a different place (no single source of truth anymore). Do you want to have the view implement similar functionality as a table by providing an instead-of trigger when performing inserts on the view? Sometimes a view might seem too much for what you might want to accomplish. Suppose you want to add a single calculated field to a table. In this case there is a much easier solution than creating a view. A virtual column. The virtual column was introduced in Oracle Database 11g. In this blog post I'll give a simple minimal example of how you can use a virtual column and some things to mind when doing. Disclaimer: this code will not conform to many standards and is only meant as a minimal example.


Suppose we have the SCOTT schema with the EMP and DEPT tables:

CREATE TABLE "SCOTT"."EMP"
  (
    "EMPNO"   NUMBER(4,0),
    "ENAME"   VARCHAR2(10 BYTE),
    "JOB"     VARCHAR2(9 BYTE),
    "MGR"     NUMBER(4,0),
    "HIREDATE" DATE,
    "SAL"     NUMBER(7,2),
    "COMM"    NUMBER(7,2),
    "DEPTNO"  NUMBER(2,0),
    CONSTRAINT "PK_EMP" PRIMARY KEY ("EMPNO"),
    CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO") REFERENCES "SCOTT"."DEPT" ("DEPTNO") ENABLE
  )

CREATE TABLE "SCOTT"."DEPT"
  (
    "DEPTNO" NUMBER(2,0),
    "DNAME" VARCHAR2(14 BYTE),
    "LOC"   VARCHAR2(13 BYTE),
    CONSTRAINT "PK_DEPT" PRIMARY KEY ("DEPTNO")
  )

Adding a virtual column

In the employee table we want to add a column for the location of the department. In order to keep it simple and thin, we do not want to create a view and avoid having to create additional objects, grants, synonyms, etc.

The expression used in the virtual column definition however has some restrictions:

  • It cannot refer to another virtual column by name.
  • It can only refer to columns defined in the same table.
  • If it refers to a deterministic user-defined function, it cannot be used as a partitioning key column.
  • The output of the expression must be a scalar value. It cannot return an Oracle supplied datatype, a user-defined type, or LOB or LONG RAW.

In order to reference a column from another table, we can use a function. PL/SQL functions however do not allow specifying the size of the return type. Thus while the LOC column in the SCOTT.DEPT table is 13 bytes, the virtual column will be of type varchar2 and thus use the maximum allowed size for a varchar2. In order to avoid this, you can cast the return value of the function to the correct size. You can also encounter the following error:

SQL Error: ORA-30553: The function is not deterministic
Cause: The function on which the index is defined is not deterministic
Action: If the function is deterministic, mark it DETERMINISTIC.  If it is not deterministic (it depends on package state, database state, current time, or anything other than the function inputs) then do not create the index.  The values returned by a deterministic function should not change even when the function is rewritten or recompiled.

Thus the function should be deterministic. See below for a working example of a function and a virtual column:

CREATE OR REPLACE FUNCTION SCOTT.GET_DEPT_LOC(
    p_deptno IN NUMBER)
  RETURN VARCHAR2 DETERMINISTIC
AS
  l_retval SCOTT.DEPT.loc%type;
BEGIN
  SELECT loc INTO l_retval FROM SCOTT.DEPT WHERE SCOTT.DEPT.DEPTNO=p_deptno;
  RETURN l_retval;
END;

ALTER TABLE "SCOTT"."EMP" ADD( LOC VARCHAR2(13 BYTE) GENERATED ALWAYS
AS
  (CAST(SCOTT.GET_DEPT_LOC(DEPTNO) AS VARCHAR2(13 BYTE) )));

The result looks as followed with LOC as the virtual column:



Serially reusable

Something to mind is when you are using packages which have PRAGMA SERIALLY_REUSABLE specified, and you have your function inside that package, you will encounter the following error:

ORA-06534: Cannot access Serially Reusable package string
Cause: The program attempted to access a Serially Reusable package in PL/SQL called from SQL context (trigger or otherwise). Such an access is currently unsupported.
 Action: Check the program logic and remove any references to Serially Reusable packages (procedure, function or variable references) which might happen in PL/SQL called from sql context (trigger or otherwise).

Using PRAGMA SERIALLY_REUSABLE can have performance benefits so I recommend to put the function in a separate package so the other package code can remain serially reusable.

Seamless source "migration" from SOA Suite 12.1.3 to 12.2.1 using WLST and XSLT

$
0
0
When you migrate sources from SOA Suite 12.1.3 to SOA Suite 12.2.1, the only change I've seen JDeveloper do to the (SCA and Service Bus) code is updating versions in the pom.xml files from 12.1.3 to 12.2.1 (and some changes to jws and jpr files). Service Bus 12.2.1 has some build difficulties when using Maven. See Oracle Support: "OSB 12.2.1 Maven plugin error, 'Could not find artifact com.oracle.servicebus:sbar-project-common:pom' (Doc ID 2100799.1)". Oracle suggests updating the pom.xml of the project, changing the packaging type from sbar to jar and removing the reference to the parent project. This however will not help you because the created jar file does not have the structure required of Service Bus resources to be imported. To deploy Service Bus with Maven I've used the 12.1.3 plugin to create the sbar and a custom WLST file to do the actual deployment of this sbar to a 12.2.1 environment.

Updates to the pom files can easily be automated as part of a build pipeline. This allows you to develop 12.1.3 code and automate the migration to 12.2.1. This can be useful if you want to avoid keeping separate 12.1.3 and 12.2.1 versions of your sources during a gradual migration. You can do bug fixes on the 12.1.3 sources and compile/deploy to production (usually production is the last environment to be upgraded) and use the same pipeline to compile and deploy the same sources (using altered pom files) to a 12.2.1 environment.


In order to achieve this I've created a WLST script to use XSLT transformations to update the pom files. For SOA and Service Bus the transformation to get from 12.1.3 to a working 12.2.1 project is slightly different. You can expand this to also update the group Id for your artifact repository to keep the 12.1.3 and 12.2.1 code separated there also. The transform.py file which is provided in this blog can be used to do other XSLT transformations from WLST also.

WLST

The WLST file (transform.py):
Usage: <jython|wlst> transform.py -<parameter>=<value> <stylesheetfile> [inputfile] [outputfile]

If you do not specify an outputfile, the output is send to the console. If you do not specify an inputfile, the console is used as input. You can specify XSLT parameters which will be used in the transformation. I've taken the sample code to do the XSLT transformation in WLST from here and expanded it. When using WLST to execute the script and pipe it to a file (not specifying an outputfile) do mind that you will get "Initializing WebLogic Scripting Tool (WLST) ..." and such above your actual script output.

import sys

from java.io import FileReader, PrintWriter
from java.lang import System
from javax.xml.transform import TransformerFactory, Transformer
from javax.xml.transform.stream import StreamSource, StreamResult

def transform(source, stylesheet, result, parameters):
    transformer = TransformerFactory.newInstance().newTransformer(stylesheet)
    for (p, v) in parameters: transformer.setParameter(p, v)
    transformer.transform(source, result)

args = sys.argv[1:]
parameters = []
while args and args[0].startswith('-'):
   try:
       i = args[0].index('=')
   except ValueError:
       parameters.append((args[0], ""))
   else:
       parameters.append((args[0][1:i], args[0][i+1:]))
   args = args[1:]
   
if len(args) == 1: source = StreamSource(System.in)
elif len(args) >= 2: source = StreamSource(FileReader(args[1]))
else: raise "Usage: <jython|wlst> process.py -<parameter>=<value> <stylesheetfile> [inputfile] [outputfile]"

if len(args) == 3: output = args[2]
else: output = ""

stylesheet = StreamSource(FileReader(args[0]))
if len(output) == 0:
result = StreamResult(PrintWriter(System.out))
else:
result = StreamResult(FileWriter(File(output)))

transform(source, stylesheet, result, parameters)

stylesheet.reader.close()
source.reader and source.reader.close()
result.writer.close()

XSLT

The transformation for SCA project pom files (migratesca.xsl):

<xsl:stylesheet
    version="1.0"
    xmlns:src="http://maven.apache.org/POM/4.0.0" 
    xmlns="http://maven.apache.org/POM/4.0.0"  
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:namespace-alias stylesheet-prefix="src" result-prefix=""/>

<xsl:template match="/src:project/src:parent/src:version">
<src:version>12.2.1-0-0</src:version>
</xsl:template>


<xsl:template match="/src:project/src:build/src:plugins/src:plugin/src:version">
<src:version>12.2.1-0-0</src:version>
</xsl:template>

<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

The transformation for Service Bus pom files (migratesb.xsl):

<xsl:stylesheet
    version="1.0"
    xmlns:src="http://maven.apache.org/POM/4.0.0" 
    xmlns="http://maven.apache.org/POM/4.0.0"  
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:namespace-alias stylesheet-prefix="src" result-prefix=""/>

<xsl:template match="/src:project/src:parent"/>

<xsl:template match="/src:project/src:packaging[text()='sbar']">
<src:packaging>jar</src:packaging>
</xsl:template>

<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

You can download the sources, sample pom files and a sample command-line here: https://github.com/MaartenSmeets/migrate1213to1221

Oracle SOA Suite Code Quality: SonarQube Quality Gates, XML Plugin and custom XPath rules

$
0
0
There are several ways to do code quality checks in SOA Suite. In this blog post I will describe a minimal effort setup which uses Jenkins 2.9, SonarQube 5.6 and the SonarQube XML Plugin 1.4.1. SonarQube is a popular tool to check and visualize code quality. An XML Plugin is available for SonarQube which allows you to define custom XPath rules. At the end of this post I will shortly describe several other options which you can consider to help you improve code quality by doing automated checks.


Using SonarQube and the XML Plugin to do code quality checks on SOA Suite components has several benefits compared to other options described at the end of this post.
  • It is very flexible and relatively technology independent. It allows you to scan any XML file such as BPEL, BPMN, OSB, Mediator, Spring, composite.xml files
  • It requires only configuration of SonarQube, the SonarQube XML Plugin and the CI solution (Jenkins in this example)
  • It has few dependencies. It does not require an Oracle Home or custom JAR files on your SonarQube server. 
  • The XML Plugin has support (by SonarSource) so high probability it will still work in future versions of SonarQube.
  • Writing rules is simple; XPath expressions. it does not require you to write Java code to create checks.
What we can't do with this setup is check relations between files since the XPath expressions are executed on single documents (defined with an Ant-style file-mask). Usually though when compiling or deploying SOA Suite composites, it will fail if there are references to files which are not present.

Jenkins / SonarQube setup

Setting up the environment

In this setup I've used Git, Jenkins, Maven, SonarQube. I've used an Ubuntu Server 16.04 install. The installation of the tools is pretty straightforward. Git and Maven are easiest: sudo apt-get install git maven. Jenkins is also pretty easy since there is a Debian package available. See here. For SonarQube I've installed a MySQL server (sudo apt-get install mysql-server). Next I've used the following manual. After the installation I've set the default admin password to admin (see here). I have also got Sonatype Nexus 3 installed on the server. This required a bit more effort. Nexus 2.x and Nexus 3.x use different API locations. Maven needed to be able to find Nexus (settings.xml file used for Nexus 2 cannot be used OOTB for Nexus 3). The init.d script had some different installation steps. See here.

Of course most people will know how to use Git. I prefer a setup in which the server has a single Git user who owns the repository and grant other users access with SSH keys to that repository. You can see how this is done here.

SonarQube

I've used the XML Plugin in SonarQube to define XPath rules. This first needs to be installed. Administration, System, Update Center and install the plugin:


You have to define a project in SonarQube. Administration, Projects, Management, Create Project.


The SonarQube Scanner (called from the CI tool) requires some configuration in order to know where in SonarQube to store the results of the analysis and what to analyse. This configuration can be stored in your source code project in a sonar.properties. In my case this file contained the following (match the settings from when you created the project in SonarQube):

sonar.projectKey=SampleApplication:master
sonar.projectName=SampleApplication
sonar.projectVersion=1.0
sonar.sources=SampleApplication/HelloWorldProject/SOA

I put this sonar.properties in the project directory (SampleApplication/HelloWorldProject). The sources location is relative to the checkout directory. I checked out the entire application so that is the root of my SonarQube analysis. For a composite compilation you might want to make the build more specific in that you only checkout a specific project and not the entire application. In that case the source path will also be different.

SonarQube rules

In order to create rules in SonarQube, you can go to Rules, Language XML, Xpath rule. Here you can create custom XPath rules.


In this case I'm checking .bpel files. The rule will be violated if the value of the name attribute of the process tag does not end with Process. Thus my BPEL process should have a name ending in Process. You should mind that XPath 1.0 is used (see here) in this plugin and not XPath 2.0. Thus you cannot use the ends-with function (which is why I needed to use the substring/string-length XPath expression).

There are two options for defining XPath rules which become apparent from browsing the source code of the XPath check here. You can use a boolean expression (false = violation) and XPath queries selecting violating nodes. First the boolean expression:

not(count(/process[substring(@name, string-length(@name) - string-length('Process') +1) = 'Process'])=1)

If this is true, then a rule violation is displayed on top of the page showing the source code (it cannot determine the specific node):


If however you want to have the rule violation displayed at the node which is violating the rule, you should restructure your rule to only select violating nodes, such as:

/process[not(substring(@name, string-length(@name) - string-length('Process') +1) = 'Process')]



Now the rule violation can be pinpointed to the violating node.

SonarQube Quality Gate

SonarQube uses the concept of quality gates. You can define rules which define when the quality gate will be passed. In my case I have defined the rule as Critical in the Quality profile Sonar Way.



I have also defined a rule in the Quality Gate that Critical Issues are not allowed.


Jenkins configuration

You can make the SonarQube analysis part of your CI solution. In this example I'm using Jenkins. First install the following plugins:
Under Global Configuration, you have to add your SonarQube installation:


You can obtain the authentication token from SonarQube, Administration, My Account, Generate Token.


You also have to do this for the Quality Gates plugin.


Under Global Tool Configuration, you have to add SonarQube Scanner configuration. See below:


Below you can see part of the job configuration indicating the SonarQube Scanner will be used. If a SonarQube Quality Gate is not passed, the build will fail.


A failed build indicates the reason why it has failed:


After the issue is fixed, the Quality Gate has been passed.


Inside the Maven build or as a separate step?

You can make the SonarQube code quality checks part of the Maven pom.xml file (application or project level). This requires you to make the SonarQube configuration available to the pom file which is used to do the build. This has the risk a developer will send measures to SonarQube of code which has not yet been committed, polluting the measures in SonarQube. Also there is a loss of separation of concerns. The CI tool usually has the configuration of different tools (such as VCS, build tools, JVM, code quality tools, automated testing tools, etc) defined and the order in which they are executed (usually in jobs, stages). These tools such as Jenkins, Bamboo, Hudson are good at keeping this configuration and visualizing the progress during a build. This task for the code quality checks will (if you define the sonar properties in a pom.xml file) now be delegated to the Maven build. Having a separate CI tool to do this, allows you to implement a loose coupling between the tools used to execute the build and the source code.

Other options

Code Compliance Inspector

You can use the AIA Code Compliance Inspector (CCI). Using the Code Compliance Inspector allows you to define XPath expressions to do checks. You can only check a single file at a time and JDeveloper 11.1.1.7 or later is required (see here). You can call the Code Compliance Inspector from within JDeveloper. Read more here


You can use the following SonarQube plugin to put the Code Compliance Inspector output in SonarQube.

OJAudit

Oracle JDeveloper comes with its own audit framework called OJAudit. There is a plug-in available to put the ojaudit output in SonarQube. In order to use OJAudit, you should define your own rules using Java code. For ADF there is already a set of rules available. You can see how this works here. In the below picture you can see an example on how you can give suggestions to fix issues as part of the rules.

In order to get this working, as you can see from the (4 part) tutorial, you have to do several things such as (but not limited to): create a JDeveloper extension project, write your audit rules in Java, packaging the audit rules, making the audit rules available on your SonarQube server which requires an Oracle home since it is ojaudit you will be using. Of course as described in this post, you also need to do the described configuration of your CI tool and SonarQube.

You can create something similar for SOA/BPM/OSB and other components. This has the benefit that it can also be used within JDeveloper and not only in SonarQube. Also you can check references to files and consistency between files since the rules will be applied on application level.

Node.js: A simple pattern to increase perceived performance

$
0
0
The asynchronous nature of code running on Node.js provides many interesting options for service orchestration. In this example I will call two translation services (Google and SYSTRAN). I will call both of them quickly after each other (milliseconds). The first answer to be returned, will be the answer returned to the caller. The second answer will be ignored. I've used a minimal set of Node modules for this; http, url, request. Also I wrapped the translation API's to provide a similar interface which allows me to call them with the same request objects. You can download the code here. In the below picture this simple scenario is illustrated. I'm not going to talk about the event loop and the call stack. Watch this presentation for a nice elaboration on those.


What does it do?

The service I created expects a GET request in the form of:

http://localhost:8000?text=犬&source=ja&target=en

In this case I'm translating the Japanese 犬 to the English dog.

The result of this call in the console is:
Server running at http://127.0.0.1:8000
0s, 0.054ms - Request start
0s, 147.451ms - Google response: dog
0s, 148.196ms - Response returned to caller
0s, 184.605ms - Systran response: dog
The result returned is:

{
"result": "dog",
"source": "Google"
}
As you can see, Google is first to respond. The response from Google is returned to the client which does not have to wait for the result of Systran to come in.

If we slow down the returning of Google's response with 1 second (setTimeout), we see the following:
Server running at http://127.0.0.1:8000
0s, 0.003ms - Request start
0s, 107.941ms - Systran response: dog
0s, 108.059ms - Response returned to caller
1s, 78.788ms - Google response: dog
These are just single requests thus timing values differ slightly.

The following result is returned:
{
"result": "dog",
"source": "Systran"
}

How does it work?

Actually this setup is surprisingly simple using JavaScript and callbacks. The http module is used to create an HTTP server and listen on a port. The url module is used to parse the incoming request. The request module is used to create the GET request needed for SYSTRAN. See systran-translate.js (I've of course changed the API key ;). In the callback function of the server (which is called in the callback functions of the Google and Systran calls) I check if a response has already been returned. If not then I return it. If it has already been returned, I do nothing.

Below is a snippet from my main file which starts the server, calls the services and returns the response.


I've used the Google API as can be used with the node-google-translate-skidz module. Not much interesting to show here. To do the Systran translation, I've used the following code:


If you uncomment the console.log lines you can see the actual request which is being send such as: https://api-platform.systran.net/translation/text/translate?key=GET_YOUR_OWN_API_KEY&source=ja&target=en&input=%E7%8A%AC

%E7%8A%AC is of course 犬

Why is this interesting?

Suppose you are running a process engine which executes your service orchestration in a single thread. This process engine might in some cases not allow you to split your synchronous request/reply in a separated request and reply which might be received later, often making this a blocking call. When execution is blocked, how are you going to respond to another response arriving at your process? Also there are several timeouts you have to take into account such as maybe a JTA timeout. What happens if a reply never comes? This might be a serious issue since it might keep an OS thread blocked, which might cause stuck threads and might even hang the server if this happens often.

Through the asynchronous nature of Node.js, a scenario as shown above, suddenly becomes trivial as you can see from this simple example. By using a pattern such as this, you can get much better perceived performance. Suppose you have many clustered services which are all relatively lightweight. Performance of the different services might vary due to external circumstances. If you call a small set of different services at (almost) the same time, you can get a quick response to give to the customer. At the same time you might call services of which the answer might not be interesting anymore when it returns, increasing total system load.

In this example several things are missing such as correct error handling. You might also want to return a response if one of the services fails. Also, if the server encounters an error, the entire server crashes. You might want to avoid that. Routing has not been implemented to keep the example as simple as possible. For security you of course have your API platform solution.

Node.js: My first SOAP service

$
0
0
I created a simple HelloWorld SOAP service running on Node.js. Why did I do that? I wanted to try if Node.js was a viable solution to use as middleware layer in an application landscape. Not all clients can call JSON services. SOAP is still very common. If Node.js is to be considered for such a role, it should be possible to host SOAP services on it. My preliminary conclusion is that it is possible to host SOAP services on Node.js but you should carefully consider how you want to do this.

I tried to create the SOAP service in two distinct ways.
  • xml2js. This Node.js module allows transforming XML to JSON and back. The JSON which is created can be used to easily access content with JavaScript. This module is fast and lightweight, but does not provide specific SOAP functionality.
  • soap. This Node.js module provides some abstractions and features which make working with SOAP easier. The module is specifically useful when calling SOAP services (when Node.js is the client). When hosting SOAP services, the means to control the specific response to a call are limited (or undocumented)
Using both modules, I encountered some challenges which I will describe and how (and if) I solved them. You can find my sample code here.


xml2js

xml2js is relatively low level and specifically meant to convert XML to JSON and the other way around. It is SAX based which helps keeping the service calls non-blocking. Hosting a service is something you can control with express routers. You can see this here. The rest of the service code can be found here.

body-parser

The first challenge was getting the SOAP request in a usable form to my service. You have to make sure you have a correct body-parser configured to respond to the correct content type in the request. If you set the body-parser to text for type */* it will work nicely. I did this in my service JavaScript file since different services might require different body-parsers.

router.use(bodyParser.text({ type: '*/*' }));

Serving the WSDL

In order for a SOAP service to provide functionality, it helps greatly if it can serve its own WSDL. I respond to a GET request at ?wsdl with the WSDL file. You have to mind that ?wsdl is a GET query string and you have to check for it accordingly.

async

There were several asynchronous function calls in the processing of the request and creating the response of the service call. In order to make the code better readable, I used the async module waterfall function to provide something what looks like a synchronous chain and is more easy to read than several levels of nested callbacks.

Namespace prefix

Namespace prefixes are not static.

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="http://www.examples.com/wsdl/HelloService.wsdl">
   <soap:Body>
      <tns:sayHelloResponse>
         <tns:greeting>Hello Maarten</tns:greeting>
      </tns:sayHelloResponse>
   </soap:Body>
</soap:Envelope>

Is the same as

<blabla:Envelope xmlns:blabla="http://schemas.xmlsoap.org/soap/envelope/" xmlns:blablabla="http://www.examples.com/wsdl/HelloService.wsdl">
   <blabla:Body>
      <blablabla:sayHelloResponse>
         <blablabla:greeting>Hello Maarten</blablabla:greeting>
      </blablabla:sayHelloResponse>
   </blabla:Body>
</blabla:Envelope>

Thus it is dangerous to query for a fixed namespace prefix in the request. To work around this, I stripped the namespace prefixes. This is of course not a solid solution if a certain node contains two elements with the same name but a different namespace, this will fail. Such a case however is rare and to be avoided.

parseString(req.body, { tagNameProcessors: [stripPrefix] }, cb);

Finding elements

When a JSON object is returned by xml2js, elements are put in an array of objects. It is dangerous to just pick the first item in the array, because that item might not always be the first (depending on optional elements for example and I'm not sure xml2js puts an object always at the same spot in the array). I created a little search function to get around that.

Creating the response

xml2js can create XML if you provide it with the correct JSON input. What I did to obtain this correct JSON message was to first use SOAP-UI to create a sample XML response message (by creating a mock service). I used this XML as input for xml2js parseString function. This gave me the correct JSON output which I could alter to give me an output message which contained processed input.

soap

Using the soap module, I managed to create a simple helloworld service with very little coding. You can find the code here. I was quite happy with it until I noticed the created response had some errors. I wanted:


<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:examples:helloservice">
   <soapenv:Header/>
   <soapenv:Body>
      <urn:sayHelloResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <greeting xsi:type="xsd:string">Hello Maarten</greeting>
      </urn:sayHelloResponse>
   </soapenv:Body>
</soapenv:Envelope>

I got:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="http://www.examples.com/wsdl/HelloService.wsdl">
   <soap:Body>
      <tns:sayHelloResponse>
         <tns:greeting>Hello Maarten</tns:greeting>
      </tns:sayHelloResponse>
   </soap:Body>
</soap:Envelope>

Although it was pretty close, I did not manage to get the namespace of the sayHelloResponse and greeting element fixed. It is one of the dangers of abstractions. I noticed that the possible options for the client part were far more elaborate than for the server part. I did not find a suitable alternative for this module though.

Some things

The soap module provides an easy way to create simple SOAP services and clients. However, I found it lacking in flexibility (or documentation with samples). Some handy features though are support for basic authentication and WS-Security headers. Currently I would go for the xml2js option instead of trying to invest serious time in understanding how to get the soap module to do exactly what I want it to do. I would consider soap for SOAP clients though. WS-Security can also be implemented without the soap module (wssecurity module). Also the setup with the express routers and body parsers works quite nicely. I did not find an easy way to validate a message based on a WSDL.

Application Container Cloud: Node.js hosting with enterprise-grade features

$
0
0
Oracle's Application Container Cloud allows you to run Java SE, Node.js and PHP applications (and more is coming) in a Docker container hosted in the Oracle Public Cloud (OPC). Node.js can crash when applications do strange things. You can think of incorrect error handling, blocking calls or strange memory usage. In order to host Node.js in a manageable, stable and robust way in an enterprise application landscape, certain measures need to be taken. Application Container Cloud provides many of those measures and makes hosting Node.js applications easy. In this blog article I'll describe why you would want to use Oracle Application Container Cloud. I'll illustrate this with examples of my experience with the product.


Forking (not a real cluster)

Node.js without specifically coded forking / clustering, runs in a single OS thread.This single thread uses a single CPU. You can fork processes/workers to use multiple CPU's. Node.js provides (among other things) the core module cluster to do this. It depends on IPC between master and workers (which can be cumbersome to manually code). Also there is no easy way to graceful shutdown workers and restart them without downtime. StrongLoop (IBM) has developed modules such as strong-cluster-control and strong-store-cluster to make this more easy. If the master process fails however, you still have a problem.

Multiple Node.js instances (a real cluster)

If you want to provide true clustering over Node.js instances and not just for forks / child processes you need additional tooling; process managers. On the express site is a short list of the most popular ones. StrongLoop Process Manager, PM2 and Forever. For example StrongLoop Process Manager encapsulates features such as nginx load balancing, supervision as well as devops functions of build, deploy, monitor and scale on remote servers and Docker containers. I have not tried this though but can imagine this requires some setting up.


Application Container Cloud

Oracle Application Container Cloud provides out of the box with very little configuration, a set of clustering and stability features to allow Node.js to run in an enterprise landscape. If you want to get up and running quickly without thinking about many of these things, you should definitely look at Application Container Cloud.
  • Application Container Cloud provides an extensive user interface and API to allow you to do most required tasks easily. You do not need an expert to configure or operate Application Container Cloud (if you like, you can still hire me though ;).
  • Node.js instances (inside Docker containers) can be added / deleted on the fly. The load-balancer (also hosted in the OPC) is configured for you. Thus you get cluster functionality (important for scaling and high availability) over Node.js instances with almost no effort.
  • If one of the instances does not respond anymore, the load-balancer notices and sends requests to other instances. It does this by checking the root of your application. 
  • When a Node.js instance crashes (by means of the Node.js process exiting), it is automagically restarted (you can confirm this by looking at the log files)
Creating and deploying an application


Creating an application is easy. You can use the provided API to easily create and manage an application or use the web interface. The format of the application to upload is also very straightforward. You upload a ZIP file with your complete application and a manifest.json file which can contain as little as for example:

{
  "runtime":{
    "majorVersion":"0.12"
  },
  "command": "node app.js",
  "release": {},
  "notes": ""
}

You can also add a deployment.json file which can contain variables you can use within your application. These variables can be updated with the web interface or the API and the application will be restarted to apply the new settings.


After multiple uploads and downloads, I noticed from the log files that my archive did not update. I changed the filename of the zip-file I uploaded and the problem did not occur anymore. Apparently, sometimes the uploaded file cannot be overwritten by a new upload (when doing certain actions at the same time probably). This can be dangerous. For a Continuous Delivery scenario I suggest using unique filenames to avoid this issue.

You can easily use a Maven build with the maven-assembly-plugin to create the archive to be deployed in case you want to embed this in a Continuous Delivery pipeline. You can of course also use the provided Developer Cloud Service. Read more about that here. There is a nice demo here.

Management

Application Container applications can be restarted, stopped, started, deleted. You can add and remove instances. You can not restart or start/stop a single instance. When a single instance does not respond anymore (on the application root URL), the load-balancer notices and does not send requests to that instance anymore. If you want to make it available again, you have to restart your entire application (or remove and add instances and hope the faulty one is removed and recreated). When adding instances, existing instances will keep running and for the new instances, when they are done creating, the load-balancer is updated. When removing instances, the load-balancer is also updated.



If the application ends the Node.js process, a new process will to be started immediately. This new process used the same IP and hostname during my tests. If I start/stop or restart the application, the hostname and IP get new values.

Log files

Log files can be downloaded from running applications.


If an application creation fails, you can also download the log files. See an example at 'Accessing the API' below. This can greatly help in debugging why the application cannot be created or started. Mostly the errors have been application errors. For example:

Aug 12 14:14:42: Listening on port: 8080
Aug 12 14:14:47: Request on url: /
Aug 12 14:14:47: /u01/app/app.js:49
Aug 12 14:14:47:   if (req.url.startsWith("/oraclecloud")) {
Aug 12 14:14:47:               ^
Aug 12 14:14:47: TypeError: undefined is not a function
Aug 12 14:14:47:     at Server.<anonymous> (/u01/app/app.js:49:15)
Aug 12 14:14:47:     at Server.emit (events.js:110:17)
Aug 12 14:14:47:     at HTTPParser.parserOnIncoming [as onIncoming] (_http_server.js:492:12)
Aug 12 14:14:47:     at HTTPParser.parserOnHeadersComplete (_http_common.js:111:23)
Aug 12 14:14:47:     at Socket.socketOnData (_http_server.js:343:22)
Aug 12 14:14:47:     at Socket.emit (events.js:107:17)
Aug 12 14:14:47:     at readableAddChunk (_stream_readable.js:163:16)
Aug 12 14:14:47:     at Socket.Readable.push (_stream_readable.js:126:10)
Aug 12 14:14:47:     at TCP.onread (net.js:540:20)

Do mind that the Node.js version running in the Application Container Cloud currently is 0.12.14. In this version for example you have to start Node.js with the --harmony switch if you want to use startsWith on the String object. My bad obviously.

Managing access

Even though there is an extensive user interface for management and monitoring of the Node.js application and also an extensive API (see more about about that below), the load-balancer configuration is not directly accessible. You can for example not configure a specific load-balancer probe or procedure to check whether the instance is up again. Also I did not find a way to easily secure my Node.js services to avoid them from being called by just anyone on the internet (I might have missed it though). It would be nice if for example the Node.js instance was behind an API platform or even just a configurable firewall.

Out of memory issue

I have found one situation which is not dealt with accordingly. I tried the following piece of code here.

This exposes 3 endpoints. /crashmenot, /crashmebykillingprocess and /crashmebyoutofmemory. I had created two instances of my application. By the hostname in the response message I could see which instance I was accessing.

Killing the server by out of memory however (GET request to /crashmebyoutofmemory) gave me locally the following exception in a local console (among some other things):

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory

When running this in Application Container Cloud I did not see the out of memory error. I did specify though that the instance should have 1Gb of RAM (the minimum allowed). An instance can currently be assigned as much as 20Gb of RAM.

Killing the process by causing out of memory, did not cause the instance to be auto restarted. The load-balancer however send me to the instance which was still working though. When I killed all instances with out of memory, it did not automatically recover. After the manual restart, the instances worked again. When the instances were running, a manual restart did not cause noticeable downtime.

Accessing the API

Application Container Cloud has an extensive and well documented API. In order to debug issues it is nice you can access the Application Container Cloud API by first determining the URL to call.


In this example my application is called CrashDummy7 and my Identity domain is accstrial. You can use an API call like (of course replace user and pass with actual values):

curl -k -i -X GET -u user:pass -H "X-ID-TENANT-NAME:accstrial" https://apaas.europe.oraclecloud.com/paas/service/apaas/api/v1.1/apps/accstrial/CrashDummy7

HTTP/1.1 200 OK
Date: Fri, 12 Aug 2016 18:10:57 GMT
Server: Oracle-Application-Server-11g
Content-Length: 1335
X-ORACLE-DMS-ECID: 005EUFDqWVE3z015Rvl3id00068i000ZBB
X-ORACLE-DMS-ECID: 005EUFDqWVE3z015Rvl3id00068i000ZBB
X-Frame-Options: DENY
Content-Language: en
Content-Type: application/json

{"identityDomain":"accstrial","appId":"a2c7998b-c905-466a-b89f-bb9b8c4044dd","name":"CrashDummy7","status":"RUNNING","createdBy":"maarten.smeets@amis.nl","creationTime":"2016-08-12T17:43:17.245+0000","lastModifiedTime":"2016-08-12T17:43:17.202+0000","subscriptionType":"MONTHLY","instances":[{"name":"web.1","status":"RUNNING","memory":"1G","instanceURL":"https://apaas.europe.oraclecloud.com/paas/service/apaas/api/v1.1/apps/accstrial/CrashDummy7/instances/web.1"},{"name":"web.2","status":"RUNNING","memory":"1G","instanceURL":"https://apaas.europe.oraclecloud.com/paas/service/apaas/api/v1.1/apps/accstrial/CrashDummy7/instances/web.2"}],"runningDeployment":{"deploymentId":"5a9aef17-8408-494c-855e-bc618dfb69e9","deploymentStatus":"READY","deploymentURL":"https://apaas.europe.oraclecloud.com/paas/service/apaas/api/v1.1/apps/accstrial/CrashDummy7/deployments/5a9aef17-8408-494c-855e-bc618dfb69e9"},"lastestDeployment":{"deploymentId":"5a9aef17-8408-494c-855e-bc618dfb69e9","deploymentStatus":"READY","deploymentURL":"https://apaas.europe.oraclecloud.com/paas/service/apaas/api/v1.1/apps/accstrial/CrashDummy7/deployments/5a9aef17-8408-494c-855e-bc618dfb69e9"},"appURL":"https://apaas.europe.oraclecloud.com/paas/service/apaas/api/v1.1/apps/accstrial/CrashDummy7","webURL":"https://CrashDummy7-accstrial.apaas.em2.oraclecloud.com"}

You can download logfiles such as:


By doing:

curl -u user:pass -k -i -X GET -H "X-ID-TENANT-NAME:accstrial" https://accstrial.storage.oraclecloud.com/v1/Storage-accstrial/_apaas/forwarder8/d177756e-399e-414f-bc9b-d2bb6e698ae6/logs/web.1/f0f62da1-b240-4251-aabe-9c1244069ed6/server.out.zip -o file.zip --raw

Here my application was called forwarder8.

Finally

I have explained when and why it is worthwhile to check out Oracle Application Container Cloud. Also I've shown some samples on how easy it it to use. I've described some of my experiences and have given some tips on how to efficiently work with it.

I have not touched on for example the easy integration with Oracle database instances running inside your cloud. The Oracle DB driver is supplied and configured for you in your Node.js instances and can be used directly with only simple configuration from the UI or API.

If you want to know more I suggest watching the following presentation from Oracle here. If you want to know more about the Oracle Db driver for Node.js, you can watch this presentation. And using the driver inside Application Container Cloud service here.

Great stuff!

Node.js and Oracle NoSQL Database

$
0
0
Oracle NoSQL Database is an interesting option to consider when you want a schemaless, fast, scale-able database which can provide relaxed (eventual) consistency. Oracle provides a Node.js driver for this database. In this blog I'll describe how to install Oracle NoSQL database and how to connect to it from a Node.js application.

The Node.js driver provided by Oracle is currently in preview version 3.3.7. It uses NoSQL client version 12.1.3.3.4 which does not work with 4.x versions of NoSQL database, so I downloaded Oracle NoSQL Database, Enterprise Edition 12cR1 (12.1.3.3.5) from here (the version number was closest to the version number of the client software).

NoSQL installation

To get NoSQL Database up and running, I followed the steps described in the installation manual here. This was quite educational as it showed me the parts a NoSQL database consists of. If you want to do a quick installation, you can do the steps described here. Do mind that the {} variable references do not work in every shell. On Oracle Linux 7.2 (inside Virtualbox) I did the following. First download kv-ee-3.3.5.zip here (previous versions on the Oracle NoSQL download page).

I made sure a Java was installed. I used a Oracle Java 1.8 64 bit.

I created the user oracle
mkdir -p /home/oracle/nosqldb/data
mkdir -p /home/oracle/nosqldb/root
cd /home/oracle/nosqldb
unzip kv-ee-3.3.5.zip

I updated /etc/environment
KVHOME="/home/oracle/nosqldb/kv-3.3.5"
KVDATA="/home/oracle/nosqldb/data"
KVROOT="/home/oracle/nosqldb/root"

Logout and login to make the environment active

Next I created an initial boot config
java -jar $KVHOME/lib/kvstore.jar makebootconfig -root $KVROOT -store-security none -capacity 1 -harange 5010,5030 -admin 5001 -port 5000 -memory_mb 1024 -host localhost -storagedir $KVDATA

I started the Oracle NoSQL Database Storage Agent(SNA).

nohup java -Xmx256m -Xms256m -jar $KVHOME/lib/kvstore.jar start -root $KVROOT &

And I configured it:

java -Xmx256m -Xms256m -jar $KVHOME/lib/kvstore.jar runadmin -port 5000 -host localhost <<EOF
configure -name mystore
plan deploy-zone -name "LocalZone" -rf 1 -wait
plan deploy-sn -zn zn1 -host localhost -port 5000 -wait
plan deploy-admin -sn sn1 -port 5001 -wait
pool create -name LocalPool
show topology
pool join -name LocalPool -sn sn1
topology create -name topo -pool LocalPool -partitions 10
topology preview -name topo
plan deploy-topology -name topo -wait
show plan
EOF

You can test if it is running by executing:

java -Xmx256m -Xms256m -jar $KVHOME/lib/kvstore.jar ping -port 5000 -host localhost

Oracle NoSQL Database basics

NoSQL Database has built-in load balancing, sharding and several other features related to high availability quite clearly integrated as an essential part of the software and not as some kind of add-on. Read more about it here.


Also different consistency models are available. You can sacrifice immediate consistency to gain more performance. Read more about that here.


It provides an Admin console to look at the topology and execution of plans. The console does not allow you to do actual changes to the configuration. For that you can use a CLI.


It also allows you to browse log files


And look at performance details for specific nodes.


For development, kvlite available. It is a simple single node store which can be used locally. Read more here. When using kvlite, you do not need to do the configuration as described in the installation.

Node.js application

Installation of the Node.js module is easy. Just do a npm install nosqldb-oraclejs. The NoSQL Node.js driver page gives a piece of code which you can use to test your application. The default installation of NoSQL however as described above causes a port conflict with the proxy server which is started. This port conflict is not immediately clear as it gives you the below exception.

{ NoSQLDB-ConnectionError: Error with NoSQL DB Connection: Error verifying the proxy connection
NoSQLDB-ConnectionError: Error with NoSQL DB Connection: Connection timeout
    at /home/oracle/nodejsnosql/node_modules/nosqldb-oraclejs/lib/store.js:277:25
    at Timeout._onTimeout (/home/oracle/nodejsnosql/node_modules/nosqldb-oraclejs/lib/store.js:181:7)
    at tryOnTimeout (timers.js:228:11)
    at Timer.listOnTimeout (timers.js:202:5)

I changed the port and some log settings and used this test application. When I run it with node app.js I get the following output:

[2016-08-16 19:05:02.717] [INFO]  [at Object.startProxy (/home/oracle/nodejsnosql/node_modules/nosqldb-oraclejs/lib/proxy.js:353:10)] [PROXY] Start proxy

Connected to store
Table is created.
Inserting data...
Reading data...
Writing row #0
Writing row #1
Reading row #0
{ id: 0, name: 'name #0' }
Reading row #1
{ id: 1, name: 'name #1' }
Closing connection...
[2016-08-16 19:05:09.630] [INFO]  [at Store.close (/home/oracle/nodejsnosql/node_modules/nosqldb-oraclejs/lib/store.js:299:12)] Store close

Store connection closed.
Shutting down proxy.
Proxy closed.

How does this Node.js module work?

I read that the proxy translates network activity between the Node.js module and the Oracle NoSQL Database store. The proxy can be spawned as a child process (JVM) from the Node.js module. A JavaScript Thrift client (see Thrift protocol) has been generated with the Apache Thrift compiler which is used by the module to communicate with the proxy. The proxy then uses kvclient to connect to the database. This would be something like the image below.
I wondered what the performance cost would be of having a Java proxy and two translations between the Node.js module and the NoSQL database. It would be interesting to compare the bare RMI Java client performance with the Node.js module performance and to compare performance of a query executed from within the database with a query executed from outside by the RMI kvclient to determine the performance cost of the different hops/translations. I can understand the usage of Thrift though since it provides a relatively easy way to create clients in different languages.

Oracle NoSQL Database 4.x and the Node.js driver 3.x

$
0
0
There are two ways you can access Oracle NoSQL database from a Node.js application. These are illustrated below. You can use the nosqldb-oraclejs driver and you can use Oracle REST Data Services.


In my previous blog post I illustrated how you can access Oracle NoSQL database by using the nosqldb-oraclejs driver. I encountered an issue when using the NoSQL database version 12R1.4.0.9 with the currently newest available Node.js driver for NoSQL database nosqldb-oraclejs 3.3.15.

INFO: PS: Connect to Oracle NoSQL Database mystore nodes : localhost:5000
Aug 15, 2016 10:10:06 PM oracle.kv.proxy.KVProxy <init>
INFO: PS:   ... connected successfully
Exception in thread "main" oracle.kv.FaultException: Unable to get table metadata:Illegal character in: SYS$IndexStatsLease (12.1.3.3.4)
Fault class name: org.apache.avro.SchemaParseException
Remote stack trace: org.apache.avro.SchemaParseException: Illegal character in: SYS$IndexStatsLease
               at org.apache.avro.Schema.validateName(Schema.java:1068)
               at org.apache.avro.Schema.access$200(Schema.java:79)

The nosqldb-oraclejs driver currently does not support NoSQL database versions 4.x and only 3.x. There is a workaround available though kindly provided by Oracle.

nosqldb-oraclejs 3.x and NoSQL database 4.x

The nosqldb-oraclejs driver creates an instance of a proxy server by starting a JVM. This proxy server uses kvclient.jar to connect to the database using RMI. The kvclient.jar from the 3.x version of the driver does not like talking to a 4.x version of the database.


The first try was replacing the kvclient.jar from the 3.x version of the driver with the kvclient.jar supplied with 4.x of the database. This allowed the proxy-server to start, but when connected to it, it gave the following error:

[ERROR] [at Object.getProxyError (/home/oracle/nosqlnode/nodejssamples/nosql/node_modules/nosqldb-oraclejs/lib/errors.js:165:10)] Capturing proxy error: TProxyException: org/antlr/v4/runtime/RecognitionException

In order to get the proxy-server working completely, I had to download the Java driver from the Oracle download site: kv-client-4.0.9.zip (version corresponding to the version of the database). In this zip file was a directory kv-4.0.9/lib which contained several other jar files which were also required to get the proxy-server working. When I copied the contents of that folder to my node_modules/nosqldb-oraclejs/kvproxy folder (the same folder as kvproxy.jar) and restarted the proxy server, I could use the driver. I have not checked thoroughly though if all functionality works as expected. I used the example which is available here to check if it works.

Finally

A drawback of using this solution is that you manually update driver code after it has already been fetched from NPM. When you remove the node_modules folder and do an npm install, the jar files will be reverted to their previous 3.x version. This can be an issue in a continuous delivery environment. Probably the best solution for this is using your own repository manager to proxy remote npm registries such as https://registry.npmjs.org. For example by using JFrog Artifactory or Sonatype Nexus in which you have full control over the artifacts. Here you can create your own version of the driver which is already bundled with the correct jar files. This has the additional benefit of improving performance by not requiring every client to download the libraries from the internet but from a local repository proxy. This also allows you to have more control over which libraries can be used and some visibility of which are being used.

Sonatype Nexus 3.0. Using the new Groovy API

$
0
0
Sonatype Nexus 3.0 does not have the REST API which was available in Nexus 2.x (see the discussion here). This provides a challenge in case you want to automate certain tasks. Nexus 3 does provide a Groovy API however which allows you to write your own scripts and upload them to Nexus. You can then call your scripts and use the JSON result. In order to get this working however, several things need to be done. First the script needs to be developed (during which code completion comes in handy). Next the script needs to be condensed to a single line and put in a JSON request. After that, the JSON request needs to be send to a specific endpoint. You can imagine this can be cumbersome. Sonatype has provided Groovy scripts to deploy their Groovy scripts. See here. I've created something similar using Python so you do not require a download of dependencies, a JVM and a Groovy installation to perform this task. This makes it more easy to do this from for example a build-server.

Getting up and running

Development environment

First you can install your development environment. The documentation mentions IntelliJ IDEA. The community edition supports Groovy editing and code completion so I installed that. Next you can download sample code from here. Below is an example of how the project structure looks and working code completion. It is quite easy to get this part working.


Documentation

Since Nexus 3 is (at the moment of writing) quite new, there is not much information about the API online available yet. There are some samples and links at: https://books.sonatype.com/nexus-book/3.0/reference/scripting.html#scripting-configuration.
You can download Javadoc JAR files from http://repo1.maven.org/maven2/org/sonatype/nexus. These can help you understanding the class structure and how to get from one class to another. Also it helps a lot to watch the YouTube movies mentioned here (thank you Manfred!).

Building your script

The mechanism by which you can deploy a script is interesting to say the least. You have to create a JSON request which contains your Groovy script and send it to an API to deploy your API. Your Groovy script needs to be a single line in this JSON file for it to remain valid JSON. Also you have to take into account the JSON file uses " characters. Your script should thus use ' characters to delimit strings. You can POST your JSON file to http://[HOST]:[PORT]/service/siesta/rest/v1/script. Next you can call the script by calling http://[HOST]:[PORT]/service/siesta/rest/v1/script/[scriptname]/run". You have the option to use arguments in your script.

Automating

It is nice you can use an API to upload and run Groovy scripts and use an IDE to write Groovy scripts with code completion support, however there is no 'one-button-deploy' option to quickly test your script.

Running locally from IntelliJ IDEA is also not straightforward because your script will miss the context from running on the server. The script itself cannot be used as is to send to the server since it cannot contain line breaks in the code. Also sending the script will fail if the script has been previously deployed, thus it should first be undeployed. Sample shell scripts are available to do all these tasks, however during development it can be tedious to execute them all constantly one after each other after every change in the code. Also the shell scripts of course are *NIX specific and will not execute on Windows (unless you are using Bash on Ubuntu on Windows, Cygwin, a VM or something similar). Next to that, the more complex example provided, provides you with Groovy scripts but they have some dependencies. They require for example downloading of dependencies, a JVM and a Groovy installation.

That's why I wrote the below Python script. Why Python? Well, next to personal preference, also because it is present on most Linux systems and can easily be installed on Windows as well. In my opinion it is a bit more flexible/readable than shell scripts or Groovy scripts and has few dependencies.

You can download the script code here. I've also supplied an IntelliJ workspace/project to complete the example. You of course need to replace the obvious variables like script location and the Nexus host name, port, username, password.

Disclaimer: the script has not been tested thoroughly and has not been put to use in an enterprise environment. Especially the part where the Groovy script is rewritten to be put inside a JSON request can use some tweaking.

Sonatype Nexus 2.x: Using the REST API to clean-up your repository

$
0
0
Sonatype provides Nexus. An extensive artifact Repository Manager. It can hold large amounts of stored artifacts and still requests get processed quickly. Also it has an extensive easy to use API which is a definite asset. When a project has been running for a longer period (say years), the repository often gets filled with large numbers of artifacts. This can become especially troublesome if artifacts are quite large in size such as for example JSF EAR files. These artifacts might not even have been released (be part of a deployed release). Nexus provides the option to remove artifacts older than a specific date. This however might also remove artifacts which are dependencies of other artifacts (older releases) which you might want to keep. When those other artifacts are build, the build might break because the artifacts it refers to, have been removed. In order to allow more fine grained control over what to remove, I've created the following script. The script uses only the releases repository (snapshots are not taken into account. not sure what the script does there) Disclaimer: first test if this script does what you want in your situation. It is provided as is without any warranties.

What does it do

Selecting releases to be deleted

The script considers a release as a pom file which has dependencies to artifacts. Also it considers artifacts to be deployed before the release which refers to the artifact. Usually you first build your artifact and when it passed several quality gates, it is added to a release. Those artifacts which are dependencies of the release, can have other dependencies, and so forth. First releases older than a specific date are determined. These can be considered for deletion. The script allows you to specify to keep at least a specific number of releases in the repository. These will be the newest releases. Other releases will be removed. The lastModified date of the pom files is used to determine the age of the release/artifact.

Artifacts

Artifacts older than the specified date which are not in the dependency tree of a release, are removed. Artifacts which are newer than the specified date are not removed. These might be work in progress artifacts which will be added to a release at a later time. Because the entire dependency tree starting with the release is determined, even if there is a nesting in dependencies of artifacts, the script will be able to deal with it.

About the script

Parameters:

NEXUS_HOST is the hostname of the NEXUS machine. When running this script on the same machine as Nexus, this can be localhost
NEXUS_PORT is the port used by Nexus on NEXUS_HOST
NEXUS_USERNAME is a Nexus username which is allowed to query and delete artifacts (builduser, admin)
NEXUS_PASSWORD is the password of NEXUS_USERNAME
NEXUS_BASE_CONTENT is the base path of the Nexus API. usually /nexus/service/local/repositories/releases/content
NEXUS_BASE_RELEASE_SEARCH is the path after NEXUS_BASE_CONTENT where releases can be found to be deleted. releases (artifacts themselves) have dependencies to other artifacts. dependencies do not need to be in this path
NEXUS_BASE_ARTIFACT_SEARCH is the path after NEXUS_BASE_CONTENT where artifacts can be found to be deleted
DUMMYRUN if true, no actual artifacts/releases are deleted. if not true, they are
REMOVEBEFOREDATE if the date as a string. formatted like 'YYYY-MM-DD HH24:mi:ss' for example 2016-12-27 14:30:01
MINRELEASESTOKEEP is the number of releases not to remove

A sample commandline: 

It uses Python 2.7. I did not download additional modules (stuck to the basics making it more portable). A sample command-line for the script is:

python ./nexuscleanup.py localhost 8081 /nexus/service/local/repositories/releases/content /nl/amis/smeetsm/releases/ /nl/amis/smeetsm/applications/ admin admin123 true '2017-01-01 01:01:01' 1

You can indicate from the commandline you want to do a dummy run. This executes the script the same as without a dummyrun however it doesn't do the actual release and artifact removal. Inside the script there is a variable DEBUG. If you set this to 'true' you will get a lot more information on individual requests to the API.

Some considerations

If artifacts are deployed after a release which was removed, these artifacts might not be removed if they have been added after the specified date; the script does not detect and remove 'orphan' artifacts.

If you have a situation where artifacts have dependencies on other artifacts and the other artifacts have not been selected for removal, it is possible dependencies might break. This should not occur however if you stick to the rule to first add your base artifacts to Nexus and next artifacts which have them as dependencies. If you remove artifacts in a dependency chain, the script might not be able to determine correct dependencies.

The script can be called from the command-line with several parameters. These parameters are required to specify behavior of the script and properties to call the Nexus API. The script has been tested with Nexus Repository Manager OSS 2.14.0-01. In Nexus 3.x the API is being revisited and might drastically change so it is very likely this script will nog work on Nexus 3.x versions. If you want to use it on Nexus 3.x, you should wait until Sonatype has implemented a suitable API and change the methods which do the HTTP calls and the methods which process the XML result from those calls. Most likely the structure of responses will be different and browsing a tree using the API might also differ significantly.

Special care has been taken to verify the correct number and format of the supplied parameters. Also every HTTP response code is checked against expectations. Extensive logging is available to debug errors.

The script in action

Consider the following releases and artifacts


Release 3.0
Depends on artifact 3.0

Release 4.0
Depends on artifact 4.0

Release 5.0
Depends on artifact 4.0

Artifact version 1.0 and 2.0 are not part of any release

When executed, the script output is as follows
 [oracle@localhost browsenexus2]$ python ./nexuscleanup.py localhost 8081 /nexus/service/local/repositories/releases/content /nl/amis/smeetsm/releases/ /nl/amis/smeetsm/applications/ admin admin123 true '2017-01-01 01:01:01' 1  
2016-10-28 13:28:15.846401 INFO : Executing dummy run
2016-10-28 13:28:15.879159 INFO : Found 3 releases
2016-10-28 13:28:15.879267 INFO : Removing old releases (before: 2017-01-01 01:01:01) but keeping: 1
2016-10-28 13:28:15.879319 INFO : Not removing old release: {'url': 'http://127.0.0.1/nexus/service/local/repositories/releases/content/nl/amis/smeetsm/releases/simplewebapp-release/5.0/simplewebapp-release-5.0.pom', 'date': datetime.datetime(2016, 10, 28, 11, 2, 39)} because keeping 1 releases
2016-10-28 13:28:15.879369 INFO : Removing old release: {'url': 'http://127.0.0.1/nexus/service/local/repositories/releases/content/nl/amis/smeetsm/releases/simplewebapp-release/4.0/simplewebapp-release-4.0.pom', 'date': datetime.datetime(2016, 10, 28, 10, 59, 26)} because: 2016-10-28 10:59:26<2017-01-01 01:01:01
2016-10-28 13:28:15.879409 INFO : delete_artifact http://127.0.0.1/nexus/service/local/repositories/releases/content/nl/amis/smeetsm/releases/simplewebapp-release/4.0/simplewebapp-release-4.0.pom
2016-10-28 13:28:15.879448 INFO : delete_artifact path: http://127.0.0.1/nexus/service/local/repositories/releases/content/nl/amis/smeetsm/releases/simplewebapp-release/4.0
2016-10-28 13:28:15.879492 INFO : Removing old release: {'url': 'http://127.0.0.1/nexus/service/local/repositories/releases/content/nl/amis/smeetsm/releases/simplewebapp-release/3.0/simplewebapp-release-3.0.pom', 'date': datetime.datetime(2016, 10, 28, 10, 59, 2)} because: 2016-10-28 10:59:02<2017-01-01 01:01:01
2016-10-28 13:28:15.879565 INFO : delete_artifact http://127.0.0.1/nexus/service/local/repositories/releases/content/nl/amis/smeetsm/releases/simplewebapp-release/3.0/simplewebapp-release-3.0.pom
2016-10-28 13:28:15.879605 INFO : delete_artifact path: http://127.0.0.1/nexus/service/local/repositories/releases/content/nl/amis/smeetsm/releases/simplewebapp-release/3.0
2016-10-28 13:28:15.879643 INFO : Releases removed: 2
2016-10-28 13:28:15.879685 INFO : Releases not removed: 1
2016-10-28 13:28:15.879718 INFO : New number of releases: 1
2016-10-28 13:28:15.890064 INFO : Found 1 release dependencies
2016-10-28 13:28:15.954508 INFO : Found 4 artifacts
2016-10-28 13:28:15.954577 INFO : Artifact found as dependency in release. Do not touch!: Artifact: {'url': 'http://127.0.0.1/nexus/service/local/repositories/releases/content/nl/amis/smeetsm/applications/simplewebapp/4.0/simplewebapp-4.0.pom', 'date': datetime.datetime(2016, 10, 28, 11, 3, 53), 'version': '4.0', 'groupid': 'nl.amis.smeetsm.applications', 'artifactid': 'simplewebapp'} Release: {'date': datetime.datetime(2016, 10, 28, 11, 2, 39), 'version': '4.0', 'pom': 'http://127.0.0.1/nexus/service/local/repositories/releases/content/nl/amis/smeetsm/releases/simplewebapp-release/5.0/simplewebapp-release-5.0.pom', 'groupid': 'nl.amis.smeetsm.applications', 'artifactid': 'simplewebapp'}
2016-10-28 13:28:15.954630 INFO : Artifact not found as dependency and old so remove: {'url': 'http://127.0.0.1/nexus/service/local/repositories/releases/content/nl/amis/smeetsm/applications/simplewebapp/3.0/simplewebapp-3.0.pom', 'date': datetime.datetime(2016, 10, 28, 10, 58, 41), 'version': '3.0', 'groupid': 'nl.amis.smeetsm.applications', 'artifactid': 'simplewebapp'}
2016-10-28 13:28:15.954646 INFO : delete_artifact http://127.0.0.1/nexus/service/local/repositories/releases/content/nl/amis/smeetsm/applications/simplewebapp/3.0/simplewebapp-3.0.pom
2016-10-28 13:28:15.954671 INFO : delete_artifact path: http://127.0.0.1/nexus/service/local/repositories/releases/content/nl/amis/smeetsm/applications/simplewebapp/3.0
2016-10-28 13:28:15.954728 INFO : Artifact not found as dependency and old so remove: {'url': 'http://127.0.0.1/nexus/service/local/repositories/releases/content/nl/amis/smeetsm/applications/simplewebapp/2.0/simplewebapp-2.0.pom', 'date': datetime.datetime(2016, 10, 28, 10, 58, 31), 'version': '2.0', 'groupid': 'nl.amis.smeetsm.applications', 'artifactid': 'simplewebapp'}
2016-10-28 13:28:15.954755 INFO : delete_artifact http://127.0.0.1/nexus/service/local/repositories/releases/content/nl/amis/smeetsm/applications/simplewebapp/2.0/simplewebapp-2.0.pom
2016-10-28 13:28:15.954770 INFO : delete_artifact path: http://127.0.0.1/nexus/service/local/repositories/releases/content/nl/amis/smeetsm/applications/simplewebapp/2.0
2016-10-28 13:28:15.954804 INFO : Artifact not found as dependency and old so remove: {'url': 'http://127.0.0.1/nexus/service/local/repositories/releases/content/nl/amis/smeetsm/applications/simplewebapp/1.0/simplewebapp-1.0.pom', 'date': datetime.datetime(2016, 10, 28, 10, 58, 18), 'version': '1.0', 'groupid': 'nl.amis.smeetsm.applications', 'artifactid': 'simplewebapp'}
2016-10-28 13:28:15.954818 INFO : delete_artifact http://127.0.0.1/nexus/service/local/repositories/releases/content/nl/amis/smeetsm/applications/simplewebapp/1.0/simplewebapp-1.0.pom
2016-10-28 13:28:15.954838 INFO : delete_artifact path: http://127.0.0.1/nexus/service/local/repositories/releases/content/nl/amis/smeetsm/applications/simplewebapp/1.0
2016-10-28 13:28:15.954852 INFO : Artifacts removed: 3
2016-10-28 13:28:15.954872 INFO : Artifacts not removed: 1

Thus there are 3 releases to be considered. All releases are before the requested clean date. 1 release needs to remain in the repository. The newest release version 5.0 is thus not removed. The newest release has artifact version 4.0 as a dependency. As you can see from the logging, this artifact is also not removed. At the top of the logging you can see I'm executing a dummy run so no releases or artifacts are actually removed. Would I have set dummy run to 'false' 2 releases and 3 artifacts would be removed. You can also see why the script removes or does not remove a release/artifact which allows you to easily look back in the log what has happened should questions arrise.

You can download the script here.

Oracle Service Bus: A quickstart for the Kafka transport

$
0
0
As mentioned on the following blog post by Lucas Jellema, Kafka is going to play a part in several Oracle products. For some usecases it might eventually even replace JMS. In order to allow for easy integration with Kafka, you can use Oracle Service Bus to create a virtualization layer around Kafka. Ricardo Ferreira from Oracle's A-Team has done some great work on making a custom Kafka Service Bus transport available to us. Read more about this here: http://www.ateam-oracle.com/osb-transport-for-apache-kafka-part-1/, http://www.ateam-oracle.com/oracle-service-bus-transport-for-apache-kafka-part-2/ and http://www.ateam-oracle.com/custom-transports-in-osb-12-2-1/The Kafka transport is not an 'officially supported' transport. Quote from the A-team blog: 'The Kafka transport is provided for free to use “AS-IS” but without any official support from Oracle. The A-Team reserves the right of help in the best-effort capacity.'. I hope it will become an officially supported part of the Service Bus product in the future.

In this blog I summarize what I have done to get the end to end sample working for SOA Suite 12.2.1.2.0 and Kafka 0.10.1.0 based on the blogs I mentioned. This allows you to quickly start developing against Apache Kafka.


Setting up Apache Kafka

Setting up Apache Kafka for development is easy. You follow the quickstart on: https://kafka.apache.org/quickstart. To summarize the quickstart:
- Unzip it: tar -xzf kafka_2.11-0.10.1.0.tgz
- Go to the Kafka directory: cd kafka_2.11-0.10.1.0
- Start ZooKeeper: bin/zookeeper-server-start.sh config/zookeeper.properties
- Start a new console
- Start the Kafka broker: bin/kafka-server-start.sh config/server.properties
- Create a topic: bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test

Setting up the Kafka transport in OSB

Copy the following files: 
– $KAFKA_HOME/libs/slf4j-api-1.7.21.jar
– $KAFKA_HOME/libs/kafka-clients-0.10.1.0.jar
To $OSB_DOMAIN/lib.

In my case this was /home/oracle/.jdeveloper/system12.2.1.2.42.161008.1648/DefaultDomain/lib. I'm using the JDeveloper IntegratedWebLogicServer


Extract the zip file.
Copy kafka-transport.ear and kafka-transport.jar to $MW_HOME/osb/lib/transports.

Start the domain

Execute install.py from the kafka-transport zipfile. Use wlst.sh in my case from: /home/oracle/Oracle/Middleware12212/Oracle_Home/oracle_common/common/bin/wlst.sh

Provide the required information. It will ask for Url, username, password of your WebLogic server and deploy the kafka-transport.jar and kafka-transport.ear to the specified server (AdminServer + cluster targets). If the deployments are already there, they are first undeployed by the script.

Stop the domain

The below part I got from the following blog: http://www.ateam-oracle.com/custom-transports-in-osb-12-2-1/. This is required to be able to configure the Kafka transport from the webinterface.

Locate the following file: $MW_HOME/osb/lib/osbconsoleEar/webapp/WEB-INF/lib/adflib_osb_folder.jar.

Extract this JAR and edit /oracle/soa/osb/console/folder/l10n/FolderBundle.properties.

Add the following entries:

desc.res.gallery.kafka=The Kafka transport allows you to create proxy and business services that communicate with Apache Kafka brokers.
desc.res.gallery.kafka.proxy=The Kafka transport allows you to create proxy services that receive messages from Apache Kafka brokers.
desc.res.gallery.kafka.business=The Kafka transport allows you to create business services that route messages to Apache Kafka brokers.

ZIP up the result as a new adflib_osb_folder.jar

Check the Service Bus console

After the above steps are completed, you can start the domain and use the Kafka transport from the servicebus console.






Setting up JDeveloper

Copy the JDeveloper plugin descriptor (transport-kafka.xml) to the plugins folder:
$MW_HOME/osb/config/plugins. In my case this is: /home/oracle/Oracle/Middleware12212/Oracle_Home/osb/config/plugins/. The Kafka transport, since it is a custom transport, is not visible in the regular palette. You can however do File, New, Proxy or Business service to use the Kafka transport.


You will not see possible options for consumer or producer settings but you can use the settings from: https://kafka.apache.org/documentation#consumerapi

Running an end to end sample

Apache Kafka provides shell scripts to test producing and consuming messages:
- Producing: bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test
- Consuming: bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning

It helps to add a report, log or alert action to your Service Bus pipeline so you can see messages which have passed. As a report key I have used the Kafka offset from $inbound: ./ctx:transport/ctx:request/tp:headers/kafka:offset



And now?

As you can see, several steps need to be performed to install this custom transport. It is only supported on a best-effort basis by the A-Team. I could not see options for properties in the Service Bus Console as was shown in the blog posts mentioned at the start of this post, but that is not a real issue since if a fixed set would be provided and more options would become available in a new version of Kafka, this might become limiting. It is a shame custom transports are not visible in the component palette in JDeveloper. Once you know however you can use the Kafka transport by creating Proxy and Business services from File, New this also becomes a non-issue.

There are of course other solutions to take care of the integration with Kafka such as using Kafka connectors or create a custom service to wrap Kafka, but I like the way this custom transport allows you to integrate it with Service Bus. This allows you to make Kafka only available through this channel. This offers options like easily applying policies, monitoring, alerting, etc. I do expect in Oracle's Cloud offering interaction with Kafka products running in the Oracle Cloud such as the Event Hub, will of course be much easier. We're looking forward to it.


Viewing all 142 articles
Browse latest View live