Как сгенерировать кастомный апк с apache camel hl7
Я пытаюсь настроить слушатель mllp для сообщений hl7v2.x, используя верблюда.
Моя среда
- верблюд и компоненты apache версии 2.18.3
Также я хотел бы избежать использования библиотеки HAPI, так как я предпочитаю настраиваемый парсер для полученных и сгенерированных сообщений. Так как каждый из моих клиентов использует разные версии стандартного и действительно разные поля использования, поэтому нет никакого демаршаллинга к типу данных hl7 на следующем маршруте, только к строке. Я сделаю парсер сам.
И мой маршрут (все компоненты и переменные определены в другом месте кода, я думаю, что они не имеют отношения)
from("netty4:tcp://0.0.0.0:3333?
encoder=#encoderHl7&decoder=#decoderHl7&sync=true")
.log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
.unmarshal().string()
.to("file://" + rutaSalidaFichero)
;
Во-первых, как подтверждение концепции, я просто пытаюсь скопировать все полученные сообщения в каталог файловой системы. Сообщения правильно принимаются и записываются в каталог. Но я не знаю, как генерировать и отправлять ACK, автоматически генерируется и отправляется неверный.
Если я отправляю сообщение hl7 из внешней / отправляющей системы, верблюжий компонент отправляет то же сообщение, что и подтверждение, поэтому отправляющая система отправляет в ответ сообщение об ошибке, поскольку подтверждение не ожидается. Я отправляю сообщение hl7, используя mirth, dcm4chee, hapi... все с тем же результатом.
Например, если я отправлю следующее сообщение из внешней / отправляющей системы MSH|^~\&|LIS|LIS|HIS|HIS|20170412131105||OML^O21|0000000001|P|2.5|||AL|||8859/1|||1.0 PID|1||123456||APELLIDO1&APELLIDO2^NOMBRE|19200101 ORC|RP|009509452919|317018426||||||20170412000000 OBR|1|317018426|317018426|CULT^CULTIVO
Я получил так же, как подтверждение в системе отправки. Это верблюд, генерирующий подтверждение в виде принимающего сообщения MSH | ^ ~ \ & | LIS | LIS | HIS | HIS | 20170412131105 || OML ^ O21 | 0000000001 | P | 2.5 ||| AL ||| 8859/1 || | 1.0 PID | 1 || 123456 || APELLIDO1 & APELLIDO2 ^ NOMBRE | 19200101 ORC | RP | 009509452919 | 317018426 |||||| 20170412000000 OBR | 1 | 317018426 | 317018426 | CULT ^ CULTIVO
Я не нашел в документах верблюда ссылки на генерацию ack, или если я могу использовать пользовательское "что-то" для его генерации. Я хотел бы изменить это поведение по умолчанию.
2 ответа
Как сказано в документации по верблюжьему компоненту hl7 ( http://camel.apache.org/hl7.html, "выражение подтверждения HL7"), вы можете сгенерировать ack по умолчанию, просто используя
import static org.apache.camel.component.hl7.HL7.ack;
...
from("direct:test1")
// acknowledgement
.transform(ack())
Здесь "ack()" является вызовом для "org.apache.camel.component.hl7.HL7#ack()". Но вы можете проверить, что "org.apache.camel.component.hl7.HL7" содержит некоторые другие полезные методы, такие как
org.apache.camel.component.hl7.HL7#ack(ca.uhn.hl7v2.AcknowledgmentCode code)
или же
org.apache.camel.component.hl7.HL7#ack(ca.uhn.hl7v2.AcknowledgmentCode code, java.lang.String errorMessage, ca.uhn.hl7v2.ErrorCode )
Вы можете использовать их для настройки фактического ответа ACK. Если мы пойдем глубже, то вы увидите, что "org.apache.camel.component.hl7.HL7#ack" являются просто обертками для
new ValueBuilder(new AckExpression(...))
и большинство параметров из методов "ack" направляются непосредственно в org.apache.camel.component.hl7.AckExpression. Фактическая генерация ACK выполняется в "org.apache.camel.component.hl7.AckExpression#valu" и выглядит как
public Object evaluate(Exchange exchange) {
Throwable t = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Throwable.class);
Message msg = exchange.getIn().getBody(Message.class);
try {
HL7Exception hl7e = generateHL7Exception(t);
AcknowledgmentCode code = acknowledgementCode;
if (t != null && code == null) {
code = AcknowledgmentCode.AE;
}
return msg.generateACK(code == null ? AcknowledgmentCode.AA : code, hl7e);
} catch (Exception e) {
throw ObjectHelper.wrapRuntimeCamelException(e);
}
}
Если вам нужна более глубокая настройка, вы можете просто написать свое собственное выражение MyCustomAckExpression, которое расширит org.apache.camel.component.hl7.AckExpression и реализует требуемую логику вместо
return msg.generateACK(code == null ? AcknowledgmentCode.AA : code, hl7e);
и использовать его как
...
from("direct:test1")
// acknowledgement
.transform(new ValueBuilder(new MyCustomAckExpression()))
Вот что я сделал на своем проекте:
<bean id="hl7Processor" class="com.mediresource.MessageRouting.HL7.HL7Processor" />
<route>
<from uri="mina2:tcp://10.68.124.140:2575?sync=true&codec=#hl7codec" />
<onException>
<exception>org.apache.camel.RuntimeCamelException</exception>
<exception>ca.uhn.hl7v2.HL7Exception</exception>
<redeliveryPolicy maximumRedeliveries="0" />
<handled>
<constant>true</constant>
</handled>
<bean ref="hl7Processor" method="sendACKError" />
</onException>
<bean ref="hl7Processor" method="sendACK" />
</route>
На классе HL7Processor у меня есть это:
public Message sendACK(Message message, Exchange exchange ) throws HL7Exception, IOException {
logger.debug("Entering");
Message ack = message.generateACK();
logger.info("(10-4), End - ACK sent for " + exchange.getExchangeId());
return ack;
}
public Message sendACKError(Message message, Exception ex) throws HL7Exception, IOException {
try {
logger.warn("Internal Error:" + ex);
Message ack = message.generateACK(AcknowledgmentCode.AE, new HL7Exception("Internal Error") );
logger.warn("(10-4), End - NACK");
return ack;
} catch (Exception ex1) {
logger.error("Fatal error on processError! ", ex1);
}
return null;
}