Reputation: 5238
I am starting to use Google Cloud Endpoints and I am running in a problem when specifying multiple services classes. Any idea how to get this working?
ApiConfigurationError: Attempting to implement service myservice, version v1, with multiple classes that aren't compatible. See docstring for api() for examples how to implement a multi-class API.
This is how I am creating my endpoint server.
AVAILABLE_SERVICES = [
FirstService,
SecondService
]
app = endpoints.api_server(AVAILABLE_SERVICES)
and for every service class I am doing this:
@endpoints.api(name='myservice', version='v1', description='MyService API')
class FirstService(remote.Service):
...
@endpoints.api(name='myservice', version='v1', description='MyService API')
class SecondService(remote.Service):
...
Each one of these work perfectly separately, but I am not sure how to get them working when combining them.
Thanks a lot.
Upvotes: 5
Views: 2017
Reputation: 298
I've managed to successfuly deploy single api implemented in two classes. You can try using following snippet (almost directly from google documentation):
an_api = endpoints.api(name='library', version='v1.0')
@an_api.api_class(resource_name='shelves')
class Shelves(remote.Service):
...
@an_api.api_class(resource_name='books', path='books')
class Books(remote.Service):
...
APPLICATION = endpoints.api_server([an_api],
restricted=False)
Upvotes: 1
Reputation: 3791
If it was Java ...
https://developers.google.com/appengine/docs/java/endpoints/multiclass
cloudn't be easier.
Upvotes: 0
Reputation: 41
For local development I'm using a temporary workaround, which is to disable the exception (I know I know...)
In my sdk in google_appengine/google/appengine/ext/endpoints/api_backend_service.py
around line 97:
elif service_class != method_class:
pass
# raise api_config.ApiConfigurationError(
# 'SPI registered with multiple classes within one '
# 'configuration (%s and %s). Each call to register_spi should '
# 'only contain the methods from a single class. Call '
# 'repeatedly for multiple classes.' % (service_class,
# method_class))
if service_class is not None:
In combination with that I'm using the construct:
application = endpoints.api_server([FirstService, SecondService, ...])
Again, this won't work in production, you'll get the same exception there. Hopefully this answer will be obsoleted by a future fix.
Confirmed it's now obsolete (tested against 1.8.2).
Upvotes: 0
Reputation: 10163
The correct way is to create an api
object and use the collection
api_root = endpoints.api(name='myservice', version='v1', description='MyService API')
@api_root.collection(resource_name='first')
class FirstService(remote.Service):
...
@api_root.collection(resource_name='second')
class SecondService(remote.Service):
...
where resource name would be inserted in front of method names so that you could use
@endpoints.method(name='method', ...)
def MyMethod(self, request):
...
instead of
@endpoints.method(name='first.method', ...)
def MyMethod(self, request):
...
The api_root
object is equivalent to a remote.Service
class decorated with endpoints.api
, so you can simply include it in the endpoints.api_server
list. For example:
application = endpoints.api_server([api_root, ...])
Upvotes: 6
Reputation: 168
If I'm not mistaken, you should give different names to each service, so you'll be able to access both, each one with the specific "address".
@endpoints.api(name='myservice_one', version='v1', description='MyService One API')
class FirstService(remote.Service):
...
@endpoints.api(name='myservice_two', version='v1', description='MyService Two API')
class SecondService(remote.Service):
...
Upvotes: 2