Pages

Friday, January 16, 2009

JBoss Drools: Reasoning on QuickFIX-J data model

I just tried to make a simple JBoss Drools example which could probably handle QuickFIX-J messages. So I created the simplest rule flow, including one RuleSet node, mapped onto a ruleflow-group in a DRL file.

Simple Drools Flow Example
same in textual form:

<?xml version="1.0" encoding="UTF-8"?>
<process xmlns="http://drools.org/drools-5.0/process"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xs:schemaLocation="http://drools.org/drools-5.0/process drools-processes-5.0.xsd"
type="RuleFlow" name="oms" id="my.oms" package-name="my.oms" >

<header>
</header>

<nodes>
<start id="1" name="Start" x="16" y="16" width="80" height="40" />
<actionNode id="2" name="Action" x="128" y="16" width="80" height="40" >
<action type="expression" dialect="java" >System.out.println("Action Start");</action>
</actionNode>
<ruleSet id="3" name="RuleSet" x="240" y="16" width="80" height="40" ruleFlowGroup="my-oms" />
<actionNode id="4" name="Action" x="352" y="16" width="80" height="40" >
<action type="expression" dialect="java" >System.out.println("Action End");</action>
</actionNode>
<end id="5" name="End" x="464" y="16" width="80" height="40" />
</nodes>

<connections>
<connection from="1" to="2" />
<connection from="2" to="3" />
<connection from="3" to="4" />
<connection from="4" to="5" />
</connections>

</process>


Next describe to rule in a DRL file:


package my.oms

import quickfix.fix44.NewOrderSingle
import quickfix.field.MinQty

rule "reset minqty"
dialect "mvel"
ruleflow-group "my-oms"
when
$order : NewOrderSingle($qty : minQty)
MinQty(value == 1.0 || value > 100.0) from $qty
then
System.out.println("reset order: " + $order);
modify($order){
$order.set(new MinQty(20));
}
end

What looks a little strange to me is the when part:

$order : NewOrderSingle($qty : minQty)
MinQty(value == 1.0 || value > 100.0) from $qty

I spent just quite a few minutes to figure out why my first version of the rule didn't work as I expected. It seemed to me that it would be more natural to make it just in one line, something like this:

NewOrderSingle(MinQty(value == 1.0 || value > 100.0))


With a Java code from the Drools examples (which may also are generated when you create a Drools Project with the Drools eclipse plug-in), I run the example and it works fine.

package my.oms;

import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.*;
import org.drools.io.ResourceFactory;
import org.drools.logger.KnowledgeRuntimeLogger;
import org.drools.logger.KnowledgeRuntimeLoggerFactory;
import org.drools.runtime.StatefulKnowledgeSession;

import quickfix.field.MinQty;
import quickfix.fix44.NewOrderSingle;


public class MyOms {

public static final void main(String[] args) {
try {
// load up the knowledge base
KnowledgeBase kbase = readKnowledgeBase();
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
// go !

NewOrderSingle order = new NewOrderSingle();
order.set(new MinQty(1.0));

NewOrderSingle order1 = new NewOrderSingle();
order1.set(new MinQty(111.0));

NewOrderSingle order2 = new NewOrderSingle();
order2.set(new MinQty(222.0));

ksession.insert(order);
ksession.insert(order1);
ksession.insert(order2);
ksession.startProcess("my.oms");
ksession.fireAllRules();

logger.close();
} catch (Throwable t) {
t.printStackTrace();
}
}

private static KnowledgeBase readKnowledgeBase() throws Exception {
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("oms.drl"), ResourceType.DRL);
kbuilder.add(ResourceFactory.newClassPathResource("oms.rf"), ResourceType.DRF);
KnowledgeBuilderErrors errors = kbuilder.getErrors();
if (errors.size() > 0) {
for (KnowledgeBuilderError error: errors) {
System.err.println(error);
}
throw new IllegalArgumentException("Could not parse knowledge.");
}
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
return kbase;
}

}


