Hosted by Three Crickets

Prudence
Scalable REST Platform
For the JVM

Prudence logo: bullfinch in flight

The Internal URI-space

Who says that you need HTTP, or any kind of networking, for REST? The principles are themselves applicable and suitable to in-memory communication, and represent an attractive architectural paradigm for APIs: attractive especially because it can work both locally and over the wire. This useful feature gives you considerable deployment flexibility: you can easily export a whole API layer to another running instance in the cluster. For an example of this, see the MVC chapter.

The RIAP Pseudo-Protocol

In Prudence, internal REST is straightforwardly supported by specifying the "RIAP" pseudo-protocol in URIs. RIAP stands for "Restlet Internal Access Protocol". There are two common formats for RIAP URIs:
In both cases the wildcard will exactly match the URI templates you've mapped in app.routes.

Internal Requests

You can use RIAP URIs everywhere a full URI is used in Prudence, for example, when using the Prudence.Resources.request and document.external APIs. See the section on external requests for examples.
However, the APIs can also implicitly create these RIAP URIs for you. For example:
document.require('/prudence/resources/')
var weather = Prudence.Resources.request({
	uri: '/weather/',
	mediaType: 'application/json'
})
Prudence.Resources.request will automatically assume that URIs beginning with "/" are internal, and thus set the "internal" param to true. The URI used would in fact be an RIAP URI: "riap://application/weather/".
To access a different application:
var weather = Prudence.Resources.request({
	uri: '/weather/',
	internal: 'weatherapp'
	mediaType: 'application/json'
})
The actual URI would be "riap://component/weatherapp/weather/".
Low Level
For non-JavaScript you can use the lower-level document.internal and document.internalOther APIs:
document.require('/sincerity/json')
var resource = document.internal('/weather/', 'application/json')
result = resource.get()
if (null !== result) {
	weather = Sincerity.JSON.from(result.text)
}
To access a different application:
resource = document.internalOther('weatherapp', '/weather/', 'application/json')

Private URI-space

Internal requests bypass the hiding mechanism in routing.js. Thus, if you want some URIs to only be usable internally, simply hide them from the public URI-space.

Avoiding Serialization for Internal Requests

The web data chapter covers the creation of response payloads. There is, however, a possible optimization for internal requests. If your textual and binary representations are serialized versions of data structures, it would be unnecessary and wasteful to go through serialization/deserialization for an internal request. A simple optimization would be to pass the data "as is," which is actually very similar to a return value for a mundane function call.
This works using the special "application/internal" MIME type. If selected—whether negotiated for or explicitly overridden—then return values are indeed sent "as is." For example:
function handleInit(conversation) {
	conversation.addMediaTypeByName('application/json')
	if (conversation.internal) {
		conversation.addMediaTypeByName('application/internal')
	}
}
​
function handleGet(conversation) {
	var data = ...
	return conversation.mediaTypeName == 'application/internal' ?
		data : Sincerity.JSON.to(data)
}
Note that we've added support for "application/internal" only to internal requests, verified using the conversation.internal API. The reason is that we don't want to allow "application/internal" representations over HTTP. (Actually, that could work if the object is itself JVM-serializable, but that's a more advanced use case we won't deal with here.)

The Prudence Manual is provided for you under the terms of the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. The complete manual is available for download as a PDF.

Download manual as PDF Creative Commons License