Remoteable service API
Defines an API for remote proxy interfaces (e.g. Remoteable Services).
The Remoteable Service API allows for client side code to use interface proxies for calling methods on POJOs on the server side.
Proxy interfaces are retrieved using the {@link org.apache.juneau.rest.client.RestClient#getRemoteableProxy(Class)} method. The remoteable servlet is a specialized subclass of {@link org.apache.juneau.rest.RestServlet} that provides a full-blown REST interface for calling remoteable services (e.g. POJOs) remotely.
The following simplified example shows how a method on a POJO on a server can be called through an interface on a client...
The client side code for invoking this method is shown below...
The requirements for a method to be callable through the remoteable service are:
Remoteable interface proxies are retrieved through the existing {@link org.apache.juneau.rest.client.RestClient} class.
It may seem that the client-side code would need to be complex.
In reality, it builds upon existing serializing, parsing, and REST capabilities in Juneau resulting in very
little additional code.
The entire code for the RestClient.getRemoteableProxy(Class)
method is shown below:
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.
The server side is only slightly more complex, but boasts useful debugging and discovery capabilities.
The {@link org.apache.juneau.rest.remoteable.RemoteableServlet} class is an implementation of
{@link org.apache.juneau.rest.RestServlet} that provides a REST interface for invoking calls on POJOs.
The RemoteableServlet
class is abstract and must implement a single method for providing the set
of POJOs to expose as remote interfaces.
The samples bundle includes a sample implementation of a remoteable service that can be used to interact with the address book POJO also included in the bundle. The method that must be implemented is {@link org.apache.juneau.rest.remoteable.RemoteableServlet#getServiceMap()} that simply returns a mapping of Java interfaces (or classes) to POJO instances.
Since this class is a servlet, and can be deployed as such.
In the sample code, it's listed as a child resource to org.apache.juneau.rest.samples.RootResources
which makes it available under the URL /juneau/sample/remoteable
.
If you point your browser to that URL, you get a list of available interfaces:
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.
Since AddressBook
extends from LinkedList
, you may notice familiar collections
framework methods listed.
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 /juneau/sample/remoteable/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, 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):
When specifying the POST body as a &content
parameter, the method arguments should be in UON
notation.
See {@link org.apache.juneau.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.
What if you want fine-tuned control over which methods are exposed in an interface instead of just all public methods? For this, the {@link org.apache.juneau.remoteable.Remoteable @Remoteable} annotation is provided. It can be applied to individual interface methods to only expose those methods through the remoteable servlet.
For example, to expose only the first 2 methods in our IAddressBook
interface...
On the server side, the option to restrict access to only annotated methods is defined through a property:
The