Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Secure, Scalable and Dynamic Invocation of SOAP in Python with Zato and Suds

DZone's Guide to

Secure, Scalable and Dynamic Invocation of SOAP in Python with Zato and Suds

· Integration Zone ·
Free Resource
CRM integration has become the cornerstone to meeting initiatives across organizations. Explore the top 6 value-driven Salesforce CRM integrations ebook.  

Zato ESB and app server in Python has grown additional means through which it is now even easier to invoke SOAP services without a need for generating stub classes or clients.

Given an existing WSDL, all that is needed is filling out a couple of forms and a pool of SOAP clients is automatically generated and available in a cluster

Built on top of Suds, the feature is available in git master and here's a preview showing how to consume SOAP services without any need for direct XML manipulations in order to build a RESTful service validating credit card numbers with JSON output.

First, let's upload the service that will connect to SOAP and produce JSON on output.

Note that the service doesn't really know what type of output it produces - this is configured from the GUI and no code changes are needed for the service to produce XML instead of JSON.

   # -*- coding: utf-8 -*-
   
   # Zato
   from zato.server.service import Service
   
   class ValidateCreditCard(Service):
   
       class SimpleIO:
           input_required = ('number',)
           output_required = ('card_type', 'is_valid')
   
       def handle(self):
           conn = self.outgoing.soap['Credit Card Validator'].conn
   
           with conn.client() as client:
   
               # Invoke SOAP dynamically - no need for stub classes
               result = client.service.CheckCC(self.request.input.number)
   
               # Results are turned into Python objects automatically
               self.response.payload.card_type = result.CardType
               self.response.payload.is_valid = result.CardValid

While not strictly required, let's say we need to secure our REST service with Basic Auth: Form to create an HTTP Basic Auth definition

Now a channel is created through which requests will flow in. Note that the URL path is a pattern - all named attributes, such as *number* here, are available as input to services.

And although it's not used in this example, both JSON or XML can be mixed on input with URL parameters with full control of what has priority over other parts. Form to create a new HTTP channel

Next an outgoing SOAP connection is needed. Note that its serialization type is Suds - this is the new feature. The WSDL points to a free SOAP service online courtesy of CDYNE .

In the example below, each server will be given a pool of 20 SOAP clients, each generated dynamically on fly from the WSDL provided on input.

If you're coming from Java or C# background you'll note that no stubs nor client classes need to be generated. This is all taken care of behind the scenes so one can focus on invoking SOAP services straightaway. Form to create a new outgoing SOAP connection

With all that in place, the Zato service can now be invoked. curl is used from command line in the examples below:

   $ curl -u user:password localhost:17010/validate-cc/4111111111111111
   {"response": {"card_type": "VISA", "is_valid": true}}
   $
   $ curl -u user:password localhost:17010/validate-cc/123456789
   {"response": {"card_type": "NONE", "is_valid": false}}
   $

What if the WSDL changes with time? You only need to click 'Reload WSDL' and a new pool of SOAP clients will be created using the newest contents. Arrow points to a link through which WSDL can be reloaded

The feature will be released in the upcoming 1.2 release and until then - please use git master version.

Sync, automate, and notify lead to customer changes across marketing, CRM, and messaging apps in real-time with the Cloud Elements eventing framework. Learn more.

Topics:

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}