Hi everyone!
In my test project I have some schema classes: guests, rooms and bookings. I have a number of services for each schema class in separate modules to get, delete, update, create and list records, among others.
Now I am building a more complicated service in which I want the list of bookings from a guest and the rooms related to those bookings. The channel would be something like:
/genesisng/guests/{id}/bookings
And the desired output would be something like:
{
# Guest attributes
"id": "1",
// More attributes
"bookings": [
{
# Booking attributes
"id": "1",
// More attributes
},
{
# Booking attributes
"id": "2",
// More attributes
},
],
"rooms": [
{
# Room attributes
"id": "1",
// More attributes
},
{
# Room attributes
"id": "2",
// More attributes
}
]
}
To do this, my plan would be:
- Invoke guest.get service.
- Invoke booking.list service. Loop the results to get the list of room ids.
- Invoke room.get multiple times or invoke room.list.
At the moment all my module.list services use query string parameters to handle filtering, fields projection, pagination, sorting and searching. For example:
curl -v -g "http://127.0.0.1:11223/genesisng/guests/list?page=4&size=40&sort_by=name&order_by=desc&fields=id&fields=name&filters=id|gt|50"
Invoking the guest.get
module is working fine:
id_ = self.request.input.id
result = {}
# Get guest data
input_data = {'id': id_}
guest = self.invoke('guest.get', input_data, as_bunch=True)
if guest:
result = guest
But invoking booking.list
is not because I use this bit of code to parse the query string:
# Check for parameters in the query string
qs = parse_qs(self.wsgi_environ['QUERY_STRING'])
if qs:
# Handle pagination
# Handle sorting
# Handle filtering
# Handle fields projection
# Handle search
The call I make is as follows:
# Get the list of bookings from the guest
result.bookings = []
input_data = {'filters': 'id_guest|eq|%s' % id_}
bookings = self.invoke('booking.list', input_data, as_bunch=True)
if bookings:
rooms = [] # Used to later retrieve the list of rooms to be added to result
for b in bookings:
result.bookings.append(b)
rooms.append(b.id_room)
And the error I get is:
2018-10-16 20:03:11,636 DEBG 'zato-server2' stdout output:
2018-10-16 20:03:11,636 - INFO - 116:DummyThread-55 - guest.bookings:429 - Invoking guest.get...
2018-10-16 20:03:11,643 DEBG 'zato-server2' stdout output:
2018-10-16 20:03:11,643 - INFO - 116:DummyThread-55 - guest.bookings:431 - Response is: response:
address1: 221 B Baker St
address2: Woolsthrope Manor
birthdate: '1643-01-04'
country: GB
email: inewton@genesis.com
gender: '1'
home_phone: '+44.2079460702'
id: 1
locality: Lincolnshire
mobile_phone: '+44.2079460701'
name: Isaac
passport: 12345678A
postcode: 07180
province: Midlands
surname: Newton
2018-10-16 20:03:11,643 DEBG 'zato-server2' stdout output:
2018-10-16 20:03:11,643 - INFO - 116:DummyThread-55 - guest.bookings:438 - Invoking booking.list...
2018-10-16 20:03:11,644 DEBG 'zato-server2' stdout output:
2018-10-16 20:03:11,644 - WARNING - 116:DummyThread-55 - zato.server.service:501 - Traceback (most recent call last):
File "/opt/zato/3.0/code/zato-server/src/zato/server/service/__init__.py", line 476, in update_handle
self._invoke(service, channel)
File "/opt/zato/3.0/code/zato-server/src/zato/server/service/__init__.py", line 398, in _invoke
service.handle()
File "/opt/zato/env/qs-1/server2/work/hot-deploy/current/booking.py", line 324, in handle
qs = parse_qs(self.wsgi_environ['QUERY_STRING'])
KeyError: u'QUERY_STRING'
2018-10-16 20:03:11,644 DEBG 'zato-server2' stdout output:
2018-10-16 20:03:11,644 - WARNING - 116:DummyThread-55 - zato.server.service:585 - Could not invoke `booking.list`, e:`Traceback (most recent call last):
File "/opt/zato/3.0/code/zato-server/src/zato/server/service/__init__.py", line 583, in invoke_by_impl_name
return self.update_handle(*invoke_args, **kwargs)
File "/opt/zato/3.0/code/zato-server/src/zato/server/service/__init__.py", line 476, in update_handle
self._invoke(service, channel)
File "/opt/zato/3.0/code/zato-server/src/zato/server/service/__init__.py", line 398, in _invoke
service.handle()
File "/opt/zato/env/qs-1/server2/work/hot-deploy/current/booking.py", line 324, in handle
qs = parse_qs(self.wsgi_environ['QUERY_STRING'])
KeyError: u'QUERY_STRING'
`
2018-10-16 20:03:11,645 DEBG 'zato-server2' stdout output:
2018-10-16 20:03:11,644 - WARNING - 116:DummyThread-55 - zato.server.service:501 - Traceback (most recent call last):
File "/opt/zato/3.0/code/zato-server/src/zato/server/service/__init__.py", line 476, in update_handle
self._invoke(service, channel)
File "/opt/zato/3.0/code/zato-server/src/zato/server/service/__init__.py", line 398, in _invoke
service.handle()
File "/opt/zato/env/qs-1/server2/work/hot-deploy/current/guest.py", line 439, in handle
bookings = self.invoke('booking.list', input_data, as_bunch=True)
File "/opt/zato/3.0/code/zato-server/src/zato/server/service/__init__.py", line 601, in invoke
return self.invoke_by_impl_name(self.server.service_store.name_to_impl_name[name], *args, **kwargs)
File "/opt/zato/3.0/code/zato-server/src/zato/server/service/__init__.py", line 583, in invoke_by_impl_name
return self.update_handle(*invoke_args, **kwargs)
File "/opt/zato/3.0/code/zato-server/src/zato/server/service/__init__.py", line 476, in update_handle
self._invoke(service, channel)
File "/opt/zato/3.0/code/zato-server/src/zato/server/service/__init__.py", line 398, in _invoke
service.handle()
File "/opt/zato/env/qs-1/server2/work/hot-deploy/current/booking.py", line 324, in handle
qs = parse_qs(self.wsgi_environ['QUERY_STRING'])
KeyError: u'QUERY_STRING'
2018-10-16 20:03:11,645 DEBG 'zato-server2' stdout output:
2018-10-16 20:03:11,645 - ERROR - 116:DummyThread-55 - zato.server.connection.http_soap.channel:324 - Caught an exception, cid:`2a58008b147d56da39c57ce7`, status_code:`500`, _format_exc:`Traceback (most recent call last):
File "/opt/zato/3.0/code/zato-server/src/zato/server/connection/http_soap/channel.py", line 268, in dispatch
payload, worker_store, self.simple_io_config, post_data, path_info, soap_action)
File "/opt/zato/3.0/code/zato-server/src/zato/server/connection/http_soap/channel.py", line 502, in handle
params_priority=channel_item.params_pri)
File "/opt/zato/3.0/code/zato-server/src/zato/server/service/__init__.py", line 476, in update_handle
self._invoke(service, channel)
File "/opt/zato/3.0/code/zato-server/src/zato/server/service/__init__.py", line 398, in _invoke
service.handle()
File "/opt/zato/env/qs-1/server2/work/hot-deploy/current/guest.py", line 439, in handle
bookings = self.invoke('booking.list', input_data, as_bunch=True)
File "/opt/zato/3.0/code/zato-server/src/zato/server/service/__init__.py", line 601, in invoke
return self.invoke_by_impl_name(self.server.service_store.name_to_impl_name[name], *args, **kwargs)
File "/opt/zato/3.0/code/zato-server/src/zato/server/service/__init__.py", line 583, in invoke_by_impl_name
return self.update_handle(*invoke_args, **kwargs)
File "/opt/zato/3.0/code/zato-server/src/zato/server/service/__init__.py", line 476, in update_handle
self._invoke(service, channel)
File "/opt/zato/3.0/code/zato-server/src/zato/server/service/__init__.py", line 398, in _invoke
service.handle()
File "/opt/zato/env/qs-1/server2/work/hot-deploy/current/booking.py", line 324, in handle
qs = parse_qs(self.wsgi_environ['QUERY_STRING'])
KeyError: u'QUERY_STRING'
`
It is clear that, since the service is being invoked, self.wsgi_environ[‘QUERY_STRING’] does not exist. So, how should I proceed?
- Check whether self.wsgi_environ[‘QUERY_STRING’] exists before attempting to extract parameter values from it.
- Otherwise, see if the parameters expected in the QUERY_STRING are available at self.request.input?
Incidentally, I’ve been trying to invoke the room.list
service with multiple filters with no luck. If we were using curl, what I want to do would look like:
curl -v -g "http://127.0.0.1:11223/genesisng/rooms/list?filters=id|eq|1&filters=id|eq|2"
If I were to invoke it, how would I have to do it? Something like the following?
input_data = {'filters': ['id|eq|1', 'id|eq|2']}
rooms = self.invoke('room.list', input_data, as_bunch=True)
Then loop self.request.input.filters
, same as I would do with qs['filters']
?
Thanks in advance.