montaque

小碗喝酒,小口吃肉

博客园 首页 新随笔 联系 订阅 管理
  108 Posts :: 1 Stories :: 603 Comments :: 7 Trackbacks

2008年6月10日 #

如何用写一个bat脚本返回昨天的年月日,其实用bat写很麻烦,你要写一个For 来拿到Date的年月日,然后再写一个小程序来推算昨天的年月日。其实要使能直接执行.net代码多好,.net Datetime.Now.AddDays(-1) 就是昨天了

 

其实Powershell就帮你回答这个问题,可以利用.net 类库丰富的功能支持,比如操作XML,文件IO,网络等特性。当然也可也自己来写一个类库,来实现复杂的脚本。

 

这时候,你打开powershell,敲入 [DateTime]::Now

则返回当前的日期,如果看看Now有哪些方法和属性

[DateTime]::Now | get-member

image

当然你要计算你长了多大的话,[DateTime]::Now-[DateTime]("yourbirthday")就返回你的年龄了,呵呵。我通常用这个来计算一下我baby几个月几天了。

 

powershell允许你定义一个变量,针对FTP下载的问题。你首先生成你要下载的文件名,然后整理到一个String,发给FTP就可以了。

以下是一个简单的例子。

$yersterday=[DateTime]::Now.AddDays(-1);
$yyyy=$yersterday.Year;
$mm=$yersterday.Month;
$day=$yersterday.Day;
$file1=[String]::Format("90193698_{0}{1:00}{2:00}_{0}{1:00}{2:00}.zip",$yyyy,$mm,$day); 

$cmd = "open yourftpserver
user username password

binary
get $file1"

$cmd | ftp -i -n

 

把他另存为一个PS1文件。 如果让他自动运行的话,写一个windows schedule task "powershell fullpathoftheps1"

默认poweshell有一个执行策略,不运行执行伟签名的文件。你可以改为

set-ExecutionPolicy RemoteSigned

或者直接改一下注册表

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell

image

 

或许这是个PS很好的一个实用例子吧。

posted @ 2008-06-10 02:27 montaque 阅读(1933) | 评论 (4)编辑

2008年5月30日 #

EDI in Biztalk 2006 R2 举了一个简单的例子。 通过裁剪满足特定vendor格式的EDI Schema,接受EDI转换成XML。

这时候的EDI很简单。

ISA*00*          *00*          *01*Fedex          *ZZ*Montaque       *070607*1555*U*00401*000000025*0*T*>~
GS*IN*Fedex*Montaque*20070607*1555*25*X*004010~
ST*810*0025~
N1*SF*COMPANY X~
N3*P.O. BOX 12345~
N4*ANYTOWN*OH*45678~
IT1*1*0.528*TS*1.13**VP*1AGHA1223221~
CTT*1~
SE*7*0025~
GE*1*25~
IEA*1*000000025~

只有一个Group,Group中只有一个Transaction Set。 如果包含多个TransactionSet,Biztalk是怎么处理呢

假设EDI文件改为以下格式。一个GS中,有三个TransactionSet。

ISA*00*          *00*          *01*Fedex          *ZZ*Montaque       *080529*0927*U*00401*000000014*0*T*>~
GS*IN*Fedex*Montaque*20080529*0927*14*T*00401~
ST*810*0014~
N1*SF*Montaque~
N3*16839 E Gale Ave. 91745~
N4*ANYTOWN*OH*45678~
IT1*1*0.528*TS*1.13**VP*1AGHA1223221~
CTT*1~
SE*7*0014~
ST*810*0015~
N1*SF*Montaque~
N3*16839 E Gale Ave. 91745~
N4*ANYTOWN*OH*45678~
IT1*1*0.528*TS*1.13**VP*1AGHA1223221~
CTT*1~
SE*7*0015~

ST*810*0016~
N1*SF*Montaque~
N3*16839 E Gale Ave. 91745~
N4*ANYTOWN*OH*45678~
IT1*1*0.528*TS*1.13**VP*1AGHA1223221~
CTT*1~
SE*7*0016~
GE*3*14~
IEA*1*000000014~

在Batch Inbound的时候,EDIReceiver Pipeline首先识别Party,然后找到该Party的Setting。默认是会Split成N个单独的消息。每个消息包含一个TransactionSet。

image 

如果把上面的EDI丢到Biztalk的话,他会产生三个消息。

每个消息包含一个TS。比如

image 

而我们也可以把它设置为。Preserver interchange,后面两个选项。告诉你出错的时候,刮起对应的Interchange还是TS。

这时候再处理的话,就会看大他把几个消息放在一个文件中。

 image

这个设置会牵涉到系统的设计。如果Vendor给一个包含10000个TS的EDI文件是启动一个Orchestration 实例处理,还是启动10000个。

一个的话,需要自己写一个Loop,而且load一个这么大的文件到内存。性能也不好。好处是实例数很少。

posted @ 2008-05-30 03:02 montaque 阅读(1056) | 评论 (1)编辑

Biztalk 可以做EAI,也可以做B2B。 做EAI的话,是企业内部的一个信息Hub或者总线。如果做B2B的话,则相当于企业对外的一个Gateway。不同的partner有不同的平台或者标准以及设置。所以biztalk除了做集成之外,还要去管理这些契约和元数据。

假定企业A使用EDI来跟不同的上下游做集成和信息交换。EDI经常会问几个问题?

  • 这家企业使用的是那个版本?EDI有好多版本。对应到Biztalk就是我收到这家企业的EDI之后,该用哪个Schema来解释
  • 使用X12还是EDIFact
  • 要不要处理double posting的问题。
  • Batch Inbound/outbound 处理。
  • 要不要ACK
  • 文件格式,换行时CR,还是CRLF等。

面对这个问题,Biztalk R2的EDI是通过一个新的Party识别机制来实现的。

每个Party都有具体的设定针对以上问题。Biztalk通过设别Party,从而应用该Party的设置。

我们看一下典型的EDI头。

ISA*00*          *00*          *01*Fedex          *ZZ*Montaque       *070607*1555*U*00401*000000025*0*T*>~

