Friday, December 1, 2006

A minimal Ruby Web Service client

Five lines of code are enough to write a Web Service client in Ruby:

require 'soap/wsdlDriver'

wsdl = 'http://www.webservicex.com/CurrencyConvertor.asmx?wsdl'
driver = SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver
input = {:FromCurrency => 'USD', :ToCurrency => 'EUR' }
print driver.ConversionRate(input).conversionRateResult


Save this file as "currency.rb" and run it from command line with:

ruby currency.rb

JUnit testing JMS systems with Netbeans and Mockrunner

Scenario


You are developing a JMS-based application and you want to use those nice test-driven development habits that you have learned are so good in keeping your code clean and bug-free, but sending messages to a real JMS server is slowing down your edit - compile - test process. First because you always need to remember to start your JMS server each morning, second because running JUnit against the real system is a bit slow. Maybe you have an external server hosting your JMS server, so the first point does not apply to you, but in my case I use to run everything on my laptop, so it does matter.

A mock JMS implementation


Here is where Mockrunner comes in the scene.

"Mockrunner is a lightweight framework for unit testing applications in the J2EE environment. It supports servlets, filters, tag classes and Struts actions and forms. Furthermore it includes a JDBC, a JMS and a JCA test framework and can be used in conjunction with MockEJB to test EJB based applications.

Mockrunner extends JUnit and simulates the necessary behaviour without calling the real infrastructure. It does not need a running application server or a database. Furthermore it does not call the webcontainer or the Struts ActionServlet. It is very fast and enables the user to manipulate all involved classes and mock objects in all steps of the test. It can be used to write very sophisticated unit-tests for J2EE based applications without any overhead. Mockrunner does not support any type of in-container testing."


Actors


Setup

Download the mockrunner-0.3.7.zip file and unzip it somewhere. Then you need to setup your Netbeans project to make use of Mockrunner's libraries.


Add Mockrunner libs to your project's test library by right-clicking the libraries node in your project and selecting "Properties"


In my case I'm connecting to CAPS JMS server, so I need both jms.jar and com.stc.jmsis.jar files. The latter is part of the CAPS eGate APIkit distribution and allows to connect to Sun SeeBeyond JMS server implementation from a generic Java client: you need to put here your specific JMS server client libraries. My intention is to run my custom Java application against the real JMS server (as said, in my case it is CAPS), but to run automatic JUnit tests against the mock implementation.


Now add Mockrunner's necessary libraries to the "Compile-time Test Libraries" tab:



The final result should looks like the picture below:


A simple test-case

Here I show a simple test for the "sendText" method of my class which uses Mockrunner's stubs. Mockrunner internally uses MockEJB libraries to simulate a J2EE container:

/*
 * TesterTest.java
 * JUnit based test
 *
 * Created on 28 November 2006, 17:33
 */
package it.stc.meter.jms;

import com.mockrunner.ejb.EJBTestModule;
import com.mockrunner.jms.JMSTestCaseAdapter;
import com.mockrunner.mock.jms.MockQueue;
import it.stc.utils.Config;
import java.io.IOException;
import java.util.List;
import javax.jms.JMSException;
import javax.jms.TextMessage;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class TesterTest extends JMSTestCaseAdapter {

    private EJBTestModule _ejbModule;
    private MockQueue _queIN;
    private MockQueue _queOUT;
    private InitialContext _initialContext;

    public TesterTest(String testName) {
        super(testName);
    }

    protected void setUp() throws Exception {
        super.setUp();
        _ejbModule = createEJBTestModule();
        _ejbModule.bindToContext("connectionfactories/queueconnectionfactory",
                getJMSMockObjectFactory().getMockQueueConnectionFactory());
        _queIN = getDestinationManager().createQueue("quIN");
        _queOUT = getDestinationManager().createQueue("quOUT");
        _ejbModule.bindToContext("queues/quIN", _queIN);
        _ejbModule.bindToContext("queues/quOUT", _queOUT);
        _initialContext = new InitialContext();
    }

    protected void tearDown() throws Exception {
    }

    public void testSendText() throws IOException, NamingException,
            JMSException {
        final String text = "prova";
        final int numSamples = 3;
        Tester m = new Tester(_initialContext, numSamples);
        m.sendText(text);
        verifyNumberOfReceivedQueueMessages("quIN", 3);
        List receivedMessages = getReceivedMessageListFromQueue("quIN");
        for (Object message : receivedMessages) {
            assertEquals(text, ((TextMessage) message).getText());
        }
        verifyNumberQueueSessions(1);
        verifyAllQueueSessionsClosed();
        verifyQueueConnectionClosed();
        verifyAllQueueSessionsCommitted();

    }
}

