{"id":42,"date":"2004-08-25T15:06:40","date_gmt":"2004-08-25T15:06:40","guid":{"rendered":"http:\/\/www.pleus.net\/blog\/?p=42"},"modified":"2010-08-13T00:11:34","modified_gmt":"2010-08-12T22:11:34","slug":"generic-web-service-interfaces-the-right-choice","status":"publish","type":"post","link":"https:\/\/www.pleus.net\/blog\/?p=42","title":{"rendered":"Generic Web Service Interfaces &#8211; The Right Choice?"},"content":{"rendered":"<p>Sometimes I hear the question &#8220;Why not decouple the service from the caller by using generic interfaces?&#8221;<\/p>\n<p>To better understand this question let&#8217;s have a look at the following pseudo code example:<br \/>\n<font face=\"Courier\"><br \/>\nBookingService<br \/>\n{<br \/>\n   Flight[] getAvailableFlights(date flightDate, string destination);<br \/>\n   bool bookFlight(int flightId);<br \/>\n}<br \/>\n<\/font><\/p>\n<p>The Web Service BookingService has two methods, which can be called by the clients and is described in an BookingService.wsdl file.<br \/>\nIf we would like to add a new method for instance cancelFlight(int flightId) we have to change the caller of the service. In most cases this means rebuilding the client side proxy.<\/p>\n<p>Why not using a generic interface like one of the following:<\/p>\n<p>Generic parameter approach:<br \/>\n<font face=\"Courier\"><br \/>\nBookingService<br \/>\n{<br \/>\n   Map getAvailableFlights(Map params);<br \/>\n   Map bookFlight(Map params);<br \/>\n}<br \/>\n<\/font><\/p>\n<p>This approach uses only generic parameters but no generic service operations.<\/p>\n<p>Generic service approach:<br \/>\n<font face=\"Courier\"><br \/>\nGenericService<br \/>\n{<br \/>\n   Map execute(int commandId,Map params);<br \/>\n}<br \/>\n<\/font><\/p>\n<p>This approcach uses the common command pattern. It means the client sends a command id toghether with the required parameters to the service.<br \/>\nDependent of the command id the service dispatches the call to the service implementation.<br \/>\nIn order to add the service method cancelFlight we simply have to add a new command. The contract remains unchanged and the proxy hasn&#8217;t to be rebuild.<br \/>\nAnd even better the parameters can be processed in a generic way. That&#8217;s cool, isn&#8217;t it?<\/p>\n<p>At first glance this approach looks promising. But at what price? <\/p>\n<p>A common misunderstanding is that the Web Service Signature described in the WSDL file forms the service contract. This is only one option.<br \/>\nMore precisely said the name of the service operation (or command id) in conjunction with the required in and out parameters form the contract.<br \/>\nIt doesn&#8217;t matter where this information is stored.<\/p>\n<p>What really happens when using generic interfaces is that the contract is shifted from a standarized to a custom layer.<br \/>\nThat means the contract is not described in the BookingService.wsdl file anymore. Now the service and the caller need a proprietary way to describe and exchange the contract.<br \/>\nMoreover the type safety is lost because only generic types are used.<br \/>\nThe command dispatching must be implemented. This is usually handled by the Web Service infrastructure for instance by using the SoapAction in the HTTP-Header.<br \/>\nGeneric parameter processing is not a reason to use generic interfaces. If necessary reflection can be used to process typed parameters in a generic way, but without loosing type safety.<\/p>\n<p>I think the drawbacks of generic interfaces outweight the benefits.<br \/>\nWhat do you think?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Sometimes I hear the question &#8220;Why not decouple the service from the caller by using generic interfaces?&#8221; To better understand this question let&#8217;s have a look at the following pseudo code example: BookingService { Flight[] getAvailableFlights(date flightDate, string destination); bool bookFlight(int flightId); } The Web Service BookingService has two methods, which can be called by &hellip; <a href=\"https:\/\/www.pleus.net\/blog\/?p=42\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Generic Web Service Interfaces &#8211; The Right Choice?<\/span><\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,1],"tags":[],"class_list":["post-42","post","type-post","status-publish","format-standard","hentry","category-soa","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.pleus.net\/blog\/index.php?rest_route=\/wp\/v2\/posts\/42","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pleus.net\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pleus.net\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pleus.net\/blog\/index.php?rest_route=\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pleus.net\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=42"}],"version-history":[{"count":2,"href":"https:\/\/www.pleus.net\/blog\/index.php?rest_route=\/wp\/v2\/posts\/42\/revisions"}],"predecessor-version":[{"id":339,"href":"https:\/\/www.pleus.net\/blog\/index.php?rest_route=\/wp\/v2\/posts\/42\/revisions\/339"}],"wp:attachment":[{"href":"https:\/\/www.pleus.net\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=42"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pleus.net\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=42"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pleus.net\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=42"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}