IS5-6事实上说sender是谁?比如*01*Fedex         

*ZZ*Montaque       * 则是说发给谁。 因为一家公司可能有不同的子公司。后面其实有00401 说明是什么版本。

Biztalk的Party识别就是基于这两个信息。首先看有没有一个party设置,完全匹配 Sender 和 receiver。

image

如果完全匹配,则使用该Party的设置。以上截图说明我们正好有个party叫Fedex。他的发送和接受完全匹配。设置其默认schema用来解析EDI。

一般来说一个party通常我们制定其Targetnamespace都一样。不同的文件,810还是850再做详细的剪裁。

然后如果Sender和Receiver不完全匹配。我们可能只指定Sender,Receiver为空。这时候适合一家公司下面有多个子公司,vendor发给你的时候,Biztalk作为Gateway忽略这些不同。

如果我们希望多个Sender来自不同的公司,使用一样的一组设置。那么可以设定QualifiedName

image

如果这些都没做,那么系统会默认使用Global Setting。

image

如何知道接收的消息所以那个Party呢? 一旦一个消息被解析为特定的一个party之后,该message会有一个PromotedProperty,叫做PartyName,比如下图所示。如果任何一个都没有被命中的话,则显示为Guestparty。

image

R2 EDI 很大程序上依赖这个party设置。包括AS2.  所以了解这个party解析算法很重要。

 

以上提到的是接受来自partner的EDI。 在party setting中称为Sender Setting。

如果是发送呢?

怎么知道该用哪个party的设置发送给Vendor?

这个正好反过来。你需要在系统中Promote PartyName,如果没有party的话,则会用Global的 Receiver Setting。

image

这里的Sender和Receiver是相对Biztalk 来说。 Sender 表示有个partner 发送消息给Biztalk。biztalk事实上是接受消息。这时候的IS5-8 是来识别Party。

Receiver表示有个partner需要加收Biztalk的消息。biztalk则是发消息给他。 这时候的IS5-8 是来制定EDI上的头。

posted @ 2008-05-30 02:51 montaque 阅读(994) | 评论 (0)编辑

在biztalk 2006 R2中,EDI做了很大的加强。其中之一就是Party的识别算法和 EDI 由 Adpater 移到Pipeline中。

EDI 的schema在Biztalk R2中很大,C:\Program Files\Microsoft Biztalk Server\XSD_Schema\EDI 下面有一个压缩文件。加压后大概有4G多。

一把来说,你用哪个,把对应的schema从中加压出来。然后修改之,达到你想要的效果。一来默认的schema非常大,一个schema可能有5M左右,编译成Dll 翻倍,10M。 而.net assembly的大小不能大于75M,所以一般来说一个Dll只能包含5个左右的Schema。

这个时候,你就要小心剪辑你的Schema文件。

比如我有一个810 invoice的文件。如下,接下来我们一步一步的配置Biztalk ,解析成xml文件。这个EDI是版本00401,810.

ISA*00*          *00*          *01*Fedex          *ZZ*Montaque       *070607*1555*U*00401*000000025*0*T*>~
GS*IN*Fedex*Montaque*20070607*1555*25*X*004010~
ST*810*0025~
N1*SF*COMPANY X~
N3*P.O. BOX 12345~
N4*ANYTOWN*OH*45678~
IT1*1*0.528*TS*1.13**VP*1AGHA1223221~
CTT*1~
SE*7*0025~
GE*1*25~
IEA*1*000000025~

 

我们首先从schema压缩包中解压缩这个文件。

image

新建一个Biztalk的项目,把这个schema 添加进去。

image

这个schema还好1M多,接下来我们剪辑一下。假定Fedex给我们的文件,只需要ST,Nloop,CTT

我们把其他的都删除,你可以ctl多选或者shifit所中所有的节点。删除之,把他瘦身一下。

image

Biztalk是通过schema的TargetNamespace和RootElement来区分不同的schema。由于这个schema我们是专门针对Fedex的,所以不能直接部署到biztalk。我们把他的namespace有

http://schemas.microsoft.com/BizTalk/EDI/X12/2006

改为

http://schemas.microsoft.com/BizTalk/EDI/X12/2006/Fedex

image

然后选择项目属性,给他一个AssemblyKey,部署到EDIDemo这个Application中。然后点击部署

此时可以看到EDIDemo中有我们剪切好的Schema

image

 

Biztalk R2如果你Enable EDI的话,会默认帮你新建一个Biztalk EDI Application

用于处理EDI的系统Schema,Pipeline,等对象都在这个Application中。

默认我们的EDiDemo中并没有EDISend和EDIReceive的Pipiline

image

接下来右键EDIDemo Application,选择Add->Reference,EDI Application.这时候你就可以使用这些pipeline了。

我们首先新建一个Static one-way ReceivePort叫做 ReceivePort1

然后新建一个receivelocation,选择FileAdapter,PipeLine选择EDiReceive

image

然后Enable这个ReceiveLocation。

 

接着建立一个SendPort,设置一个Filter,如果从ReceivePort1来的消息,直接发出去。

image

设置一个Filter,这样不同写Orchastration来订阅这个消息。

 

image

这时候先Enlist这个sendport,注意不要Enable。为了调试方便。这样的话,你就可以看到将要发出什么消息出来。

 

这时候我们就可以发消息了。 把我们写好的EDI文件,Copy一份到接受目录。

这时候不巧,消息并没有出来。看一下系统日志,有个错误。错误如下:


Error encountered during parsing. The X12 transaction set with id '' contained in functional group with id '25', in interchange with id '000000025', with sender id 'Fedex          ', receiver id 'Montaque       ' is being suspended with following errors:

Error: 1 (Miscellaneous error)
    6: Missing or invalid or duplicate Transaction set identifier 'http://schemas.microsoft.com/BizTalk/EDI/X12/2006#X12_00401_810'

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

意思是说我们没有指定TransactionSet,这里的The X12 transaction set with id ''  id是空。哪里出错了呢?

