RSS

Creating a template in Oracle Service Bus 12C

Creating a template in Oracle Service Bus 12C

 
Leave a comment

Posted by on August 1, 2014 in JDeveloper, OSB

 

Tags: , , ,

Building a simple service using Oracle Service Bus 12C

Building a simple service using Oracle Service Bus 12C

 
Leave a comment

Posted by on July 31, 2014 in JDeveloper, OSB

 

Tags: , ,

Reference another project in SoapUI

For an example see here

 
Leave a comment

Posted by on March 30, 2014 in Uncategorized

 

Custom maven plugin

See an example here!

 
Leave a comment

Posted by on March 17, 2014 in Java

 

Tags: ,

Relocated

As for now….all my previous and new posts can be found on http://weblog.redrock-it.nl

 
Leave a comment

Posted by on March 14, 2014 in Uncategorized

 

Get numbers from Scrumwise through API

As you have seen from my previous posts, I have been using Scrumwise to help me facilitate Scrum in my projects. The think which I am missing but is on the wish-list is reporting. As teamlead I had to report to projectmanagers about progress, hours burned etc… All these things I can get from Scrumwise through its API. See https://www.scrumwise.com/api.html .

To get this done I wrote a simple Java program to get the a nice up-to-date printout of the stats. The first thing is you need to generate an API key in Scrumwise and get the code from there. Is this next bit I will show you how to connect to Scrumwise. It looks like this:


/**
* Connect to Scrumwise and get all the scrumwise details in a JSONObject
*
* @return JSONObject the result of the call
* @throws Exception
*/
private static JSONObject callScrumwise() throws Exception {

JSONObject result = null;

// Setup proxy
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(
"PROXY_IP", PROXY_PORT));
// Setup connection
URL url = new URL("https://api.scrumwise.com/service/api/v1/getData");
HttpURLConnection connection = (HttpURLConnection) url
.openConnection(proxy);
connection.setRequestMethod("POST");
connection.setDoOutput(true);

// setup credentials
String loginPassword = "SCRUMWISE_LOGIN:SCRUMWISE_KEY";
// Overwrite the setting or else it will cut of the encoded password
String encoded = new sun.misc.BASE64Encoder() {
@Override
protected int bytesPerLine() {
return 9999;
}
}.encode(loginPassword.getBytes());
connection.setRequestProperty("Authorization", "Basic " + encoded);
// setup POST parameters
String urlParameters = "projectIDs=null&includeProperties=Project.backlogItems,BacklogItem.timeEntries, BacklogItem.tasks, Task.timeEntries, Data.persons";

DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();

int responseCode = connection.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + urlParameters);
System.out.println("Response Code : " + responseCode);

BufferedReader in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();

while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();

// proces result
result = (JSONObject) JSONSerializer.toJSON(response.toString());
return result;

}

After that I loop through the items and pick out the backlogitems I need per project. I named the backlog items following the next convention: <project-code> <project-name>.


//project MyProject
private static String MyProject = "131206 MyProject: ";
//project MyProject backlog items
private static List<String> myprojectBacklogItems = new ArrayList<String>(Arrays.asList("Design", "Develop", "Test", "Coordinate"));

After this I call my generic method which prints me all the backlogitems with their hours and status. This looks something like this:


/**
* Print the houres used for a certain backlogitem in Scrumwise
*
* @param aJson
*            the JSON object which holds all the info
* @param aName
*            the name of the backlogitem
* @return the hours used
*/

private static void printUsedTimePerBacklogItem(JSONObject aJson, String aName) {

int result = 0;

JSONArray projects = (JSONArray) aJson.getJSONObject("result").getJSONArray("projects");
//loop through all projects
for (int i = 0; i < projects.size(); i++) {

JSONObject project = projects.getJSONObject(i);
JSONArray backlogitems = project.getJSONArray("backlogItems");

//loop through all backlogitems
for (int j = 0; j < backlogitems.size(); j++) {
JSONObject backlogItem = backlogitems.getJSONObject(j);
//filter only the mosaic backlogitems
if (backlogItem.getString("name").startsWith(aName)) {
System.out.printf("\n====================================================================================================================================================================\n");
int backlogTime = backlogItem.getInt("usedTime");
if (backlogTime < 0) {
backlogTime = 0;
}
System.out.printf("Subject | %-115s = %-3s uur | %s \n", backlogItem.getString("name"), backlogTime, backlogItem.getString("status"));
// get tasks under backlogitem
JSONArray tasks = backlogItem.getJSONArray("tasks");
for (int l = 0; l < tasks.size(); l++) {
JSONObject task = tasks.getJSONObject(l);
int taskTime = task.getInt("usedTime");
if (taskTime < 0) {
taskTime = 0;
}
System.out.printf("Task | %-120s = %-3s uur | %s \n", task.getString("name"), taskTime, task.getString("status"));
}
}

}
}
}

