Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using BizTalk Web Service to re-publish an internal Web Service

I'm trying to use BizTalk for communicating between two web services. It has to be like this:

  • Service1 gets an input and sends message through BizTalk to Service2,
  • Service2 responds that message, forwards it to BizTalk, and delivers it to Service1.
  • Finally Service1 returns the response to user.

I'm trying hard to do it for days, but I couldn't manage to build orchestration without compiler errors, and I couldn't find a single piece of example with web services and web ports with typing inputs. I started to believe that this is impossible, at least with BizTalk.

The big question is: Is it possible? If yes, how?

like image 722
ferit Avatar asked Mar 23 '23 22:03

ferit


1 Answers

The scope of your question is rather large, and I guess answering it is probably not well suited to the SO "Q+A" format.

However, providing a composite enterprise service which is composed of one or more underlying web services appears to be a common requirement.

I've built a quick and dirty example (BTS 2010 / VS 2010), and uploaded to GitHub here (download the source as a zip on the lower right)

Here's the 'cookbook' of steps taken to implement this from scratch, but I believe that you'll need to obtain the code to follow.

Create a new Solution in Visual Studio

Add a WCF service project and publish to IIS (scope not covered in this sample)

  • Used the default VS2010 WCF project, and called the project WCFService
  • Used basicHttpBinding for simplicity, but obviously other bindings can be used (but will require additional concerns such as security etc)
  • Note that the NameSpace on ServiceContract, ServiceBehavior, and in the web config for behaviour namespace have all been set (Otherwise these will default to tempuri)

Add 4 new BizTalk Projects to the solution:

I've call them BizTalkWCF.Orch, BizTalkWCF.Maps, BizTalkWCF.WCFPorts, and BizTalkWCF.Schemas

