Chamar serviços de documentos AIF diretamente do X++ no Dynamics AX 2012
Publicado: 16 de fevereiro de 2025 às 11:23:11 UTC
Neste artigo, explico como chamar serviços de documentos do Application Integration Framework no Dynamics AX 2012 diretamente a partir do código X++, emulando chamadas de entrada e saída, o que pode tornar significativamente mais fácil encontrar e depurar erros no código AIF.
Calling AIF Document Services Directly from X++ in Dynamics AX 2012
As informações neste post são baseadas no Dynamics AX 2012 R3. Pode ou não ser válido para outras versões.
Recentemente, ajudei um cliente a implementar uma porta de entrada do Application Integration Framework (AIF) para criar clientes com base em dados que estavam a receber de outro sistema. Como o Dynamics AX já fornece o serviço de documentos CustCustomer, que implementa a lógica para tal, decidimos mantê-lo simples e utilizar a solução padrão.
No entanto, cedo descobrimos que existiam muitos problemas para fazer com que o sistema externo gerasse XML que o Dynamics AX aceitasse. O esquema XML gerado pelo Dynamics AX é bastante complexo e também parece haver alguns bugs no Dynamics AX que por vezes o fazem rejeitar XML cujo esquema é válido de acordo com outras ferramentas, pelo que, no geral, provou ser menos simples do que eu pensava.
Durante o processo, muitas vezes tive dificuldade em descobrir qual era exatamente o problema com determinados ficheiros XML porque as mensagens de erro fornecidas pelo AIF são pouco informativas. Também era tedioso, porque tinha de esperar que o sistema externo enviasse uma nova mensagem através do MSMQ e depois novamente para o AIF receber a mensagem e processá-la antes de poder ver um erro.
Por isso, investiguei se é possível chamar o código de serviço diretamente com um ficheiro XML local para testes um pouco mais rápidos e descobri que é possível.
O trabalho de exemplo abaixo lê um ficheiro XML local e tenta utilizá-lo com a classe AxdCustomer (que é a classe de documento utilizada pelo serviço CustCustomer) para criar um cliente. Pode criar tarefas semelhantes para todas as outras classes de documentos, por exemplo AxdSalesOrder, se necessário.
{
FileNameOpen fileName = @'C:\\TestCustomerCreate.xml';
AxdCustomer customer;
AifEntityKey key;
#File
;
new FileIoPermission(fileName, #IO_Read).assert();
customer = new AxdCustomer();
key = customer.create( XmlDocument::newFile(fileName).xml(),
new AifEndpointActionPolicyInfo(),
new AifConstraintList());
CodeAccessPermission::revertAssert();
info('Done');
}
O objeto AifEntityKey devolvido pelo método customer.create() (que corresponde à operação de serviço "create" no AIF) contém informação sobre qual o cliente que foi criado, entre outras coisas, o RecId do registo CustTable criado.
Se o que está a tentar testar é uma porta de saída ou se apenas necessita de um exemplo de como o XML deve ficar na porta de entrada, também pode utilizar a classe document para exportar um cliente para um ficheiro chamando o método read() (correspondente à operação de serviço "read"), assim:
{
FileNameSave fileName = @'C:\\TestCustomerRead.xml';
Map map = new Map( Types::Integer,
Types::Container);
AxdCustomer customer;
AifEntityKey key;
XMLDocument xmlDoc;
XML xml;
AifPropertyBag bag;
#File
;
map.insert(fieldNum(CustTable, AccountNum), ['123456']);
key = new AifEntityKey();
key.parmTableId(tableNum(CustTable));
key.parmKeyDataMap(map);
customer = new AxdCustomer();
xml = customer.read(key,
null,
new AifEndpointActionPolicyInfo(),
new AifConstraintList(),
bag);
new FileIoPermission(fileName, #IO_Write).assert();
xmlDoc = XmlDocument::newXml(xml);
xmlDoc.save(fileName);
CodeAccessPermission::revertAssert();
info('Done');
}
É claro que deve substituir '123456' pelo número de conta do cliente que pretende ler.