接下来我们用Cordbg调试一下,一般来说在Biztalk里面使用EDI,很容易出这样那样的错误。尤其是EDI,出错了之后错误日志很模糊,由于Biztalk是个典型的.net application,我们可以通过查看异常的StackTrace,看到底发生什么了。

run Cordbg

Ca e

a [Biztalk的Process]

g

这时候再丢一个文件进去。cordbug就看到错误了。run De,退出调试,让程序直接走。

image

意思是说EDI的Pipeline,试图用://schemas.microsoft.com/BizTalk/EDI/X12/2006#X12_00401_810 来解析这个消息。可是这个schema并没有部署。为什么呢? 我们改了schema的namespace。 后面我会讲EDI得schema识别算法

EDI 有四种算法来解析改用那个schema。我们什么都没有设置,所以shema是由Global EDI Setting设置的

打开Party下面,右键Global EDI setting

image

果然,他设置的还是旧的那个Schema。我们把它改一下

改为 http://schemas.microsoft.com/BizTalk/EDI/X12/2006/Fedex

reboot一下Biztalk Service

然后确认,再丢一个消息进去。

打开biztalk的管理界面,查看一下suspended instance

就可以看到系统将要发出去的消息

image

你可以双击查看消息的明文

image

右键,resume这个instance。

image

然后接看到文件被发出来了。

image

 

当然这个只是一个Demo。可以写一个流程来处理该消息,比如写入数据库等。

我们剪切了一个Schema,针对一个vendor Fedex。然后配置了全局都使用这个schema。事实上可以配置Party,不同的party使用针对他们的schema

后面继续讲。

posted @ 2008-05-30 01:32 montaque 阅读(1005) | 评论 (0)编辑

2008年5月26日 #

Hello, Biztalk 2006 R2 BAM 中提到了如何配置一个BAM的Activity模型以及通过BAM API直接把关键业务数据喂给BAM。这个适合于企业中Legacy 系统的场景。

 

接下来我们还是以上次的HelloBamActivity模型为例,配置一个WCF程序。通过添加一个Behavior,定义一个IC(interceptor Configuration)拦截模型。把WCf运行过程中的一些关键业务数据喂给BAM。

 

我们首先写一个简单的WCF 程序。客户端发送一个订单到WCF 服务。订单包括State,和 Amount以及ID,这个订单的两个属性我们认为是个关键业务数据,需要提取出来反映在BAM中。

 

写一个WCF 程序。 由于WCF是基于消息的应用,不像Remoting,会有对象的跨Appdomain调用,写一个remoting应用需要两个appdomain,一般来说是两个应用程序。所以很简单,我就把WCF的Client和Service 都放在一个Console程序中。 为了调试方便,采用最简单的basicHttpBinding,没有安全。这样我们可以很轻松用TCPTrace,看到消息的传递过程。编译IC中的Xpath配置。

 

New一个Console Application叫做SingleWCF,添加对System.ServiceModel 和 System.Runtime.Serialization 的引用。

然后新建一个Class,定义Contract,Service实现。代码如下:

using System;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Threading;

namespace SingleWCF
{
    [DataContract()]
    public class PO
    {
        [DataMember]
        public float Amount;

        [DataMember]
        public string State;

        [DataMember]
        public string Id;
    }

    [ServiceContract()]
    public interface IPOService
    {
        [OperationContract()]
        string SubmitPo(PO po);
    }

    [ServiceBehavior(AddressFilterMode=AddressFilterMode.Any)]
    public class POServiceImpl : IPOService
    {

        #region IPOService Members

        public string SubmitPo(PO po)
        {
            Console.WriteLine("Service get the PO");
            Thread.Sleep(3000);
            Console.WriteLine("Service Processed the PO");
            return po.Id;
        }

        #endregion
    }
}

然后添加一个 APP.Config 文件。来Host这个Service。文件如下,

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
      <system.serviceModel>
               <behaviors>
                      <serviceBehaviors>
                <behavior name="enableWSDL">
                    <serviceMetadata httpGetEnabled="true" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <services>
            <service behaviorConfiguration="enableWSDL" name="SingleWCF.POServiceImpl">
                <endpoint address="ws" binding="basicHttpBinding" bindingConfiguration="basicBindingNoSecurity"
                    contract="SingleWCF.IPOService" behaviorConfiguration="bamBehavior" />
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:8888/service" />
                    </baseAddresses>
                </host>
            </service>
        </services>
      <client>
        <endpoint address=http://localhost:8888/service/ws behaviorConfiguration="bamBehavior" binding="basicHttpBinding" bindingConfiguration="basicBindingNoSecurity"
                   contract="SingleWCF.IPOService" name="clientendpoint" />
      </client>
      <bindings>
        <basicHttpBinding>
          <binding name="basicBindingNoSecurity">
            <security mode="None"/>
          </binding>
        </basicHttpBinding>
      </bindings>
    </system.serviceModel>
</configuration>

然后来Host Service并且调用。

using System;
using System.ServiceModel;
using System.Threading;

namespace SingleWCF
{
    class Program
    {
        static System.Threading.ManualResetEvent mre;
        static void Main(string[] args)
        {
             mre = new ManualResetEvent(false);
            System.Threading.ThreadPool.QueueUserWorkItem(StartHost);
            mre.WaitOne();
            System.Threading.ThreadPool.QueueUserWorkItem(StartClient);           
            Console.ReadLine();
        }

        public static void StartHost(object o)
        {
            ServiceHost host = new ServiceHost(typeof(POServiceImpl));
            host.Open();
            Console.WriteLine("HostStarted");
            mre.Set();
            Console.ReadLine();
        }

        public static void StartClient(object o)
        {
            ChannelFactory<IPOService> factory = new ChannelFactory<IPOService>("clientendpoint");

            IPOService client = factory.CreateChannel();
            PO p=new PO();
            p.Amount=120;
            p.State="WA";
            p.Id = Guid.NewGuid().ToString();
            client.SubmitPo(p);
            Console.WriteLine("PO Sent Done");

        }
    }
}

然后运行一下,就可以看到Service正常调用。

