Multiple Services
------------------
Soaplib supports supplying multiple service classes
(:obj:`~soaplib.core.service.DefinitionBase`) to a single soap Application.
This allows you to group functionality and deploy the services as needed. ::
from wsgiref.simple_server import make_server
from soaplib.core import Application
from soaplib.core.server import wsgi
# UserManager and ComputerManager are both instances of DefinitionBase
from mysoapservices.user import UserManager
from mysoapservices.it import ComputerManager
def create_soap_app():
app = Application(
[UserManager, ComputerManager],
"managementServices"
)
return app
if __name__ == "__main__":
soap_app = create_soap_app()
wsgi_app = wsgi.Application(soap_app)
server = make_server("localhost", 7789, wsgi_app)
server.server_forever()
Default Service and PortType behaviour
---------------------------------------
The WSDL bindings for portType and Service that results from the last example
are as follows. ::
....
....
....
This is likely far from what one would expect..i.e services and/or portTypes
being used to group services and functionality. Soaplib does support
multiple service and portType bindings however it was added well into 2.0
development cycle. So, the decision was made to maintain the default behaviour
in order to prevent breaking backward compatibility outright. However, in
future release this may change based on user feedback.
Custom Service and PortType bindings
-------------------------------------
The Service binding can be overridden by explicitly setting the
:attr:`~soaplib.core.service.Service.__service_interface__` attribute in
:obj:`~soaplib.core.service.Service` class.
Additionally, defining explicit portType bindings is accomplished by setting the
:attr:`~soaplib.core.service.DefinitionBase.__port_types__` attribute and supplying
the ``_port_type`` parameter to the @:func:`~soaplib.core.service.soap` method decorator.
For example modifying the UserManager service class as follows ::
class UserManager(DefinitionBase):
__service_interface__ = "UserService"
__port_types__ = ["user_services"]
@soap(User,_returns=Integer, _port_type="user_services")
def add_user(self,user):
global user_database
global userid_seq
user.userid = userid_seq
userid_seq = userid_seq + 1
user_database[user.userid] = user
return user.userid
When this class is passed to a soaplib :obj:`~soaplib.core.server.Application`,
the generated WSDL will now include bindings for a Service named "UserService"
as well as portType bindings for "user_services".
For a more complete example please see the "service_portType_binding.py" example
included with soaplib.