{updated} restRPC
The restRPC (RPC over REST) API allows the creation of client-side remote proxy interfaces for calling methods on server-side POJOs using entirely REST.
The following example shows a remote interface:
The requirements for a remote interface method are:
Throwables
.
Throwables with public no-arg or single-arg-string constructors are automatically recreated on the client side when thrown on the server side.
Remote Interface proxies are instantiated on the client side using one of the following methods:
Since we build upon the existing RestClient
API, we inherit all of it's features.
For example, convenience methods for setting POJO filters and properties to customize the behavior of the
serializers and parsers, and the ability to provide your own customized Apache HttpClient
for
handling various scenarios involving authentication and Internet proxies.
Here's an example of the above interface being used:
Under the covers, this method call gets converted to a REST POST.
HTTP POST http://localhost:10000/remote/org.apache.juneau.examples.addressbook.IAddressBook/createPerson(org.apache.juneau.examples.addressbook.Person) Accept: application/json Content-Type: application/json [ { "name":"John Smith", "birthDate":"Aug 1, 1999", "addresses":[ { "street":"My street", "city":"My city", "state":"My state", "zip":12345, "isCurrent":true } ] } ]
Note that the body of the request is an array. This array contains the serialized arguments of the method. The object returned by the method is then serialized as the body of the response.
There are two ways to expose remote interfaces on the server side:
@RestMethod (name=RRPC )
annotation on a Java method.
In either case, the proxy communications layer is pure REST. Therefore, in cases where the interface classes are not available on the client side, the same method calls can be made through pure REST calls. This can also aid significantly in debugging, since calls to the remote interface service can be made directly from a browser with no coding involved.
The {@link oajr.remote.RrpcServlet} class is a simple specialized servlet with an abstract
getServiceMap()
method to define the server-side POJOs:
The
approach is easier if you only have a single
interface you want to expose.
You simply define a Java method whose return type is an interface, and return the implementation of that
interface:
If you point your browser to the servlet above, you get a list of available interfaces:
http://localhost:10000/remote
Clicking the hyperlinks on each shows you the list of methods that can be invoked on that service.
Note that the IAddressBook
link shows that you can only invoke methods defined on that
interface, whereas the AddressBook
link shows ALL public methods defined on that class.
http://localhost:10000/remote/org.apache.juneau.examples.addressbook.IAddressBook
Since AddressBook
extends from LinkedList
, you may notice familiar collections
framework methods listed.
http://localhost:10000/remote/org.apache.juneau.examples.addressbook.AddressBook
Let's see how we can interact with this interface through nothing more than REST calls to get a better idea on how this works. We'll use the same method call as in the introduction. First, we need to create the serialized form of the arguments:
Object[] args =
That produces the following JSON output:
[
{
name:
Note that in this example we're using JSON. However, various other content types can also be used such as XML, URL-Encoding, UON, or HTML. In practice however, JSON will preferred since it is often the most efficient.
Next, we can use a tool such as Poster to make the REST call. Methods are invoked by POSTing the serialized object array to the URI of the interface method. In this case, we want to POST our JSON to the following URL:
http://localhost:10000/remote/org.apache.juneau.examples.addressbook.IAddressBook/createPerson(org.apache.juneau.examples.addressbook.CreatePerson)
Make sure that we specify the Content-Type
of the body as text/json
.
We also want the results to be returned as JSON, so we set the Accept
header to
text/json
as well.
When we execute the POST, we should see the following successful response whose body contains the returned
Person
bean serialized to JSON:
From there, we could use the following code snippet to reconstruct the response object from JSON:
String response =
If we alter our servlet to allow overloaded GET requests, we can invoke methods using nothing more than a browser...
For example, to invoke the getPeople()
method on our bean:
http://localhost:10000/remote/org.apache.juneau.examples.addressbook.IAddressBook/getPeople?method=POST
Here we call the findPerson(
method to retrieve a person and get the
returned POJO (in this case as HTML since that's what's in the Accept
header when calling from a
browser):
http://localhost:10000/remote/org.apache.juneau.examples.addressbook.IAddressBook/findPerson(int)?method=POST&body=@(3)
When specifying the POST body as a &body
parameter, the method arguments should be in UON
notation.
See {@link oaj.uon.UonSerializer} for more information about this encoding.
Usually you can also pass in JSON if you specify &Content-Type=text/json
in the URL parameters
but passing in unencoded JSON in a URL may not work in all browsers.
Therefore, UON is preferred.
The hyperlinks on the method names above lead you to a simple form-entry page where you can test passing parameters in UON notation as URL-encoded form posts.