image

 

这时候把程序App.Config少许该一下,让客户端发送的目的地址由http://localhost:8888/service/ws 端口8888改为9999,然后TCPTrace负责forward9999到8888.这样客户和服务端之间的http通讯都可以被监视到。类似Soaptoolkit的monitor工具。

image

首先启动TCPTrace,可以从 http://www.pocketsoap.com/tcptrace/ 下载。

image


 

在运行程序,就可以在TCPTrace看到消息的调用。包括发送和接受的消息。

image

到这里我们的WCF service 就写好了。接下来需要配置我们的拦截模型IC,并且部署到BAM的配置库。

关于拦截模型。

首先需要定义一个事件源(EventSource),比如WCF程序是一个事件源。WF程序也是一个事件源。Biztalk也是事件源。

对于事件源,如果是.net 程序集,需要制定Assembly的fullname,如果是Biztalk,要制定是messagebox还是orchastration。

有了事件源,需要定义一个或者多个事件模型。

事件的定义,是通过Filter来筛选,事件发生后有要更改Activity的那些属性,通过Update来配置。另外还可以指定Reference,类似引用那个文档或者Activity。以及如何把多个事件源生成的Activity关联到一个的Continous模型。这个后面会讲。

对于事件源,一下是一个例子。

image

对于WCF,manifest是Contract的fullname,WF,则是workflow的fullname。

然后是一个事件的tree

image

 

接下来我们配置一个我们的IC.

我们需要配置的IC的事件源来自WCF。

当客户端发出一个请求的时候,并且是调用SubmitPo 的时候,我们称这个事件叫做BeginOrder。这时候拦截到State,Amount 属性。并且把当前的时间更新到Activity的BeginOrder。

当客户端收到submitPO的时候,我们成为事件EndOrder,更新Activity的EndOrder属性。

为了方便生成这个XML。Biztalk R2提供了三个Schema,分别面向WCF、WF,Common IC

WcfInterceptorConfiguration.xsd

CommonInterceptorConfiguration.xsd

这两个文件可以在SDK目录下面找到,如果没有的话,在安装盘Msi\Program Files\SDK\Samples\BIX 下面。可以把这两个文件copy到visual studio的schema 目录下面。方便有智能提示。

我们新建一个XML到项目中,成为wcfInterceptor.xml

<?xml version="1.0" encoding="utf-8" ?>
<bam:InterceptorConfiguration xmlns:bam="http://schemas.microsoft.com/BizTalkServer/2004/10/BAM/InterceptorConfiguration"
                          xmlns:bamwcf="http://schemas.microsoft.com/BizTalkServer/2004/10/BAM/WcfInterceptorConfiguration">
</bam:InterceptorConfiguration>

这时候按照智能提示,大多数配置可以轻松搞定。

定义一个事件源

<bam:EventSource Manifest="SingleWCF.IPOService, SingleWCF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" Name="wcfSource" Technology="WCF">
</bam:EventSource>

注意这里的manifest是fullname,wcf程序在运行的时候会根据当前endpoint所绑定的contract的全名去数据库中选招match的ic。如果manifest写错了的话,你就得不到任何BAM数据。

 

然后定义第一个事件。条件是:

ClientRequest 一个Operation是SubmitPo 

对应成语法是GetServiceContractCallPoint()=ClientRequest And GetOperationName()="SubmitPO"

IC 采用一个特殊的语法,叫做反向表达式。就是操作数在前,操作符在后。比如我们计算2+3×4 写作 234×+

WCF 有一些特殊的Operation,比如:

AutoGenerateCorrelationToken
GetContextProperty
GetEndpointName
GetOperationName //返回当前的调用的Contract的Operation
GetServiceContractCallPoint//调用拦截点。是ClientRequest还是ServiceReply
XPath//从message中抓数据。

这些可以从MSDN看到返回值和使用方式。

 

对应成ic的xml就是

<bam:OnEvent Name="BeginOrder" IsBegin="true" IsEnd="false" Source="wcfSource">
     <bam:Filter>
       <bam:Expression>
         <bamwcf:Operation Name="GetServiceContractCallPoint">           
         </bamwcf:Operation>
         <bam:Operation Name="Constant">
           <bam:Argument>ClientRequest</bam:Argument>
         </bam:Operation>
         <bam:Operation Name="Equals">           
         </bam:Operation>
         <bamwcf:Operation Name="GetOperationName">           
         </bamwcf:Operation>
         <bam:Operation Name="Constant">
           <bam:Argument>SubmitPo</bam:Argument>
         </bam:Operation>
         <bam:Operation Name="Equals">
         </bam:Operation>
         <bam:Operation Name="And"></bam:Operation>
       </bam:Expression>       
     </bam:Filter>
     <bam:CorrelationID>
       <bam:Expression>
         <bamwcf:Operation Name="XPath">
           <bamwcf:Argument>
             //*[local-name(.)='Id']
           </bamwcf:Argument>
         </bamwcf:Operation>
       </bam:Expression>
     </bam:CorrelationID>
     <bam:Update DataItemName="BeginOrder" Type="DATETIME">
       <bam:Expression>
         <bamwcf:Operation Name="GetContextProperty">
           <bamwcf:Argument>EventTime</bamwcf:Argument>
         </bamwcf:Operation>
       </bam:Expression>
     </bam:Update>
     <bam:Update DataItemName="State" Type="NVARCHAR">
       <bam:Expression>
         <bamwcf:Operation Name="XPath">
           <bamwcf:Argument>//*[local-name(.)='State']</bamwcf:Argument>
         </bamwcf:Operation>
       </bam:Expression>
     </bam:Update>
     <bam:Update DataItemName="Amount" Type="FLOAT">
       <bam:Expression>
         <bamwcf:Operation Name="XPath">
           <bamwcf:Argument>//*[local-name(.)='Amount']</bamwcf:Argument>
         </bamwcf:Operation>
       </bam:Expression>
     </bam:Update>
   </bam:OnEvent>

其中有一个element是CorrelationID,相当于Activity的PK值。不同的事件触发如何关联到一个Activity

