Prudence
The Scalable REST/JVM
Web Development Platform

Creative Commons License

Tutorial

The goal of this tutorial is to get you up and running with Prudence's most basic features. Along the way, we'll point you to those sections in the manual where you can explore some topics in depth.
We recommend going through this tutorial using the Firefox browser and the Firebug add-on, which will let you see in detail exactly how Prudence responds to client requests.

First Things First

Get It

Prudence is available in six flavors, so choose one and download it!
A friendly page is available to help you decide.
For this tutorial, we'll use the savory JavaScript flavor, under the assumption that JavaScript would be the most widely known. But, let's be clear: the JavaScript in Prudence runs on the server, not in the browser. Wrap your head around that for a minute… JavaScript is here used not for live manipulation of HTML elements, but to do the usual server-side work: communicating with data stores, rendering HTML pages to send to clients, etc. Of course, in your project, you might be writing JavaScript code to run on the client, too. We'll even show you an example of it in this tutorial.
It should be very easy to use any other flavor with this tutorial, since we'll be keeping actual programming to a minimum. Just replace references to "JavaScript" with your flavor of choice.

JVM

The only requirement for Prudence is a Java Virtual Machine (JVM), at least version 5, so make sure you have one installed. An excellent, open-source JVM is available from the OpenJDK project.
A Java Runtime Environment (JRE) is enough for Prudence. You need a Java Development Kit (JDK) only if you plan to write code in Java. Also, Prudence does not require anything from Java Enterprise Edition (JEE). In fact, you can see Prudence as a RESTful, minimal alternative to developing web applications under JEE.

Fire It Up

Start Prudence with the appropriate "run" script in the /bin/ directory. Use "/bin/run.sh" for Unix-like systems (Linux, *BSD and OS X), and "/bin/run.bat" for Windows. Use "console" as an argument to the script.
Prudence should declare its version and list the installed demo applications. When it announces that it is listening on port 8080, it's ready to go. You can quit Prudence at any time by breaking (CTRL-C).
Open your web browser to http://localhost:8080/. You should see the Prudence Administration application, which will link you to the demos. Also, check out the /logs/ directory for running, ongoing logs.

Further Exploration

Hello, World

The /applications/ directory is where you install your applications. You'll find the demo applications there, but let's create a new one, called "Wacky Wiki". Just create an "/applications/wackywiki/" directory and restart Prudence. The Prudence Administration application should show your application listed under the http://localhost:8080/wackywiki/ URL, but you won't see anything when you click on it quite yet.
Now, let's create our first web page. Create "/applications/wackywiki/web/", and then "/applications/wackywiki/web/static/". By "static" here is meant that the contents do not change per user request. Your /web/static/ directory functions pretty much like a regular web server, from which you can serve images, HTML, CSS files, etc. Let's create a "/web/static/index.html" file:
<html>
<body>
	<p>Hello, world! Welcome to Wacky Wiki.</p>
</body>
</html>
You should be able to see this page under http://localhost:8080/wackywiki/. If you're using Firebug, you can see that the contents are compressed (using deflate, zip or gzip) and that conditional HTTP is also handled automatically, such that subsequent page visits return the 304 "the document has not been modified" status code. When receiving a 304, the browser will use its cached version instead of downloading it from Prudence.

Further Exploration

Hello, Dynamic World

In this section, we're going to teach you how to dynamically generate web pages. Prudence offers some terrific features for this, such as sophisticated caching, but if you're more interested in how Prudence lets you to easily create RESTful resources, just skip ahead and come back here later.
Create a /web/dynamic/ directory and move your "index.html" file to there. Unlike /web/static/, you can put programming language code in these files. Edit "index.html", and add some code:
<html>
<body>
	<p>Hello, world! Welcome to Wacky Wiki.</p>
<%
var entry = {title: 'I Love Prudence', contents: 'This is a love letter to Prudence'}
%>
	<h2><%= entry.title %></h2>
	<p><%= entry.contents %></p>
</body>
</html>
The "<% … %>" delimiters are used to insert "scriptlets" of pure JavaScript code. The "<%= … %>" delimiters accept a JavaScript expression, and print it out onto the HTML page.
Refresh your browser, and you should see the dynamically generated page. Hello!
Make sure you understand the significance of newlines and whitespace in scriptlets, especially if you're using Python!

