Author: Michael.Czapski@sun.com
Updated and Verified on OpenEsb2.3 by Jay Shankar Gupta, Logicoy Inc
Table Of Contents
JVM-Global, Ephemeral Sequence Generator
Creating POJO for getting Sequence
Introduction
When working on the HA solutions discussed in my blog[1] I realized that it will be difficult to work out whether messages are delivered in order, as was required, and whether any are missing. I got over the issue by ensuring that my test data was prepared in such a way that messages in each test file had increasing, contiguous sequence numbers embedded in the message. For HL7 v2, which is the messaging standard with which I dealt, I used MSH-10, Message Control ID field. I wrote processed messages and acknowledgements to files whose names embedded MSH-10 Message Control Id, with the sequence number, so that breaks in sequence and out of order messages could be readily detected. With multiple message files containing between 1 and 50,000 messages, adding a sequence number to each message by hand was clearly out of the question. I put the GlassFish ESB to use. I constructed a file-to-file BPEL module project to read each test file and to prepend a sequence number to each message’s MSH-10 field. The only snag was how to get a sequence number that would start at 0 and increase by 1 for each message, such that each BPEL process instance would get the next sequence, and that messages would be written to the output file in order. This note discusses how I went about accomplishing the task.
JVM-Global, Ephemeral Sequence Generator
After considering a couple of possibilities I resolved to use a Java static int to hold the sequence number, knowing that it will be good until the project is redeployed or until the Application Server is restarted, which was good enough for my purpose. To make the Java code accessible to BPEL I decided to create a POJO, to invoke from BPEL.
Creating POJO for getting Sequence
Let’s create a “New Project” -> “Java” -> “Java Application”, POJOGetSeqNum, making sure to uncheck the ”create main class” option.
Right Click on project name, Choose New other ….Chose ESB -POJO Service
Specify Class Name: GetSeqNum, package name: pkg.GetSeqNum, method name: NextSeq, and accept input and output parameters as strings.
When the skeleton POJO code is shown in the editor, add the following source code as indicated:
First we declare private static int to hold the most recent sequence number, and a synchronization object, since the formatter may not be thread-safe.
Inside the NetSeq method body we initialize the return variable, assign the most recent sequence value to it with post-increment, inside a synchronization block, create a formatter to format the number as numeric string, format the number and return it to the caller.
Once the code is added, right click inside the source window and choose “Fix Imports”, to resolve missing import statements.
If I was interested in the sequence number as an int I could have skipped the formatting bit and returned an int. To keep my messages in order by sequence number, I prefer to have a zero-filled, right-justified number strings, like 000001.
Compile the file. It should compile unless something got messed up in transcription.
To test the code let’s add a Main class to the project and use it to invoke the NextSeq method in our class.
Right-click the name of the project and choose “New” _ “Java Class”. Name it GetNextSeqDriver and make sure to include it in the same package as GetNetSeq.
Insert the following code as shown:
Right-click the name of this calss, GetSeqNumDriver, choose “Run File” and observebthe outcome in the output window:
Right-click the project name and choose “Build”.
The utility class is ready.
HL7 Message ID Encricher
With the sequence number generator ready we are now in a position to process HL7 v2 messages by prepending increasing sequence number to the MSH-10 Message Control ID, so we can use these messages in HA testing.
Obtain HL7 v2 XML Schema documents, from which we will need ORU_RO1 and related schemas, from http://wiki.open-esb.java.net/attach/HL7/hl7v2xsd.zip. Unzip it to a convenient location.
Create a “New Project” “SOA” “BPEL Module”, named HL7Sequencer.
Create a sub-folder, HL7v231, in the “Process Files” folder. Right click the name of the subfolder and choose “New” “External XML Schema Document(s)”. Locate the ORU_RO1.xsd in the hl7 v2.3.1 folder hierarchy hl7v2xsd/2.3.1, and choose it:
Supplementary files, included in ADT_A03.xsd, were added as well. The project will now look like this:
We expect to read one or more HL7 version 2.3.1 delimited ORU_RO1 messages, enrich the MSH-10 field, and write out HL7 v 2.3.1 delimited ORU_RO1 messages.
This requires a File BC to read and write records. We could use one File BC configuration for reading and one for writing, but we can also use a single File BC configuration to both read records from a file and to write records to a different file in the same directory.
Devloping Wsdl and Xsds
Let’s create “New” “WSDL Document”, named HL7Sequencer_FileInOut:
WSDL Type: Concrete
Binding: FILE
Type: poll and write back reply
Request Configuration
File Polling:
File Name: ADT_A03_raw_%d.hl7
Polling Directory: /GFESBv22Projects/GFESB_HA_LB/data (or whatever directory you need to use or we can use application variable to define input and output file location.
Record processing:
Multiple Records: true
Delimiter: \r\n
Payload Processing:
Message Type: encoded data
XSD Element/Type: ADT_A03
Encoded type: hl7encoder
Remove Trailing EOL: true
Sometime in case of Window system, Delimited by “\r\n’ does not work, (could be because of difficulties in creating such input file) In that case we can use any string as delimited character such as “<>” but we must ensure that next record start just after delimited character not from next line to avoid any discrepancy in file.
Below screenshot is to check your File Wsdl configuration once you have created it .Open wsdl go to Wsdl tab . Click on Binding Poll input file:message ,Right click and open properties .
You can check all your request and response configuration here .and can made modification . (As in this case I have made delimited character as <>)
Response Configuration
File Write:
File Name: Hl7Message_%d.hl7
File Exists: Append to existing file
Delimited By: \r\n
Payload Processing:
Message Type: encoded data
XSD Element/Type: ORU_RO1
Encoded type: hl7encoder
Remove Trailing EOL: true
BPEL Design
Open the BPEL Process and drag the WSDL onto the right-hand swim line. Name partner link FielInOut.
Expand the project POJOGetSeqNum, through the Source Packages _pkg.GetSeqNum node. Drag the GetSeqNum.wsdl onto the right hand swim line and name the partner link GetSeq.
Drag the Receive, Assign, Invoke, Assign and Reply activities onto the canvas and connect as shown:
Edit Receive1 activity and create an Input Variable: vA03In:
Edit Reply1 activity and create Normal Response: Output Variable: vA03Out:
Edit Invoke1 activity and create two variables, Input Variable: vFormat and Output Variable: vNextSeq:
Select Assign1 activity, switch to Mapper and assign string literal “000000” to variable vFormat:
Map concatenation of vNextSeq -> part1, literal “_” and vA03In ->part1 -> MSH -> MessageControl ID to vA03Out part1 -> MSH ->MessageControl ID.
Save and Build the project.
Create Composite Application
Create “New Project -> SOA -> Composite Application”, named HL7Sequencer_CA:
Drag HL7Sequencer and POJOGetSeqNum projects onto the CASA canvas and click Build.
Righ-click the QoS icon on the link form the File BC to the BPEL process and set Max Concurrency Limit to 1, to serialize message processing. Having gone to all this trouble to assign sequential numbers we need to make sure the records are indeed written out in order.
Deploy the project.
Testing
Submit the file, ADT_A03_raw_1.hl7, containing 1 HL7 message.
Inspect the input file content.
Test Input File :
OutPut Result :
Sequence number, 000000, was prepended to the MSH-10 content. Delete, or move elsewhere, the output file. If you don’t do that records from the next run will be appended to that file, as requested in the File BC configuration.
Submit a file with multiple HL7 messages, and inspect the content.
Inspect the output file and note that sequence numbers were prepended and started from 000000.
JVM global, ephemeral sequencing works.
To reset the sequence to zero re-deploy the project. This is why this kind of sequencing is called ephemeral (short lived – http://www.google.com.au/search?q=define%3Aephemeral).
The private static int, which holds the current sequence, will be destroyed if the application server is restarted, application is undeployed or redeployed.
Summary
This note walked through development of a JVM global, ephemeral sequence number generator, in a form of a POJO useable from a BPEL process. To demonstrate the use of the sequence generator a BPEL project, enriching HL7 v2.3.1 messages with sequence numbers prepended to the MSH-10 filed, was also developed and exercised.
This kind of project can be used, as I have done, to prepare data for HA testing, and other occasions where message processing in sequence is required and needs to be confirmed.
References
1 “GlassFish ESB v2.2 Field Notes – Exercising Load Balanced, Highly Available, Horizontally Scalable HL7 v2 Processing Solutions”, Accessed: January 9, 2010, Available: http://blogs.sun.com/javacapsfieldtech/entry/glassfish_esb_v2_2_field1