-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmanual.html
More file actions
548 lines (479 loc) · 56.1 KB
/
manual.html
File metadata and controls
548 lines (479 loc) · 56.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Bowler - RESTful Scala Web Framework: Manual</title>
<link rel="stylesheet" type="text/css" href="css/style.css"/>
</head>
<body>
<div id="container">
<span ><!-- header panel here --></span>
<div id="header">
<h1 >Bowler</h1>
<p >RESTful Scala Web Framework</p>
</div>
<div>
<!-- <ul class="tabs-nav">
<li ><a href="/"><span>Home</span></a></li>
</ul>
</div> -->
<div class="tabs-container">
<div id="body">
<h2>The Bowler Manual</h2>
This is the Bowler manual and will continually be expanded on. In addition to this manual, the <a href="https://github.com/wfaler/Bowler/tree/master/examples">Bowler Example Application</a> and the <a href="https://github.com/wfaler/bowler-quickstart">Bowler Quickstart</a> are good places to start getting into Bowler and how it works.
<ul>
<li><a href="#build">SBT or Maven dependencies</a></li>
<ul>
<li><a href="#basebuild">Bowler Core</a></li>
<li><a href="#squerylbuild">Bowler with Squeryl Integration</a></li>
<li><a href="#jpabuild">Bowler with JPA Integration</a></li>
<li><a href="#snapshotreleases">SNAPSHOT releases</a></li>
</ul>
<li><a href="#setup">Application Setup</a></li>
<li><a href="#structure">Application Structure</a></li>
<li><a href="#routes">The Controller - Defining Routes/URL's</a></li>
<ul>
<li><a href="#routeordering">Ordering of Routes</a></li>
</ul>
<li><a href="#view">The View</a></li>
<ul>
<li><a href="#resourceview">The Resource View & View Model</a></li>
<ul>
<li><a href="#nestedresourceview">What about Dropdowns and other UI elements that need additional models?</a></li>
</ul>
<li><a href="#scalatmodelalias">Scalate Templates & View Model Aliases</a></li>
<li><a href="#templatemapping">Template Mapping</a></li>
<ul>
<li><a href="#templateReuse">Template Re-use</a></li>
<li><a href="#localisation">Localisation</a></li>
</ul>
<li><a href="#componentRenderSupport">Re-usable UI Components with ComponentRenderSupport</a></li>
<li><a href="#jsonhtml">Return JSON or HTML?</a></li>
<li><a href="#layouts">Layouts</a></li>
<ul>
<li><a href="#layoutbasics">Basics</a></li>
<li><a href="#layoutmodels">Layout Models</a></li>
<li><a href="#nestedlayouts">Nested Layouts</a></li>
<li><a href="#layoutcomposition">Layout Composition: Layout Models</a></li>
</ul>
<li><a href="#components">"Wicket-like" Component Oriented Templating with Squery</a></li>
</ul>
<li><a href="#model">The Model: POST, PUT, GET, DELETE - Handling Requests</a></li>
<ul>
<li><a href="#parametermapping">Parameter Mapping: Mapping Requests to Beans/instances</a></li>
<ul>
<li><a href="#formvjson">What about Form Encoded vs. JSON requests?</a></li>
<li><a href="#optionalparameters">Optional Parameters</a></li>
<li><a href="#valuetransformers">Lookup Complex Objects by Id: StringValueTransformers</a></li>
<li><a href="#putpostvsgetdelete">Creating & Editing instances: PUT & POST vs. GET & DELETE</a></li>
</ul>
<li><a href="#validation">Validation</a></li>
<ul>
<li><a href="#customvalidations">Creating Custom Validators</a></li>
<li><a href="#validationmessages">Validation Messages & Localisation</a></li>
<li><a href="#defaultvalidation">Default Validators for Models</a></li>
<li><a href="#jsonvalidation">Validation Errors and JSON Responses</a></li>
</ul>
<li><a href="#forms">Forms</a></li>
<ul>
<li><a href="#validationerrorscomponent">Displaying Validation Errors in Forms</a></li>
</ul>
</ul>
<li><a href="#requestcycle">The Request Cycle</a></li>
<ul>
<li><a href="#interceptingrequests">Intercepting Requests (example: transactionality)</a></li>
<li><a href="#nestedinterception">Nested Interception(example: transactionality + authentication/authorization)</a></li>
</ul>
<li><a href="#persistence">Persistence Integration</a></li>
<ul>
<li><a href="#squeryl">Squeryl</a></li>
<li><a href="#jpa">Jpa</a></li>
<li><a href="#persistencehelpers">Persistence Helpers</a></li>
<ul>
<li><a href="#entitytransformer">EntityTransformer StringValueTransformer</a></li>
<li><a href="#uniqueentityvalidator">UniqueEntityValidator</a></li>
<li><a href="#crudcontroller">CRUD Controller</a></li>
</ul>
</ul>
<li><a href="#testing">Testing</a></li>
</ul>
<h4>Deeper Customization</h4>
<ul>
<li>Multi-Channel Support</li>
<ul>
<li>Layout Selectors & Client/Request Specific Layouts</li>
<li>View Suffixes for Client/Request Specific Views</li>
</ul>
<li>Customizing the Framework</li>
<ul>
<li>Request Mapping Strategies</li>
<li>Render Strategies & View Renderers</li>
</ul>
</ul>
<h3><a name="build">SBT or Maven dependencies</a></h3>
<h4><a name="basebuild">Bowler Core</a></h4>
<h5><a name="sbt">Simple Build Tool</a></h5>
The below <a href="http://code.google.com/p/simple-build-tool/">Simple Build Tool (sbt)</a> project file should give you all you need to start using Bowler if you're a Sbt user (place the file in your project/build folder). It should download all the dependencies required from Sonatypes public repo once you run the sbt "update" command.
<script src="https://gist.github.com/782223.js"> </script>
<h5><a name="maven">Getting Started Using Maven</a></h5>
If you're using Maven, you need to add the following into your pom.xml (in addition to the other Scala stuff you may want to set up for compilation):
<script src="https://gist.github.com/782228.js?file=gistfile1.txt"></script>
<h4><a name="squerylbuild">Bowler with Squeryl Integration</a></h4>
If you want Squeryl integration you may want to add the following lines to <a href="#basebuild">the project description shown in the previous section</a> (last two are optional, and you should add a dependency on the JDBC driver for your deployment database):
<script src="https://gist.github.com/841460.js?file=squerylbowlerproject.scala"></script>
Also, compared to the baseline Bowler project, you can remove the dependency on "bowler-core_2.8.1", as this is implicit through "squeryl-mapper_2.8.1". For Maven users, I'm sure you can deduce the dependency definitions from the example here and in the previous section.
<h4><a name="jpabuild">Bowler with JPA Integration</a></h4>
Below are the extra settings required for JPA integration compared to the <a href="#basebuild">base build</a>, the comments explain the specific reasons for some of the dependencies:
<script src="https://gist.github.com/841465.js?file=jpaproject.scala"></script>
For Maven users, again, hopefully you can deduce what the dependencies and repo definitions are, as they follow the Maven format, but are defined in sbt's style.
<h4><a name="snapshotreleases">SNAPSHOT releases</a></h4>
The Bowler project will occassionally, but unfrequently make snapshot releases for the framework when major milestones are reached in development or bug fixes are made, but there is not sufficient QA done to make a full release. These will reside in the <a href="https://oss.sonatype.org/content/repositories/snapshots">Sonatype SNAPSHOTS repository</a>.<br/>
The current SNAPSHOT release is <b>0.3-SNAPSHOT</b>
<h3><a name="setup">Application Setup</a></h3>
Below is an example of the web.xml for a typical Bowler application:
<script src="https://gist.github.com/783537.js?file=web.xml"></script>
The only thing of note here is the BowlerFilter (you could also use BowlerServlet), which takes an init-parameter called "bootstrapClass". The bootstrapClass is simply the starting point of your application, where as the name implies, you bootstrap your whole application.<br/>
Below is an example of a minimal Bowler bootstrap class:
<script src="https://gist.github.com/783541.js?file=Bootstrap.scala"></script>
The Bootstrap class above is a simple basic class with a no-args constructor, which does the following from top to bottom:
<ul>
<li>Sets up a default view Layout for the application</li>
<li>Adds a LayoutSelector for the Layout, in this case a catch-all DefaultLayoutSelector which will use the layout for all requests (more about Layout selection later)</li>
<li>Starts a Controller that responds to Requests</li>
<li>Sets the Scalate RenderEngine to disallow caching and allow reloading - this will slow down rendering, but is useful if you want to change Scalates on the fly during runtime during development</li>
</ul>
That's it, there's really not much more to setting up a basic Bowler Applications! Of course, you could add much more here: more Controllers, add StringValueTransformers to the TransformerRegistry for looking up complex objects based on request parameters such as id's, add more complex Layouts etc.
<h3><a name="structure">Application Structure</a></h3>
A typical Bowler Application, as seen from a Maven or SBT default project structure will have a structure as follows:
<ul>
<li>src/main/</li>
<ul>
<li>webapp/WEB-INF/web.xml</li>
<li>scala/[yourpackage] <i>(your application sources)</i></li>
<li>scala/[your validator package] <i>(package with your validator classes)</i></li>
<li>resources/layouts/ <i>(location for your application layouts)</i></li>
<ul>
<li>default.mustache <i>(illustration of possible default layout location)</i></li>
</ul>
<li>resources/views/ <i>(location for your views)</i></li>
<ul>
<li>GET/ <i>(views are held in locations based HTTP Method and path, for instance "GET /" could be in "/views/GET/index.mustache")</i></li>
<ul>
<li>index.mustache <i>(illustration of possible template name. Can be .mustache, .ssp, .jade or .scaml)</i></li>
</ul>
</ul>
<li>resources/[your validator package] <i>(package with your validator .properties message files)</i></li>
</ul>
</ul>
What is noteworthy above is that views and layouts are kept on the classpath, layouts on the /layouts/ path, and views in the /views/ package, followed by the HTTP Method and path, for instance /views/GET/somepath.ssp.
<h3><a name="routes">The Controller - Defining Routes/URL's</a></h3>
You define "routes" in Bowler based on the approach <a href="https://github.com/scalatra/scalatra">inherited from Scalatra</a>, which Bowler is built on top of. You typically do this by inheriting the <i>Controller</i> trait and adding your Controller in the bootstrap-class of your application.<br/>
Below is an example of a simple Controller, please note the comments:
<script src="https://gist.github.com/783603.js?file=MyController.scala"></script>
In the example above, you can see that each HTTP Method has it's own equivalent verb in the Bowler DSL which allows you to create an application route that takes a Request and Response as arguments.<br/>
We can also do wild-card URL's as follows:
<script src="https://gist.github.com/783606.js?file=wildcard.scala"></script>
..this will make the wildcards available in a special case request variable called "splat" in the form of a List in the order of the wildcards.<br/>
But that's not all, we can also have regular expression routes:
<script src="https://gist.github.com/783608.js?file=regexroute.scala"></script>
In a similar manner to the wildcards, the regex values captures will be available in a special case request variable called "captures" in the form of a List in the order of the wildcards.<br/>
It should be noted that regex and wildcard URL's view mappings need to be explicitly made, as the file system of some operating systems, notably Windows do not support some of the strange characters that may otherwise ensue. More about this in the section <a href="#templatemapping">Template Mapping</a>.
<h4><a name="routeordering">Ordering of Routes</a></h4>
It is important to note that your routes could clash if you define them carefully, in this case the last defined route takes precedence. For instance if you have the route <i>"/resource/:id"</i> defined, and then <i>"/resource/new"</i>, any requests to /resource/new will go to the equivalent request handling closure but every other request that matches "/resource/:id" will go to that request handling closure. Even though "/resource/new" matches the "/resource/:id", it will take precedence IF it was defined later in the class. If it was defined before "/resource/:id", it will never be called!
<h3><a name="view">The View</a></h3>
<h4><a name="resourceview">The Resource View - Separating View Model from Layout</a></h4>
The default Bowler setup makes a distinction between the <b>Resource View</b> and the <b>Layout</b>. The rationale behind this is simple: in a truly RESTful application, by getting a resource at a URL you are primarily interested in the details of the resource (most commonly a model object or several models in our case), not the "decoration" around it - navbars, headers, footers and other things you may get with a desktop browser are there for usability, but often have very little to do with the resource itself. This is why we make this distinction, more about the rationale behind can be found in <a href="http://blog.recursivity.com/post/2615673341/decomposing-the-view-in-mvc-whats-in-a-view">this blog post</a>.<br/>
Given this background, a rendered View in Bowler will usually consist of a Resource View and a Layout that wraps around the Resource View.<br/><br/>
Consider the following case class and controller:
<script src="https://gist.github.com/783654.js?file=widgetcontroller.scala"></script>
Now, consider the above controller with the following view at the classpath location of <i>/views/GET/showAWidget/index.mustache</i>
<script src="https://gist.github.com/783657.js?file=widget.html"></script>
This should render the following (excluding any layout around it for simplicity of the example):
<script src="https://gist.github.com/783660.js?file=widgetresult.html"></script>
There are a couple of things to learn from this: by extending our controller with <i>Renderable</i>, we get access to the <i>render</i> function, which is a vararg function that will invoke the rendering with your model objects. Render will eventually map your model into an appropriate model for Scalate and the mustache template to render in this case. We'll deal with this in a second.<br/>
The <i>render</i> function is central here: as you can see, you only pass in your model, or any arbitrary model objects that represent your resource, but you don't actually give it any information on how to render the model. This is important, especially if you want to render to multiple outputs, for instance JSON (which you get for free, more on that later) and HTML.
<h5><a name="nestedresourceview">What about Dropdowns and other UI elements that need additional models?</a></h5>
Dropdowns and other elements may require additional backing model data which isn't part of your immediate Resource, for instance a Resource Model may have another Resource set on it in a relationship, but you may have a form where you want to choose from a number of possible options in a dropdown.<br/>
In this case the Mustache template format is probably unsuitable in this particular case. The best practice in this case is to use something like an SSP template and a re-usable Bowler UI Component - this is detailed in the section <a href="#components">Re-usable UI Components</a>.
<h4><a name="scalatmodelalias">Scalate Templates & View Model Aliases</a></h4>
As we could see in the above example, the Widget case class instance somehow got mapped into a Scalate model object called <i>"widget"</i> for the benefit of the template, how did this happen and what governs this?
It's really quite simple, there are a couple of simple rules around this:
<ul>
<li>By default, a class passed as View Model will be called it's lower case equivalent, for instance <i>com.mypackage.Widget</i> will become <i>widget</i> in the template.</li>
<li>Sets, Seqs, Lists and java.util.Collection's will be called the plural form of the objects contained, for instance a <i>List[Widget]</i> would become <i>widgets</i>. In this sense, the pluralisation is a bit dumb and only appends an "s" to the type alias</li>
<li>You can override this behavior by wrapping whatever View Model you pass in in a <a href="http://bowler.s3.amazonaws.com/api/org/bowlerframework/view/ViewModel.html">ViewModel</a> object giving it the new alias as a constructor argument.</li>
<li>Finally, you can override the default alias by registering another one in the <a href="http://bowler.s3.amazonaws.com/api/org/bowlerframework/model/AliasRegistry$.html">AliasRegistry</a></li>
</ul>
Given these basics, other template specific questions are probably best answered by the <a href="http://scalate.fusesource.org/">Scalate</a> documentation, and depending on your preference of Scalate supported templating language, more specifically the <a href="http://scalate.fusesource.org/documentation/mustache.html">Mustache</a>, <a href="http://scalate.fusesource.org/documentation/ssp-reference.html">SSP</a>, <a href="http://scalate.fusesource.org/documentation/jade.html">Jade</a> or <a href="http://scalate.fusesource.org/documentation/scaml-reference.html">Scaml</a> docs.<br/>
Personally, I have a preference for Mustache templates in most cases, as they are logic-less and avoid any temptation to include backend application logic in the template and all the potential stupid things that can come with that.
<h4><a name="templatemapping">Template Mapping & Paths</a></h4>
As we have mentioned, we support all Scalate template types out of the box. The resolution of whether it is a .mustache, .jade, .ssp or .scaml template is done "auto-magically", so you may happily mix various types if you need/want to.<br/>
As we also mentioned, views are typically in a path according to the following format (assuming you use the default locations): <i>/views/[HTTPMETHOD]/[firstpartofpath]/[secondpart].[mustache|ssp|jade|scaml]</i>
There are some notable special cases around this (we'll use .mustache files here for simplicity, though you could use any scalate supported type):
<ul>
<li>The root of a folder/path should have an <i>index.mustache</i> file.</li>
<li>For named variables, like ":id", the semi-colon is replaced by an underscore, so request to GET <i>"/widgets/:id"</i> would be mapped to for instance a mustache template at <i>/views/GET/widgets/_id.mustache</i>. This also goes for multiple levels of nested named parameters: folders can also be prefixed with the underscore</li>
<li>Regex and Wildcard URL's need to have their view template paths set explicitly by using the method described in the <a href="#templateReuse">Template Re-use</a> section</li>
</ul>
<h5><a name="templateReuse">Template Re-use</a></h5>
If you want to re-use templates that have been defined for other parts, thus saving yourself copy pasting almost identical templates, or you want to define a template location for a regex- or wildcard URL, you can use the <i>Renderable.renderWith</i> function, as shown below:
<script src="https://gist.github.com/900563.js?file=renderWith1.scala"></script>
The ViewPath and RenderPath helper-objects used as the first argument to <i>renderWith</i> will make the TemplateResolver look for the template in the alternate location mapping instead. The alternate mapping follows the exact same syntax as your route-definitions in your controllers.
<h5><a name="localisation">Localisation</a></h5>
Localisation of Views and Layouts in Bowler is easy - simply copy your original template and suffix the filename before the file-ending with the locale:
For instance, a file called <i>index_se.mustache</i> will take precedence over <i>index.mustache</i> if the users browser has a Swedish locale set.
<h4><a name="componentRenderSupport">Re-usable UI Components with ComponentRenderSupport</a></h4>
<a href="http://scalate.fusesource.org/documentation/ssp-reference.html">The Scalate SSP template format</a> allows you to call Scala code from your template. Adding lots of code/logic in your template is generally not a good thing, however if you do it cleanly as in the example below, you are using a style which is clean, concise and nice with a minimum of actual code:
<script src="https://gist.github.com/795989.js?file=reuse.ssp"></script>
What happens in the template snippet above is that we have imported the functions & values of "SimpleComponent" to be available in the template, we then call the "show" function on the SimpleComponent singleton object with a Tuple2 parameter, for which the resulting string is unescaped by Scalate so that any resulting HTML is returned without being escaped (be careful if you are returning user input data and filter it for scripts!).<br/>
What is key to creating re-usable components in this manner is:
<ul>
<li>Create a singleton object and import it as in the example above.</li>
<li>Call a method as above that will return a String with the contents that you want to display in place of the code</li>
<li>If using SSP, you may pass any type-safe parameter you wish to the function as an argument</li>
</ul>
By doing this, you are effectively creating the equivalent of a Wicket Component, Lift Snippet or JSP custom tag, if you are familiar with any of these technologies.<br/>
A usefule utility when doing this is to let yout singleton object extend the <a href="http://bowler.s3.amazonaws.com/api/org/bowlerframework/view/scalate/ComponentRenderSupport.html">ComponentSupport</a> trait, which allows you to associate Scalate markup with a given Component class. For instance, consider the following object that extends ComponentRenderSupport:<br/>
<script src="https://gist.github.com/841249.js?file=CarDropdown.scala"></script>
ComponentRenderSupport has a couple of methods, with <i>render</i> being the most likely one to use in most cases. In the above example, the <i>show</i>-function, which we can import into SSP, Jade or Scaml markup, will render a list of Car entities, together with a Car which is selected by default.<br/>
The render-function will input this model aliased into markup that by default lives in the classpath at the pattern of /[package of your object]/[name of object]_index.[ssp|scaml|jade]. In this case the markup is ssp, at <i>/org/bowlerframework/examples/jpa/MakeDropdownComponent_index.ssp</i>, which looks as follows:
<script src="https://gist.github.com/841261.js?file=cars.ssp"></script>
All in all, extending ComponentRenderSupport gives you a nice way of creating autonomous Components that you can nest in your Layouts or Views, and that are useful to render parts that may not be part of your View Model, but that you need to fully display what you want to display (for instance a dropdown of choices of related model entities).
<h4><a name="jsonhtml">Return JSON or HTML?</a></h4>
Given the separation of Resource View and Layout that we have been banging on about, rendering JSON instead of HTML is really simple: if you set the HTTP "accept" header on a request to "application/json" the server will render a JSON representation of your View Model.
Consider the following JQuery code:
<script src="https://gist.github.com/783704.js?file=json.js"></script>
That's really all you need to emit JSON back to the client! Imagine how simple it becomes to create rich, interactive, JavaScript heavy webapps when you don't have to duplicate work to return JSON instead of HTML!
For instance, if you did a GET request to a route that rendered the Widget we used previously, it might emit something like this:
<script src="https://gist.github.com/783710.js?file=widget.json"></script>
It should be noted that JSON rendering only works well for Scala <i>case classes</i>
<h4><a name="layouts">Layouts</a></h4>
<h5><a name="layoutbasics">Basics</a></h5>
If we consider the simplest case which we showed in the <a href="#setup">Application Setup</a> section, setting up a layout is as simple as it is shown in the Application Setup section. If you create a default layout with name "default", using mustache, it will be in the classpath location of <i>/layouts/default.mustache</i>. So we may have the following layout:
<script src="https://gist.github.com/783719.js?file=defaultlayout.html"></script>
The {{&doLayout}} is the place where your Resource View will go when rendered. Also "doLayout" is the default name given to the place for the Resource View, <b>unless</b> you specify a custom <a href="http://bowler.s3.amazonaws.com/api/org/bowlerframework/view/scalate/LayoutModel.html">LayoutModel</a>, in which case it becomes the LayoutModel implementors responsibility to add the resource view to the template.
<h5><a name="layoutmodels">Layout Models</a></h5>
A Layout may not just be as simple as some static HTML, you may want to define your own <a href="http://bowler.s3.amazonaws.com/api/org/bowlerframework/view/scalate/LayoutModel.html">LayoutModels</a> that look up some data that you want for your layout, for instance related articles if your resource view is displaying an article of some sort.<br/>
To do this, simply implement the LayoutModel trait, which takes the Request, View Model as a Map (in case you want to introspect this) and the rendered Resource View as a String (so you can place it in the Layout). From this, you should produce a Map that holds all the values that you want to use as models for the Layout Scalate Template.<br/>
LayoutModels are slightly closer to Scalate in terms of how the Model is given, but this is because we no longer have to strictly adhere to the Resource View/Layout split, as we are only dealing with the Layout concern.
<h5><a name="nestedlayouts">Nested Layouts</a></h5>
You can also have levels of Layouts nested, for instance, you might want to have an "articleLayout" with links to related articles to wrap around an article resource view, which in turn is wrapped by a "section" layout and finally by the generic layout.<br/>
Consider the following code that should go into the application bootstrap class to see how you may wrap layers of layouts:
<script src="https://gist.github.com/783727.js?file=parentlayout.scala"></script>
As you can see, the composableLayout has a parent layout of "parentLayout".
The Bowler framework will take care of any traversal upwards to render your whole hierarchy of layouts.<br/>
Finally, if you want slightly different layouts for different routes, you can define these by chaining <a href="http://bowler.s3.amazonaws.com/api/org/bowlerframework/view/scalate/selectors/LayoutSelector.html">LayoutSelectors</a> you add in the <i>TemplateRegistry.appendLayoutSelectors</i> in order of evaluation (the layout that is first returned rather than "None" is the one that will be used).
<h5><a name="layoutcomposition">Layout Composition</a></h5>
What if I want to include more than the child Layout or Resource View in my Layout based on templates? Simple! You can do this in several ways with the help of LayoutModels as we have discussed, for instance you might take direct control of Scalate to add a "tabsPanel" to some Layout, just as in the code below:
<script src="https://gist.github.com/783739.js?file=advancedlayoutmodel.scala"></script>
<h5><a name="components">"Wicket-like" Component Oriented Templating with Squery</a></h5>One of the biggest additions from Bowler 0.3 and onwards is the addition of <a href="http://scalate.fusesource.org/documentation/scuery.html">Squery templating</a>, which gives a very Apache Wicket-like Component-oriented style of templating.<br/>
Out of necessity due to the differences, Squery templating differs slightly from the standard Scalate templating style.
Squery Components in Bowlerhave the following characteristics:
<ul>
<li>They consist of two artifacts: a class that extends either MarkupContainer or Component, and html,xhtml or xml markup that must have the same fully qualified name/path as its Component class, for instance the Component <i>com.myco.MyComponent</i> must have markup on the classpath at <i>/com/myco/MyComponent.html</i></li>
<li>MarkupContainer is for components that do not need to do any transformations, Component is for components that need to do programmatic transformations to the markup. Choose which to extend accordingly.</li>
<li>Squery components can be extended and composed in a fully OO fashion</li>
<li>Components can inherit markup, for instance if MyComponent has markup, and YourComponent does not, but extends MyComponent, it will automatically use the markup of MyComponent as its markup</li>
<li>If you choose to render a Component straight from a Renderable, you will have to use <i>"renderWith"</i>, and no layout will be resolved automatically (it is the responsibility of the developer to provide the full page including layout when using Squery for the full page render).</li>
<li>Components follow the same markup localisation rules as other Bowler templates/layouts</li>
</ul>
Let's look at Squery rendering in action, to render a Squery based page, we simply use the Renderable.renderWith function instead of render:
<script src="https://gist.github.com/900602.js?file=renderSquery.scala"></script>
In this case, if the "accept" Content-Type from the client is not one for which we should render HTML, Bowler will still resolve the correct way to render, for instance application/json instead of html.<br/>
For brevity, we have omitted the markup for SqueryWidgetPage, but in this instance it provides the layout for the page, whereas the view Component will be provided as a constructor argument and will be inserted with a css-selector at the element with a class of "tabs-container" (we call "render" on the child Component for it to render itself):
<script src="https://gist.github.com/900607.js?file=SqueryWidgetPage.scala"></script>
The NewWidgetForm that we passed in as an argument to SqueryWidgetPage has the following markup:
<script src="https://gist.github.com/900611.js?file=widgetform.html"></script>
NewWidgetForm has the following code making up the Component:
<script src="https://gist.github.com/900614.js?file=NewWidgetForm.scala"></script>
As you can see, NewWidgetForm does a number of things:
<ul>
<li>It adds a ValidationFeedbackPanel to display validation errors, if there are any</li>
<li>It checks in the session whether there is a Widget model that has previously failed validation available that should be rendered instead if a new Widget to be created. This is to not lose state after a submit IF a form fails validation.</li>
<li>Bind the Widget models values to the appropriate form fields using css-selectors provided by Squery (valueOrEmpty is a function of Component that "html:ifies" your model properties)</li>
</ul>
This is a very brief walk-through of how Squery can work for you that barely scratches the surface, but as you can see it gives you a lot of ways of inheriting, composing and otherwise building flexible, Component oriented UI's in Bowler.<br/>
Furthermore, if you still prefer using "standard" Scalate templates as described in the rest of the View section, there is nothing stopping you from using Squery Components inside of your SSP, Jade or Scaml templates by importing them, so you can combine the best of both worlds!
<h3><a name="model">The Model: POST, PUT, GET, DELETE - Handling Requests</a></h3>
<h4><a name="parametermapping">Parameter Mapping: Mapping Requests to Beans/instances</a></h4>
How hard is it to map from a raw Request into an arbitrary bean or other object in Bowler? Not very:
<script src="https://gist.github.com/783768.js?file=post.scala"></script>
All you need to do is have your controller (or other class taking a request) extend the <a href="http://bowler.s3.amazonaws.com/api/org/bowlerframework/model/ParameterMapper.html">ParameterMapper</a> trait, pass the generic type you want to transform into, and voila! You have your bean strongly typed.<br/>
It's also worth noting that the <i>mapRequest</i>-function can take more than one generic type, thus mapping more beans/parameters from a single request. However, mapping more than one parameter from a single Request can involve potential conflicts, so there are two ways to resolve these:
<ul>
<li>Provide the mapRequest function with a "nameHint" Stirng or List of "nameHints" Strings to hint to the mapRequest the names of the relevant parameters in the order they are defined. For obvious reasons this works best with simpler types that only require a single request parameter to be mapped.</li>
<li>Prefix the parameters/form-field names form the calling location with the alias-name of the type, for instance the "id" for a Widget may have a form input name of "widget.id". This is the recommended approach when dealing with multiple more complex objects that need several parameters to be properly mapped.</li>
</ul>
<h5><a name="formvjson">What about Form Encoded vs. JSON requests?</a></h5>
How does the ParameterMapper know whether to map from reqular HTTP Form parameters, or from the JSON contents if someone potentially POST:ed/PUT a JSON object in the request? By default, again, Bowler takes care of this: if the client has sent the HTTP Header <i>"Content-Type"</i> with a value of <i>"application/json"</i>, the ParameterMapper will check for the presence of a JSON object in the request on PUT and POST requests. If the header is not set, all will go on as usual, assuming parameters are mapped as if it was a form that was submitted or parameters passed in a URL.<br/>
Incidentally, this actually helps dealing with some fragility that sometimes happens with JSON REST API's, where API users are confused whether to POST form data or POST a JSON object: Bowler simply doesn't care and will happily deal with both transparently.
<h5><a name="optionalparameters">Optional Parameters</a></h5>
Passing null is a bad thing, as it can cause NullPointerExceptions further down, making errors harder to track down. To deal with this, Bowler simply prohibits the ParameterMapper from mapping requests to null when parameters cannot be properly mapped, and will throw an Exception at the point of mapping.
To deal with this case, and in the case of parameters that may occur but are not mandatory, ie optional parameters, you should simply use the Scala Option-construct:
<script src="https://gist.github.com/783786.js?file=OptionMapper.scala"></script>
<h5><a name="valuetransformers">Lookup Complex Objects by Id: StringValueTransformers</a></h5>
You might wonder how Bowler does the magic and looks up eventually pre-existing objects by id, maps to dates, decimals, integers, longs etc.<br/>
There is a two step approach to this:<br/>
<ul>
<li>You should implement a <i>StringValueTransformer</i> for <b>each</b> object type that you want to map to from Requests</li>
<li>You must register said StringValueTransformer with a <i>TransformerRegistry</i> in the bootstrap-class</li>
</ul>
Here's an example of a typical StringValueTransformer:
<script src="https://gist.github.com/783798.js?file=WidgetTransformer.scala"></script>
As you can see, the contract is simple: if an object can be mapped, return it wrapped in a Some(), if it cannot be mapped, or an error occurs that is related to mapping, return "None".<br/>
To enable the transformer and register it with the app, add something similar to the following into your application bootstrap class:
<script src="https://gist.github.com/783800.js?file=TransformerRegistry.scala"></script>
<h5><a name="putpostvsgetdelete">Creating & Editing instances: PUT & POST vs. GET & DELETE</a></h5>
It is important to distinguish between the behavior of PUT & POST vs. GET & DELETE with the ParameterMapper:<br/>
PUT and POST requests can create new objects without a hit in a StringValueTransformer, as you'd expect, because a type persisted in a database has obviously cannot be looked up by id if it is just about to be created. <br/>
PUT and POST allows creation of new objects even though a StringValueTransformer is unable to look it up. PUT and POST are also allowed to change the values of properties of a more complex object.<br/>
GET and DELETE however are NOT allowed to create new objects nor mutate the properties of more complex objects. They are only allowed to be looked up based on registered transformers. The reason for this is simple: it is in accordance and in keeping with RESTful principles: only PUT and POST are allowed to change existing objects or create new ones. GET and DELETE are for retrieving a resource or deleting it. Of course you could circumvent this by explicitly changing values after mapping in your own code, but in most cases this would likely be a very bad idea.
<h4><a name="validation">Validation</a></h4>
For validation, we need to extend the Validations trait and use the validate(){} block as seen below:
<script src="https://gist.github.com/783814.js?file=Validation.scala"></script>
..now you can see we're starting to put everything together:
<ul>
<li>We map a request into a Widget</li>
<li>Validate the Widget</li>
<li>Create the Widget, then render it</li>
</ul>
The validate-block used in the example below has a simple contract: return a <i>Option[List[Tuple2[String, String]]]</i>, whereby:
<ul>
<li>None means there are no validation errors.</li>
<li>Some containing a non-empty List[Tuple2[String, String]] means there where validation errors</li>
<ul>
<li>The first String in the Tuple is the property key, like "id", "name" or the like</li>
<li>The second String in the Tuple is the actual error message to be displayed back</li>
</ul>
</ul>
The validation handling doesn't really care what validation framework you use as long as you follow the contract, you could write manual validation code if you wanted to, however, you probably don't want to, which is why Bowler has a sensible default validation framework:
<h5><a name="customvalidations">Validators & Creating Custom Validators</a></h5>
As <a href="https://github.com/wfaler/recursivity-commons">Recursivity Commons</a> (same author as Bowler) is a dependency of Bowler and contains a simple validation support, this can be used with Bowler with ease. Consider the following code:
<script src="https://gist.github.com/783825.js?file=validator.scala"></script>
The <a href="http://bowler.s3.amazonaws.com/api/org/bowlerframework/model/DefaultModelValidator.html">DefaultModelValidator</a> is a convenience class for adding all the validations that belong together for a single validation context. You may add any number of <a href="https://github.com/wfaler/recursivity-commons/tree/master/src/main/scala/com/recursivity/commons/validator">Recursivity Validators</a> to a DefaultModelValidator, or extend the class.<br/>
If you want to implement your own validators, it is as simple as implementing the com.recursivity.commons.validator.Validator interface:
<script src="https://gist.github.com/783831.js?file=validator2.scala"></script>
The custom validator above simply takes a function/closure that returns a Long as a constructor argument, then uses the function to get a Long, which is used to check if a Widget already exists or not.<br/>
The getKey and getReplaceModel functions have to do with validation messages, which we will get to in a second (normally you'd probably want to set the key returned from the constructor rather than hard-code it).
<h5><a name="validationmessages">Validation Messages & Localisation</a></h5>
If you look at the previous WidgetValidator example above, you can see that the DefaultModelValidator takes a classOf "WidgetValidator" as an argument. What this tells the DefaultModelValidator is the context/location of the properties file where validation error messages can be resolved. For instance:<br/>
If WidgetValidator is org.bowlerframework.examples.WidgetValidator we would need a properties file on the classpath at /org/bowlerframework/examples/WidgetValidator.properties that contains validation messages.<br/>
A typical Validation error message properties file might look as follows for the WidgetValidator example:
<script src="https://gist.github.com/783838.js?file=WidgetValidator.properties"></script>
The rules for validator properties files are quite simple:
<ul>
<li>A message for a validator will be keyed by the class-name of the validator, less package</li>
<li>The "key" in the validator is used to look up the property name, such as "yearMade" becoming "Year Made" in the final error message</li>
<li>The "replaceModel" defined in the validator is used to replace values such as the "{min}" and "{max}" for the number validators to give more information on the exact validation constraints</li>
</ul>
Finally a word on localisation: the validation message properties files support validation, if you create a file called WidgetValidator_se.properties, this will be the preferred source of messages for any client that has a locale set to Swedish.
<h5><a name="defaultvalidation">Default Validators for Models</a></h5>
If you don't want to duplicate validation code for models that you know will always have approximately the same validation, you can add and register default <a href="http://bowler.s3.amazonaws.com/api/org/bowlerframework/model/ModelValidatorBuilder.html">ModelValidatorBuilders</a> for a model type:
<script src="https://gist.github.com/841272.js?file=ModelValidatorBuilder_sample.scala"></script>
A ModelValidatorBuilder is a class that you define, that has an <i>initialize</i> function, which takes a model of the type you define, and returns a <a href="http://bowler.s3.amazonaws.com/api/org/bowlerframework/model/ModelValidator.html">ModelValidator</a>. A ModelValidator in turn is grouping of Validators with a validate-function, which will run all validators. A ModelValidator can also have Validators added to it, which is the purpose of the ModelValidatorBuilders initialize function - to add all the validators to the current model under validation:
<script src="https://gist.github.com/841279.js?file=CarValidatorBuilder.scala"></script>
If you then want to access your ModelValidator, you can either just instantiate a ModelValidatorBuilder directly and call initialize, or you can use the apply function of the ModelValidatorBuilder companion object to retrieve the appropriate ModelValidatorBuilder (if there is one):
<script src="https://gist.github.com/841293.js?file=ModelValidatorBuilderApply.scala"></script>
Now, just validate away to your hearts content!
<h5><a name="jsonvalidation">Validation Errors and JSON</a></h5>
For JSON Validation errors the default behavior of the Bowler <a href="http://bowler.s3.amazonaws.com/api/org/bowlerframework/view/JsonViewRenderer.html">JsonViewRenderer</a> is to throw an HTTP 400 error, together with a <a href="http://bowler.s3.amazonaws.com/api/org/bowlerframework/exception/ValidationException.html">ValidationException</a>.<br/>
If you want to render something more meaningful for the HttpExceptions than the servers default error messages, you should override your Servlet Containers default behavior for dealing with Exceptions. If you are using Jetty the way to do this is <a href="http://docs.codehaus.org/display/JETTY/How+to+Create+Custom+Error+Pages">implementing a Custom error handler class and making the appropriate reference in your web.xml</a>, you can then retrieve the validation messages from the ValidationException and render the appropriate JSON response together with the HTTP 400 error.
<h4><a name="forms">Forms</a></h4>
When editing or creating new, it's recommended that you pass object you are editing, or wanting to create into the render function (as an empty object as below if necessary):
<script src="https://gist.github.com/783846.js?file=newwidget.scala"></script>
If you combine the above with the following template given the Widget case class Widget(id: Long, name: String, priceInPence: Int):
<script src="https://gist.github.com/783844.js?file=new.mustache"></script>
It's pretty straightforward, but we can note a few things:
<ul>
<li><i>validationErrors</i>: This template block is used to render any validation errors that may occur after submission if validation fails. This would be empty to begin with. However, this is only for demo purposes, for the same effect, there is a cleaner way of displaying validation errors as explained in <a href="#validationerrorscomponent">in the next sub-section</a></li>
<li>We have given the form fields the "alias hint", by prefixing the input names with "widget", though not necessary in this case, it makes life easier for the mapper if we had more objects to map than just the widget</li>
<li>Even though we know the widget bean is initially empty, we still set the values of the fields to the properties of the widget. This is so that we can retain form-state if validation was to fail on posting the form.</li>
</ul>
If there are object relationships to deal with in a form, you could obviously deal with this with the use of StringValueTransformers as described in the section <a href="#valuetransformers">Lookup Complex Objects by Id: StringValueTransformers</a>.
<br/><br/><b>Important!</b> Even if you create new objects that have synthetic keys, such as incrementing numbers, having an id as a hidden field in your form, assigned to something like "0" will save you a lot of pain when the ParameterMapper tries to map a value to your id field. Most ORM's/persistence frameworks will assign a new value on insert anyway.
<h5><a name="validationerrorscomponent">Displaying Validation Errors in Forms</a></h5>
Rather than writing your own markup for displaying validation errors, you can also use the Bowler pre-existing <i>ValidationFeedbackPanel</i> component, simply add the correct import and call as below in the appropriate places in your template to get an un-ordered html list of validation error messages. If there are no error messages, nothing at all will be displayed:
<script src="https://gist.github.com/900578.js?file=validationerrors.scala"></script>
<h3><a name="requestcycle">The Request Cycle</a></h3>
<h4><a name="interceptingrequests">Intercepting Requests (example: transactionality)</a></h4>
Intercepting requests in a catch-all function can be a useful thing for many types of scenarios, for instance transaction-management with persistence, or cleaning up other resources to avoid having developers call ".close()" functions all over the code. This is catered for in Bowler quite easily by extending the InterceptingController trait. The example below shows an example of transaction- and connection management in the InterceptingController "around"-function as used by the Bowler Squeryl mapper module:
<script src="https://gist.github.com/828574.js?file=intercepting.scala"></script>
The "controller"-function received as an argument in this case is simply the actual function/closure you defined as your request-handler in a get(..), post(..), put(..) or delete(..) block. To proceed to your normal request processing it needs to be called in your around-function.
<h4><a name="nestedinterception">Nested Interception(example: transactionality + authentication/authorization)</a></h4>
But what if I want to add something in a sub-class to the above example that needs to run <i>inside</i> the transaction, but around the controller-function?
Easy, just override "around", define an anonymous function with the correct signature ((Request, Request) => Unit ) and call the controller-function from within it as in the example below:
<script src="https://gist.github.com/828581.js?file=extendedaround.scala"></script>
This example shows how to easily add authentication that would run inside the transactional block, but before and after the actual request-handling, this giving you control whether for instance you actually want to run the default request handling, or perhaps re-direct to something like a login page if it is a authentication/authorization use case.
<h3><a name="persistence">Persistence Integration</a></h3>
Bowler has a flexible persistence integration framework available in add-on modules/sbt/maven dependencies. In most cases adding a new persistence integration is as simple as implementing the <a href="https://github.com/wfaler/Bowler/blob/master/persistence-mapper/src/main/scala/org/bowlerframework/persistence/Dao.scala">Bowler Dao</a>-trait and extending the <a href="http://bowler.s3.amazonaws.com/api/org/bowlerframework/controller/InterceptingController.html">InterceptingController</a>-trait to do transaction management. The Bowler persistence integration in most cases uses a "Open Session in View" style pattern, which simply opens a connection and transaction on the beginning of a request, and closes and commits it at the end (or does a rollback in an Exception). The example below shows the InterceptingController integration for <a href="http://squeryl.org/">Squeryl</a>:
<script src="https://gist.github.com/841349.js?file=SquerylController.scala"></script>
As you can see, it's pretty straightforward. If you want to add additional things, like authentication, authorization or other checks around a request, but inside a transaction, you can just follow the pattern that we described in the <a href="#interceptingrequests">Intercepting Requests</a> section.<br/>
Finally, it is worth noting though that the Bowler Persistent Mapper framework does not assume a relational database - in theory any persistent store should work!
<h4><a name="squeryl">Squeryl</a></h4>
<a href="http://squeryl.org/">Squeryl</a> is an excellent Scala based ORM/persistence framework which gives you a number of benefits over Java persistence frameworks like Hibernate and JPA. I quite like it. To set up a project with the Squeryl module, add the dependencies described in the <a href="#squerylbuild">Squeryl Build</a> to your project.<br/>
Once you have done so, you need to set-up your datasource, you can do this programmatically in your Bootstrap if you want, below is an example with C3P0 connection pooling:
<script src="https://gist.github.com/841361.js?file=squerylpooling.scala"></script>
Once you have done this setup, in most cases you can just extend the <a href="https://github.com/wfaler/Bowler/blob/master/squeryl-mapper/src/main/scala/org/bowlerframework/squeryl/SquerylController.scala">org.bowlerframework.squeryl.SquerylController</a> trait!<br/>
You may also want to use some of the generic Squeryl DAO's for simple CRUD like functionality, or with some of the <a href="persistencehelpers">Persistence Helpers described later</a>.
The Squeryl module has an abstract <a href="https://github.com/wfaler/Bowler/blob/master/squeryl-mapper/src/main/scala/org/bowlerframework/squeryl/SquerylDao.scala">SquerylDao</a>, which in turn can be extended, and is extended by:
<ul>
<li><a href="https://github.com/wfaler/Bowler/blob/master/squeryl-mapper/src/main/scala/org/bowlerframework/squeryl/dao/LongKeyedDao.scala">org.bowlerframework.squeryl.dao.LongKeyedDao</a> - for entities with a Long identifier</li>
<li><a href="https://github.com/wfaler/Bowler/blob/master/squeryl-mapper/src/main/scala/org/bowlerframework/squeryl/dao/StringKeyedDao.scala">org.bowlerframework.squeryl.dao.StringKeyedDao</a> - for entities with a String identifier</li>
<li><a href="https://github.com/wfaler/Bowler/blob/master/squeryl-mapper/src/main/scala/org/bowlerframework/squeryl/dao/IntKeyedDao.scala">org.bowlerframework.squeryl.dao.IntKeyedDao</a> - for entities with a Int identifier</li>
</ul>
For how to use Squeryl specifically in more debt, please refer to the <a href="http://squeryl.org/">Squeryl site</a>.
<h4><a name="jpa">Jpa</a></h4>
The JPA integration module follows exactly the same pattern as the Squeryl integration, in that you simply setup your JPA persistence.xml as you would otherwise, then extend the <a href="https://github.com/wfaler/Bowler/blob/master/jpa-mapper/src/main/scala/org/bowlerframework/jpa/JpaController.scala">JpaController</a> trait in most cases. If/when you want to access a JPA EntityManager anywhere in your code that is running directly or indirectly inside a JpaController, your EntityManagers are just one import away:
<script src="https://gist.github.com/841391.js?file=BowlerJpa.scala"></script>
One thing here is of course that to access EntityManagers without providing a persistence-unit name, you need to set a default name in the <i>com.recursivity.jpa.PersistenceUnit.unitName</i> object variable.<br/>
If you want to use any of the Persistence Helper detailed next, the JPA integration only has one Dao to worry about (but you can extend/override parts of it of course): <a href="https://github.com/wfaler/Bowler/blob/master/jpa-mapper/src/main/scala/org/bowlerframework/jpa/JpaDao.scala">JpaDao</a>
<h4><a name="persistencehelpers">Persistence Helpers</a></h4>
The Persistence Mapper modules have the following generic persistence helpers which are independent of the persistence implementation, such as JPA or Squeryl:
<h5><a name="entitytransformer">EntityTransformer (StringValueTransformer)</a></h5>
As we have previously mentioned, StringValueTransformers are a useful way to ensure you can transform simple request parameters such as id's transparently into more complex objects. This becomes even more important when dealing with persistent objects, and or objects that have persistent objects set on them via id from a dropdown list.<br/>
Below is an example of how to re-use the generic <i>org.bowlerframework.persistence.EntityTransformer</i> to enable lookups of a Car domain model object with the help of Jpa:
<script src="https://gist.github.com/841402.js?file=entitytransformer.scala"></script>
This code would typically go into your bootstrap class, or some other part where the transformer is registered with the TransformerRegistry before it is needed.<br/>
As you can see, the EntityTransformer uses generics, so should be usable for most types of persistent objects provided you have a Dao implementation to provide the transformer.
<h5><a name="uniqueentityvalidator">UniqueEntityValidator</a></h5>
The <a href="https://github.com/wfaler/Bowler/blob/master/persistence-mapper/src/main/scala/org/bowlerframework/persistence/UniqueEntityValidator.scala">org.bowlerframework.persistence.UniqueEntityValidator</a> is a Validator that checks that an Entity is unique in a persistent store - probably useful if you have resources where the user assigns an id!
<h5><a name="crudcontroller">CRUD Controller</a></h5>
The Bowler Persistence Mapper framework also provides a simple <a href="https://github.com/wfaler/Bowler/blob/master/persistence-mapper/src/main/scala/org/bowlerframework/persistence/CrudController.scala">org.bowlerframework.persistence.CrudController</a> if you have simple needs that just consist of, well, Create, Read, Update and Delete. You would typically set it up in the following way in your bootstrap (example with Squeryl):
<script src="https://gist.github.com/841412.js?file=crudcontrollersqueryl.scala"></script>
As you can see, it takes type parameters of the entity type and its key-type. In addition it takes a persistence controller (in this case Squeryl), a Dao implementation and a resource name as arguments. The resourcename "people" will in this case mean that the root of the controller will be at "/people/".<br/>
The reason the CRUD controller takes another Controller as an argument is that it is actually only a proxy for a controller and not a controller itself: The CRUD controller will initialize the provided controller with the correct business logic.<br/>
The CRUD controller does the following things:
<ul>
<li><i>GET /[resource]/</i>: gets the first n elements of type T (n defaults to 10)</li>
<li><i>GET /[resource]/?itemsInList=n</i>: gets the n first elements of type T, changes n default to provided parameter</li>
<li><i>GET /[resource]/page/2</i>: get's second page of paginated list of elements as above</li>
<li><i>GET /[resource]/:id </i>: displays the T with the id provided</li>
<li><i>GET /[resource]/new </i>: should return a create form that POSTs a new T to /</li>
<li><i>GET /[resource]/:id/edit</i> : should return an edit form that POSTs an updated T to /:id</li>
<li><i>DELETE /[resource]/:id </i>: Deletes the T with the provided id</li>
<li><i>POST /[resource]/</i>: Creates a new entity of type T and renders it</li>
<li><i>POST /[resource]/:id</i>: Updates an entity of type T with the provided id and renders it</li>
</ul>
<h3><a name="testing">Testing</a></h3>
Testing can be done both in an "in-vm container" <a href="https://github.com/wfaler/bowler-quickstart/blob/master/src/test/scala/bowlerquickstart/SimpleRequestTest.scala">using ScalatraFunSuite like this</a>, or completely without any dependencies on even a mock container.<br/>
<b>[TESTING SECTION TO BE EXPANDED]</b>
</div>
</div>
<div id="footer">
<p>
<span wicket:id="copyrightNotice">Copyright © Recursivity limited, 2010-
</p>
</div>
</div>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-1376753-12']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</body>
</html>