接下来定义另外一个事件,服务返回。更新EndOrder时间。

<bam:OnEvent Name="EndOrder" IsBegin="false" IsEnd="true" Source="wcfSource">
     <bam:Filter>
       <bam:Expression>
         <bamwcf:Operation Name="GetServiceContractCallPoint">
         </bamwcf:Operation>
         <bam:Operation Name="Constant">
           <bam:Argument>ServiceReply</bam:Argument>
         </bam:Operation>
         <bam:Operation Name="Equals">
         </bam:Operation>
       </bam:Expression>
     </bam:Filter>
     <bam:CorrelationID>
       <bam:Expression>
         <bamwcf:Operation Name="XPath">
           <bamwcf:Argument>
             //*[local-name(.)='SubmitPoResult']
           </bamwcf:Argument>
         </bamwcf:Operation>
       </bam:Expression>
     </bam:CorrelationID>
     <bam:Update DataItemName="EndOrder" Type="DATETIME">
       <bam:Expression>
         <bamwcf:Operation Name="GetContextProperty">
           <bamwcf:Argument>EventTime</bamwcf:Argument>
         </bamwcf:Operation>
       </bam:Expression>
     </bam:Update>
   </bam:OnEvent>

 

请注意CorrelationID 的两个写法。从TCPTrace中可以看到这两个值对应一个请求。

写好这个IC之后,通过BM.exe部署

bm deploy-interceptor -filename:"xxx\SingleWCF\wcfInterceptor.xml"

这样IC模型就部署到BAM的元数据库中。你可以查询

image

数据中记录了该IC对应的Activity,以及事件的XML描述。

 

接下来我们要配置WCF程序,enable 一个BAM提供的EndpointBehavior,来横向拦截IC模型的数据。

右键 app.config,选择用EDIT with WCF Configuration.

Advance-> Extensions->new behavior element extension

image

新建一个Element 叫做bamEndpoinBehavior 名字可以自己随便输入。

Type 是Microsoft.BizTalk.Bam.Interceptors.Wcf.BamEndpointBehavior, Microsoft.BizTalk.Bam.Interceptors, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35

当然你可以点击Browser,定位到Gac中的Microsoft.BizTalk.Bam.Interceptors 程序集。

image

接下来新建一个EndpointBehavior叫做bamBehavior。把新建好的Element拖进去。配置

BAM数据连接字符串:指向本地BAM数据库

以及Polling的时间,写5,代表没5秒查询数据库看有没有新的IC定义。

然后配置service和client endpoint使用该behavior

image

此时完整的App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
      <system.serviceModel>
        <extensions>
            <behaviorExtensions>
                <add name="bamEndpointBehavior" type="Microsoft.BizTalk.Bam.Interceptors.Wcf.BamEndpointBehavior, Microsoft.BizTalk.Bam.Interceptors, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            </behaviorExtensions>
        </extensions>
        <behaviors>
            <endpointBehaviors>
                <behavior name="bamBehavior">
                    <bamEndpointBehavior ConnectionString="Data Source=.;Initial Catalog=bamprimaryimport;Integrated Security=True"
                        PollingIntervalSec="5" />
                </behavior>
            </endpointBehaviors>
            <serviceBehaviors>
                <behavior name="enableWSDL">
                    <serviceMetadata httpGetEnabled="true" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <services>
            <service behaviorConfiguration="enableWSDL" name="SingleWCF.POServiceImpl">
                <endpoint address="ws" binding="basicHttpBinding" bindingConfiguration="basicBindingNoSecurity"
                    contract="SingleWCF.IPOService" behaviorConfiguration="bamBehavior" />
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:8888/service" />
                    </baseAddresses>
                </host>
            </service>
        </services>
      <client>
        <endpoint address="http://localhost:9999/service/ws"
                  behaviorConfiguration="bamBehavior" binding="basicHttpBinding"
                  bindingConfiguration="basicBindingNoSecurity"
                   contract="SingleWCF.IPOService" name="clientendpoint" />
      </client>
      <bindings>
        <basicHttpBinding>
          <binding name="basicBindingNoSecurity">
            <security mode="None"/>
          </binding>
        </basicHttpBinding>
      </bindings>
    </system.serviceModel>
</configuration>

 

大功告成了,Run 一下应用程序。然后打开BAM portal, http://localhost/bam 就可以看到数据进去了。

beginorder,endorder之间相差3秒左右。应为我们程序休息了3秒。 state是WA,amount是120.这些都是WCF 提供的数据。

image

 

如何调试知道Event有没有被命中呢? wcf intercepotr 采用.net标准的Trace模型。在App.config中加入

<system.diagnostics>
  <sources>
    <source name="Microsoft BizTalk Bam Interceptors" switchValue="All">
      <listeners>
        <add name="consolelistener" type="System.Diagnostics.ConsoleTraceListener"/>
      </listeners>
    </source>
  </sources>
</system.diagnostics>

注意SourceName必须是Microsoft BizTalk Bam Interceptors

我上次写成Microsoft Biztalk Bam Interceptors,结果什么也没有。debug了半天,hoho

再运行程序就看到结果了。一堆日志消息。

image

这样。WCF程序通过定义个interceptor模型,就可以把业务关键数据喂给bam了。

这里是完整的模型文件。

