The source code below relates to this blog posting which discussed generating HL7 ACK and NAK messages using the HL7 API (HAPI) library. I have put the complete NetBeans project for the Apache Camel / HL7 / JMS sample in the public Subversion repository on the Assembla site. This link will take you to the project's SVN page on the Assembla site. /* * * Copyright 2009 Roger Searjeant. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package camelhl7jmspersist; import ca.uhn.hl7v2.HL7Exception; import ca.uhn.hl7v2.app.DefaultApplication; import ca.uhn.hl7v2.model.Message; import ca.uhn.hl7v2.model.Segment; import ca.uhn.hl7v2.sourcegen.SourceGenerator; import ca.uhn.hl7v2.util.Terser; import java.io.IOException; /** * Trivial bean to handle HL7 messages. * @author Roger Searjeant */ public class HL7MessageHandler { public Message badMessage(Message originalMsg) throws HL7Exception, IOException { // Use the custom makeACK method to create a NAK: Message ack = this.makeACK(originalMsg, "AR"); return ack; } /** * Convenience overload for makeACK which accepts a Message. * * @param inboundMessage * @param ackCode * @return * @throws ca.uhn.hl7v2.HL7Exception * @throws java.io.IOException */ public Message makeACK(Message inboundMessage, String ackCode) throws HL7Exception, IOException { Terser t = new Terser(inboundMessage); Segment inboundHeader = null; try { inboundHeader = t.getSegment("MSH"); } catch (HL7Exception ex) { throw new HL7Exception("Need an MSH segment to create a response ACK"); } return this.makeACK(inboundHeader, ackCode); } /** * Create and return an ACK message of the same HL7 version as the inboundHeader. * The MSH of the ACK is correctly populated. The acknowledgement code (MSA-1) * value can be set using the ackCode parameter. If ackCode is null, makeACK * will insert "AA" (application accept). * * This code was lifted from ca.uhn.hl7v2.app.DefaultApplication and modified * slightly to suit my needs. * * @param inboundHeader The MSH segment from the inbound message being ACKnowledged. * @param ackCode The MSA-1 value you want the ACK to carry. If null, MSA-1 will contain "AA". * @return Correctly constructed ACK message. * @throws ca.uhn.hl7v2.HL7Exception * @throws java.io.IOException */ public Message makeACK(Segment inboundHeader, String ackCode) throws HL7Exception, IOException { if (!inboundHeader.getName().equals("MSH")) throw new HL7Exception( "Need an MSH segment to create a response ACK (got " + inboundHeader.getName() + ")"); // Find the HL7 version of the inbound message: // String version = null; try { version = Terser.get(inboundHeader, 12, 0, 1, 1); } catch (HL7Exception e) { // I'm not happy to proceed if we can't identify the inbound // message version. throw new HL7Exception("Failed to get valid HL7 version from inbound MSH-12-1"); } // Make an ACK of the same version as the inbound message: // String ackClassName = SourceGenerator.getVersionPackageName(version) + "message.ACK"; Message out = null; try { Class ackClass = Class.forName(ackClassName); out = (Message)ackClass.newInstance(); } catch (Exception e) { throw new HL7Exception("Can't instantiate ACK of class " + ackClassName + ": " + e.getClass().getName()); } // Create a Terser instance for the outbound message (the ACK). Terser terser = new Terser(out); // Populate outbound MSH fields using data from inbound message Segment outHeader = (Segment)out.get("MSH"); DefaultApplication.fillResponseHeader(inboundHeader, outHeader); // Now set the message type, HL7 version number, acknowledgement code // and message control ID fields: terser.set("/MSH-9", "ACK"); terser.set("/MSH-12", version); terser.set("/MSA-1", ackCode == null ? "AA" : ackCode); terser.set("/MSA-2", terser.get(inboundHeader, 10, 0, 1, 1)); return out; } public Message handleORM(Message msg) throws HL7Exception, IOException { // If the Camel route predicates have done their job, we should be able to guarantee // that msg is an ORM^O01. // Custom logic for processing ORM^O01 goes in here. // Return a positive ACKnowledgement. return this.makeACK(msg, null); } } |