This example just shows that with Drools one may handle even quite complex data model, such as QuickFIX-J's one. Next, it would have real value if I'm able to make do the same via Guvnor.

Sunday, January 11, 2009

Comparing Strings in C: Wii hack

I've just read an article about game console hacking: Console Hacking 2008: Wii Fail.
One interesting code fragment that was acquired in binary decompilation process:
strncmp(SHA1_sig, SHA1_in, 20);

SHA1_sig, SHA1_in are actually binaries, but are compared like strings, and if both of them start with \0 the strncmp will say that they are equal even if everything else is different.
(As I'm not a C expert to believe it right away) I made a simple code fragment to see it myself:

#include
#include

int main(){
char* x;
char* y;
int res;

x = "\0hello";
y = "\0bye";

res = strncmp(x, y, 20);

printf("The C strings %s and %s are ", x, y);
if (res == 0){
printf("equal\n");
} else {
printf("not equal\n");
}
return 0;
}

So the result will be:
$> ant@ubuntu:~$ gcc test.c ; ./a.out
The C strings and are equal



So ... happy hacking! :)

Wednesday, January 7, 2009

java.lang.System#getenv(String)

java.lang.System#getenv method was deprecated in Java 1.4:
public static String getenv(String name) {
throw new Error("getenv no longer supported, use properties and -D instead: " + name);
}

I would expect this method to be disappeared in Java 5, but due to the huge number of requests, the method was re-implemented again: bug4199068
This is a little strange because if the API was deprecated, you would expect this part to be removed in the next major version. But here, we can see the community influence to the technology :)

Sunday, January 4, 2009

SpringSource + Adobe = SpringFramework + Flex

Late in 2008 SpringSource, the SpringFramework vendor, and Adobe, the father of Flex, have partnered to deliver rich Internet applications to Java developers via integration between Spring and Adobe’s Flex.
It was announced that
with support from Adobe, SpringSource is introducing Spring BlazeDS Integration

And just in a few weeks an M1 version for BlazeDS integration was public. This is exactly what I need for my current project, and I can use now an available component, without recreating the wheel :)

Spring, Adobe Partner for Java RIA
Adobe and SpringSource Promise Enhanced Flash-Java Integration
Using BlazeDS with Spring

AOP for Workfow Orchestration

At InfoQ, Oleg Zhurakousky from SpringSource has published an article about Workflow Orchestration Using Spring AOP and AspectJ. The article describes what is needed to implement a flow-like process, to make it flexible and configurable using AOP techniques. I would suggest this article to everyone who is dealing with data flow orchestration and batch processing at work.
Process is a collection of coordinated activities that lead to accomplishing a set goal

Oleg distinguishes the following attributes in his description:
  • Activities - activities defining this process

  • Shared data/context - defines mechanism to share data and facts accomplished by the activities

  • Transition rule - defines which activity comes next after the end of previous activity, based on the registered facts

  • Execution Decision - defines mechanism to enforce Transition rule

  • Initial data/context (optional) - initial state of the shared data to be operated on by this process

This is actually very similar from what we experienced in designing batch processes using SpringFramework at Swedbank.
I'm happy to see that what we did looks very similar to the example from the article.

Wednesday, December 17, 2008

SSH Tips-and-Tricks

I have some ssh tips that I'm using time to time to connect to the university servers. This is cool because I can use the software from the university labs while being at home. So I don't need to drive 20 km both ways just for a single experiment.

X11 forwarding

You can encrypt X sessions over SSH. Not only is the traffic encrypted, but the DISPLAY environment variable on the remote system is set properly. So, if you are running X on your local computer, your remote X applications magically appear on your local screen.

You can enable X11 forwarding with ssh -X host.


Compressing data

SSH can use gzip compression on any connection. The default compression level is equivalent to approximately 4x compression for text. Compression is a great idea if you are forwarding X sessions on a dial-up or slow network. Turn on compression with ssh -C.