<?xml version="1.0" encoding="utf-8" ?>
<bam:InterceptorConfiguration xmlns:bam="http://schemas.microsoft.com/BizTalkServer/2004/10/BAM/InterceptorConfiguration"
                          xmlns:bamwcf="http://schemas.microsoft.com/BizTalkServer/2004/10/BAM/WcfInterceptorConfiguration">

  <bam:EventSource
    Manifest="SingleWCF.IPOService, SingleWCF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
    Name="wcfSource" Technology="WCF">
  </bam:EventSource>
  <bam:BamActivity Name="HelloBamActivity">
    <bam:OnEvent Name="BeginOrder" IsBegin="true" IsEnd="false" Source="wcfSource">
      <bam:Filter>
        <bam:Expression>
          <bamwcf:Operation Name="GetServiceContractCallPoint">           
          </bamwcf:Operation>
          <bam:Operation Name="Constant">
            <bam:Argument>ClientRequest</bam:Argument>
          </bam:Operation>
          <bam:Operation Name="Equals">           
          </bam:Operation>
          <bamwcf:Operation Name="GetOperationName">           
          </bamwcf:Operation>
          <bam:Operation Name="Constant">
            <bam:Argument>SubmitPo</bam:Argument>
          </bam:Operation>
          <bam:Operation Name="Equals">
          </bam:Operation>
          <bam:Operation Name="And"></bam:Operation>
        </bam:Expression>       
      </bam:Filter>
      <bam:CorrelationID>
        <bam:Expression>
          <bamwcf:Operation Name="XPath">
            <bamwcf:Argument>
              //*[local-name(.)='Id']
            </bamwcf:Argument>
          </bamwcf:Operation>
        </bam:Expression>
      </bam:CorrelationID>
      <bam:Update DataItemName="BeginOrder" Type="DATETIME">
        <bam:Expression>
          <bamwcf:Operation Name="GetContextProperty">
            <bamwcf:Argument>EventTime</bamwcf:Argument>
          </bamwcf:Operation>
        </bam:Expression>
      </bam:Update>
      <bam:Update DataItemName="State" Type="NVARCHAR">
        <bam:Expression>
          <bamwcf:Operation Name="XPath">
            <bamwcf:Argument>//*[local-name(.)='State']</bamwcf:Argument>
          </bamwcf:Operation>
        </bam:Expression>
      </bam:Update>
      <bam:Update DataItemName="Amount" Type="FLOAT">
        <bam:Expression>
          <bamwcf:Operation Name="XPath">
            <bamwcf:Argument>//*[local-name(.)='Amount']</bamwcf:Argument>
          </bamwcf:Operation>
        </bam:Expression>
      </bam:Update>
    </bam:OnEvent>
    <bam:OnEvent Name="EndOrder" IsBegin="false" IsEnd="true" Source="wcfSource">
      <bam:Filter>
        <bam:Expression>
          <bamwcf:Operation Name="GetServiceContractCallPoint">
          </bamwcf:Operation>
          <bam:Operation Name="Constant">
            <bam:Argument>ServiceReply</bam:Argument>
          </bam:Operation>
          <bam:Operation Name="Equals">
          </bam:Operation>
        </bam:Expression>
      </bam:Filter>
      <bam:CorrelationID>
        <bam:Expression>
          <bamwcf:Operation Name="XPath">
            <bamwcf:Argument>
              //*[local-name(.)='SubmitPoResult']
            </bamwcf:Argument>
          </bamwcf:Operation>
        </bam:Expression>
      </bam:CorrelationID>
      <bam:Update DataItemName="EndOrder" Type="DATETIME">
        <bam:Expression>
          <bamwcf:Operation Name="GetContextProperty">
            <bamwcf:Argument>EventTime</bamwcf:Argument>
          </bamwcf:Operation>
        </bam:Expression>
      </bam:Update>
    </bam:OnEvent>
  </bam:BamActivity>
</bam:InterceptorConfiguration>

posted @ 2008-05-26 13:44 montaque 阅读(1126) | 评论 (3)编辑

2008年5月24日 #

Biztalk 2006 R2的BAM,允许我们很方便的让既有系统和WCF-based 系统,通过配置或者API的方式。把程序运行过程中的关键数据库push给BAM。 允许业务人员通过BAM的portal 来集中察看,甚至做分析。接下来我们首先Enable Biztalk的BAM,然后定义一个简单的活动模型。然后通过程序APi,把数据喂给他。

 

首先要Enable BAM。 BAM跟BAS不一样,不依赖Sharepoint,它是基于asp.net 2.0的一个简单web应用。只要有IIS就可以,操作系统vista也可以。另外如果要enable OLAP的分析的话,需要安装SQLServer分析服务,还有集成服务(有几个package来partation大的活动表)。如果使用alert,需要安装Notification服务。

安装的时候,选择BAM Client( Excel add-in 来定义Activity,BAM Event,就是WCF/WF的interceptor模型,Alert 是基于SQL Notification server 的provider)

image

然后配置BAM,如果你需要OLAP聚合的话,选中下面的选项。他会在分析服务中建立数据库

image

安装好之后,你可以访问http://localhost/bam 看bam portal ,初始时空的,什么都没有。这个portal允许你自定义,关键选项都在C:\Program Files\Microsoft Biztalk Server\BAMPortal\web.config 里面。另外portal目录下面有连个访问数据库的web service。portal是对web service 的一个展现。

image

接下来你就可以用Excel 来定义一个模型。如果是2007的话,选择Office按钮->Excel Options->Add-in ->Go enable BAM add-in,然后你就看到add-in 选贤卡。

image

 

接下来我们创建一个简单的模型。定义一个模型,用户提交订单,到订单处理结束。每个订单有订单的数量,以及来自哪个州。

Activity的属性:BeginOrder, EndOrder,OrderAmount, State

image

新建一个Activity,叫做HelloBamActivity.

image

Ok之后,Activity就好了。相当于表建好了,然后我们顶一个一个视图(KPIview)

image

选中我们的视图

image

然后选中所有的Column

image

下一步,这里我们可以新建一个Alias,或者duration以及分组,跟写SQL语句一样。

我们定义一个duration,叫做订单处理时间。(processedTime),是结束时间-开始时间。统计一下订单处理了多久。

image

然后我们定义一个聚合,定义维度和测量列

image

新建一个维度,我们以州作为一个维度

image

然后定义测量指标

平均处理时间MProcessedTime,这里的聚合只能有这个五种方式。

image

就这样吧,一直Next。

image

然后我们选中我们的维度和测量值。Excel帮你生成了个模拟数据。

image

然后到Add-in, 点击右边的按钮,告诉我我需要一个分析的olap。

然后点击Export Xml,到处一个Activity的定义文件。放到C:\temp\HelloBamActivity.xml

image