First is WCFPorts

  • Right click the WCFPorts project and select "Add" then "Generated Items"
  • Select Consume WCF Service
  • Check the Metadata Exchange (Mex) Endpoint
  • Provide the URL to your WCF Service (e.g. http://localhost:57582/Service.svc)
  • Leave the namespace (BizTalkWCF.WcfPorts)
  • Complete the wizard - the WCF artifacts should now be present
  • If you need to import more than one Web Service, I would suggest you create separate Visual Studio solution folders for each

Because we've split the project up in BizTalk (which is generally a good idea), unfortunately the wizard will have marked all the imported artifacts as internal, which isn't very helpful if they are referenced from other assemblies. Open the imported generated Orchestration (MyService.odx) (NB never delete or move this ODX as it contains the generated ports - just leave it with the generated WCF artifacts).

In the orchestration View, at the bottom, open up types. Under Port types, you should see the WCF Interface (IService). Click it and change the property type modifier to "Public" Do the same for the Multi-part message types (4 x IService_* - note that there are 2 x message types for each WCF Method on the Service (one for request, one for response).

The WCF Ports project should now build.

Next up is the Schemas project Add 2 x Schemas representing what will be exposed (published) from the BizTalk (I've called them BizTalkServiceRequest and BizTalkServiceResponse) This sample simply provides a thin façade onto the underlying WCF Service, so I've just got similar fields to the original WCF service on the request and response, with the same xs types. Note however that the concept of an "Entity" on the underlying WCF service has been replaced by request and response messages. It is possible however refactor and reuse common elements in the Schemas (xsd:import) across multiple messages. I've just used the default namespaces, and 'Root' node, but note that these will be visible to your BizTalk service consumers, so in a real project you'll want to give this more thought.

Note that we haven't reused the imported / generated WCF Service schemas. In a comprehensive enterprise, a 3rd set of schemas can also be used, 'canonical' schemas, which are agnostic of both the formats used by the consumer of the BizTalk service and consumed service (and more maps would have been required as well).

Next up are the maps, between the incoming Request to the WCF Input Schema, and then another map for the Response from the WCF Output schema back to the BizTalk service consumer. On the map project, add .Net references to both the WCFPorts project and to the Schemas project. Add a new Map to the Map project For the Source Schema find the Referenced Schemas - BizTalkServiceRequest schema. For the Destination Schema, select the WCF Ports schema (the name mangled is awful, but it will be the one with MyService - not the datacontracts or microsoft schemas one). Note that you are then required to select which of the contained schemas you need to use. Select the GetDataUsingContract schema. Under the elements, drag the mouse from the source Name element to the destination schema value, and from the IsAddSuffix to the BoolValue element. Do the same for the return response message - obviously this time the WcfResponse message is the source, and the exposed BizTalk response is the destination. The boolean isn't useful in the repsonse, so just the string value is mapped. Maps should now Compile.

Last up is the Orchestration project

  • Add reference to the Maps, Schemas and Ports projects
  • Add a new Orchestration (I've called AddServiceOrchestration).
  • You'll need to add an Receive port (added on the left) and Send Port (on the right).
  • Send Port uses the existing imported WCF Port (that we made public earlier). I'll be sending a request and receiving response.
  • Port binding select Direct Binding, and routed by filter expression.
  • For the receive port, you'll need to create a new port type - request response. Receive a request, send a response, and again, Direct binding, with routing via filter expressions.
  • Again, you need to make the Port public
  • You'll need to set the message types on the receive port for both the request and response (click on request and response and then find the message types in the Schemas assembly)
  • The shapes in the orchestration should be self explanatory and straightforward - basically just tie in the ports to receive and send shapes, and then use the maps in transform shapes.
  • The initial receive shape is the activation.

Build + Publish

Everything should now build, so its time to publish to BizTalk (I've assumed a local server) For now we'll publish the orchestration using the Wizard, and will use IIS to front the exposed web service, although note that Biztalk can also self host. Remember to set the Application Name in the Deployment tab on all 4 of the Biztalk projects (else they'll wind up in the default app). Also, remember that BizTalk assemblies need to be signed, so create a .SNK (Signing tab)

Right click the solution, and click Deploy. (Note that the project must be built + deployed before you can use the publishing wizard to expose the service) Assuming a successful deploy, you'll need to configure the orchestration (the other Orch is the one generated by the WCF import - it owns the WCF ports) Create a send Static Solicit Response Send Port - WCF basicHttpBinding, point it to your WCF Web Service URL. You can get the SOAP action from the WCF WSDL e.g. YourNameSpaceHere/IService/GetDataUsingDataContract Add a Filter to the send port for the message (xmlns#root), e.g., YourNameSpaceHere#GetDataUsingDataContract

Back in Visual Studio, you can now publish the Orch as a WebService (Tools : BizTalk WCF Services publishing Wizard) Enable metadata publishing. I've used basicHttpBinding again. And create the Receive Port, selecting the application (BizTalkWCFSample)

When prompted, select the assembly containing the Orchestrations (BizTalkWCF.Orchs) You will also be prompted to set the target namespace of the WCF service - keep a record of this as if you need to republish your service, you'll likely want to keep the namespace the same.

The location at the end is where it will be published in IIS. Select "allow anonymous access" if you don't want to be bothered with locking the exposed service security. AFAIK there is no way to control the name given to the auto created receive port.

You now need to start up the BizTalk app - address any outstanding config issues (e.g. assigning orchs to processes)

You'll need a new .Net 4 App pool in IIS (Call it something like BizTalkIsolatedHost),
And then move the wizard created app in IIS to this App Pool You should now be able to navigate to your Orchestration 'endpoint', e.g.: http://localhost/BizTalkWCF.Orchs/BizTalkWCF_AddSuffixService_RcvSuffixService.svc

Summing up - was it all worth it?

As you can see from the above, it is quite a lot of work to re-expose a web service in BizTalk, and we haven't really added any value in BizTalk, other than perhaps to have some BizTalk tracking and retry capability :). When orchestrating a composite service (one incoming request requires multiple back end service calls to fulfill, and if using canonical schemas as well), there will be many more schemas and maps to consider, plus additional complexity with the orchestration. And when working with web services, you get a large number of artifacts (schemas, maps, messages, ports etc etc) very quickly, so a strict naming convention is essential.

And we haven't considered things like exception handling, retries, etc.

So, just a sanity check before planning to publish 100's of services in this manner, I guess we need to consider other technology alternatives:

  • BizTalk ESB toolkit (especially if there is a degree of commonality in your enterprise, and / or you have control over the services consumer)
  • Other ESBs (Mass Transit, NServiceBus, ServiceMix etc, or DIY buses built on Camel, Mule, Drools, Rabbit, Windows Service Bus etc), possibly with a custom facade for exposing web services 'end points'
  • For bulk 'service facades', Microsoft started prototyping a promising technology called Managed Service Engine but unfortunately this seems to be on ice.

But if there are only a few, high value services like this, especially if such services require composition and mapping of multiple internal services, or use different consumed technologies (SAP RFC, SQL, SOAP, etc) then BizTalk is about right for the job.

like image 50
StuartLC Avatar answered Apr 26 '23 12:04

StuartLC