Caching

Look at how Firefox communicates with your dynamic page using Firebug: the contents are compressed, but there is no conditional HTTP. That's because Prudence generates a new version of the page per every user request. Since each such version might be different from the last, the default behavior is that clients should never expect their cached version to be correct.
We can change this by adding caching to our page, specifically for 10 seconds (10,000 milliseconds):
<html>
<body>
	<p>Hello, world! Welcome to Wacky Wiki.</p>
<%
document.cacheDuration = 10000
var entry = {title: 'I Love Prudence', contents: 'This is a love letter to Prudence.'}
%>
	<h2><%= entry.title %></h2>
	<p><%= entry.contents %></p>
</body>
</html>
Keep refreshing the page, and you'll see that for every 10 seconds you are getting 304 status codes.
Actually, something far more important is happening: any browser from any computer would see the same version of the page for those 10 seconds. Prudence caches and serves a static version of the page during that interval and does not run any of your JavaScript code. We've effectively throttled execution of our code.
Our code didn't do much in this example, but what if it were fetching data for that wiki page from a database? Caching would allow us to serve a very large number of user requests without ever touching the database. We could very precisely state that we want the database accessed only, at the most, every 10 seconds. That's excellent scalability, easily accomplished.

Debugging

For fun, let's purposely introduce an error into our JavaScript code: just type some nonsense into the scriptlet above. When you refresh the page, you'll see a generic error.
Now, tet's enable Prudence's debug page. Create a file named "/applications/wackywiki/settings.js":
document.execute('/defaults/application/settings/')
showDebugOnError = true
Restart Prudence, and refresh the page. You'll see a lot of useful information to help you understand what went wrong, including a link directly to your source code. Of course, you wouldn't want to enable this debug page for production systems. Moreover, you might want to show a custom error message instead: Prudence can do that.

Further Exploration

Hello, Fragmented World

As your application grows, you'll likely have a lot of reusable code. Prudence can help you manage it.
Let's create a /web/fragments/ directory, and put the following files in it. Here's "header.html":
<html>
<head>
	<title>Wacky Wiki</title>
</head>
<body>
	<h1>Wacky Wiki</h1>
Here's "footer.html":
</body>
</html>
And here's "entry.html":
<h2><%= entry.title %></h2>
<p><%= entry.contents %></p>
We can now edit our original "/web/dynamic/index.html" using special "<%& … %>" include scriptlets:
<%& '/header/' %>
<p>Hello, world! Welcome to Wacky Wiki.</p>
<%
document.cacheDuration = 10000
var entry = {
	title: 'I Love Prudence',
	contents: 'This is a love letter to Prudence (fragmented).'}
%>
<%& '/entry/' %>
<%& '/footer/' %>
We can use the same fragments in other pages, too. Let's create "/web/dynamic/home.html":
<%& '/header/' %>
<p>This is the home wiki.</p>
<%
document.cacheDuration = 10000
var entry = {
	title: 'Wiki Home',
	contents: 'This wiki page is empty.'}
%>
<%& '/entry/' %>
<%& '/footer/' %>
Note that this page is available under the URL http://localhost:8080/wackywiki/home/. Prudence by default ignores filename extensions for URLs and requires trailing slashes, leading to prettier, more coherent URLs for users.

Caching Fragments

Fragments help organize your code, but they also offer another advantage: because Prudence caches each fragment individually, you can have certain parts of your pages cached longer than others. Moreover, you can alter the cache key to make sure that you are not caching different versions of the fragments per URL. This is a more advanced topic, but we'll provide a quick preview of it example below for our "header" and "footer" fragments. The cache key pattern we will use ensures that the fragment is cached just once per application name ("{an}") and document name ("{dn}"). This is appropriate for our case, because "index.html" and "home.html" never change their content for whatever Wacky Wiki page they're in. If they did change, we could leave the cache pattern at its default, or otherwise tweak it. Maximum efficiency here for maximum scalability.
So, here's the new "header.html":
<html>
<head>
	<title>Wacky Wiki</title>
</head>
<body>
<%
document.cacheDuration = 300000
document.cacheKeyPattern = '{an}|{dn}'
%>
And "footer.html":
</body>
</html>
<%
document.cacheDuration = 300000
document.cacheKeyPattern = '{an}|{dn}'
%>
You won't see any significant difference in your application's behavior with your single browser, but for heavy fragments in large production applications serving many thousands of concurrent users the savings can be dramatic.