Roaming behind the firewall.

Suppose you have to connect to machines, that are located in some remote place behind a firewall. The gateway "G" is a remote server that has the authority to connect to those machines.

What we would like to do is to use any kind of X11 UI on workstation A, for instance. We need two ssh tunnels to connect to the workstations. With the first tunnel we will remap the local port using -L option. The general syntax will be:

ssh -L{local_port}:{workstation}:{remote_port} {user}@{hostname}

After this the gateway will become transparent for us. The second tunnel created for localhost will actually go forward to the gateway and connect to {workstation}.

ssh -X -o "HostKeyAlias {workstation}" {user}@localhost

Given the example above, let's try to connect user "ant" to the workstation "corona" via "aragorn" gateway. Note that we want to use X11 forwarding to be able to work with graphical environment. There are several ways to do this. I'll describe two possible solutions here (assuming that you have M$ Windows running on your PC).


Cygwin

With Cygwin environment one may get the connection to the workstation using following steps.

  1. Start cygwing environment

  2. Start X11 environment, type strartx

  3. Ensure you have at least two xterm windows. Type xterm & to start another xterm

  4. Create first SSH tunnel: ssh -L2222:corona:22 ant@aragorn

  5. In another xterm window create the second SSH tunnel: ssh -X -C -o "HostKeyAlias corona" -p 2222 ant@localhost




To verify is the X forwarding works fine, just type any app. name to the remote xterm, like xclock - and the xclock application should open on your machine while actually running on the remote host.


WinAxe + Putty

If you don't have cygwin environment installed and you're unwilling to install it, then we have another solution here. WinAxe and putty can be used to create the same SSH tunnels as with cygwin. Follow the steps:


  1. Install WinAxe, and run XSession

  2. Start putty, specify the connection parameters and create a tunnel as shown on the pictures below.



  3. Start another putty window and create new tunnel against localhost with X-forwarding enabled.




After putty sessions are started you can do the same trick again as with cygwin, start a remote application so that it looks like running on your machine.

Tuesday, December 2, 2008

Oracle 10g JDBC driver and BigDecimal.toString()

I would like to share an issue with you regarding Oracle 10g JDBC driver and migration to Java 5.

Recently we encountered a production bug where a client got some extra money on his/her account. The bug appeared with Oracle JDBC driver (ojdbc14.jar) version 10.1.0.4 once we migrated the application to Java 5 from Java 1.4.

In order to safe the precision in Java it is the common practice to use BigDecimals. Oracle driver, while binding the objects to SQL types, is calling BigDecimal.toString() method. In Java 5, the method was altered in order to support JSR-13:Decimal Arithmetic Enhancement standard. This issue exists in Sun bug database

Here's a piece of code to reproduce this problem:
-- table for the test
create table test_table ( value number )


// java code to reproduce the behaviour
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class HelloFromOracle {
public static void main(String[] args) throws Exception {
Class.forName("oracle.jdbc.OracleDriver");
Connection connection = DriverManager.getConnection("jdbc:oracle:thin:user/passwd@DB:1521:SID");
String query = "insert into test_table values (?)";
PreparedStatement stmt = connection.prepareStatement(query);
BigDecimal bd = new BigDecimal("0.000000000000001");
stmt.setBigDecimal(1, bd);
stmt.execute();
stmt.close();
connection.close();
}
}


Now, with Oracle driver v 10.1.0.4 the value in database will be:
> select * from test_table
VALUE
-------------------------
5115

... And with Oracle driver v 10.1.0.5
> select * from test_table
VALUE
-------------------------
0.000000000000001


So my message is to replace the Oracle driver 10.1.0.4 to 10.1.0.5, especially with migration to Java 5 from Java 1.4. What is interesting is that oracle driver 8.1.7.4 doesn't suffer from this problem.

Thursday, November 20, 2008