In the end….when you run all this you will get a simple output of the all the items which will look something like this:

Sending ‘POST’ request to URL : https://api.scrumwise.com/service/api/v1/getData
Post parameters : projectIDs=null&includeProperties=Project.backlogItems,BacklogItem.timeEntries, BacklogItem.tasks, Task.timeEntries, Data.persons
Response Code : 200

MyProject: hours per item

====================================================================================================================================================================
Subject | 131206 MyProject: Design                                                   = 99  uur | Sprint completed
Task | Design Database                                                                                               = 99  uur | Done

====================================================================================================================================================================
Subject | 31206 MyProject: Develop                                        = 31  uur | In progress
Task | Create proxy service                                                           = 11  uur | Done
Task | Create business service                                                                      = 4   uur | Done
Task | Create xquery                                                       = 4   uur | In progress
Task | Import WSDL’s                                                                                                        = 6   uur | Done
Task | Junit test                                                                                                               = 6   uur | In progress

…….etc

As you can see I haven’t really spend a lot of time optimizing code etc as i needed something quick and dirty and this does the job. Still work in progress but it will give you an idea of what is possible.

 
Leave a comment

Posted by on December 6, 2013 in Java, Scrum/Agile

 

Tags: , ,

Scrumwise review

I have been a fan of Scrum for many years now. I did my Scrummaster course in 2007 with Jeff Sutherland and since then, I try to use Scrum on every project I participate on. At most companies you can grab a blank wall and stick a piece of paper on it to create a physical Scrum board. The company I work for now didn’t have that luxury so I went out to look for a virtual scrumboard.