Libraries

Prudence further helps reusability by easily allowing code libraries. Libraries are source code files with functions, classes, etc., that you'll want to reuse in your scriptlets and in other Prudence code.
Let's create an "/applications/wackywiki/libraries/" directory, and put "wikidata.js" in it:
function getWikiEntry(id) {
	// (Note the forced conversion to JavaScript string)
	switch(String(id)) {
		case 'index':
			return {
				title: 'I Love Prudence',
				contents: 'This is a love letter to Prudence (from the database).'}
		case 'home':
			return {
				title: 'Wiki Home',
				contents: 'This wiki page is empty (from the database).'}
		case 'todo':
			return {
				title: 'Things to Do',
				contents: 'Nothing to do right now (from the database).'}
		default:
			return {
				title: ",
				contents: "}
	}
}
(This is just a silly example: in a real application, you'll probably be fetching your wiki entries from a data store. )
Here is our new "index.html" page:
<%& '/header/' %>
<p>Hello, world! Welcome to Wacky Wiki.</p>
<%
document.execute('/wikidata/')
var entry = getWikiEntry('index')
%>
<%& '/entry/' %>
<%& '/footer/' %>
We'll leave it as an exercize to you to make similar changes to "home.html".
Note the use of "document.execute" here: this is a Prudence API that lets you run code from /libraries/. We're using it here because the JavaScript language doesn't have it's own include facility. However, if you're using Prudence for Python, Ruby, PHP or Clojure, you can use those language's natural inclusion facilities: "import", "require", etc. The /libraries/ directory is automatically added to your inclusion path. Note that Groovy has the same limitation as JavaScript in this respect, so just use "document.execute" there.

Further Exploration

Hello, Captured World

Creating a file per URL can only take you so far. For example, in our Wacky Wiki we had "index.html" and "home.html", but we wouldn't want to create a file per wiki entry. What if we had a million entries?
The pages are generic enough that they could be generated by the same code. And so, Prudence has a feature called "capturing" that lets you use one file to handle many URLs: we can "capture" URLs that fit a generic URL pattern into a single file.
Let's capture our wiki URLs! First, let's create the generic page, "/web/dynamic/wiki.html":
<%& '/header/' %>
<p>Hello, world! Welcome to Wacky Wiki.</p>
<%
document.execute('/wikidata/')
var entryID = conversation.locals.get('entryid')
var entry = getWikiEntry(entryID)
%>
<%& '/entry/' %>
<%& '/footer/' %>
You see that we're expecting the "conversation locals" to contain the actual entry ID. This will be supplied by Prudence's capturing.
Now, let's capture by creating "/applications/wackywiki/routing.js" in our application's root directory:
document.execute('/defaults/application/routing/')
router.capture('/wiki/{entryid}/', '/wiki/')
Note that you have to restart Prudence in order for your "routing.js" to take effect. Then, try to access http://localhost:8080/wackywiki/wiki/home/, http://localhost:8080/wackywiki/wiki/index/ and http://localhost:8080/wackywiki/wiki/todo/.
We are capturing all URLs in the form of "wiki/…/" into ‘/web/dynamic/wiki.html", where the ellipsis could be any URL segment. We send all these URLs to one file, internally named "wiki/". (It's actually our "wiki.html" from above: remember, Prudence always ignores filename extensions and requires a trailing slash.) That URL segment is also captured by Prudence and sent as a special conversation local value named "entryid".
We can also edit our "index.html" to be a simple stub to display the "index" wiki page:
<%
conversation.locals.put('entryid', 'index')
document.include('/wiki/')
%>

Further Exploration

Hello, REST of the World

Introduction: What's REST?

Prudence is designed from the ground up around REST ("Representational State Transfer") principles, a term coined by Roy Fielding in Chapter 5 of his 2000 dissertation. Fielding's analysis perceptively identified the key features of the Internet infrastructure that have made the World Wide Web and email protocols scale so well horizontally. His conclusions have helped us make better use of available technology, and have generally inspired more practical approaches to the problem of sharing state in diverse, distributed environments.
In "The Case for REST", we show how REST suggests a "resource-oriented architecture." The "resource" is the thing that lies behind the Internet URL. REST resources you are already familiar with include HTML pages, images, videos—everything we see in the World Wide Web. But resources can also be thought of more logically as blog entries, social networking profiles, inventory items in a store or warehouse, etc. Moreover, you should think about resources as single things with multiple representations. An HTML web page might be one representation, but we can represent the same resources in any format, whether it's meant for direct human consumption, such as PDF or plain text, or a format that can be consumed by software, such as XML, JSON and proprietary binary formats.
The ubiquitous HTTP supports sophisticated negotiation of representational formats between the client and the server, and also multiple operations on resources: in addition to GET and POST, which are commonly used in HTML forms, you can also PUT new resources where none were before and DELETE existing resources. This makes HTTP an attractive protocol for distributed applications—and, of course, it's already there, deployed and ready for you to build upon.

Your First Resource

In Prudence, creating a RESTful resource is as easy as creating a dynamic web page.
Create an "/applications/wackywiki/resources/" directory to host your resources. Then, create an "entry.js" file in it:
function handleInit(conversation) {
	conversation.addMediaTypeByName('text/plain')
}
​
function handleGet(conversation) {
	return 'Hello, REST of the World!'
}
The "media type" mentioned in the code is just an abstract way to refer to MIME types, which are a standard way to name representation formats in the Internet. (Actually, they were originally used to identify the format of email attachments.)
Point your browser to http://localhost:8080/wackywiki/entry/ to see your first resource. Not very interesting, is it? Let's add support for another representation format:
function handleInit(conversation) {
	conversation.addMediaTypeByName('text/plain')
	conversation.addMediaTypeByName('text/html')
}
​
function handleGet(conversation) {
	if(conversation.mediaTypeName == 'text/html') {
		return '<html><h1>Hello, <i>REST</i> of the World!</h1></html>'
	}
	return 'Hello, REST of the World!'
}
Refresh you browser, and now you should see your resource represented as snazzy HTML. Because desktop web browsers announce, in their HTTP requests, that they prefer HTML, and Prudence properly negotiated the correct format from among those we stated in our handleInit function, we could give the client what it wanted.

You First Real Resource

OK, enough saying hello to the world! Let's create a resource that actually does something useful in Wacky Wiki. We're assuming here that you created the "/libraries/wikidata.js" we introduced previously. Here's our new "entry.js":
document.execute('/wikidata/')
​
function handleInit(conversation) {
	conversation.addMediaTypeByName('text/plain')
	conversation.addMediaTypeByName('text/html')
	conversation.addMediaTypeByName('application/json')
}
​
function handleGet(conversation) {
	var entryID = conversation.locals.get('entryid')
	var entry = getWikiEntry(entryID)
	switch(String(conversation.mediaTypeName)) {
		case 'application/json':
			return '{"title":"' + entry.title + '", "contents":"' + entry.contents + '"}'
		case 'text/html':
			return '<html><h1>' + entry.title + '</h1><p>' + entry.contents + '</p></html>'
		default:
			return entry.title + '\n' + entry.contents
	}
}
For this to work for all wiki entry URLs, we also have to "capture" them, using the method we learned above. Here's our updated "routing.js":
document.execute('/defaults/application/routing/')
router.capture('/entry/{entryid}/', '/entry/')
router.capture('/wiki/{entryid}/', '/wiki/')
You need to restart Prudence for this new "routing.js" to take effect. Then, you'll be able to see HTML representations of your wiki entries at http://localhost:8080/wackywiki/entry/index/, http://localhost:8080/wackywiki/entry/home/ and http://localhost:8080/wackywiki/entry/todo/.
But, what about those JSON representations? We'll get to them in the next section.

"AJAX"

Modern web browsers are more than consumers of HTML, images and other formats available via plugins (PDF, Flash, etc.). With their internal JavaScript engines, the are adequate RESTful clients. We'll use that feature to access our resource.
Accessing RESTful resources from within web browsers is sometimes called AJAX, which stands for "Active JavaScript and XML." In this example, we're preferring the more compact JSON format over XML, so perhaps we should call it "AJAJ"? Well, the end result is the same.
If you've ever worked with JavaScript in web browsers, you know how painful it is to write code that runs well on all major web browsers. For this example, we'll avoid that pain by using the cross-browser jQuery library, which is freely hosted by Google.
Let's add some AJAX magic to our "index.html":
<html>
<head>
	<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
</head>
<body>
	<p>Enter wiki page name:</p>
	<p><input id="entryid"></input></p>
	<p><button id="fetch">Fetch!</button></p>
	<h2 id="title"></h2>
	<p id="content"></p>
<script>
$(document).ready(function() {
	$('#fetch').click(function() {
		$.ajax({
			type: 'GET',
			url: 'entry/' + $('#entryid').val() + '/',
			dataType: 'json',
			success: function(entry) {
				$('#title').text(entry.title);
				$('#content').text(entry.contents);
			}
		});
	});
});
</script>
</body>
</html>
We currently support three entry names: "index", "home" and "todo". Type any of them into the input box, and click "Fetch!". You should see the results displayed in your browser. Make sure to use Firebug to see the browser communicating with your resource.
This little example might not seem too exciting, but think of what's going on here: Prudence is giving the web browser "raw" data, which it can then represent in sophisticated ways. The burden of rendering the user interface has moved from the server to the client, allowing for an improved user experience on modern browsers, and more room for your server to scale.
But there's a lot more to REST than AJAX: clients for your raw JSON data can be full-blown desktop applications, mobile phone apps, and even other servers on the network (perhaps also powered by Prudence). Taken together, your resources can be considered an API. In fact, a rich, RESTful API can be a valuable Internet product in itself. You can do great things without serving a single web page.
We'll repeat it, because it does get confusing: In the code segment above, the JavaScript is running in your browser, while in all the previous examples we had JavaScript running in Prudence. The language is the same, but the programming environment is vastly different. In the browser, you have access to the DOM and browser services. In Prudence, you have the Prudence API as well everything in the JVM. We think it's nice to be able to write your web application in a single language, whether it's on the client or the server, but if you find it confusing, go ahead and use any of the other Prudence flavors: Python, Ruby, PHP, Clojure or Groovy.
P.S. You may have noticed that we've used semicolons at the end of statements on our client code. Semicolons are optional in the JavaScript language, but many experts recommend you use them anyway in web browsers, because many code analysis and compression tools expect them. Since there's no need to compress your server-side code, we recommend you follow your own preference there. We happen to prefer no semicolons.

Reader Meets Author

Though we won't cover it in this tutorial, with Prudence—and HTTP, and AJAX—you can also accept data from the client into your resource. Use handlePut to create entirely new resources at the URL identified by the client. For example, Wacky Wiki clients can send you JSON data via a PUT, which you can then parse and save in the database as a new wiki entry. There's also handlePost, used to update existing resources, and handleDelete for getting rid of them.

Safe and Sound

Worried about unauthorized access to your data? Prudence has a friendly API for cookies, and allows for sophisticated authentication mechanisms and secure connections.

Further Exploration

What Next?

The best way to learn Prudence is by creating your own applications. Why not turn Wacky Wiki into the next Internet hit, or into an online discussion board for your organization?
Furthermore, Prudence comes with example code, and even a complete, data-driven, RESTful application: Stickstick. Stickstick is a shared, online bulletin board on which anyone can post notes for everyone else to see. You can move notes around and delete them. The Stickstick source code demonstrates how you can save your resource data into a SQL database, scalable handling of conditional HTTP, and even a few AJAX tricks.
And then there's the Prudence Manual: very detailed, and available online in what we hope is a friendly, easy-to-use format. A PDF of it is included with all Prudence flavors, ready to print out or read on your e-reader.
Finally, make sure to join the Prudence Community online, to ask questions, contribute ideas and see how others are making good use of Prudence. And please report any bugs and make suggestions for improvement!
Before you run off to play with Stickstick, we'll mention just two important features that weren't covered in the tutorial:

Filters

Prudence lets you write code that will filter every incoming and outgoing request. This makes it easy to do a wide variety of general work such as authenticating, sanitizing, transformation/encoding, monitoring, throttling, caching, processing, etc. See filters for complete documentation.

Tasks

Prudence lets you write and run tasks asynchronously, and even to schedule them using a crontab-like configuration file. This is very useful for maintenance work such as releasing unused connections and sessions, for sending email reminders and administrative alerts, for monitoring services, etc. See tasks for complete documentation.