-
Notifications
You must be signed in to change notification settings - Fork 16
/
chap-advanced.lyx
4920 lines (3586 loc) · 90.5 KB
/
chap-advanced.lyx
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
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#LyX 1.6.10 created this file. For more info see http://www.lyx.org/
\lyxformat 345
\begin_document
\begin_header
\textclass book
\use_default_options false
\language english
\inputencoding auto
\font_roman default
\font_sans default
\font_typewriter default
\font_default_family default
\font_sc false
\font_osf false
\font_sf_scale 100
\font_tt_scale 100
\graphics default
\paperfontsize default
\spacing single
\use_hyperref false
\papersize default
\use_geometry false
\use_amsmath 1
\use_esint 1
\cite_engine basic
\use_bibtopic false
\paperorientation portrait
\secnumdepth 3
\tocdepth 3
\paragraph_separation indent
\defskip medskip
\quotes_language english
\papercolumns 1
\papersides 1
\paperpagestyle default
\tracking_changes false
\output_changes false
\author ""
\author ""
\end_header
\begin_body
\begin_layout Chapter
Advanced Lift Architecture
\begin_inset CommandInset label
LatexCommand label
name "cha:Advanced-Lift-Guts"
\end_inset
\end_layout
\begin_layout Standard
\begin_inset Box Framed
position "t"
hor_pos "c"
has_inner_box 0
inner_pos "t"
use_parbox 0
width "100col%"
special "none"
height "1in"
height_special "totalheight"
status open
\begin_layout Plain Layout
This chapter is still under active development.
The contents will change.
\end_layout
\end_inset
\end_layout
\begin_layout Standard
Congratulations! You've either made it through the introduction to Lift,
or maybe you've just skipped Basics and jumped right to here to Advanced;
either way, the next group of chapters will be exciting.
\end_layout
\begin_layout Standard
In this chapter we're going to dive into some of the advanced guts of Lift
so that you have a thorough understanding of what's going on before we
explore further.
\end_layout
\begin_layout Section
Architectural Overview
\end_layout
\begin_layout Standard
Before we jump into the specific details of the architecture, let's refresh
our memories.
Figure
\begin_inset CommandInset ref
LatexCommand ref
reference "fig:Architecture-diagram"
\end_inset
highlights the main Lift components and where they live in the ecosystem.
Scala compiles down to Java bytecode, so we sit on top of the JVM.
Lift Applications are typically run in a J(2)EE web container, such as
Jetty or Tomcat.
As we explained in section
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:Entry-into-Lift"
\end_inset
, Lift is set up to act as a Filter
\begin_inset Foot
status open
\begin_layout Plain Layout
\begin_inset CommandInset href
LatexCommand href
target "http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/Filter.html"
\end_inset
\end_layout
\end_inset
that acts as the entry point.
Usage of the rest of the framework varies from application to application,
depending on how simple or complex you make it.
\end_layout
\begin_layout Standard
\align center
\begin_inset Float figure
wide false
sideways false
status open
\begin_layout Plain Layout
\begin_inset Caption
\begin_layout Plain Layout
Architecture
\begin_inset CommandInset label
LatexCommand label
name "fig:Architecture-diagram"
\end_inset
\end_layout
\end_inset
\end_layout
\begin_layout Plain Layout
\align center
\begin_inset Graphics
filename images/LiftArchDiagram.pdf
BoundingBox .25in 5.75in 4.85in 10.75in
clip
\end_inset
\end_layout
\end_inset
\end_layout
\begin_layout Standard
The major components outlined in the diagram are:
\end_layout
\begin_layout Description
LiftCore The engine of the framework responsible for request/response lifecycle,
rendering pipeline, invoking user's functions etc.
We don't directly cover the core in this book since essentially all of
the functionality that we do cover sits on top of the core
\end_layout
\begin_layout Description
SiteMap Contains the web pages for a Lift application (chapter
\begin_inset CommandInset ref
LatexCommand ref
reference "cha:SiteMap"
\end_inset
)
\end_layout
\begin_layout Description
LiftRules Allows you to configure Lift.
We cover this in various sections throughout the book
\end_layout
\begin_layout Description
LiftSession The session state representation (section
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:Session-Management"
\end_inset
)
\end_layout
\begin_layout Description
S The stateful object impersonating the state context for a given request/respon
se lifecycle (section
\begin_inset CommandInset ref
LatexCommand ref
reference "sub:Advanced-S-Object"
\end_inset
)
\end_layout
\begin_layout Description
SHtml Contains helper functions for XHtml artifacts (chapters
\begin_inset CommandInset ref
LatexCommand ref
reference "cha:Forms-in-Lift"
\end_inset
and
\begin_inset CommandInset ref
LatexCommand ref
reference "cha:AJAX-and-COMET"
\end_inset
)
\end_layout
\begin_layout Description
Views LiftView objects impersonating a view as a XML content.
Thus pages can be composed from other sources not only from html files.
(section
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:Views"
\end_inset
)
\end_layout
\begin_layout Description
LiftResponse Represents the abstraction of a response that will be propagated
to the client.
(section
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:LiftResponse-in-Detail"
\end_inset
)
\end_layout
\begin_layout Description
Comet Represents the Comet Actors layer which allows the sending of asynchronous
content to the browser (section
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:COMET"
\end_inset
)
\end_layout
\begin_layout Description
ORM - Either Mapper or Record - The lightweight ORM library provided by
Lift.
The Mapper framework is the proposed ORM framework for Lift 1.0 and the
Record framework will be out for next releases.
(chapter
\begin_inset CommandInset ref
LatexCommand ref
reference "cha:mapper_and_record"
\end_inset
)
\end_layout
\begin_layout Description
HTTP
\begin_inset space ~
\end_inset
Auth - You can use either Basic or Digest HTTP authentication in your Lift
application.
This provides you more control as opposed to web-container's HTTP authenticatio
n model.
(section
\begin_inset CommandInset ref
LatexCommand ref
reference "sub:HTTP-Authentication"
\end_inset
)
\end_layout
\begin_layout Description
JS
\begin_inset space ~
\end_inset
API The JavaScript abstraction layer.
These are Scala classes/objects that abstract JavaScript artifacts.
Such objects can be combined to build JavaScript code (chapter
\begin_inset CommandInset ref
LatexCommand ref
reference "cha:Lift-and-Javascript"
\end_inset
)
\end_layout
\begin_layout Description
Utils Contains a number of helper functions that Lift uses internally and
are available to your application
\end_layout
\begin_layout Section
The Request/Response Lifecycle
\begin_inset CommandInset label
LatexCommand label
name "sec:Request/Response-Lifecycle"
\end_inset
\end_layout
\begin_layout Standard
We briefly discussed the Request/Response Liftcycle in section
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:The-Rendering-Process"
\end_inset
, and now we're going to cover it in depth.
This will serve not only to familiarize you with the full processing power
of Lift, but also to introduce some of the other advanced topics we'll
be discussing in this and later chapters.
\end_layout
\begin_layout Standard
One important thing we'd like to mention is that most of the configurable
properties are in
\family typewriter
LiftRules
\family default
, and are of type
\family typewriter
RulesSeq
\family default
.
With a
\family typewriter
RulesSeq
\family default
you essentially have a list of functions or values that are applied in
order.
\family typewriter
RulesSeq
\family default
defines a prepend and append method that allows you to add new configuration
items at the beginning or end of the configuration, respectively.
This allows you to prioritize things like partial functions and compose
various methods together to control Lift's behavior.
You can think of a RulesSeq as a Seq on steroids, tweaked for Lift's usage.
\end_layout
\begin_layout Standard
The following list outlines, in order, the process of transforming a Request
into a Response.
We provide references to the sections of the book where we discuss each
step in case you want to branch off.
\end_layout
\begin_layout Enumerate
Execute early functions: this is a mechanism that allows a user function
to be called on the HttpServletRequest before it enters the normal processing
chain.
This can be used for, for example, to set the XHTML output to UTF-8.
This is controlled through
\family typewriter
LiftRules.early
\end_layout
\begin_layout Enumerate
Perform URL Rewriting
\begin_inset Note Note
status open
\begin_layout Plain Layout
This needs split into stateful vs stateless
\end_layout
\end_inset
, which we already covered in detail in section
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:URL-Rewriting"
\end_inset
.
Controlled via
\family typewriter
LiftRules.rewrite
\family default
, this is useful for creating user-friendly URLs, among other things.
The result of the transformation will be checked for possible rewrites
until there are no more matches or it is explicitly stopped by setting
the
\family typewriter
stopRewriting
\family default
val in ReqwriteResponse to
\family typewriter
true
\family default
.
It is relevant to know that you can have rewriter functions per-session
hence you can have different rewriter in different contexts.
These session rewriters are prended to the LiftRules rewriters before their
application.
\end_layout
\begin_layout Enumerate
Call
\family typewriter
LiftRules.onBeginServicing
\family default
hooks.
This is a mechanism that allows you to add your own hook functions that
will be called when Lift is starting to process the request.
You could set up logging here, for instance.
\end_layout
\begin_layout Enumerate
Check for user-defined stateless dispatch in
\family typewriter
LiftRules.statelessDispatchTable
\family default
.
If the partial functions defined in this table match the request then they
are used to create a
\family typewriter
LiftResponse
\family default
that is sent to the user, bypassing any further processing.
These are very useful for building things like REST APIs.
The term stateless refers to the fact that at the time the dispatch function
is called, the stateful object, called
\family typewriter
S
\family default
, is not available and the
\family typewriter
LiftSession
\family default
is not created yet.
Custom dispatch is covered in section
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:Custom-dispatch-func"
\end_inset
\end_layout
\begin_layout Enumerate
Create a
\family typewriter
LiftSession
\family default
.
The
\family typewriter
LiftSession
\family default
holds various bits of state for the request, and is covered in more detail
in section
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:Session-Management"
\end_inset
.
\end_layout
\begin_layout Enumerate
Call
\family typewriter
LiftSession.onSetupSession
\family default
.
This is a mechanism for adding hook functions that will be called when
the LiftSession is created.
We'll get into more details when we discuss Lift's session management in
section
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:Session-Management"
\end_inset
.
\end_layout
\begin_layout Enumerate
Initialize the
\family typewriter
S
\family default
object (section
\begin_inset CommandInset ref
LatexCommand ref
reference "sub:S-object"
\end_inset
).
The
\family typewriter
S
\family default
object represents the current state of the Request and Response.
\end_layout
\begin_layout Enumerate
Call any
\family typewriter
LoanWrapper
\family default
instances that you've added through
\family typewriter
S.addAround
\family default
.
A
\family typewriter
LoanWrapper
\family default
is a way to insert your own processing into the render pipeline, similar
to how Filter works in the Servlet API.
This means that when your
\family typewriter
LoanWrapper
\family default
implementation is called, Lift passes you a function allowing you to chain
the processing of the request.
With this functionality you can execute your own pre- and post-condition
code.
A simple example of this would be if you need to make sure that something
is configured at the start of processing and cleanly shut down when processing
terminates.
LoanWrappers are covered in section
\begin_inset CommandInset ref
LatexCommand ref
reference "sub:Wrapping-Lift's-processing"
\end_inset
\end_layout
\begin_layout Enumerate
Process the stateful request
\end_layout
\begin_deeper
\begin_layout Enumerate
Check the stateful dispatch functions defined in
\family typewriter
LiftRules.dispatch
\family default
.
This is similar to the stateless dispatch in step #4 except that these
functions are executed in the context of a LiftSession and an
\family typewriter
S
\family default
object (section
\begin_inset CommandInset ref
LatexCommand ref
reference "sub:S-object"
\end_inset
).
The first matching partial function is used to generate a
\family typewriter
LiftResponse
\family default
that is returned to the client.
If none of the dispatch functions match then processing continues.
Dispatch functions are covered in section
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:Custom-dispatch-func"
\end_inset
.
This flow is wrapped by LiftSession.onBeginServicing/onEndServicing calls
\end_layout
\begin_layout Enumerate
If this is a
\series bold
Comet
\series default
request, then process it and return the response.
Comet is a method for performing asynchronous updates of the user's page
without a reload.
We cover Comet techniques in chapter
\begin_inset CommandInset ref
LatexCommand ref
reference "cha:AJAX-and-COMET"
\end_inset
\end_layout
\begin_layout Enumerate
If this is an
\series bold
Ajax
\series default
request, execute the user's callback function; the specific function is
mapped via a request parameter (essentially a token).
The result of the callback is returned as the response to the user.
The response can be a JavaScript snippet, an XML construct or virtually
any
\family typewriter
LiftResponse
\family default
.
For an overview of
\family typewriter
LiftResponse
\family default
please see section
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:LiftResponse-in-Detail"
\end_inset
.
This flow is wrapped by LiftSession.onBeginServicing/onEndServicing calls.
\end_layout
\begin_layout Enumerate
If this is a regular HTTP request, then:
\end_layout
\begin_deeper
\begin_layout Enumerate
Call
\family typewriter
LiftSession.onBeginServicing
\family default
hooks.
Mostly
\begin_inset Quotes eld
\end_inset
onBegin
\begin_inset Quotes erd
\end_inset
/
\begin_inset Quotes erd
\end_inset
onEnd
\begin_inset Quotes erd
\end_inset
functions are used for logging.
Note that the
\family typewriter
LiftRules
\family default
object also has
\family typewriter
onBeginServicing
\family default
and
\family typewriter
onEndServicing
\family default
functions but these are
\begin_inset Quotes eld
\end_inset
wrapping
\begin_inset Quotes erd
\end_inset
more Lift processing and not just statefull processing.
\end_layout
\begin_layout Enumerate
Check the user-defined dispatch functions that are set per-session (see
\family typewriter
S.addHighLevelSessionDispatcher
\family default
).
This is similar to
\family typewriter
LiftRules.dispatch
\family default
except that you can have different functions set up for a different session
depending on your application logic.
If there is a function applicable, execute it and return its response.
If there is no per-session dispatch function, process the request by executing
the Scala function that user set up for specific events (such as when clicking
a link, or pressing the submit button, or a function that will be executed
when a form field is set etc.).
Please see SHtml obejct
\begin_inset CommandInset ref
LatexCommand ref
reference "sub:SHtml"
\end_inset
.
\end_layout
\begin_layout Enumerate
Check the SiteMap and Loc functions.
We cover SiteMap extensively in chapter
\begin_inset CommandInset ref
LatexCommand ref
reference "cha:SiteMap"
\end_inset
.
\end_layout
\begin_layout Enumerate
Lookup the template based on the request path.
Lift will locate the templates using various approaches:
\end_layout
\begin_deeper
\begin_layout Enumerate
Check the partial functions defined in
\family typewriter
LiftRules.viewDispatch
\family default
.
If there is a function defined for this path invoke it and return an Either[
\begin_inset Formula $()\Rightarrow Can[NodeSeq]$
\end_inset
,LiftView].
This allows you to either return the function for handling the view directly,
or delegate to a
\family typewriter
LiftView
\family default
subclass.
\family typewriter
LiftView
\family default
is covered in section
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:Views"
\end_inset
\end_layout
\begin_layout Enumerate
If no viewDispatch functions match, then look for the template using the
ServletContext's
\family typewriter
getResourceAsStream
\family default
.
\end_layout
\begin_layout Enumerate
If Lift still can't find any templates, it will attempt to locate a View
class whose name matches the first component of the request path under
the
\family typewriter
view
\family default
folder of any packages defined by
\family typewriter
LiftRules.addToPackages
\family default
method.
If an
\family typewriter
InsecureLiftView
\family default
class is found, it will attempt to invoke a function on the class corresponding
to the second component of the request path.
If a
\family typewriter
LiftView
\family default
class is found, it will invoke the
\family typewriter
dispatch
\family default
method on the second component of the request path.
\end_layout
\end_deeper
\begin_layout Enumerate
Process the templates by executing snippets, combining templates etc.
\end_layout
\begin_deeper
\begin_layout Enumerate
Merge <head> elements, as described in section e
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:Head-Merge"
\end_inset
\end_layout
\begin_layout Enumerate
Update the internal functions map.
Basically this associates the user's Scala functions with tokens that are
passed around in subsequent requests using HTTP query parameters.
We cover this mechanism in detail in section
\begin_inset CommandInset ref
LatexCommand ref
reference "sub:Lift-Function-Mapping"
\end_inset
\end_layout
\begin_layout Enumerate
Clean up notices (see S.error, S.warning, S.notice) since they were already
rendered they are no longer needed.
Notices are covered in section
\begin_inset CommandInset ref
LatexCommand ref
reference "cha:Message-Handling"
\end_inset
.
\end_layout
\begin_layout Enumerate
Call
\family typewriter
LiftRules.convertResponse
\family default
.
Basically this glues together different pieces if information such as the
actual markup, the response headers, cookies, etc into a LiftResponse instance.
\end_layout
\begin_layout Enumerate
Check to see if Lift needs to send HTTP redirect.
For an overview please see
\begin_inset CommandInset ref
LatexCommand ref
reference "sec:HTTP-redirects"
\end_inset
\end_layout
\end_deeper
\begin_layout Enumerate
Call
\family typewriter
LiftSession.onEndServicing
\family default
hooks, the counterparts to
\family typewriter
LiftSession.onBeginServicing
\end_layout
\end_deeper
\begin_layout Enumerate
Call
\family typewriter
LiftRules.performTransform
\family default
.
This is actually configured via the
\family typewriter
LiftRules.responseTransformers
\family default
\family typewriter
RulesSeq
\family default
.
This is a list of functions on
\begin_inset Formula $LiftResponse\Rightarrow LiftResponse$
\end_inset
that allows the user to modify the response before it's sent to the client
\end_layout
\end_deeper
\begin_layout Enumerate
Call
\family typewriter
LiftRules.onEndServicing
\family default
hooks.
These are the stateless end-servicing hooks, called after the S object
context is destroyed.
\end_layout
\begin_layout Enumerate
Call any functions defined in
\family typewriter
LiftRules.beforeSend
\family default
.
This is the last place where you can modify the response before it's sent
to the user
\end_layout
\begin_layout Enumerate
Convert the
\family typewriter
LiftResponse
\family default
to a raw byte stream and send it to client as an HTTP response.
\end_layout
\begin_layout Enumerate
Call any functions defined in
\family typewriter
LiftRules.afterSend
\family default
.
Typically these would be used for cleanup.
\end_layout
\begin_layout Standard
We realize that this is a lot of information to digest in one pass, so as
we continue to cover the specific details of the rendering pipeline you
may want to keep a bookmark here so that you can come back and process
the new information in the greater context of how Lift is working.
\end_layout
\begin_layout Standard
Tyler Weir has created a set of diagrams on the following two pages that
outline Lift's processing at the global level and also for HTTP requests
in particular.
For the visually-oriented these may explain things a bit better.
\begin_inset Newpage clearpage
\end_inset