A IBM recentemente adquiriu a Initiate, uma empresa especializada em gerenciamento de dados principais (MDM) para o segmento de mercado de assistência médica. Seu principal produto, o Initiate Patient, fornece recursos avançados e líderes no segmento de mercado de Enterprise Master Patient Indexing (EMPI). O EMPI é usado nas configurações do setor de assistência médica para identificar quando diferentes registros de pacientes se referem ao mesmo indivíduo. Esta funcionalidade é essencial no estabelecimento de uma visão abrangente de um paciente — para criar um registro médico longitudinal compilado a partir dos tratamentos em diferentes hospitais, por exemplo. Ele forma a base para a maioria das implementações de Health Information Exchange (HIE).
Existem várias abordagens para integrar o Initiate Patient com os sistemas de uma empresa do setor de assistência médica. Um recurso geralmente necessário é ser capaz de notificar de forma assíncrona sistemas externos sobre eventos que acontecem dentro do Initiate, para que eles possam tomar as medidas reconciliativas apropriadas. O Message Broker Suite do Initiate possui um componente do Outbound Broker que pode ser configurado para conexão com eventos específicos dentro do hub do Initiate e enviar mensagens notificando sistemas externos quando eles acontecerem.
Este artigo abrange um novo recurso do Outbound Broker que permite o envio de notificações para sistemas externos como serviços da Web, usando mensagens SOAP em HTTP. Antes da disponibilidade deste aprimoramento, as notificações só podiam ser enviadas por soquetes de Protocolo de Controle de Transmissões, tornando a integração com sistemas com base na Web mais complexa. Esta forma de comunicação de soquete funcionava bem com sistemas do setor de assistência médica anteriores que operavam com o sistema de mensagens HL7 V2, que era implementado como LLP no Protocolo de Controle de Transmissões/Protocolo da Internet. Entretanto, com a introdução dos padrões de sistema de mensagens do HL7 V3 comumente implementado como serviços da Web com SOAP em HTTP, sistemas do setor de assistência médica mais modernos terão a necessidade de serem integrados usando tecnologias com base na Web.
Este artigo assume que você possui uma compreensão básica do Initiate Patient e de sua estrutura de dados.
Para poder usar as instruções e exemplos deste artigo, os seguintes aplicativos devem estar instalados:
- Initiate Patient V9.2.x
- Initiate Message Broker Suite V9.2.0.178 ou mais recente
- WebSphere® Application Server V6.1 ou contêiner do servlet equivalente
Uma visão geral do Outbound Broker é apresentada nesta seção. Mais detalhes específicos de implementação são mais bem abordados na documentação do Message Broker.
Após instalar o Message Broker Suite, o hub está pronto para participar da transmissão de eventos para sistemas externos. Quando uma instância do Outbound Broker está sendo configurada, há quatro eventos específicos que podem ser configurados para conexão. Como os eventos selecionados acontecem dentro do hub, uma série de etapas será acionada, culminando em uma mensagem sobre os eventos sendo enviada para um sistema externo. O formato de uma mensagem, assim como seu conteúdo, pode ser configurado com base nas necessidades de cada instância do Outbound Broker. Há também várias opções para o transporte da mensagem, que incluem TCP, SSL e SOAP em HTTP.
Os quatro eventos para os quais uma instância do Outbound Broker pode ser configurada para ser monitoramento são:
- Add Member — É acionado quando um novo membro é adicionado ao Initiate
- EID Updates — É acionado quando a entidade à qual um membro pertence é alterada
- Has Shadow — É acionado quando o atributo de um membro foi alterado por meio do Initiate Inspector e requer uma confirmação do sistema de origem para tornar-se ativa
- PreMerge — É acionado quando uma potencial tarefa duplicada no Inspector foi resolvida ao fundir dois registros de membros e requer uma confirmação do sistema de origem, para que um dos membros possa ser alterado para obsoleto
Há dois serviços instalados para cada instância do Outbound Broker criada. O serviço do Outbound Broker coloca a mensagem nas filas de saída quando eventos de acionamento são ativados no hub. O serviço Message Sender é responsável por selecionar as mensagens das filas de saída e enviá-las para o sistema externo apropriado. O Message Sender então aguardará o reconhecimento de — uma confirmação ou rejeição do sistema externo — para decidir se moverá a mensagem para a fila de sucesso ou rejeição.
As etapas envolvidas na configuração e integração de uma instância do Outbound Broker com um sistema baseado na Web será ilustrado por meio de um cenário comum. Uma empresa do setor de assistência médica criou um aplicativo java™ baseado em EE que precisa ser notificado quando um registro de paciente foi incluído no hub do Initiate, para que suas representações internas do registro de paciente possam ser preenchidas com um link para o registro no hub. Note que isso ilustra apenas uma abordagem da integração do Initiate com um sistema externo. Arquiteturas alternativas existem e devem ser avaliadas por um especialista com base em todas as informações disponíveis.
Para este exemplo, há algumas informações que deverão ser reunidas. A primeira é a instância do Outbound Broker que enviará mensagens de serviço da Web usando um SOAP no HTTP quando novos membros forem incluídos ao hub. A segunda é um terminal para o aplicativo com base em Java EE que poderá receber e processar as mensagens sendo enviadas pela instância do Message Sender. Se uma abordagem baseada em soquete de Protocolo de Controle de Transmissões for escolhida como o transporte do sistema de mensagem para a instância, um componente adaptador separado necessitará ser desenvolvido para transformar as mensagens de soquetes brutos em mensagens transportadas por HTTP que possam ser usadas pelo aplicativo com base na Web.
Abaixo há uma estrutura de tópicos das principais etapas para integrar os dois sistemas:
- Instale o Message Broker Suite (se ainda não estiver instalado). Consulte a documentação do Message Broker para instruções detalhadas.
- Crie uma origem de dados. Consulte a documentação do Message Broker para instruções detalhadas.
- Crie uma instância de saída que notificará um sistema externo quando um membro for adicionado ao hub. Consulte a documentação do Message Broker para instruções detalhadas. Preste muita atenção às seguintes opções mencionadas na documentação:
- Sending host name — O hostname do sistema externo
- Sending port number — A porta pela qual a comunicação em HTTP acontecerá com o sistema externo
- Insira
yquando perguntado se o Message Sender chamará um serviço da Web- Para a opção To URL , digite a URL do terminal completo no servlet que receberá mensagens do Message Sender
- Para a opção message type , digite
xml - Insira
yquando solicitado a criar uma mensagem quando um membro for incluído ao hub
- Após criar uma instância de saída, ela precisará ser configurada para que os dados certos sejam incluídos nas mensagens que serão enviadas. Isso é feito ao editar o arquivo de configuração OutboundEIDAddXML.ini no diretório config_<instance name> do início da instância de saída.
Entre outras coisas, este arquivo especifica os dados que serão incluídos em mensagens para sistemas externos, a partir do Message Sender. Um trecho de um único exemplo, que inclui informações demográficas básicas, é fornecido na Listagem 1. Uma mensagem de exemplo correspondente para ilustrar como a configuração direciona a criação de mensagem é exibida na Listagem 2. Note que o exemplo de configuração pode necessitar ser editado para corresponder aos nomes de dados em seu hub.
Lista 1. Exemplo de um arquivo de configuração[Global-Data] 0||MSGHEADER|||||| evtType||ADD|/EmpiMsg/MsgHeader/evtType evtId|||/EmpiMsg/MsgHeader/evtId evtInitiator|||/EmpiMsg/MsgHeader/evtInitiator evtCtime|||/EmpiMsg/MsgHeader/evtCtime 1||MEMHEAD|||||| srcCode|||/EmpiMsg/Member/MemHead/srcCode memIdnum|||/EmpiMsg/Member/MemHead/memIdnum entRecno|||/EmpiMsg/Member/MemHead/entRecno 2||MEMNAME|PATNAME||||| recStat|||/EmpiMsg/Member/MemName[attrCode="PATNAME"][@deleteInd] onmFirst|||/EmpiMsg/Member/MemName[attrCode="PATNAME"]/onmFirst onmMiddle|||/EmpiMsg/Member/MemName[attrCode="PATNAME"]/onmMiddle onmLast|||/EmpiMsg/Member/MemName[attrCode="PATNAME"]/onmLast onmPrefix|||/EmpiMsg/Member/MemName[attrCode="PATNAME"]/onmPrefix onmSuffix|||/EmpiMsg/Member/MemName[attrCode="PATNAME"]/onmSuffix onmDegree|||/EmpiMsg/Member/MemName[attrCode="PATNAME"]/onmDegree onmTitle|||/EmpiMsg/Member/MemName[attrCode="PATNAME"]/onmTitle
Lista 2. Amostra de mensagem do broker de saída<?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?> <!DOCTYPE EmpiMsg SYSTEM "initiate.dtd"> <EmpiMsg> <MsgHeader> <evtType>ADD</evtType> <evtId>103-466</evtId> <evtInitiator></evtInitiator> <evtCtime>20110222133649</evtCtime> </MsgHeader> <Member> <MemHead> <srcCode>OUTP</srcCode> <memIdnum>1782^^^&2.16.840.1.113883.3.18.104&ISO</memIdnum> <entRecno>205</entRecno> </MemHead> <MemName> <attrCode deleteInd="A">PATNAME</attrCode> <onmFirst>Blake</onmFirst> <onmMiddle></onmMiddle> <onmLast>Griffin</onmLast> <onmPrefix></onmPrefix> <onmSuffix></onmSuffix> <onmDegree></onmDegree> <onmTitle></onmTitle> </MemName> </Member> </EmpiMsg>
- A maneira mais simples de configurar um terminal de serviços da Web para um SOAP em um HTTP em Java EE é criar um código para um servlet que analisa a carga útil do SOAP e a processa de acordo. Uma abordagem mais sofisticada seria usar o conjunto de ferramentas de serviço da Web disponível em seu ambiente de desenvolvimento integrado de Java EE favorito para autogerar um código que executará o desagrupamento da mensagem em objetos de java.
- Uma amostra de mensagem SOAP é necessária para implementar totalmente o terminal do servlet. Uma maneira de obter isso é iniciar a implementação de seu servlet codificando apenas um terminal que repita quaisquer mensagens enviadas. Depois desta etapa, você pode desenvolver seu código para analisar e posteriormente processar a mensagem.
- Para que as mensagens sejam enviadas ao terminal, o serviço do Outbound Broker e o serviço do Message Sender correspondentes à instância precisarão ser iniciados. Note que a primeira vez que eles forem iniciados, uma mensagem será enviada para cada membro existente no hub. Após isso, as mensagens somente serão enviadas quando um novo membro for incluído.
- Um exemplo de implementação de servlet que usa o XPath para analisar os dados que não estão incluídos nas mensagens recebidas é mostrado na Listagem 3. Ele inclui um exemplo da resposta em XML que notifica ao Message Sender que a mensagem foi processada com sucesso, e o Message Sender move a mensagem para a fila de sucesso.
Lista 3. Implementação de Servletpackage com.ibm.initiate.broker.sample; import java.io.IOException; import java.util.Enumeration; import java.util.logging.Logger; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.soap.MessageFactory; import javax.xml.soap.MimeHeaders; import javax.xml.soap.SOAPBody; import javax.xml.soap.SOAPConstants; import javax.xml.soap.SOAPEnvelope; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPFault; import javax.xml.soap.SOAPHeader; import javax.xml.soap.SOAPMessage; import javax.xml.soap.SOAPPart; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; public class MemberAddedEndpoint extends HttpServlet { private static final long serialVersionUID = 1L; private static final String CLASS_NAME = MemberAddedEndpoint.class.getName(); private static Logger logger = Logger.getLogger(CLASS_NAME); private static final String CONTENT_TYPE_XML = "text/xml"; private static final String CHAR_ENCODING_UTF_8 = "utf-8"; // success Ack message for Outbound Broker Sender private static final String OUTBOUND_ACK_MSG = "<EmpiResp><MsgHeader><code>ok</code></MsgHeader></EmpiResp>"; private static final String XPATH_PREFIX_MEMBER = "//EmpiMsg/Member"; private static final String XPATH_PREFIX_MEMHEAD = XPATH_PREFIX_MEMBER + "/MemHead"; private static final String XPATH_SRCCODE = XPATH_PREFIX_MEMHEAD + "/srcCode"; private static final String XPATH_MEMIDNUM = XPATH_PREFIX_MEMHEAD + "/memIdnum"; private static final String XPATH_ENTRECNO = XPATH_PREFIX_MEMHEAD + "/entRecno"; private static final String XPATH_PREFIX_MEMNAME = XPATH_PREFIX_MEMBER + "/MemName"; private static final String XPATH_FIRSTNAME = XPATH_PREFIX_MEMNAME + "/onmFirst"; private static final String XPATH_MIDDLENAME = XPATH_PREFIX_MEMNAME + "/onmMiddle"; private static final String XPATH_LASTNAME = XPATH_PREFIX_MEMNAME + "/onmLast"; private static final String XPATH_NAMESUFFIX = XPATH_PREFIX_MEMNAME + "/onmSuffix"; public MemberAddedEndpoint() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { MessageFactory messageFactory = null; SOAPMessage responseMsg = null; try { messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL); SOAPMessage soapMsg = messageFactory.createMessage( getMimeHeaders( request), request.getInputStream()); SOAPBody body = soapMsg.getSOAPBody(); logger.fine( "Received SOAP Message from Initiate Outbound Broker for Member Add: " + body); // just parses message data and emits to log file // this is where business logic for the endpoint could be implemented displayParsedMessageData( body); responseMsg = messageFactory.createMessage(); response.setContentType(CONTENT_TYPE_XML); response.setCharacterEncoding(CHAR_ENCODING_UTF_8); // send HTTP OK & custom XML message Ack back to Outbound Broker sender response.setStatus( HttpServletResponse.SC_OK); response.getWriter().write( OUTBOUND_ACK_MSG); } catch ( Exception e) { try { // send HTTP error and SOAPFault back to Outbound Broker sender addSOAPFault(responseMsg); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, responseMsg.toString()); } catch (SOAPException soape) { // couldn't generate SOAPFault, so just send HTTP error back to sender response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } logger.severe( "An unexpected error occurred: " + e.getLocalizedMessage()); e.printStackTrace(); } } private void displayParsedMessageData( SOAPBody body) throws XPathExpressionException { StringBuffer buff = new StringBuffer(); buff.append( "Message received with contents: ["); buff.append( "Member ID Number=").append( getDataValue(body,XPATH_MEMIDNUM)); buff.append( ", Entity Record Number=").append( getDataValue(body,XPATH_ENTRECNO)); buff.append( ", Source Code=").append( getDataValue(body,XPATH_SRCCODE)); buff.append( ", First Name=").append( getDataValue(body,XPATH_FIRSTNAME)); buff.append( ", Last Name=").append( getDataValue(body,XPATH_LASTNAME)); buff.append( "]"); logger.info(buff.toString()); } private String getDataValue( SOAPBody body, String xpathExpr) throws XPathExpressionException { XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); String value = null; Object result = xpath.evaluate( xpathExpr, body, XPathConstants.STRING); if ( result != null) { value = result.toString(); } return value; } private MimeHeaders getMimeHeaders( HttpServletRequest request) { MimeHeaders mimeHeaders = new MimeHeaders(); Enumeration mimeHeaderNames = request.getHeaderNames(); String headerName = ""; String headerVal = ""; while (mimeHeaderNames.hasMoreElements()) { headerName = (String)mimeHeaderNames.nextElement(); headerVal = request.getHeader(headerName); mimeHeaders.addHeader(headerName, headerVal); } return mimeHeaders; } private void addSOAPFault( SOAPMessage msg) throws SOAPException { SOAPPart part = msg.getSOAPPart(); SOAPEnvelope env = part.getEnvelope(); SOAPHeader head = msg.getSOAPHeader(); SOAPBody body = msg.getSOAPBody(); head.detachNode(); SOAPFault soapFault = body.addFault(); soapFault.addNamespaceDeclaration(env.getPrefix(), env.getNamespaceURI()); soapFault.setFaultCode(env.createName("Receiver", env.getPrefix(),env.getNamespaceURI())); String faultMsg = "System is unable to process the Initiate Outbound Broker Message"; soapFault.setFaultString(faultMsg); soapFault.setFaultActor("Add Member Outbound Broker Endpoint"); } }
Geralmente é útil poder enviar mensagens do hub sem realmente incluir um novo membro, o que muitas vezes pode ser uma atividade demorada. Há uma maneira simples de fazer isso. Execute a seguinte instrução SQL no banco de dados de seu hub:
update mpi_eidtrigger_<entity name> set complete = 0 where memrecno = <existing member’s MemRecNo> |
Para depurar melhor os problemas em sua instância de saída, o nível de criação de log pode ser independentemente aumentado para o Outbound Broker e o Message Sender. Isto é feito ao editar a seção do arquivo services.ini correspondente ao serviço cujo nível de criação de log você quer aumentar. A configuração do MAD_TRACE=1 resultará em um nível mais detalhado de criação de log a ser ativado, e MAD_DEBUG é o próximo mais alto. O aumento do nível de criação de log fará com que o desempenho diminua, pois as operações adicionais de E/S necessitam ser coordenadas para gravação nos arquivos de log. Por isso, os níveis de rastreio e de depuração devem ser utilizados com cuidado em um ambiente de produção. A localização do arquivo services.ini é configurada pela variável de ambiente MAD_CONFNAME. Os arquivos de log para cada um dos serviços são eles mesmos, localizados em um diretório de log do início da instância de saída.
Existem três filas usadas para processar mensagens enviadas a sistemas externos. A de entrada, a de sucesso e a de falha são filas mantidas no sistema de arquivo por meio de uma série de arquivos inter-relacionados. Eles estão localizados no diretório data/interface/outbound_<instance name> do início da instância. Para alinhar as filas, os serviços de Outbound Broker e de Message Sender devem ser interrompidos e, então, todos os arquivos no diretório podem ser excluídos com segurança. Mais detalhes de como as filas funcionam são abordados na documentação do Message Broker.
Houve um erro que foi corrigido na V9.2.0.178 do Message Broker Suite, que causava problemas com o período de tempo que o Message Sender esperaria para receber reconhecimento de sistemas externos. Todos os Message Senders executando sistemas de mensagem de serviços da Web esperariam apenas um segundo, e se eles não recebessem um reconhecimento de sucesso neste período, as mensagens seriam recuperadas e eventualmente movidas para a fila de falha. Isso já foi corrigido, e o período de tempo que um Message Sender esperará por reconhecimento de um sistema externo pode ser agora configurado ao ajustar a configuração MAD_SOTIMEOUT na seção correspondente do arquivo services.ini.
O recurso para enviar mensagens de serviços da Web usando SOAP em HTTP está incluído na mais nova versão do Initiate Outbound Broker. Esta nova funcionalidade permite uma integração mais direta com sistemas baseados na Web em comparação com a que era suportada pela comunicação de soquete de Protocolo de Controle de Transmissões:
- Consulte Lista 1 para um trecho da amostra do arquivo de configuração do Outbound Broker.
- Consulte Lista 2 para a mensagem de amostra em XML enviada a partir do Outbound Broker.
- Consulte Lista 3 para o exemplo de terminal de Servlet do Java para receber mensagens do Outbound Broker.
Aprender
- Obtenha mais informações sobre IBM Initiate Patient.
- Obtenha mais detalhes sobre programação do Initiate Patient no Guia de referência do Initiate Message Broker Suite.
-
Confira a Classe de treinamento.
- Na área do InfoSphere no developerWorks, obtenha os recursos necessários para progredir no Master Data Management e em outras qualificações do InfoSphere.
- Saiba mais sobre Information Management na zona de Information Management no developerWorks. Encontre documentação técnica, artigos de instruções, treinamento, downloads, informações de produtos, e muito mais.
- Fique por dentro dos
eventos técnicos e webcasts do developerWorks.
- Siga o developerWorks no Twitter.
Obter produtos e tecnologias
- Crie seu próximo projeto de desenvolvimento com a
software de avaliação da IBM, disponível para download diretamente no developerWorks.
Discutir
- Participar do fórum de discussão.
- Confira o blogs do developerWorks e participe da
comunidade do developerWorks.
