(Migrated) Returning a value from a directly-invoked service

(This message has been automatically imported from the retired mailing list)

A small gotcha that caught me. Take the following simple example:

sample.py

from future import absolute_import, division, print_function,
unicode_literals
from zato.server.service import Service

class Hello(Service):
def handle(self):
self.log_input()

     response = {
         "response": "Hello!",
         "request": self.request.payload,
     }

     self.logger.info('Response: {}'.format(response))
     self.response.payload = response

When you invoke this from either the command line or the web
interface(*), it shows (None) as the response.

$ zato service invoke server1/ sample.hello --payload ‘{“abc”:“def”}’
(None)

However, logs show the service is invoked:

2015-02-25 16:08:45,891 - INFO - 8000:Dummy-417 - sample.hello:787 -
{u’impl_name’: u’sample.Hello’, u’name’: u’sample.hello’, u’cid’:
u’K07PHF6EM0MH0D06R8JT1CAGZHMG’, u’invocation_time’:
datetime.datetime(2015, 2, 25, 16, 8, 45, 891796), u’job_type’: None,
u’data_format’: u’json’, u’slow_threshold’: 99999, u’request.payload’:
{u’abc’: u’def’}, u’wsgi_environ’: {}, u’environ’: {}, u’usage’: 10,
u’channel’: u’invoke’}
2015-02-25 16:08:45,892 - INFO - 8000:Dummy-417 - sample.hello:22 -
Response: {u’request’: {u’abc’: u’def’}, u’response’: u’Hello!’}

I managed to work out what was happening - without SIO, only a response
which is a string is supported. This is documented if you search
carefully:
https://zato.io/docs/progguide/request-response.html#response

However I found it confusing that my dict was turned into (None). I’d
have expected either an exception to be raised, or some default
conversion, e.g. to JSON or repr().

Second minor point: SIO works but it wraps my JSON with an outer
{“response”…} element. I tried setting response_elem = None but then I
get:

{u’null’: {u’request’: {u’abc’: u’def’}, u’response’: u’Hello!’}}

I guess a response_elem wrapper is needed for XML responses, but it
would be nice to make it optional for JSON.

Regards,

Brian.

(*) Services > (search) > Invoker

Oh, and something odd about SIO and XML:

from __future__ import absolute_import, division, print_function, 
unicode_literals
from zato.server.service import Service

class Hello(Service):
     class SimpleIO(object):
         response_elem = 'foo'
         output_optional = ('bar', 'baz')

     def handle(self):
         self.log_input()

         response = {
             "bar": "Hello!",
             "baz": self.request.payload,
         }

         self.logger.info('Response: {}'.format(response))
         self.response.payload = response

Invoking:

$ zato service invoke server1/ sample.hello --payload 
'<a><uuu>vvv</uuu></a>' --data-format xml
<foo>
   <zato_env>
     <cid>K04VMBMEZ4H7ZYGTWB71RJV145DT</cid>
     <result>ZATO_OK</result>
   </zato_env>
   <item>
     <bar>Hello!</bar>
     <baz>
       <uuu>vvv</uuu>
     </baz>
   </item>
</foo>

My response dictionary has been wrapped in an tag. Is it possible
to override that tag, or to get rid of it entirely? This seems to be
non-symmetrical with the JSON response format which does not include an
"item", although it also does not include the “zato_env”.

$ zato service invoke server1/ sample.hello --payload ‘{“uuu”:“vvv”}’
–data-format json
{
u’foo’: {
u’bar’: u’Hello!’,
u’baz’: {
u’uuu’: u’vvv’
}
}
}

Regards,

Brian.

On 25/02/15 18:01, Brian Candler wrote:

However I found it confusing that my dict was turned into (None). I’d
have expected either an exception to be raised, or some default
conversion, e.g. to JSON or repr().

Mhm, how about the exception or repr after all. Could be configured from
server.conf which is default, most likely the latter.

I guess it won’t really happen unless during development because once
you know what to do you’ll just either set a data type on the channel or
serialize to string.

Second minor point: SIO works but it wraps my JSON with an outer
{“response”…} element. I tried setting response_elem = None but then I
get:

{u’null’: {u’request’: {u’abc’: u’def’}, u’response’: u’Hello!’}}

I guess a response_elem wrapper is needed for XML responses, but it
would be nice to make it optional for JSON.

Yes, makes sense, thanks for suggesting it.