Conclusions

This article briefly shows how to setup Netbeans to make use of Mockrunner to test JMS clients without the need to connect to the real JMS server. In a future article I'll go deeper on the CAPS JMS server facts and I'll show how to apply this scenario to create automatic JUnit test cases for EAI flows built in SeeBeyond ICAN 5.0 or Sun CAPS 5.1. Automatic testing of EAI solutions is usually sligthly more complex than testing normal applications.

Wednesday, November 15, 2006

Project Collaboration with Basecamp

Recently we started a small project and decided to try Basecamp, a collaboration tools from 37signals, authors of the famous Ruby on Rails framework.

Basecamp is a unique project collaboration tool. Projects don't fail from a lack of charts, graphs, or reports, they fail from a lack of communication and collaboration. Basecamp makes it simple to communicate and collaborate on projects.

Give this web application a try, it is really smart: it allows you to be productive in few minutes and incredibly facilitates teams collaboration. Each single operation is clean , simple and intuitive, making a wise use of Ajax widgets. We are testing the free edition, which comes with some limitations but it is good enough to start. Then it is possible to upgrade to a professional edition if you realize you need more horse-power. However, pricing looks very competitive.

Wednesday, November 8, 2006

JMS topics and message selectors in CAPS

A topic is a JMS message destination that conforms to the publish-and-subscribe messaging paradigm. In this tiny example I show how to publish a message to a topic in Java CAPS, using message selectors to filter message destinations.

Publisher JCD
This JCD (Java Collaboration Definition in CAPS idiom) is triggered by a File eWay and publishes a JMS text message to a topic

public class jcdPublisher
{

public com.stc.codegen.logger.Logger logger;

public com.stc.codegen.alerter.Alerter alerter;

public com.stc.codegen.util.CollaborationContext collabContext;

public com.stc.codegen.util.TypeConverter typeConverter;

public void receive( com.stc.connector.appconn.file.FileTextMessage input, com.stc.connectors.jms.JMS JMS_1 )
throws Throwable
{
String content = input.getText();
com.stc.connectors.jms.Message msg = JMS_1.createTextMessage();
msg.storeUserProperty( "dest", content );
msg.setTextMessage( content );
JMS_1.send( msg );
}

}

the line
msg.storeUserProperty( "dest", content );
stores the user property that will be used later by message selectors to filter messages.

Consumer JCD
This JCD simply receives a text message from the JMS source (a topic, but it is not specified here but in the Connectivity Map) and writes it to a local file using the File eWay

public class jcdConsumer {

public com.stc.codegen.logger.Logger logger;

public com.stc.codegen.alerter.Alerter alerter;

public com.stc.codegen.util.CollaborationContext collabContext;

public com.stc.codegen.util.TypeConverter typeConverter;

public void receive(com.stc.connectors.jms.Message input,
com.stc.connector.appconn.file.FileApplication FileClient_1)
throws Throwable {
FileClient_1.setText(input.getTextMessage());
FileClient_1.write();
}

}

Connectivity Map
In the connectivity map there are four services:
* svcPublisher contains an instance of jcdPublisher
* svcConsumer1, svcConsumer2 and svcDefaultConsumer all contain a copy of jcdConsumer



svcPublisher receives a file content from FileIn (File eWay instance) and publish it into tpcPublic topic. the three consumers receives messages after they are selected by message selectors.
In this toy example the input text file which triggers the process contains just a list of numbers:

4
1
2
2
1
2
3
1

message selectors are built so that they filter messages using the "dest" user property

Message Selectors
svcConsumer1 consumes only messages with an user property dest='1'



svcConsumer2 consumes only messages with an user property dest='2'



svcDefaultConsumer consumes only messages with the 'dest' user property that is neither '1' nor '2', so it can be expressed as
NOT (dest='1' OR dest='2')




Deployment Profile
The DP maps project components present in a Connectivity Map to a given Environment



Results
Results are written in three distinct files: output1.txt (it will contains only '1'), output2.txt ('2') and outputDef.txt (contains all the other numbers that are not '1' or '2', present in input.txt)

Conclusions
What happens if one of the Connectivity Maps link does not contain any message selector? The obvious response is that the connected consumer would receive *all* the messages, regardless of the user property stored into the message header.

Java CAPS - eInsight Business Processes Correlation HowTo