至此,activity就定义好了。接下来我们把它部署到BAM的数据库中。bm.exe 是一个命令行工具,来管理BAM的模型。我们先部署一个activity模型。

C:\Program Files\Microsoft Biztalk Server\Tracking>BM.exe

image

如果部署提醒你Star Schema不存在的话,说明你没有配好分析服务。

这时候你打开Portal ,就可以看到你的视图了。只是没有数据而已,

image

这时候在数据库里面,BamPrimaryImport就建立了一些表和视图。主要是这个Activity的元数据,以及存放实例的表。

image

Select * from dbo.bam_Metadata_Activities

返回activity列表。

 

接下来我们就要用API,往里面写一些关键的业务数据, 比如订单的开始时间,结束时间,以及州和数量。

新建一个Console Application

添加对C:\Program Files\Microsoft Biztalk Server\Tracking\Microsoft.BizTalk.Bam.EventObservation.dll的引用。这个Assembly 包含直接操作BAM的API。

 

我们无非是begin一个Activity,更新他的一些属性,然后退出。

代码如下

 

//begin a Astivity
          string dbConn="server=.;database=BamPrimaryImport;trusted_connection=yes";
          DirectEventStream des = new DirectEventStream(dbConn, 5);

          string activityId=Guid.NewGuid().ToString(); //Activity Id, can be any key
          des.BeginActivity("HelloBamActivity",activityId);

          Debugger.Break();
          //update atribute

          des.UpdateActivity("HelloBamActivity", activityId, "BeginOrder",
              DateTime.Now,"Amount",300,"State","CA");

          des.UpdateActivity("HelloBamActivity", activityId, "EndOrder",DateTime.Now.AddSeconds(10));

          des.EndActivity("HelloBamActivity", activityId);
          des.Flush();
          //end activiity

          Console.ReadLine();

 

如果要查看Trace的话,配置你的app.config,

 

<system.diagnostics>
    <switches>
      <add name="Microsoft.BizTalk.Bam.EventObservation" value="1"/>
    </switches>
    <trace autoflush="true">     
      <listeners>
        <add name="console" type="System.Diagnostics.ConsoleTraceListener"></add>
      </listeners>
    </trace>
  </system.diagnostics>

 

打开Portal就会看到数据了,多运行几次数据就可以看到更多的结果

image

Olap 聚合

image

如果看不到数据,检查一下你的集成服务的package是不是不能正常运行。

 

 

这样,我们可以通过了程序API的方式,把系统的业务数据push到BAM,下次讲一下怎么用配置的方式,让WCF 拦截数据到BAM

posted @ 2008-05-24 08:25 montaque 阅读(1170) | 评论 (1)编辑

Biztalk 2006 R2是Biztalk 产品到目前为止,最新的版本。R3 还没有正式出来,R3 出来之后就可以跟VS 2008 集成,包括Oslo的支持。据说R3之后的版本才会基于 workflow Foundation Service。所谓计划赶不上变化, PDC 2005 的时候,Microsoft就宣布下一个版本会基于Workflow Foundation。 之后出来2006, 2006 R2,马上 2006 R3,谁知道那个版本才会基于workflow foundation。

为什么说一定要给予Workflow foundation呢?我们知道.net framework 3.0 是个很好的平台。你基于WCF这套可扩展的模型,任何的协议,商业package都可以类似搭积木,陪协议栈一样去集成。 基于WF, 虽然workflow foundation只是个工作流的平台,没有biztalk的 可扩展稳定的消息处理引擎,可视化mapping,基于主题事实的路由,可是有一个非常简单的扩展模型,就是让你的Activity可以自由扩展。这一点也是Biztalk 改进的目标之一,就是biztalk中的Shape 远没有workflow foundation的activity 那么可扩展和定制。

具体展开的几个Blog

WCF的支持。

biztalk 2006 R2 很重要的一点就是引入了对WCF的支持, 这个不是个简单的替换web service 支持的问题。更重要的是引入了一个让你自由扩展对各种系统集成的机会。 在R2之前你要写一个Adapter,比如写一个支持SAP 的adapter是非常的困难。而到了R2只好,你要扩展一个LOB 的支持,不需要去重写一个Adpater,只要利用 WCF Adapter Framework 像是扩展WCF的Binding,Behavior一样。利用Biztak对WCF的支持(元数据,不同的安全要求,不同的Binding), 把你重写的wcf行为配置进去就可以了。 为此,R2的几个LOB Adapter 都是用这种新的模型重写了。会有哪些好处呢?

  1. 写一次,能够被Biztalk 支持,以及一切能够跟WCF 通讯的Client支持。不想以前写的Adapter,只能够Biztalk使用。所以现在.net 开发人员除了可以用.NET SAP Connector跟SAP集成。也可以用SAp Adapter for Biztalk r2
  2. 开发人员和管理人员使用一直的管理和配置界面。无非要回答使用那个Opeartion,点击生成Proxy的问题。

一下是SAP Adapter for Biztalk 2006 R2的架构

image

而之前的呢?

image

 

通过 WCF 跟Biztalk集成,相对于Web service,还有哪些好处呢?

使用soap adapter的时候,在run-time 每次都要有两次序列华,反序列化动态编译程序集的问题。到了WCF,Biztalk 和WCf直接就是直接的消息传递。 WCF 的CLient直接送消息给Biztalk,反之亦然。

下次我会讲一下各种WCF跟Biztalk集成的场景和方式。 相对于web service,非常之灵活。 比如,WCF可以控制消息的layout。对应MessageContract,还是DataContract,或者XmlSerilaizer 序列化方式。 使用WCF,有些Binding支持事务,可以从service调用段flow事务到Biztalk。 等等。

 

BAM的增强