I came across several SaaS solutions which offered this functionality such as Mingle and Scrumworks but I also came across Scrumwise (http://www.scrumwise.com)

scrumwise

I registered and gave it a whirl.

Functionality:
The thing I like the most is that it’s basic and comprehensible. You can easily create tasks and sub-task and make a sprint planning. The burn down is clear and it’s your own choice whether you want to use story point, hours or just a percentage to track the progress of the work items. The team also like the simplistic interface which you can use to move tasks around and update the board.

Security:
One of the requirements of the company was that, as it is a SaaS solution, the data wasn’t located on American soil due to the patriot act. I asked about it and all of Scrumwise, both application and data, is hosted in Amazon’s European data centers, which are located in Ireland. So no problem there.

Support:
You can notice that is a solution which is being improved. Esben Krag Hansen which is the man behind Scrumwise is always available for questions and open for improvements. Patches or improvements are done regularly and I haven’t had any problems there yet. They just released an API which you can use to create or manipulate your scrum data.

Pricing:
You pay per user….easy. It is $6,- per user per month. Payment is easily done every month by credit card.

To sum it all up…..I really like this piece of software due to its simplicity and way of working. Thumbs up from our scrum team.

 
1 Comment

Posted by on May 29, 2013 in Scrum/Agile

 

Tags: , ,

Dynamic routing in the OSB

In this post I will show how it is possible to make a dynamic routing in the OSB. You can use this if you need to route to different BusinessServices dependant of information you have. First we have to create a ProxyService CustomerService. As a last step insert an Routing element with a Dynamic Routing in it.

Route2Customers

We also create 2 BusinessServices where BS_CustomerA calls customers A service and BS_CustomerB calls customers B service. They both have an operation called Order. Dependant on certain information in our process we want to route to customer A or customer B. How do we do this? We will have to create a XQuery which will determine which BusinessService to call. This will have to look something like this:

(:: pragma  type="ctx:route" ::)

declare namespace xf = "http://www.rubix.nl/test/routingexample/";
declare namespace ctx = "http://www.bea.com/wli/sb/context";

declare function xf:mapping ()
    as element(*) {
    <mappings>
        <mapping>
            <Customer>A</Customer>
            <Service>CustomerService/business/CustomerServiceA</Service>
        </mapping>
        <mapping>
            <Customer>B</Customer>
            <Service>CustomerService/business/CustomerServiceB</Service>
        </mapping>
    </mappings>
};

declare function xf:checkDefault($value as xs:string*)
    as xs:string {
    if (exists($value))
    then $value
    else xf:mapping()/mapping[Customer="A"]/Service/text()
};

declare function xf:selectBusinessService($customer as xs:string)
    as xs:string {
    xf:checkDefault(xf:mapping()/mapping[Customer=$customer]/Service/text())
};

declare function xf:DetermineCustomerEndpoint($customer as xs:string)
    as element(*) {
    <ctx:route>
        <ctx:service isProxy="false">{ xf:selectBusinessService($customer) }</ctx:service>
        <ctx:operation>Order</ctx:operation>
    </ctx:route>
};

declare variable $customer as xs:string external;

xf:DetermineCustomerEndpoint($customer)

This piece of XQuery will set the mapping to the CustomerA businessservice if the customer string is A and to CustomerB business service if the customer is B. If the value is empty, it will also choose Customer A. Now we only need to make the Dynamic Routing make use of this XQuery. We can do this by selecting the xquery and setting the customer variable.

xqueryl

If $customer is ‘A’ it will call BS_CustomerA and if $customer is ‘B’ it will call BS_CustomerB and if empty it will also call BS_CustomerA.

 
Leave a comment

Posted by on March 13, 2013 in OSB

 

Tags: , ,

Converting JSON to XML in the OSB when consuming a REST service.

In my previous post I showed you how you could consume the Google Geo service using the OSB. In that example we used XML as the return format. It was also possible to return JSON. JSON stands for JavaScript Object Notation and is smaller then XML and faster en easier to parse. The JSON text format is syntactically identical to the code for creating JavaScript objects. That is why it is used more often now by frontend frameworks such as Apache Isis for example.

In this post I will show you how you can parse the JSON returned from Google using the OSB. To convert XML to JSON and JSON to XML, you can create a helper class in Java which can do this for you. Make the convenience methods public and static so you can use them in a Java Callout in the OSB. My class looks like this:

package nl.rubix.common;

import net.sf.json.JSON;
import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;
import net.sf.json.xml.XMLSerializer;

/**
 * This class hold a couple of static methods which can be used to convert xml to json and json into xml.
 * @author Hugo Hendriks
 *
 */
public class XMLJSONConverter {

	/**
	 * Converts a Json String to a XML string
	 * @param aRootName the name of the root element in the xml
	 * @param aJson the json string
	 * @return null or a string which holds the xml representation of the json string
	 * @throws Exception
	 */
	public static String convertJSON2XML(String aRootName, String aJson) throws Exception {
		String result = null;

        XMLSerializer xmlSerializer = new XMLSerializer();
        xmlSerializer.setRootName(aRootName);
        JSON json = JSONSerializer.toJSON( aJson );
        result = xmlSerializer.write( json );
        return result;
	}

	/**
	 * Convert a XML string to a json string
	 * @param aXml the XML string
	 * @return null or a string which holds the json representation of the xml string
	 * @throws Exception
	 */
	public static String convertXML2JSON(String aXml) throws Exception {
		String result = null;

		XMLSerializer xmlSerializer = new XMLSerializer();
		xmlSerializer.setTypeHintsEnabled(false);
		JSONObject json = (JSONObject) xmlSerializer.read(aXml);
		result = json.toString();
        return result;
	}

}

I use maven as my build tool and my pom file looks like this:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>nl.rubix.common</groupId>
	<artifactId>XmlJsonConverter</artifactId>
	<version>1.0</version>
	<name>XmlJsonConverter</name>
	<description>This library can be used to convert XML into JSON and back again</description>

	<dependencies>
		<dependency>
			<groupId>net.sf.json-lib</groupId>
			<artifactId>json-lib</artifactId>
			<version>2.4</version>
			<type>jar</type>
			<classifier>jdk15</classifier>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-io</artifactId>
			<version>1.3.2</version>
			<type>jar</type>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>xom</groupId>
			<artifactId>xom</artifactId>
			<version>1.2.5</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.10</version>
			<type>jar</type>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-dependency-plugin</artifactId>
				<version>2.5.1</version>
				<executions>
					<execution>
						<id>copy-dependencies</id>
						<phase>package</phase>
						<goals>
							<goal>copy-dependencies</goal>
						</goals>
						<configuration>
							<outputDirectory>${project.build.directory}/libs</outputDirectory>
							<overWriteReleases>true</overWriteReleases>
							<overWriteSnapshots>true</overWriteSnapshots>
							<overWriteIfNewer>true</overWriteIfNewer>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>

You can see I am using the Maven dependency plugin to create a directory which holds all the dependencies jars. This is done because I need a few of these libraries on the weblogic server. In the MY_DOMAIN/lib directory to be precise.

This is the case for:

  • json-lib-2.4-jdk15.jar
  • ezmorph-1.0.6.jar
  • xom-1.2.5.jar

You can get these from the libs directory created by maven when you run the mvn -clean -package target. The other libraries are already available in Weblogic.

After this, you can add your XMLJSONConverter library to your project.

Then you can make a java callout in which you can convert the received json into a xml string.

After that, you can parse the string to real xml by making use of the fn-bea:inlinedXML() function.

So now you know how you can convert JSON to XML and vice versa.

Example was made in 11G PS4

 
3 Comments

Posted by on November 1, 2012 in Java, OSB

 

Tags: , ,

Consuming Google Geo REST service using the OSB

In this article I will explain how you can make use of the Google Geo Service API using the OSB. Check out this page to see what we can do with this API. Basically it makes it possible to enter address details and Google comes up with the geographical details including longitude and latitude if Google can find it. The result can either be returned as JSON or as XML. In this example we are going build a webservice in the OSB which will call Google and transform the returned XML into a nice response.

So lets start with making a simple WSDL which is going to expose the Google API. Mine looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="GeoService" targetNamespace="http://www.rubix.nl/geo/service" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://www.rubix.nl/geo/service" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:geo="http://www.rubix.nl/geo/service/schema">
	<wsdl:types>
		<xsd:schema targetNamespace="http://www.rubix.nl/imports" elementFormDefault="qualified">
			<xsd:import schemaLocation="../Schemas/GeoService.xsd" namespace="http://www.rubix.nl/geo/service/schema" />
		</xsd:schema>
	</wsdl:types>
	<wsdl:message name="GetGeocodeRequest">
		<wsdl:part name="parameters" element="geo:GetGeocodeRequest">
		</wsdl:part>
	</wsdl:message>
	<wsdl:message name="GetGeocodeResponse">
		<wsdl:part name="parameters" element="geo:GetGeocodeResponse">
		</wsdl:part>
	</wsdl:message>
	<wsdl:portType name="GeoService">
		<wsdl:operation name="GetGeocode">
			<wsdl:input message="tns:GetGeocodeRequest">
			</wsdl:input>
			<wsdl:output message="tns:GetGeocodeResponse">
			</wsdl:output>
		</wsdl:operation>
	</wsdl:portType>
	<wsdl:binding name="GeoService" type="tns:GeoService">
		<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
		<wsdl:operation name="GetGeocode">
			<soap:operation soapAction="http://www.rubix.nl/geo/service"/>
			<wsdl:input>
				<soap:body use="literal"/>
			</wsdl:input>
			<wsdl:output>
				<soap:body use="literal"/>
			</wsdl:output>
		</wsdl:operation>
	</wsdl:binding>
	<wsdl:service name="GeoService">
		<wsdl:port name="GeoServicePort" binding="tns:GeoService">
			<soap:address location="http://www.rubix.nl/geo/service"/>
		</wsdl:port>
	</wsdl:service>
</wsdl:definitions>

With the data defined in a seperate file GeoService.xsd.

<?xml version="1.0" encoding="UTF-8"?>
<!-- edited with XMLSpy v2011 rel. 2 sp1 (http://www.altova.com) by Hugo Hendriks (Rubix) -->
<xsd:schema xmlns:tns="http://www.rubix.nl/geo/service/schema" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.rubix.nl/geo/service/schema" elementFormDefault="qualified">
	<xsd:element name="GetGeocodeRequest">
		<xsd:complexType>
			<xsd:sequence>
				<xsd:element name="Street" minOccurs="1" maxOccurs="1" type="xsd:string"/>
				<xsd:element name="Number" minOccurs="1" maxOccurs="1" type="xsd:integer"/>
				<xsd:element name="City" minOccurs="1" maxOccurs="1" type="xsd:string"/>
			</xsd:sequence>
		</xsd:complexType>
	</xsd:element>
	<xsd:element name="GetGeocodeResponse">
		<xsd:complexType>
			<xsd:choice>
				<xsd:element ref="tns:Messages"/>
				<xsd:sequence>
					<xsd:element name="Longitude" type="xsd:string"/>
					<xsd:element name="Latitude" type="xsd:string"/>
				</xsd:sequence>
			</xsd:choice>
		</xsd:complexType>
	</xsd:element>
	<xsd:element name="Messages">
		<xsd:complexType>
			<xsd:sequence>
				<xsd:element name="Message">
					<xsd:complexType>
						<xsd:sequence>
							<xsd:element name="Code">
								<xsd:annotation>
									<xsd:documentation>The code</xsd:documentation>
								</xsd:annotation>
							</xsd:element>
							<xsd:element name="Description">
								<xsd:annotation>
									<xsd:documentation>The description</xsd:documentation>
								</xsd:annotation>
							</xsd:element>
						</xsd:sequence>
					</xsd:complexType>
				</xsd:element>
			</xsd:sequence>
		</xsd:complexType>
	</xsd:element>
</xsd:schema>

First we are going to create a business service which will call Google. Create it as a messaging service:

Set the Request Message Type to none and the Response Message Type to XML.

And finally set the Endpoint URI to http://maps.googleapis.com/maps/api/geocode/xml

Next we are going to create a proxy service which uses the created WSDL.

After this we do the usuall stuff we want to do in our flow like a bit of logging, validation and errorhandling. As a last step insert a Route and a Routing and select the BusinessService we created.

But now for the good part. We need to make a HTTP GET request to Google with a certain set of http-parameters. You can test this in your own browser by using the following example URI: http://maps.googleapis.com/maps/api/geocode/xml?address=koningsplein+1+amsterdam&sensor=false&language=nl. Try and input your own address in there to see if Google can find it for you. In this case the http-parameters are: address=koningsplein+1+amsterdam. The sensor=false means we are not using a measuring device and the language parameter speaks for itself. Oke…..how do we make a HTTP GET request to Google using these parameters. You can accomplish this by adding an Insert action to you Route with the following settings:

This insert chances the HTTP request from a PUT to a GET. The next step is to set the http-parameters. This is done like this:

You can see we insert another piece of xml into the outbound variable. We are using an XQuery to create this piece of xml. Mine looks like this:

(:: pragma bea:global-element-parameter parameter="$GetGeocodeRequest" element="geo:GetGeocodeRequest" location="../Schemas/GeoService.xsd" ::)
(:: pragma bea:global-element-return element="http:query-string" location="../Schemas/HttpTransport.xsd" ::)

declare namespace http = "http://www.bea.com/wli/sb/transports/http";
declare namespace geo = "http://www.rubix.nl/geo/service/schema";
declare namespace xf  = "http://www.rubix.nl/transformation/SoapToHttpGet/";

declare function xf:SoapToHttpGet($GetGeocodeRequest as element(geo:GetGeocodeRequest))
    as element(http:query-string) {
        <http:query-string>{ concat("address=",$GetGeocodeRequest/geo:Street , "+" ,$GetGeocodeRequest/geo:Number, "+",
                           					 $GetGeocodeRequest/geo:City, "&sensor=false&language=nl") }
        </http:query-string>
};

declare variable $GetGeocodeRequest as element(geo:GetGeocodeRequest) external;

xf:SoapToHttpGet($GetGeocodeRequest)

You can see we create a query-string element using the request we receive from the user. The HttpTransport.xsd is needed for this which also has some references to ther xsd’s (EnvValues.xsd, MessageContext.xsd and TransportCommon.xsd) so make sure to put these in your Schemas directory. So in the end, my project looks like this:

When we make the call to Google, we receive XML back which we want to transform into a response previously defined. First we check if we receive an answer at all or multiple answers.

Next we transform the response into our pre-defined response using a replace of the body.

<sch:GetGeocodeResponse>
	<sch:Longitude>{$body/GeocodeResponse/result/geometry/location/lng/text()}</sch:Longitude>
	<sch:Latitude>{$body/GeocodeResponse/result/geometry/location/lat/text()}</sch:Latitude>
</sch:GetGeocodeResponse>

Now lets deploy and test the service.Lets use the previously used parameters for the call in the browser which where Koningsplein 1 in Amsterdam. You test in the webconsole should look something like this:

As you can see we receive the latitude and logitude for the address. As we look deeper into the Route we can see how the $outbound is transformed:

So now you know how you can consume a REST service using the OSB.

btw: You can make a maximum of 2500 calls per day using this service. If you want to make more calls, you have to get a business account.

 
Leave a comment

Posted by on October 25, 2012 in OSB

 

Tags: , ,