The Java Composite Application Platform Suite

The Java Composite Application Platform Suite (Java CAPS) allows companies to assemble large-scale applications built on existing systems and infrastructure. Java CAPS is an application-level network that unifies connectivity among people, application systems, and devices in different locations and across organizations. Business services facilitate the implementation of extended applications. Service oriented architectures (SOA) clarify design and enable reuse by sharing logic and data among different client systems and users.

eInsight and Java CAPS

eInsight is a component of Java CAPS. eInsight delivers Business Process management features and functions to Java CAPS. Business Process management is a strategic orchestration of the movement of information and the flow of complex processes between participants (systems, users, and organizations) to accomplish larger business objectives. eInsight uses the standard BPEL language to describe processes

1 Introduction

eInsight provides the means for matching existing Business Process instances to messages that are arriving into a Business Process. Correlation keys are individual data values contained within both the incoming message and the eInsight engine. When arriving messages contain data that matches the configured correlation keys, unique Business Process instances then continue processing on to the next step of a given Business Process.

2 Message Correlations

A correlation key is a value that you can assign to a Business Process, like a Purchase Order number. The correlation key provides a way to associate and route information about specific Business Process instances. For asynchronous message exchange between components, you must implement correlation of the instance identification.

An example of when you use asynchronous message exchanges is when you create a Receive Activity in the middle of a Business Process.

To have the correlation mechanisms working properly, right correlation keys are mandatory.

3 Example 1 - File trigger

In this scenario we have a calling process that sends a JMS message to another process and then waits for a reply, correlating instances through a unique ID.

Invoked Process - bpReplier

The bpReplier process is called from the main one. It is very simple for this example: it just copies the Jms Correlation ID and adds some information in the text field.



Main Process

The main process reads a correlation ID from a file, set it into the CorrelationID field of JMS->MessageProperties and then sends the message to the above mentioned bpReplier. An “Event Based Decision” waits for events: one it is a JMS.receive, second is a “Timer Event” in case nothing is received within a fixed amount of time.



Correlation key

The correlation key is made of two aliases:
* /Message/MessageProperties/CorrelationID
* /FileTextMessage/text


The correlation is used in two activities in the BP:
1 - FileClient.receive - with Initialize Set ='yes'
2 - JMS.receive (in the event based decision) - with Initialize Set='No'

4 Example 2 - JMS trigger

The second example shows how to use correlation in a process triggered by a JMS message instead of a file. The invoked service remains the previous simple "bpReplier", while the main process is slightly different.

Main Process

In this case the main process is split in two: first the trigger, which reads from a file and uses its internal BPID as the CorrelationID for the JMS message:

Second, the “real” main process:

This receives the above message, initializes the correlation key, send a message to the bpReplier (copying the received CorrelationID) and the waits for an event. The JMS.receive, which uses the correlation key but does not initialize it, in the event based decision correlates inbound messages, while the usual Timer Event would raise a timeout in case of long inactivity.

In this case, as we only have one kind of inbound event (a JMS message is received) the only necessary alias for the correlation key is:
/Message/MessageProperties/CorrelationID

Resources

* Sun Java CAPS public forum
* Product's official documentation

Sunday, November 5, 2006

Singleton pattern and Double-Checked Locking problem

Double-Checked Locking is widely cited and used as an efficient method for implementing lazy initialization in a multithreaded environment.
Unfortunately, it will not work reliably in a platform independent way when implemented in Java [...]
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

All programming languages have their share of idioms. Many are useful to know and use, and programmers spend valuable time creating, learning, and implementing them. The problem is that some idioms are later proven not to be all that they were purported, or to simply not work as described. The Java programming language contains several useful programming idioms. It also contains some that further study has shown should not be used. Double-checked locking is one such idiom that should never be used. In this article, Peter Haggar examines the roots of the double-checked locking idiom, why it was developed, and why it doesn't work.
http://www-128.ibm.com/developerworks/java/library/j-dcl.html


I think the problem with DCL comes from checking the wrong variable. Instead of checking the static instance itself one should check a boolean, which is by nature an atomic operation. This would prevent the mentioned JVM memory model "problem". What do you think?



public class Singleton {

private static Singleton _instance = null;
private static boolean _initialized = false;

private Singleton() {
}

public static Singleton getInstance() {
if (!_initialized) {
synchronized (Singleton.class) {
if (!_initialized) {
_instance = new Singleton();
_initialized = true;
}
}
}
return _instance;
}

}