Biztalk可以把异种系统,自治的Service 集成起来。run-time的时候,很多消息流来流去,往返于不同的系统。可能是WCF的服务,或者WF的流程,或者legacy 系统,当然还有Biztalk。 怎么样有一个一致的视图能够告诉用户这些消息流转是否正常,处理能力证明样,Latency有多大? 类似回答一个KPI的问题。希望有那么一个dashboard,用户一看就知道订单处理了多少,那个州的订单额度比较大,比较赚钱? 而要回答这样的一个问题,可能就要到不同的系统中抓数据。能不能够定义一个模型,让各个系统把关键数据按照定义好的关注模型push给中央呢。从Biztlak 2004 的时候,biztalk里面就有了个BAM,2004的时候只支持从流程中提取一些数据, 2006 支持到流程中的消息,而在R2的时候,支持到WCF、WF以及Legacy系统。

由于WCF本省就容易扩展,所以BAM R2 提供了一个EndpointBehavior,配置到WCF。这样WCF 在运行的时候,根据你定义的关注或者拦截模型,就会自动把你关注的数据推给Centrol。

WF也一样,Workflow本省有一个Service扩展模型,BAM R2 提供了一个BAmTrackingService,随着workflow的运行,被命中的事件和数据也会推给Centrol。

如果要是Legacy 系统,bam有个API。

当然WCF、wf需要你写一个xml 配置文件来标注你对那些事件感兴趣,命中的条件以及如何更新Activity模型。

这个xml配置文件没有图形化的配置工具,不想Biztalk的TPE。需要手动写,R2提供了schema,写起来还是很方便。

Interceptor有一个简单的模型,让不同系统写的数据关联到一个Activity所谓的Correlation、Continous模型。下次着重写一个BAM模型。

 

使用BAM帮你回答了几个问题。

  • 如何存储这些数据(可能会很大),交易和分析分开。自动partition
  • 访问的API,AOP的配置模型。
  • 业务人员简单定义模型。
  • Alert模型。

 

 

RFID的支持

RFID其实跟Biztalk 没有关系,可以单独使用。 把你去抽象不同的厂商的FRID设备。以及受到数据之后如何派发给不同的handler,比如可能是写数据库,激活一个流程等。帮你在各种RFID设备之上做了一个抽象和简单的管理。 好像到目前,被动模式的RFID标签已经很便宜了。几分钱一个,打算买个reader 和几个标签。把标签贴到身上,在厕所门边装个reader。统计一下一年上了几次厕所,哈哈。做个报表时间,频率等等。

 

EDI的支持。

早起的Biztalk虽说支持EDI,可是Schema只有一点点。 EDI本省有好多版本,如果你用的话,只能去买Convast的完整版本。R2的时候内置了4G的Schema,比2006丰富多了。

 

另外加上了AS2的支持。传统的EDI都是基于文件,Ftp。AS2基于Http

 

关于HWS。

需要人参与的workflow,在biztalk 中有个HWS,human workflow service。R2中没有做任何的加强。如果Biztalk的workflow需要人的参与,以下是集中建议的方式。

1.用SharpointWorkflow,需要人审判和review的消息。通过sharepoint adapter,送到sharepoint站点的文档区。审批通过的话继续执行。

2.用自己的workflow比如windows workflow, 可以用.net framework 3.5的worklfow service,biztalk 想调用一般的wcf service 一样去调用。

3.用商业的package,比如K2.

posted @ 2008-05-24 05:53 montaque 阅读(1109) | 评论 (3)编辑

2008年5月23日 #

Try create a blog about r2 new features using livewriter.

测试中文支持

 

testing the bitmap

image

Done

posted @ 2008-05-23 02:06 montaque 阅读(33) | 评论 (0)编辑

2008年3月9日 #

微软为了推广自己的技术,每年都会有各种各样的会议。比如TechEd,PDC,WinHEC,mobile大会等。最近随着Web技术越来越占主角,微软在web方面也不断推出自己的产品。诸如 Expression, Silverlight,WPF,IE,ASP.net AJAX,mVc新版本等。于是在美国,从前年开始,每年在las vegas 有一个MIX会议,主要是发布和介绍微软在web技术方面的一些进展。每年也都会有微软的一些大头们做Keynote,今年是Ray,Ballmer,Scott。

会议的资料和Video都可以从http://sessions.visitmix.com/ 下载,silverlight 对 Video的一些加强,为此这次的video也改为silverligt的方式来展现。

会议的几个大的主题,用户体验UX,Biz以及技术的。 大概是围绕UX,Silerlight+WPF, windows live 系列,asp.net ajax/mvc/Dynamic data

Silverlight 主要是发布了2.0 beta1 版本。相对1.1几个加强特性,DeepZoom(以前的seadragon),网络协议的增强,内置了一些用户控件。 这里有一个很有意思的演示Deepzoom http://memorabilia.hardrock.com/  内置控件以及控件模型的简化也使得我们更容易构建一个RIA的站点,比如一个购物站点,强用户交互型的应用。 当然围绕silverlight,微软WPF的skill可以共享。比如开发工具,XAML, Expression Expession blend 也出了2.5 版本。WPF 3.5则没有特多的加强,会议由一个主题都是讲 Siliverlight/WPF的 Data Binding 模型,控件开发/自定义。预计以后DeepZoom会成为一个应用亮点,之前很多人用silverlight 主要是其对video的支持。video可以当作一个不同的刷子刷到任何的元素上面。newegg也作了一个增强的搜索展示,主要用到了Silverlight的Deepzoom和控件模型。

很多人用silverlight,都考虑有多少用户装了插件,微软说每天有1.5 million+ 的下载量, 插件的普及是迟早的问题。

Windows live 则主要围绕集成他的认证,扩展 Conversation以及mesenger, 还有virtualearth的二次应用。
推荐一个JS库,http://www.codeplex.com/VEJS 让你很容易写出一个virtual earch 的mushup应用。

asp.net 的一个Preview feature, 比如 MVC, Dynamic data. 大家可以看一下scott 的blog。
http://weblogs.asp.net/scottgu/archive/2007/10/14/asp-net-mvc-framework.aspx

UX方面则是一些原则性的东西了。



posted @ 2008-03-09 14:00 montaque 阅读(1443) | 评论 (7)编辑

2008年1月17日 #

ILM 是微软的身份管理软件。 当一个员工进入公司后,ILM 会把这个人的身份标识(AD帐号,或者Email