Code Kata: The Business Rules

I'm thinking of an application for JBoss Drools. We are given a task to design a system for order management (OMS), which will sit behind a FIX gateway and serve several internal and external systems. One thing is for sure - we are to take a challenge to organize and maintain a large set of business rules and this brings up some memories.

In 2004 a colleague told me about code kata. These are the good exercises to do when learning a new language, or just empirically solve some common problems. One of the puzzlers sit in my mind permanently since then - The Business Rules Kata, which is about the hard to maintain complex business rules.
How can you tame these wild business rules? How can you build a system that will be flexible enough to handle both the complexity and the need for change? And how can you do it without condemming yourself to years and years of mindless support?

We face all these problems daily while coding the business logic for our banking system. One of the approaches some developers have taken is that
the if-the statements can be avoided while using appropriate OOP techniques

The problem is that sometimes while avoiding those if-statements the code becomes over-engineered due to a large number of classes. And it is still doesn't solve the problem of quick changes that are very hard to implement in a big organization with the "release process".

Recently I've found a discussion at joelonsoftware.com. It is dated 2005 but I think not much have changed since then. I think that most of the developers are still fighting the complexity of the business rules and in future it will still be a challenge.

My next step is to create a demo using JBoss Drools, QuickFIX/J. Apache Camel can be used to integrate both into one flow.

Also what is really cool about Drools is that it would allow our clients to maintain the order validation rules apart of the overall release process using Guvnor. So the changes in order validation logic could be introduced rapidly.

The TAGRI Approach To Ducumentation

I found a nice blog post called Developers Aren't Gonna Read It about the software requirements documentation principles, which actually refers to Scott W. Ambler's post called The TAGRI (They Aren't Gonna Read It) Principle of Software Development.
The idea behind these posts is that the developers do not read documentation. And to be honest - yes! it is true! I don't remember myself reading the documentation for a long time. In fact, I don't remember if I really have read a single document produced by analyst from start to end. Thinking of the man-hours spent on the documentation by analysts it may be horrible to calculate the total cost that was spent to produce these documents.
I was responsible for the web UI part of this system (100 pages) but had to understand also how the backend works (200 pages). ... So, did I read the documentation? I didn't. I didn't have to because I preferred direct communication with the guys who know the system throughout.

Indeed, a very familiar situation.
Not all documentation sucks. ... the best documentation is the one that is very easily changeable. Wiki is the best option here - it's easily searchable (through many projects) and changeable.

I love wiki! IMHO, it is one of the best approaches to the communication and to hold the documentation, tips-and-tricks, tutorials, etc.

To me, the best solution is to really communicate verbally. Make it to the whiteboard and draw some concepts together with the analyst. It ensures we both use the same terms, and both understand the domain of the problem. I hope our team members feel the same.

Tuesday, November 18, 2008

Creating Database Link (aka DBLINK) in Oracle

I had to mess with Oracle database links recently. Here's a good reference to the "CREATE DATABASE LINK" sentence syntax.

In my case it was:
CREATE PUBLIC DATABASE LINK MYLINK CONNECT TO USER IDENTIFIED BY PASSWORD USING 'mydb';


'mydb' has to be an entry in ORACLE_HOME/network/admin/tnsnames.ora file on the server side Oracle client installation, so that the host database can see the foreign one (which is 'mydb').

Next, make sure that sqlnet is configured to use tnsnames.ora file. Its configuration is defined ORACLE_HOME/network/admin/sqlnet.ora, which contains client side network configuration parameters (again, on the server side!). For instance:

NAMES.DIRECTORY_PATH=(TNSNAMES, LDAP)


Next, we could test this database link:

SELECT * FROM dual@mydb;


Now it makes sense to use a synonym to point to the foreign table.

CREATE SYNONYM MYSYNONYM FOR dual@mydb;


Now the initial query will look as follows:

SELECT * FROM MYSYNONYM;

Disqus for Code Impossible