Invocation-based services are simple to implement actions run on Objective-Cloud's servers. They can be used for both designing a service for an app client or a browser client.
For selecting the right type of service refer here.
You should have read the Objective-Cloud tutorial and worked through the steps described there.
Please start terrasphere, create and clone a new cloud application for this tutorial as described here, open it in Xcode and launch it by simply building it.
Invocation-based services provide a message based API to a service. As in a local environment this is provided by a class with a public API declared by an Objective-C protocol and an implementation that defines the methods reacting on messages. While the protocol is exported to the client, the implementation is hidden on the server.
A public service consists of three areas that can be understood as ranges of publicity:
You can pass arguments to the service and receive return values.
In this tutorial deals with invocation-based cloud application. Such a service is useful with a client counterpart that interacts with the service. There are several ways to send messages to the service. For this tutorial we use GET requests with URL encoded arguments. The default response you will read is in JSON. We selected this format for messaging, because we can provide links that does the work for you, so you do not have to type it yourself. Even this is an implementation detail for the service, you should have an idea of what is going on behind the scenes, last but not least for doing your own experiments:
Independently of the format invocation request contains three parts:
As mentioned we will send GET requests using our browser. The general format is:
http://localhost:10000/service/selector?[?parameter=argument{¶meter=argument}]
For example the Objective-C message …
+ (NSString*)sayHelloWithFirstName:(NSString*)firstName lastName:(NSString*)lastName;
…
[Service sayHelloWithFirstName:@"Amin" lastName:@"Negm-Awad"];
looks like this,
when it is a GET request:
http://localhost:10000/Service/sayHelloWithFirstName-lastName-?firstName=Amin&lastName=Negm-Awad
Please note that the colons of the selector are replaced by with `-` (minus). However, Objective-Cloud accepts colons inside the selector and rfc3986, section-3.3 only forbids it for scheme less path.
You get the parameter names from the parameter variables in the cloud interface.
The response you will get in this tutorial is a JSON document. But at the end we will make it be HTML.
By default every cloud application contains a simple service class named `Service` with a single method `+publicVersion`, inherited from `OCFPublicObject` taking no arguments. After starting terrasphere and the cloud application, you can check that. Sending a GET request for the Objective-C message …:
[Service publicVersion]
{
"returnValue" : 0
}
@implementation Service
…
+ (NSString *)sayHelloTo:(NSString*)name // A
{
return [@"Hello " stringByAppendingString:name];
}
@end
[Service sayHelloTo:@"Amin"]
{
"error" : {
"code" : 1407,
"domain" : "com.objective-cloud.foundation",
"userInfo" : {
"NSLocalizedDescription" : "The selector of an invocation request is unknown."
}
"__com.objective-cloud.objectType" : "NSError:NSObject",
}
}
Class
`CloudInterface`.
@protocol ServiceCloudInterface <NSObject>
+ (NSString *)sayHello;
+ (NSString *)sayHelloTo:(NSString*)name; // A
@end
[Service sayHelloTo:@"Amin"]
{
"returnValue" : "Hello Amin"
}
@implementation Service
…
+ (NSArray *)addItem:(NSString *)item toList:(NSMutableArray*)list
{
[list addObject:item];
return list;
}
@end
@protocol ServiceCloudInterface <NSObject>
…
+ (NSArray *)addItem:(NSString *)item toList:(NSMutableArray*)list;
@end
group[name]=Developers&group[members][0][firstName]=Amin&group[members][0][lastName]=Negm&group[members][1][firstName]=Chris&group[members][1][lastName]=Kienle
@{
@"name" : @"Developers",
@"members" :
@[ // Array
@{
@"firstName" : @"Amin", // Dictionary
@"lastName" : @"Negm"
},
@{
@"firstName" : @"Chris", // Dictionary
@"lastName" : @"Kienle"
}
]
}
@}
[Service addItem:@"Chris" toList:@[@"Amin"]] // Passed as mutable array
{
"returnValue" : [
"Amin",
"Chris"
]
}
@protocol ServiceCloudInterface <NSObject>
…
+ (NSSet *)addItem:(NSString *)item toList:(NSMutableSet*)list;
@end
@implementation Service
…
+ (NSSet *)addItem:(NSString *)item toList:(NSMutableSet*)list
{
[list addObject:string];
return list;
}
@end
[Service addItem:@"Chris" toList:@[@"Amin"] // Passed as mutable set
{
"returnValue" : [
"Chris",
"Amin"
]
}
@protocol ServiceCloudInterface <NSObject>
…
+ (NSSet *)addItem:(NSString *)item toList:(NSMutableSet*)list error:(NSError **)error;
@end
@implementation Service
…
+ (NSSet *)addItem:(NSString *)item toList:(NSMutableSet*)list error:(NSError**)error
{
if (list==nil)
{
*error = [NSError errorWithDomain:@"yourDomain" code:1 userInfo:nil];
return nil;
}
[list addObject:item];
return list;
}
@end
http://localhost:10000/Service/addItem-toList-?item=Chris
http://localhost:10000/Service/addItem-toList-?item=Chris&list[0]=Amin
{
"outArguments" : [
{
"code" : 1,
"domain" : "yourDomain",
"userInfo" : {
},
"__com.objective-cloud.objectType" : "NSError:NSObject"
}
],
"returnValue" : null
}
@protocol ServiceCloudInterface <NSObject>
…
+ (NSNumber *)addItem:(NSString *)item toList:(inout NSMutableSet*)list error:(NSError **)error;
@end
@implementation Service
…
+ (NSNumber *)addItem:(NSString *)item toList:(inout NSMutableSet*)list error:(NSError**)error
{
if (list==nil)
{
*error = [NSError errorWithDomain:@"yourDomain" code:1 userInfo:nil];
return @NO;
}
[list addObject:string];
return @YES;
}
@end
http://localhost:10000/Service/addItem-toList-error-?item=Chris&list[0]=Amin
{
"outArguments" : [
[
"Chris",
"Amin"
],
null
],
"returnValue" : true
}
http://localhost:10000/Service/addItem-toList-error-?item[firstName]=Chris&item[lastName]=Kienle&list[0]=Amin
{
"error" : {
"code" : 1002,
"domain" : "com.Objective-Cloud.JSONCoding",
"userInfo" : {
"expectedClassName" : "NSString",
"NSLocalizedDescription" : "Incompatible types of value. Expected NSString, found __NSDictionaryM.",
"foundClassName" : "__NSDictionaryM"
},
"__com.objective-cloud.objectType" : "NSError:NSObject"
}
}
@protocol ServiceCloudInterface
…
+ (NSNumber *)addItem:(id)item toList:(inout NSMutableSet*)list error:(NSError **)error;
@end
@implementation Service
…
+ (NSNumber *)addItem:(id)item toList:(inout NSMutableSet*)list error:(NSError**)error
{
if (list==nil)
{
*error = [NSError errorWithDomain:@"yourDomain" code:1 userInfo:nil];
return @NO;
}
[list addObject:string];
return @YES;
}
@end
Now we can add a dictionary instance to the list:
http://localhost:10000/Service/addItem-toList-error-?item[firstName]=Chris&item[lastName]=Kienle&list[0]=Amin
curl -X POST http://localhost:10000/Service -d '{"selector" : "addItem:toList:error:", "arguments" : [2,["Amin"]]}';2D;2D;2D;2D
{
"outArguments" : [
[
{
"firstName" : "Chris",
"lastName" : "Kienle"
},
"Amin"
],
null
],
"returnValue" : true
}
There are many additional capabilities of invocation-based services, i. e.
To get information about this in detail, please refer to Invocation-based services in Detail