Criando Custom Pipeline Disassembler - Quebra de FF em N Registros. Parte 2
terça-feira, 6 de março de 2012
|
|
Olá Pessoal. Essa é o segundo post sobre como criar um Custom Pipeline Disassembler.
Na primeira parte do post, falamos sobre quando criar esse tipo de componente, como criar o projeto e adicionar as referencias necessárias.
Como prometido vamos implementar a Interface IDisassemblerComponent.
Nessa interface exige que implementemos basicamente dois métodos: o Disassemble e o GetNext.Adicionando as Bibliotecas
Antes de começar, vamos adicionar a dll Microsoft.Biztalk.XpathReader e Microsoft.BizTalk.Component.UtilitiesBasta clicar em Add Reference e apontar para o caminho abaixo:
C:\Windows\assembly\GAC_MSIL\Microsoft.Biztalk.XpathReader\3.0.1.0__31bf3856ad364e35\Microsoft.Biztalk.XpathReader.dllE precisamos adicionar as seguintes bibliotecas:
C:\Windows\assembly\GAC_MSIL\Microsoft.BizTalk.Component.Utilities\3.0.1.0__31bf3856ad364e35\Microsoft.BizTalk.Component.Utilities.dll
Adicione as váriaveis globais:using System.Resources;
using System.Reflection;using System.Diagnostics;using System.Collections;
using System.ComponentModel;
using System.Xml.XPath;
using System.Xml;
using Microsoft.BizTalk.XPath;
using Microsoft.BizTalk.Message.Interop;
using Microsoft.BizTalk.Component.Interop;
using Microsoft.BizTalk.Component;
using Microsoft.BizTalk.Messaging;
using Microsoft.BizTalk.Component.Utilities;
using Microsoft.Samples.BizTalk.Pipelines.CustomComponent;
Compilando a classe SeekableReadOnlyStreamprivate ArrayList outboundMessages = null; private int currentMessage = 0; private bool stopCollectingMessages = false;
No mundo do Biztalk devemos evitar usar a classe xmlDocument para tratar mensagens grandes (leia-se > 2mb). Junto com a instalação do Biztalk a Microsoft disponibiliza a classe SeekableReadOnlyStream, que pode tratar arquivos > 100 mb. Bastante hein?
Só que, essa classe não é nativa do .NET, ela esta disponivel em um Sample e deve ser compilado e publicado no GAC com strong key (chave de registro).
1 - Então vá até o diretório:
%Diretorio_de_Instalacao%\Microsoft BizTalk Server 2010\SDK\Samples\Pipelines\SchemaResolverComponent\SchemaResolverFlatFileDasm2 - Abra a solution SchemaResolverFlatFileDasm.sln
3 - Acrescente uma strong key e faça o deploy normalmente.
Implementando as Interfaces
Agora no nosso projeto adicione a dll que foi gerada e cole o código abaixo na classe TrataFlatFile.cs1: void IDisassemblerComponent.Disassemble(IPipelineContext pContext, IBaseMessage pInMsg)
2: {
3: try
4: {
5: base.DocumentSpecName = this.DocumentSpecName;
6: base.Disassemble(pContext, pInMsg);
7: }
8: catch (Exception ex)
9: {
10: System.Diagnostics.EventLog.WriteEntry("SampleDisassemble", ex.Message,
11: EventLogEntryType.Error);
12: }
13:
14: }
15:
16: IBaseMessage IDisassemblerComponent.GetNext(IPipelineContext pContext)
17: {
18: //System.Diagnostics.EventLog.WriteEntry("GetNext:Called", currentMessage.ToString());
19: try
20: {
21: if (stopCollectingMessages == false)
22: {
23: outboundMessages = new ArrayList();
24: IBaseMessage ibmTemp = base.GetNext(pContext);
25: GetSplittedMessages(ibmTemp, pContext);
26: stopCollectingMessages = true;
27: if (0 == outboundMessages.Count)
28: return null;
29: }
30: }
31: catch (Exception ex)
32: {
33: System.Diagnostics.EventLog.WriteEntry("SampleDisassemble", ex.Message,
34: EventLogEntryType.Error);
35: }
36:
37: if (currentMessage == outboundMessages.Count)
38: return null;
39: // Return the current collected message
40: return (IBaseMessage)outboundMessages[currentMessage++];
41:
42: }
Segue o código:
1: private void GetSplittedMessages(IBaseMessage ibmParam, IPipelineContext pCxt)
2: {
3: XmlDocument xDoc = new XmlDocument();
4:
5: SeekableReadOnlyStream seek = new SeekableReadOnlyStream(ibmParam.BodyPart.Data);
6:
7: XPathCollection xCollection = new XPathCollection();
8: XPathReader xReader = new XPathReader(new XmlTextReader(seek), xCollection);
9:
10: int iHeader = xCollection.Add("/*[local-name()='Root' and namespace-uri()='Namespace']/*[local-name()='Intercambio' and namespace-uri()='']");
11:
12: bool blnMoveNext = true;
13: int iCont = 1;
14:
15: while (blnMoveNext)
16: {
17: blnMoveNext = xReader.ReadUntilMatch();
18: iCont++;
19: XmlElement xeHeader = xDoc.CreateElement("Header");
20:
21: StringBuilder xml = new StringBuilder();
22:
23: do
24: {
25: if ("Header" != xReader.LocalName)
26: {
27: switch (xReader.NodeType)
28: {
29: case XmlNodeType.Element:
30: xml.Append("<" + xReader.LocalName + ">");
31: if (xReader.IsEmptyElement)
32: xml.Append("<" + xReader.LocalName + "/>");
33: break;
34: case XmlNodeType.Text:
35: xml.Append(xReader.Value);
36: break;
37: case XmlNodeType.EndElement:
38: xml.Append("</" + xReader.LocalName + ">");
39: break;
40: case XmlNodeType.XmlDeclaration:
41: xml.Append("</" + xReader.Name + ">");
42: //writer.WriteProcessingInstruction(xReader.Name, xReader.Value);
43: break;
44: }
45: }
46: } while (xReader.Read() && !xReader.Match(iHeader));
47:
48:
49: if (iCont > 50) //Quantidade de Registros na quebra
50: {
51: iCont = 1;
52: XmlElement xeRoot = xDoc.CreateElement("Root");
53: xeRoot.InnerXml = xml.ToString();
54:
55: xDoc.AppendChild(xeRoot);
56:
57: IBaseMessage msg = null;
58: msg = pCxt.GetMessageFactory().CreateMessage();
59: msg.Context = ibmParam.Context;
60:
61: IBaseMessagePart msgPart = pCxt.GetMessageFactory().CreateMessagePart();
62: System.IO.MemoryStream memStrm = new MemoryStream();
63: xDoc.Save(memStrm);
64:
65: memStrm.Position = 0;
66: memStrm.Seek(0, System.IO.SeekOrigin.Begin);
67: msgPart.Data = memStrm;
68: msg.AddPart(ibmParam.BodyPartName, msgPart, true);
69:
70: outboundMessages.Add(msg);
71: pCxt.ResourceTracker.AddResource(memStrm);
72: }
73: }
74: }
Lembrando que é necessário publicar a dll no GAC com o strong key, assim o custom Disassembler criado irá aparecer na tag Pipeline Components.
Conclusão:
Aprendemos neste post a usar a classe SeekableReadOnlyStream que pode tratar arquivos > 100 mb e vimos como quebrar essas mensagens em 50 registros por vez.
Assim quando o Biztalk receber um arquivo com 200 registros irá ser criado 4 instancias contendo 50 registros cada uma.
Espero que tenham gostado! Até a próxima…
Seja o primeiro a comentar ;)
Postar um comentário