SlideShare a Scribd company logo
1 of 93
Seaside

                                             Build
                                                    ing
                                               Web
                                        App
                                            licat
                                        VA S ions i
                                                        n
                                              mall
                                                   talk
                                         Vers
                                              ion
                                                   8
© Joachim Tuchel, www.objektfabrik.de
This is not...
This is not...


        A Seaside
         Tutorial
What we‘ll look at
What we‘ll look at

Quick, what is Seaside?
What we‘ll look at

Quick, what is Seaside?
Parallels between Fat client development in
VAST and Seaside Web development
What we‘ll look at

Quick, what is Seaside?
Parallels between Fat client development in
VAST and Seaside Web development
Turning a fat client into a Seaside Web
application
Quick, what is
  Seaside?
Quick, what is
  Seaside?

                A very short
        introduction to the
                Seaside Web
     Application Framework
Overview

Open Source
Started by Avi Bryant in 2001
Currently maintained by Lukas Renggli,
Adrian Lienhardt and others
In productive use since 2002
Available for Squeak,VisualWorks,
Gemstone, Dolphin and soon VA Smalltalk
In Production

DabbleDB (by Avi        Reserve Travel (Hotel
Bryant‘s company)       Booking engine)

CMSBox                  Run Basic
www.cmsbox.ch
                        auctomatic.com
Seaside.st (Homepage
                        whooka.com (outdoor
of Seaside)
                        sports)
In-house applications
                        many more...
Seaside is different

Components vs. html-pages
You never see http requests or responses
(unless you want to)
No templating or mixing code and design
(like jsp‘s)
Share as much as possible
   Components hold application state
Pure Smalltalk

Components defined in Smalltalk
Control Flow in Smalltalk
   No XML configuration, no state machine
   Plain Smalltalk code
Debugging in Smalltalk !
You can read all code and learn from it
Components

Subclasses of WAComponent
Hold state
render themselves: #renderContentOn:
Can have subcomponents (#children)
Reusable (same page and other pages)
Pages are composed of components
Rendering a Component
WAStoreCartView>>renderContentOn: html
   cart hasItems ifFalse: [^ self].
   html div
      id: 'cart';
      with: [
          html small: [ html strong: 'Your cart:' ].
          html table: [
             cart countsAndItems do: [:assoc |
                 self renderRowForCount: assoc key
                     of: assoc value
                     on: html ].
             html tableRow: [ html space].
             html tableRow: [
                html tableData: ''.
                html tableData: ''.
                html tableData: [
                   html strong: cart totalPrice
                   printStringAsCents ] ] ] ]
Rendering a Component
                                     html is the canvas
                                     we‘re painting on

WAStoreCartView>>renderContentOn: html
   cart hasItems ifFalse: [^ self].
   html div
      id: 'cart';
      with: [
          html small: [ html strong: 'Your cart:' ].
          html table: [
             cart countsAndItems do: [:assoc |
                 self renderRowForCount: assoc key
                     of: assoc value
                     on: html ].
             html tableRow: [ html space].
             html tableRow: [
                html tableData: ''.
                html tableData: ''.
                html tableData: [
                   html strong: cart totalPrice
                   printStringAsCents ] ] ] ]
Rendering a Component
WAStoreCartView>>renderContentOn: html
   cart hasItems ifFalse: [^ self].
   html div
      id: 'cart';
      with: [
          html small: [ html strong: 'Your cart:' ].
          html table: [
             cart countsAndItems do: [:assoc |
                 self renderRowForCount: assoc key
                     of: assoc value
                     on: html ].
             html tableRow: [ html space].
             html tableRow: [
                html tableData: ''.
                html tableData: ''.
                html tableData: [
                   html strong: cart totalPrice
                   printStringAsCents ] ] ] ]
Rendering a Component
                              rendering can include
                                 application logic
WAStoreCartView>>renderContentOn: html
   cart hasItems ifFalse: [^ self].
   html div
      id: 'cart';
      with: [
          html small: [ html strong: 'Your cart:' ].
          html table: [
             cart countsAndItems do: [:assoc |
                 self renderRowForCount: assoc key
                     of: assoc value
                     on: html ].
             html tableRow: [ html space].
             html tableRow: [
                html tableData: ''.
                html tableData: ''.
                html tableData: [
                   html strong: cart totalPrice
                   printStringAsCents ] ] ] ]
Rendering a Component
WAStoreCartView>>renderContentOn: html
   cart hasItems ifFalse: [^ self].
   html div
      id: 'cart';
      with: [
          html small: [ html strong: 'Your cart:' ].
          html table: [
             cart countsAndItems do: [:assoc |
                 self renderRowForCount: assoc key
                     of: assoc value
                     on: html ].
             html tableRow: [ html space].
             html tableRow: [
                html tableData: ''.
                html tableData: ''.
                html tableData: [
                   html strong: cart totalPrice
                   printStringAsCents ] ] ] ]
Rendering a Component
                   a DIV tag for
WAStoreCartView>>renderContentOn: html
                   applying CSS
   cart hasItems ifFalse: [^ self].
                    formatting
   html div
      id: 'cart';
      with: [
          html small: [ html strong: 'Your cart:' ].
          html table: [
             cart countsAndItems do: [:assoc |
                 self renderRowForCount: assoc key
                      of: assoc value
                      on: html ].
             html tableRow: [ html space].
             html tableRow: [
                html tableData: ''.
                html tableData: ''.
                html tableData: [
                   html strong: cart totalPrice
                   printStringAsCents ] ] ] ]
Rendering a Component
WAStoreCartView>>renderContentOn: html
   cart hasItems ifFalse: [^ self].
   html div
      id: 'cart';
      with: [
          html small: [ html strong: 'Your cart:' ].
          html table: [
             cart countsAndItems do: [:assoc |
                 self renderRowForCount: assoc key
                     of: assoc value
                     on: html ].
             html tableRow: [ html space].
             html tableRow: [
                html tableData: ''.
                html tableData: ''.
                html tableData: [
                   html strong: cart totalPrice
                   printStringAsCents ] ] ] ]
Rendering a Component
         this is a brush to
WAStoreCartView>>renderContentOn: html
        paint on the canvas
   cart hasItems ifFalse: [^ self].
   html div
      id: 'cart';
      with: [
         html small: [ html strong: 'Your cart:' ].
         html table: [
             cart countsAndItems do: [:assoc |
                self renderRowForCount: assoc key
                    of: assoc value
                    on: html ].
             html tableRow: [ html space].
             html tableRow: [
                html tableData: ''.
                html tableData: ''.
                html tableData: [
                  html strong: cart totalPrice
                  printStringAsCents ] ] ] ]
Rendering a Component
WAStoreCartView>>renderContentOn: html
   cart hasItems ifFalse: [^ self].
   html div
      id: 'cart';
      with: [
          html small: [ html strong: 'Your cart:' ].
          html table: [
             cart countsAndItems do: [:assoc |
                 self renderRowForCount: assoc key
                     of: assoc value
                     on: html ].
             html tableRow: [ html space].
             html tableRow: [
                html tableData: ''.
                html tableData: ''.
                html tableData: [
                   html strong: cart totalPrice
                   printStringAsCents ] ] ] ]
Rendering a Component
WAStoreCartView>>renderContentOn: html
   cart hasItems ifFalse: [^ self].
           with: is always the
   html div call on a brush
          last
      id: and writes xhtml
            'cart';
      with: [
          html small: [ html strong: 'Your cart:' ].
          html table: [
                  cart countsAndItems do: [:assoc |
                        self renderRowForCount: assoc key
                               of: assoc value
                               on: html ].
                  html tableRow: [ html space].
                  html tableRow: [
                        html tableData: ''.
                        html tableData: ''.
                        html tableData: [
                             html strong: cart totalPrice
                             printStringAsCents ] ] ] ]
Rendering a Component
WAStoreCartView>>renderContentOn: html
   cart hasItems ifFalse: [^ self].
   html div
      id: 'cart';
      with: [
          html small: [ html strong: 'Your cart:' ].
          html table: [
             cart countsAndItems do: [:assoc |
                 self renderRowForCount: assoc key
                     of: assoc value
                     on: html ].
             html tableRow: [ html space].
             html tableRow: [
                html tableData: ''.
                html tableData: ''.
                html tableData: [
                   html strong: cart totalPrice
                   printStringAsCents ] ] ] ]
Rendering a Component
WAStoreCartView>>renderContentOn: html
   cart hasItems ifFalse: [^ self].
   html div
      id: 'cart';      blocks for nesting
      with: [         certain brushes/tags
          html small: [ html strong: 'Your cart:' ].
          html table: [
             cart countsAndItems do: [:assoc |
                 self renderRowForCount: assoc key
                     of: assoc value
                     on: html ].
             html tableRow: [ html space].
             html tableRow: [
                html tableData: ''.
                html tableData: ''.
                html tableData: [
                   html strong: cart totalPrice
                   printStringAsCents ] ] ] ]
Rendering a Component
WAStoreCartView>>renderContentOn: html
   cart hasItems ifFalse: [^ self].
   html div
      id: 'cart';
      with: [
          html small: [ html strong: 'Your cart:' ].
          html table: [
             cart countsAndItems do: [:assoc |
                 self renderRowForCount: assoc key
                     of: assoc value
                     on: html ].
             html tableRow: [ html space].
             html tableRow: [
                html tableData: ''.
                html tableData: ''.
                html tableData: [
                   html strong: cart totalPrice
                   printStringAsCents ] ] ] ]
Rendering a Component
WAStoreCartView>>renderContentOn: html
   cart hasItems ifFalse: [^ self].
   html div
      id: 'cart';
      with: [ cart is an inst var
          html small: [ html strong: 'Your cart:' ].
               of the component
          html table: [
             cart countsAndItems do: [:assoc |
                  self renderRowForCount: assoc key
                         of: assoc value
                         on: html ].
             html tableRow: [ html space].
             html tableRow: [
                 html tableData: ''.
                 html tableData: ''.
                 html tableData: [
                      html strong: cart totalPrice
                      printStringAsCents ] ] ] ]
Rendering a Component
WAStoreCartView>>renderContentOn: html
   cart hasItems ifFalse: [^ self].
   html div
      id: 'cart';
      with: [
          html small: [ html strong: 'Your cart:' ].
          html table: [
             cart countsAndItems do: [:assoc |
                 self renderRowForCount: assoc key
                     of: assoc value
                     on: html ].
             html tableRow: [ html space].
             html tableRow: [
                html tableData: ''.
                html tableData: ''.
                html tableData: [
                   html strong: cart totalPrice
                   printStringAsCents ] ] ] ]
Rendering and Callbacks
WAStoreCartView>>renderRowForCount: aNumber of: anItem
on: html
   | countString |
   countString := (aNumber = 1)
       ifTrue: ['']
       ifFalse: ['(', aNumber displayString, ') '].
   html tableRow: [
      html tableData: [
         html anchor callback: [ cart remove: anItem ];
         with: '-'].
      html tableData: countString, anItem title.
      html tableData:
         (aNumber * anItem price) printStringAsCents ]
Rendering and Callbacks
WAStoreCartView>>renderRowForCount: aNumber of: anItem
on: html
   | countString |
   countString := (aNumber = 1)
       ifTrue: ['']
                 the anchor brush
       ifFalse: ['(', aNumber displayString, ') '].
   html tableRow: [ a link
                    draws

      html tableData: [
         html anchor callback: [ cart remove: anItem ];
         with: '-'].
      html tableData: countString, anItem title.
      html tableData:
         (aNumber * anItem price) printStringAsCents ]
Rendering and Callbacks
WAStoreCartView>>renderRowForCount: aNumber of: anItem
on: html
   | countString |
   countString := (aNumber = 1)
       ifTrue: ['']
       ifFalse: ['(', aNumber displayString, ') '].
   html tableRow: [
      html tableData: [
         html anchor callback: [ cart remove: anItem ];
         with: '-'].
      html tableData: countString, anItem title.
      html tableData:
         (aNumber * anItem price) printStringAsCents ]
Rendering and Callbacks
WAStoreCartView>>renderRowForCount: aNumber of: anItem
on: html
   | countString |
   countString := (aNumber = 1)
                                         this block will be
       ifTrue: ['']                    evaluated when user
       ifFalse: ['(', aNumber displayString,the link '].
                                           clicks ')
   html tableRow: [
      html tableData: [
         html anchor callback: [ cart remove: anItem ];
         with: '-'].
      html tableData: countString, anItem title.
      html tableData:
         (aNumber * anItem price) printStringAsCents ]
Rendering and Callbacks
WAStoreCartView>>renderRowForCount: aNumber of: anItem
on: html
   | countString |
   countString := (aNumber = 1)
       ifTrue: ['']
       ifFalse: ['(', aNumber displayString, ') '].
   html tableRow: [
      html tableData: [
         html anchor callback: [ cart remove: anItem ];
         with: '-'].
      html tableData: countString, anItem title.
      html tableData:
         (aNumber * anItem price) printStringAsCents ]
Rendering and Callbacks
                   f!
                 o
WAStoreCartView>>renderRowForCount: aNumber of: anItem


               g tS
on: html



               ns
   | countString |


              ie
   countString := (aNumber = 1)


              su
       ifTrue: ['']


            r
       ifFalse: ['(', aNumber displayString, ') '].



            aq
   html tableRow: [
      html tableData: [


           Pe
         html anchor callback: [ cart remove: anItem ];
         with: '-'].


        oR
      html tableData: countString, anItem title.



       NP
      html tableData:
         (aNumber * anItem price) printStringAsCents ]


          T
         T
       H
Rendering Result - the page
Rendering Result - the page
                           this is the
                         subcomponent
                        we just rendered
Rendering Result - the page
Rendering Result - html
<!DOCTYPE html PUBLIC quot;-//W3C//DTD XHTML 1.0 Strict...>
<html xmlns=...>
...
<div id=quot;cartquot;>
 <small><strong>Your cart:</strong><small>
 <table>
  <tr>
       <td><a href=quot;http://localhost:...quot;>-</a></
       td><td>California Roll</td><td>$2.50</td></tr>
  <tr>
       <td><a href=quot;http://localhost:...quot;>-</a></
       td><td>Akagai</td><td>$3.00</td></tr>
  <tr>&nbsp;</tr>
  <tr>
       <td></td><td></td><td><strong>$5.50</strong></
       td></tr>
 </table>
</div>
CSS for the Design

Components generate valid XHTML only
CSS files for Designing the XHTML output
   separation between code and design
   code is written by developer, css is
   written by web designer
Served from within Image or from external
web sever
Seaside development
 for VA Smalltalkers
Seaside development
   for VA Smalltalkers
       lels
  aral
P
        een
   etw
b
      side
 Sea           ent
         lopm
    eve
  d
   and       ient
          Cl
    Rich        ent
            opm alk
        vel
    de          allt
          A Sm
     in V
Components vs.
    Visual Parts
Both can be composed to complex
components with subcomponents
Controls are event driven
Callbacks to perform Smalltalk methods
Composed Components
                 vs. Subparts
                                                                     Component
                                                                     renderContentOn:
                                                                                                                               renderContentOn: html
                                                                      Your personal todomatic Page
                                                                                                                                  ...
                                                                                                                                  html render: mySubComponent1.
                                                                                                                                  html render: mySubComponent2.
                                                                                                                                  ...
                                                                                                Save   Logoff




                                                                                                            Subcomonent
Subcomponent
                                                                                                            renderContentOn:
renderContentOn:
   Checkbox Array:         Option 1   ! Option 3       ! Option 5
                                                                                                                Your rating:
                        ! Option 2      Option 4

    Multi-select:      Full List                     My Items
                       Item 1
                                                     none                                                       avarage:
                       Item 2
                       Item 3
                       Item 4
                                                                                                                Favourite:
 City, State, Postal                                                                                                              - Select One -
                          City                              Postal
                                                   State
              Code:
Composed Components
                 vs. Subparts                                                                                                                            don‘t call
                                                                                                                                                   renderContentOn: of
                                                                                                                                                    child components!
                                                                                                                                                     Seaside calls it!

                                                                     Component
                                                                     renderContentOn:
                                                                                                                               renderContentOn: html
                                                                      Your personal todomatic Page
                                                                                                                                  ...
                                                                                                                                  html render: mySubComponent1.
                                                                                                                                  html render: mySubComponent2.
                                                                                                                                  ...
                                                                                                Save   Logoff




                                                                                                            Subcomonent
Subcomponent
                                                                                                            renderContentOn:
renderContentOn:
   Checkbox Array:         Option 1   ! Option 3       ! Option 5
                                                                                                                Your rating:
                        ! Option 2      Option 4

    Multi-select:      Full List                     My Items
                       Item 1
                                                     none                                                       avarage:
                       Item 2
                       Item 3
                       Item 4
                                                                                                                Favourite:
 City, State, Postal                                                                                                              - Select One -
                          City                              Postal
                                                   State
              Code:
Event-to-Action
             connections

abtBuildInternals
...
refreshButton
    abtWhenPrimitive: #clicked
    perform: (
       conn22 :=
           AbtEventToActionConnection new
               source: refreshButton;
               eventName: #clicked;
               actionProvider: applicationModel
                  variableFeatureName: #refreshTrafficMessages
                  featureSelector: #IS_refreshTrafficMessages).
Action and Value
             Callbacks
renderContentOn: html
  ...
  html submitButton
    callback: [self applicationModel refreshTrafficMessages];
    with: ‘Refresh‘.

  ...
  html label: ‘Please enter a name:‘.
  html textInput
      callback: [:txt| self name: txt];
      value: self name.
  “or in short form“
  html textInput on: #name of: self.
Differences
Feedback cycle:
 Fat client: instant feedback
 Web: On Submit (AJAX / Scriptaculous for
 immediate feedback)
Seaside has no GUI painter out of the box
 projects going on
 useful in HTML/CSS ?
Control Flow
Tasks


Subclasses of WATask
Control flow
single method #go
Can call Tasks and Components
Call and Answer

Components and Tasks can #call: and
#answer:
Caller gets replaced by callee / delegate
Control is delegated to callee
#answer:returns a result to caller and
returns control to caller
Call and Answer (2)

        Component 1
handleSomeCallbackWith: param
 ...
                                                 Component 2
 result := self call:
         ((Component2 new)
                                      renderContentOn: html
         someInstVar: param;
                                      html form: [
         yourself).
                                             html text: someInstVar
 result ifTrue: [self saveData]
                                             printString.
        ifFalse: [self discardAll].
                                             html submitButton
                                                 callback: [self answer: true]
                                                 text: ‚Okay, save this‘].
Call and Answer (2)
                                             Component 2 gets
                                      rendered in place of Component
        Component 1                    1 and takes control of request/
                                           response processing

handleSomeCallbackWith: param
 ...
                                                    Component 2
 result := self call:
         ((Component2 new)
                                        renderContentOn: html
         someInstVar: param;
                                        html form: [
         yourself).
                                               html text: someInstVar
 result ifTrue: [self saveData]
                                               printString.
        ifFalse: [self discardAll].
                                               html submitButton
                                                   callback: [self answer: true]
                                                   text: ‚Okay, save this‘].
Call and Answer (2)
                                                    Component 2 gets
                                             rendered in place of Component
        Component 1                           1 and takes control of request/
                                                  response processing

handleSomeCallbackWith: param
 ...
                                                           Component 2
 result := self call:
         ((Component2 new)
                                               renderContentOn: html
         someInstVar: param;
                                               html form: [
         yourself).
                                                      html text: someInstVar
 result ifTrue: [self saveData]
                                                      printString.
        ifFalse: [self discardAll].
                                                      html submitButton
                                                          callback: [self answer: true]
                                                          text: ‚Okay, save this‘].
                 Component 1 gets back
              control as soon as Comp.2
             was submitted and can use the
                  answer to continue
A typical Fat Client
  in VA Smalltalk
A typical Fat Client
  in VA Smalltalk
                      typically your
 Workflow Controller
                       framework
A typical Fat Client
        in VA Smalltalk
                               typically your
          Workflow Controller
                                framework

   View
Controller(s)                     typically
                               a visual part /
                               Composition
                                   Editor
A typical Fat Client
        in VA Smalltalk
                                 typically your
          Workflow Controller
                                  framework

   View             View
Controller(s)    Controller(s)      typically
                                 a visual part /
                                 Composition
                                     Editor
A typical Fat Client
        in VA Smalltalk
                                       typically your
          Workflow Controller
                                        framework

   View             View         ...
Controller(s)    Controller(s)            typically
                                       a visual part /
                                       Composition
                                           Editor
A typical Seaside
  Application
A typical Seaside
  Application
                     call:
   WATask           answer:
A typical Seaside
        Application
                           call:
            WATask        answer:

                         rendering
Component             request handling
                        call/answer


                       rendered by
                       Web browser
A typical Seaside
        Application
                             call:
            WATask          answer:

                             rendering
Component     Component   request handling
                            call/answer


                           rendered by
                           Web browser
A typical Seaside
        Application
                                   call:
            WATask                answer:

                                   rendering
                          ...
Component     Component         request handling
                                  call/answer


                                 rendered by
                                 Web browser
ga
               tin          ion
            ri           at
          W          lic          ga
                   p
               Ap            itin
          ide like wr
       as
   Se                           ion
                h          cat
            uc           li
         m          pp
      ry
   ve            IA
is          GU
         al
     od
   M
Seaside and
Rich Internet Applications
Ajax

Most popular RIA technology
Combination of
   Server Side-Application Code
   JavaScript in the Browser
   XML HTTP Request as transport protocol for
   portions of a page
JavaScript Libraries

Numerous available
Most Popular (and one of the most mature /
complete)
    Prototype
    Script.aculo.us
Full access to CSS styles, DOM objects
XmlHttpRequest
Browser-neutral
Seaside and Scriptaculous

Seaside wrappers Prototype / Scriptaculous
Developer writes Smalltalk code
JavaScript ‚rendered‘ in Smalltalk
JavaScript is embedded in HTML Page
html updater
      id: ‚myelement‘
      callback: [:html| self
      renderNewStuffOn: html].
Demo
From Fat Client to
Seaside Application

            What you have to
                  look at
            and change in an
           existing application
From Fat Client to
 Seaside Application
Persistency

               What you have to
                     look at
               and change in an
              existing application
From Fat Client to
 Seaside Application
Persistency
Back-end access
                   What you have to
                         look at
                   and change in an
                  existing application
From Fat Client to
 Seaside Application
Persistency
Back-end access
                   What you have to
                         look at
GUI Interaction
                   and change in an
                  existing application
From Fat Client to
 Seaside Application
Persistency
Back-end access
                   What you have to
                         look at
GUI Interaction
                   and change in an
                  existing application
Miscellaneous
Comparing the two
  architectures
                                                                       Database
               Database
                                          fat
                                        client

                          Persistency
 Persistency                                                                              server
                                                                      Persistency
                       Business logic
Business logic Persistency
                                                                     Business logic
                        Presentation
Presentation Business logic
                                                                     Presentation
               Presentation

                                                                                                   browser



                                                      Presentation                    Presentation

                                                                      Presentation




                                                 34
Changing the
          Architecture
Easier when layers are clearly structured
MVC Pattern
Business logic should be fully reusable

   Persistency                   Persistency
  Business logic                Business logic
                   Transition

                                                 Controller
   Presentation                 Presentation



                                Presentation     View


                          35
Persistency
                            on a Fat Client
                                                                                1 or only a few
                       ID   lastname        firstname
                       1    Henderson       Joe

                                                                                active transactions
                       2    Levinson        Mark
                       3    McLachlan       Sarah


                                                                                per client
                                 Database


                                                                                Each client holds
                                                                                its own copy
                                                            1

                                                                                Concurrency &
                                                           Joe
    1                                                   Henderson
   Joe

                                                                                Isolation on
Henderson
                                  1
                                 Joe                                 Client 1

                                                                                Database level
                              Henderson
            Client 1


                                          Client 1




                                                                    36
Persistency
                                 on a Web Server
                                                                                                              Many active
                                                                                                              transactions
                            ID    lastname                     firstname
                            1     Henderson                    Joe
                            2     Levinson                     Mark
                            3     McLachlan                    Sarah
                                                                                                              Server holds 1
                                                                                                              copy per session
                                             Database



                                                                                                              Concurrency in
                                         1

                                                                                                              Image or DB
                                1               1
                                        Joe
                               Joe             Joe
                                     Henderson
                            Henderson       Henderson




                                                                                                              Isolation on
                                                                     Web Server



                                                                                                              Server / Session
todomatic.com                      todomatic.com                                  todomatic.com


                                                                                                              level
 Details of Joe Henderson           Details of Joe Henderson                       Details of Joe Henderson




                                                                                             37
Persistency
   on a Web Server
Connection Pooling
Parallel Transactions
Isolation on Image Level
Multithreading
All supported by current Frameworks

                  38
Accessing Backend
     Systems
CICS, Host-programs etc.
Requests may not block the server
Multithreading
Last Resort: Replace existing library
with TCP/IP based communications


                 39
Another Interaction
      model
HTML is different than a local GUI
Server Round-Trip vs. instant Event
handling
 Validation
 Error Reporting
HTML knows no Datatypes, only text

                 40
Possible Solutions
JavaScript-based
                                Ajax-calls for server-side
Validation in the
                                validation
Browser
         Faster                 Slower, many requests
Server-side validation              validation only
     necessary                implemented on the server

Type info needs to be           Type info only on the
sent to the browser                    server


                         41
Other Topics
  Access Control

Many fat client apps use DB
password of current user
User management and access
control needs to be implemented



               42
Other Topics
      Performance
Server Smalltalk and Seaside can
handle several hundred requests per
second on a normal PC
Overall performance depends on
application code more than SST/
Seaside

                43
Other Topics
      Production
Logging
Error reporting
Health checks
Performance measurement and
reporting


                  44
Other Topics
        Availability
Scheduled Downtimes for
Maintenance Tasks
 DB Reorganization
 Installing Fixpacks
 New releases
 Database Migrations

Most important for Internet Apps
                       45
Deployment scenario
Seaside       Seaside         Seaside        Seaside
 Image         Image           Image          Image


               Sticky Sessions
                                                       Static Files
   HTTP Server with Load Balancing                       Images
(e.g. Apache with mod_proxy_balancer or mod_rewrite)     CSS
                                                         Media...




                               46
How to start
a conversion project?
Build a prototype (3-4 developers)
Choose a few dialogs of your app
 Some easier ones to start with
 ca. 2 complex ones to see if possible

Address architectural risks
~2 months to make a decision
Advantages of
a conversion project?
Reuse existing Smalltalk Know-How
Reuse existing business code
Adopt corporate Design Standards
 seamless visual integration

Keep the Pace of Smalltalk
Make Teams‘ strengths visible
Questions?


       Contact details:
       objektfabrik Joachim Tuchel
       Fliederweg 1
       71640 Ludwigsburg,
       Germany
       email:
       jtuchel@objektfabrik.de
       http://www.objektfabrik.de
u
              o
            y
         k
       n            !
     a            g
   h           in
T            n
          te           !
        s            e
      li          id
   r            s
  o           a
f           e
          S
       y
    jo
  n
E

More Related Content

Similar to Building Seaside Applications in VA Smalltalk

Ajava oep shopping application
Ajava oep shopping applicationAjava oep shopping application
Ajava oep shopping applicationPaneliya Prince
 
Workflow Engines & Event Streaming Brokers - Can They Work Together?
Workflow Engines & Event Streaming Brokers - Can They Work Together?Workflow Engines & Event Streaming Brokers - Can They Work Together?
Workflow Engines & Event Streaming Brokers - Can They Work Together?HostedbyConfluent
 
Workflow Engines & Event Streaming Brokers - Can they work together? [Current...
Workflow Engines & Event Streaming Brokers - Can they work together? [Current...Workflow Engines & Event Streaming Brokers - Can they work together? [Current...
Workflow Engines & Event Streaming Brokers - Can they work together? [Current...Natan Silnitsky
 
Cart creation-101217222728-phpapp01
Cart creation-101217222728-phpapp01Cart creation-101217222728-phpapp01
Cart creation-101217222728-phpapp01Jason Noble
 
Create a mobile web app with Sencha Touch
Create a mobile web app with Sencha TouchCreate a mobile web app with Sencha Touch
Create a mobile web app with Sencha TouchJames Pearce
 
Your First ASP_Net project part 1
Your First ASP_Net project part 1Your First ASP_Net project part 1
Your First ASP_Net project part 1Biswadip Goswami
 
Hello I a having an issue with the code written in this ass.pdf
Hello I a having an issue with the code written in this ass.pdfHello I a having an issue with the code written in this ass.pdf
Hello I a having an issue with the code written in this ass.pdfabsgroup9793
 
MTaulty_DevWeek_Silverlight
MTaulty_DevWeek_SilverlightMTaulty_DevWeek_Silverlight
MTaulty_DevWeek_Silverlightukdpe
 
Share Point
Share PointShare Point
Share Pointjimbelo
 
Scaling Rails Sites by default
Scaling Rails Sites by defaultScaling Rails Sites by default
Scaling Rails Sites by defaultYi-Ting Cheng
 
HTML5 Introduction
HTML5 IntroductionHTML5 Introduction
HTML5 Introductionbeforeach
 
Microservice Websites (microXchg 2017)
Microservice Websites (microXchg 2017)Microservice Websites (microXchg 2017)
Microservice Websites (microXchg 2017)Gustaf Nilsson Kotte
 
Html, CSS, Javascript, Jquery, Meteor應用
Html, CSS, Javascript, Jquery, Meteor應用Html, CSS, Javascript, Jquery, Meteor應用
Html, CSS, Javascript, Jquery, Meteor應用LearningTech
 
Introduction of Html/css/js
Introduction of Html/css/jsIntroduction of Html/css/js
Introduction of Html/css/jsKnoldus Inc.
 
How We Brought Advanced HTML5 Viewing to ADF
How We Brought Advanced HTML5 Viewing to ADFHow We Brought Advanced HTML5 Viewing to ADF
How We Brought Advanced HTML5 Viewing to ADFSeanGraham5
 
Note of CGI and ASP
Note of CGI and ASPNote of CGI and ASP
Note of CGI and ASPWilliam Lee
 

Similar to Building Seaside Applications in VA Smalltalk (20)

Ajava oep shopping application
Ajava oep shopping applicationAjava oep shopping application
Ajava oep shopping application
 
Satchmo
SatchmoSatchmo
Satchmo
 
Workflow Engines & Event Streaming Brokers - Can They Work Together?
Workflow Engines & Event Streaming Brokers - Can They Work Together?Workflow Engines & Event Streaming Brokers - Can They Work Together?
Workflow Engines & Event Streaming Brokers - Can They Work Together?
 
Workflow Engines & Event Streaming Brokers - Can they work together? [Current...
Workflow Engines & Event Streaming Brokers - Can they work together? [Current...Workflow Engines & Event Streaming Brokers - Can they work together? [Current...
Workflow Engines & Event Streaming Brokers - Can they work together? [Current...
 
Managing states
Managing statesManaging states
Managing states
 
Cart creation-101217222728-phpapp01
Cart creation-101217222728-phpapp01Cart creation-101217222728-phpapp01
Cart creation-101217222728-phpapp01
 
Create a mobile web app with Sencha Touch
Create a mobile web app with Sencha TouchCreate a mobile web app with Sencha Touch
Create a mobile web app with Sencha Touch
 
GHC
GHCGHC
GHC
 
Your First ASP_Net project part 1
Your First ASP_Net project part 1Your First ASP_Net project part 1
Your First ASP_Net project part 1
 
Hello I a having an issue with the code written in this ass.pdf
Hello I a having an issue with the code written in this ass.pdfHello I a having an issue with the code written in this ass.pdf
Hello I a having an issue with the code written in this ass.pdf
 
MTaulty_DevWeek_Silverlight
MTaulty_DevWeek_SilverlightMTaulty_DevWeek_Silverlight
MTaulty_DevWeek_Silverlight
 
Share Point
Share PointShare Point
Share Point
 
Scaling Rails Sites by default
Scaling Rails Sites by defaultScaling Rails Sites by default
Scaling Rails Sites by default
 
HTML5 Introduction
HTML5 IntroductionHTML5 Introduction
HTML5 Introduction
 
Microservice Websites (microXchg 2017)
Microservice Websites (microXchg 2017)Microservice Websites (microXchg 2017)
Microservice Websites (microXchg 2017)
 
How cgi scripting works
How cgi scripting worksHow cgi scripting works
How cgi scripting works
 
Html, CSS, Javascript, Jquery, Meteor應用
Html, CSS, Javascript, Jquery, Meteor應用Html, CSS, Javascript, Jquery, Meteor應用
Html, CSS, Javascript, Jquery, Meteor應用
 
Introduction of Html/css/js
Introduction of Html/css/jsIntroduction of Html/css/js
Introduction of Html/css/js
 
How We Brought Advanced HTML5 Viewing to ADF
How We Brought Advanced HTML5 Viewing to ADFHow We Brought Advanced HTML5 Viewing to ADF
How We Brought Advanced HTML5 Viewing to ADF
 
Note of CGI and ASP
Note of CGI and ASPNote of CGI and ASP
Note of CGI and ASP
 

Recently uploaded

The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 

Recently uploaded (20)

The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 

Building Seaside Applications in VA Smalltalk

  • 1. Seaside Build ing Web App licat VA S ions i n mall talk Vers ion 8 © Joachim Tuchel, www.objektfabrik.de
  • 3. This is not... A Seaside Tutorial
  • 5. What we‘ll look at Quick, what is Seaside?
  • 6. What we‘ll look at Quick, what is Seaside? Parallels between Fat client development in VAST and Seaside Web development
  • 7. What we‘ll look at Quick, what is Seaside? Parallels between Fat client development in VAST and Seaside Web development Turning a fat client into a Seaside Web application
  • 8. Quick, what is Seaside?
  • 9. Quick, what is Seaside? A very short introduction to the Seaside Web Application Framework
  • 10. Overview Open Source Started by Avi Bryant in 2001 Currently maintained by Lukas Renggli, Adrian Lienhardt and others In productive use since 2002 Available for Squeak,VisualWorks, Gemstone, Dolphin and soon VA Smalltalk
  • 11. In Production DabbleDB (by Avi Reserve Travel (Hotel Bryant‘s company) Booking engine) CMSBox Run Basic www.cmsbox.ch auctomatic.com Seaside.st (Homepage whooka.com (outdoor of Seaside) sports) In-house applications many more...
  • 12. Seaside is different Components vs. html-pages You never see http requests or responses (unless you want to) No templating or mixing code and design (like jsp‘s) Share as much as possible Components hold application state
  • 13. Pure Smalltalk Components defined in Smalltalk Control Flow in Smalltalk No XML configuration, no state machine Plain Smalltalk code Debugging in Smalltalk ! You can read all code and learn from it
  • 14. Components Subclasses of WAComponent Hold state render themselves: #renderContentOn: Can have subcomponents (#children) Reusable (same page and other pages) Pages are composed of components
  • 15. Rendering a Component WAStoreCartView>>renderContentOn: html cart hasItems ifFalse: [^ self]. html div id: 'cart'; with: [ html small: [ html strong: 'Your cart:' ]. html table: [ cart countsAndItems do: [:assoc | self renderRowForCount: assoc key of: assoc value on: html ]. html tableRow: [ html space]. html tableRow: [ html tableData: ''. html tableData: ''. html tableData: [ html strong: cart totalPrice printStringAsCents ] ] ] ]
  • 16. Rendering a Component html is the canvas we‘re painting on WAStoreCartView>>renderContentOn: html cart hasItems ifFalse: [^ self]. html div id: 'cart'; with: [ html small: [ html strong: 'Your cart:' ]. html table: [ cart countsAndItems do: [:assoc | self renderRowForCount: assoc key of: assoc value on: html ]. html tableRow: [ html space]. html tableRow: [ html tableData: ''. html tableData: ''. html tableData: [ html strong: cart totalPrice printStringAsCents ] ] ] ]
  • 17. Rendering a Component WAStoreCartView>>renderContentOn: html cart hasItems ifFalse: [^ self]. html div id: 'cart'; with: [ html small: [ html strong: 'Your cart:' ]. html table: [ cart countsAndItems do: [:assoc | self renderRowForCount: assoc key of: assoc value on: html ]. html tableRow: [ html space]. html tableRow: [ html tableData: ''. html tableData: ''. html tableData: [ html strong: cart totalPrice printStringAsCents ] ] ] ]
  • 18. Rendering a Component rendering can include application logic WAStoreCartView>>renderContentOn: html cart hasItems ifFalse: [^ self]. html div id: 'cart'; with: [ html small: [ html strong: 'Your cart:' ]. html table: [ cart countsAndItems do: [:assoc | self renderRowForCount: assoc key of: assoc value on: html ]. html tableRow: [ html space]. html tableRow: [ html tableData: ''. html tableData: ''. html tableData: [ html strong: cart totalPrice printStringAsCents ] ] ] ]
  • 19. Rendering a Component WAStoreCartView>>renderContentOn: html cart hasItems ifFalse: [^ self]. html div id: 'cart'; with: [ html small: [ html strong: 'Your cart:' ]. html table: [ cart countsAndItems do: [:assoc | self renderRowForCount: assoc key of: assoc value on: html ]. html tableRow: [ html space]. html tableRow: [ html tableData: ''. html tableData: ''. html tableData: [ html strong: cart totalPrice printStringAsCents ] ] ] ]
  • 20. Rendering a Component a DIV tag for WAStoreCartView>>renderContentOn: html applying CSS cart hasItems ifFalse: [^ self]. formatting html div id: 'cart'; with: [ html small: [ html strong: 'Your cart:' ]. html table: [ cart countsAndItems do: [:assoc | self renderRowForCount: assoc key of: assoc value on: html ]. html tableRow: [ html space]. html tableRow: [ html tableData: ''. html tableData: ''. html tableData: [ html strong: cart totalPrice printStringAsCents ] ] ] ]
  • 21. Rendering a Component WAStoreCartView>>renderContentOn: html cart hasItems ifFalse: [^ self]. html div id: 'cart'; with: [ html small: [ html strong: 'Your cart:' ]. html table: [ cart countsAndItems do: [:assoc | self renderRowForCount: assoc key of: assoc value on: html ]. html tableRow: [ html space]. html tableRow: [ html tableData: ''. html tableData: ''. html tableData: [ html strong: cart totalPrice printStringAsCents ] ] ] ]
  • 22. Rendering a Component this is a brush to WAStoreCartView>>renderContentOn: html paint on the canvas cart hasItems ifFalse: [^ self]. html div id: 'cart'; with: [ html small: [ html strong: 'Your cart:' ]. html table: [ cart countsAndItems do: [:assoc | self renderRowForCount: assoc key of: assoc value on: html ]. html tableRow: [ html space]. html tableRow: [ html tableData: ''. html tableData: ''. html tableData: [ html strong: cart totalPrice printStringAsCents ] ] ] ]
  • 23. Rendering a Component WAStoreCartView>>renderContentOn: html cart hasItems ifFalse: [^ self]. html div id: 'cart'; with: [ html small: [ html strong: 'Your cart:' ]. html table: [ cart countsAndItems do: [:assoc | self renderRowForCount: assoc key of: assoc value on: html ]. html tableRow: [ html space]. html tableRow: [ html tableData: ''. html tableData: ''. html tableData: [ html strong: cart totalPrice printStringAsCents ] ] ] ]
  • 24. Rendering a Component WAStoreCartView>>renderContentOn: html cart hasItems ifFalse: [^ self]. with: is always the html div call on a brush last id: and writes xhtml 'cart'; with: [ html small: [ html strong: 'Your cart:' ]. html table: [ cart countsAndItems do: [:assoc | self renderRowForCount: assoc key of: assoc value on: html ]. html tableRow: [ html space]. html tableRow: [ html tableData: ''. html tableData: ''. html tableData: [ html strong: cart totalPrice printStringAsCents ] ] ] ]
  • 25. Rendering a Component WAStoreCartView>>renderContentOn: html cart hasItems ifFalse: [^ self]. html div id: 'cart'; with: [ html small: [ html strong: 'Your cart:' ]. html table: [ cart countsAndItems do: [:assoc | self renderRowForCount: assoc key of: assoc value on: html ]. html tableRow: [ html space]. html tableRow: [ html tableData: ''. html tableData: ''. html tableData: [ html strong: cart totalPrice printStringAsCents ] ] ] ]
  • 26. Rendering a Component WAStoreCartView>>renderContentOn: html cart hasItems ifFalse: [^ self]. html div id: 'cart'; blocks for nesting with: [ certain brushes/tags html small: [ html strong: 'Your cart:' ]. html table: [ cart countsAndItems do: [:assoc | self renderRowForCount: assoc key of: assoc value on: html ]. html tableRow: [ html space]. html tableRow: [ html tableData: ''. html tableData: ''. html tableData: [ html strong: cart totalPrice printStringAsCents ] ] ] ]
  • 27. Rendering a Component WAStoreCartView>>renderContentOn: html cart hasItems ifFalse: [^ self]. html div id: 'cart'; with: [ html small: [ html strong: 'Your cart:' ]. html table: [ cart countsAndItems do: [:assoc | self renderRowForCount: assoc key of: assoc value on: html ]. html tableRow: [ html space]. html tableRow: [ html tableData: ''. html tableData: ''. html tableData: [ html strong: cart totalPrice printStringAsCents ] ] ] ]
  • 28. Rendering a Component WAStoreCartView>>renderContentOn: html cart hasItems ifFalse: [^ self]. html div id: 'cart'; with: [ cart is an inst var html small: [ html strong: 'Your cart:' ]. of the component html table: [ cart countsAndItems do: [:assoc | self renderRowForCount: assoc key of: assoc value on: html ]. html tableRow: [ html space]. html tableRow: [ html tableData: ''. html tableData: ''. html tableData: [ html strong: cart totalPrice printStringAsCents ] ] ] ]
  • 29. Rendering a Component WAStoreCartView>>renderContentOn: html cart hasItems ifFalse: [^ self]. html div id: 'cart'; with: [ html small: [ html strong: 'Your cart:' ]. html table: [ cart countsAndItems do: [:assoc | self renderRowForCount: assoc key of: assoc value on: html ]. html tableRow: [ html space]. html tableRow: [ html tableData: ''. html tableData: ''. html tableData: [ html strong: cart totalPrice printStringAsCents ] ] ] ]
  • 30. Rendering and Callbacks WAStoreCartView>>renderRowForCount: aNumber of: anItem on: html | countString | countString := (aNumber = 1) ifTrue: [''] ifFalse: ['(', aNumber displayString, ') ']. html tableRow: [ html tableData: [ html anchor callback: [ cart remove: anItem ]; with: '-']. html tableData: countString, anItem title. html tableData: (aNumber * anItem price) printStringAsCents ]
  • 31. Rendering and Callbacks WAStoreCartView>>renderRowForCount: aNumber of: anItem on: html | countString | countString := (aNumber = 1) ifTrue: [''] the anchor brush ifFalse: ['(', aNumber displayString, ') ']. html tableRow: [ a link draws html tableData: [ html anchor callback: [ cart remove: anItem ]; with: '-']. html tableData: countString, anItem title. html tableData: (aNumber * anItem price) printStringAsCents ]
  • 32. Rendering and Callbacks WAStoreCartView>>renderRowForCount: aNumber of: anItem on: html | countString | countString := (aNumber = 1) ifTrue: [''] ifFalse: ['(', aNumber displayString, ') ']. html tableRow: [ html tableData: [ html anchor callback: [ cart remove: anItem ]; with: '-']. html tableData: countString, anItem title. html tableData: (aNumber * anItem price) printStringAsCents ]
  • 33. Rendering and Callbacks WAStoreCartView>>renderRowForCount: aNumber of: anItem on: html | countString | countString := (aNumber = 1) this block will be ifTrue: [''] evaluated when user ifFalse: ['(', aNumber displayString,the link ']. clicks ') html tableRow: [ html tableData: [ html anchor callback: [ cart remove: anItem ]; with: '-']. html tableData: countString, anItem title. html tableData: (aNumber * anItem price) printStringAsCents ]
  • 34. Rendering and Callbacks WAStoreCartView>>renderRowForCount: aNumber of: anItem on: html | countString | countString := (aNumber = 1) ifTrue: [''] ifFalse: ['(', aNumber displayString, ') ']. html tableRow: [ html tableData: [ html anchor callback: [ cart remove: anItem ]; with: '-']. html tableData: countString, anItem title. html tableData: (aNumber * anItem price) printStringAsCents ]
  • 35. Rendering and Callbacks f! o WAStoreCartView>>renderRowForCount: aNumber of: anItem g tS on: html ns | countString | ie countString := (aNumber = 1) su ifTrue: [''] r ifFalse: ['(', aNumber displayString, ') ']. aq html tableRow: [ html tableData: [ Pe html anchor callback: [ cart remove: anItem ]; with: '-']. oR html tableData: countString, anItem title. NP html tableData: (aNumber * anItem price) printStringAsCents ] T T H
  • 36. Rendering Result - the page
  • 37. Rendering Result - the page this is the subcomponent we just rendered
  • 38. Rendering Result - the page
  • 39. Rendering Result - html <!DOCTYPE html PUBLIC quot;-//W3C//DTD XHTML 1.0 Strict...> <html xmlns=...> ... <div id=quot;cartquot;> <small><strong>Your cart:</strong><small> <table> <tr> <td><a href=quot;http://localhost:...quot;>-</a></ td><td>California Roll</td><td>$2.50</td></tr> <tr> <td><a href=quot;http://localhost:...quot;>-</a></ td><td>Akagai</td><td>$3.00</td></tr> <tr>&nbsp;</tr> <tr> <td></td><td></td><td><strong>$5.50</strong></ td></tr> </table> </div>
  • 40. CSS for the Design Components generate valid XHTML only CSS files for Designing the XHTML output separation between code and design code is written by developer, css is written by web designer Served from within Image or from external web sever
  • 41. Seaside development for VA Smalltalkers
  • 42. Seaside development for VA Smalltalkers lels aral P een etw b side Sea ent lopm eve d and ient Cl Rich ent opm alk vel de allt A Sm in V
  • 43. Components vs. Visual Parts Both can be composed to complex components with subcomponents Controls are event driven Callbacks to perform Smalltalk methods
  • 44. Composed Components vs. Subparts Component renderContentOn: renderContentOn: html Your personal todomatic Page ... html render: mySubComponent1. html render: mySubComponent2. ... Save Logoff Subcomonent Subcomponent renderContentOn: renderContentOn: Checkbox Array: Option 1 ! Option 3 ! Option 5 Your rating: ! Option 2 Option 4 Multi-select: Full List My Items Item 1 none avarage: Item 2 Item 3 Item 4 Favourite: City, State, Postal - Select One - City Postal State Code:
  • 45. Composed Components vs. Subparts don‘t call renderContentOn: of child components! Seaside calls it! Component renderContentOn: renderContentOn: html Your personal todomatic Page ... html render: mySubComponent1. html render: mySubComponent2. ... Save Logoff Subcomonent Subcomponent renderContentOn: renderContentOn: Checkbox Array: Option 1 ! Option 3 ! Option 5 Your rating: ! Option 2 Option 4 Multi-select: Full List My Items Item 1 none avarage: Item 2 Item 3 Item 4 Favourite: City, State, Postal - Select One - City Postal State Code:
  • 46. Event-to-Action connections abtBuildInternals ... refreshButton abtWhenPrimitive: #clicked perform: ( conn22 := AbtEventToActionConnection new source: refreshButton; eventName: #clicked; actionProvider: applicationModel variableFeatureName: #refreshTrafficMessages featureSelector: #IS_refreshTrafficMessages).
  • 47. Action and Value Callbacks renderContentOn: html ... html submitButton callback: [self applicationModel refreshTrafficMessages]; with: ‘Refresh‘. ... html label: ‘Please enter a name:‘. html textInput callback: [:txt| self name: txt]; value: self name. “or in short form“ html textInput on: #name of: self.
  • 48. Differences Feedback cycle: Fat client: instant feedback Web: On Submit (AJAX / Scriptaculous for immediate feedback) Seaside has no GUI painter out of the box projects going on useful in HTML/CSS ?
  • 50. Tasks Subclasses of WATask Control flow single method #go Can call Tasks and Components
  • 51. Call and Answer Components and Tasks can #call: and #answer: Caller gets replaced by callee / delegate Control is delegated to callee #answer:returns a result to caller and returns control to caller
  • 52. Call and Answer (2) Component 1 handleSomeCallbackWith: param ... Component 2 result := self call: ((Component2 new) renderContentOn: html someInstVar: param; html form: [ yourself). html text: someInstVar result ifTrue: [self saveData] printString. ifFalse: [self discardAll]. html submitButton callback: [self answer: true] text: ‚Okay, save this‘].
  • 53. Call and Answer (2) Component 2 gets rendered in place of Component Component 1 1 and takes control of request/ response processing handleSomeCallbackWith: param ... Component 2 result := self call: ((Component2 new) renderContentOn: html someInstVar: param; html form: [ yourself). html text: someInstVar result ifTrue: [self saveData] printString. ifFalse: [self discardAll]. html submitButton callback: [self answer: true] text: ‚Okay, save this‘].
  • 54. Call and Answer (2) Component 2 gets rendered in place of Component Component 1 1 and takes control of request/ response processing handleSomeCallbackWith: param ... Component 2 result := self call: ((Component2 new) renderContentOn: html someInstVar: param; html form: [ yourself). html text: someInstVar result ifTrue: [self saveData] printString. ifFalse: [self discardAll]. html submitButton callback: [self answer: true] text: ‚Okay, save this‘]. Component 1 gets back control as soon as Comp.2 was submitted and can use the answer to continue
  • 55. A typical Fat Client in VA Smalltalk
  • 56. A typical Fat Client in VA Smalltalk typically your Workflow Controller framework
  • 57. A typical Fat Client in VA Smalltalk typically your Workflow Controller framework View Controller(s) typically a visual part / Composition Editor
  • 58. A typical Fat Client in VA Smalltalk typically your Workflow Controller framework View View Controller(s) Controller(s) typically a visual part / Composition Editor
  • 59. A typical Fat Client in VA Smalltalk typically your Workflow Controller framework View View ... Controller(s) Controller(s) typically a visual part / Composition Editor
  • 60. A typical Seaside Application
  • 61. A typical Seaside Application call: WATask answer:
  • 62. A typical Seaside Application call: WATask answer: rendering Component request handling call/answer rendered by Web browser
  • 63. A typical Seaside Application call: WATask answer: rendering Component Component request handling call/answer rendered by Web browser
  • 64. A typical Seaside Application call: WATask answer: rendering ... Component Component request handling call/answer rendered by Web browser
  • 65.
  • 66. ga tin ion ri at W lic ga p Ap itin ide like wr as Se ion h cat uc li m pp ry ve IA is GU al od M
  • 68. Ajax Most popular RIA technology Combination of Server Side-Application Code JavaScript in the Browser XML HTTP Request as transport protocol for portions of a page
  • 69. JavaScript Libraries Numerous available Most Popular (and one of the most mature / complete) Prototype Script.aculo.us Full access to CSS styles, DOM objects XmlHttpRequest Browser-neutral
  • 70. Seaside and Scriptaculous Seaside wrappers Prototype / Scriptaculous Developer writes Smalltalk code JavaScript ‚rendered‘ in Smalltalk JavaScript is embedded in HTML Page html updater id: ‚myelement‘ callback: [:html| self renderNewStuffOn: html].
  • 71. Demo
  • 72. From Fat Client to Seaside Application What you have to look at and change in an existing application
  • 73. From Fat Client to Seaside Application Persistency What you have to look at and change in an existing application
  • 74. From Fat Client to Seaside Application Persistency Back-end access What you have to look at and change in an existing application
  • 75. From Fat Client to Seaside Application Persistency Back-end access What you have to look at GUI Interaction and change in an existing application
  • 76. From Fat Client to Seaside Application Persistency Back-end access What you have to look at GUI Interaction and change in an existing application Miscellaneous
  • 77. Comparing the two architectures Database Database fat client Persistency Persistency server Persistency Business logic Business logic Persistency Business logic Presentation Presentation Business logic Presentation Presentation browser Presentation Presentation Presentation 34
  • 78. Changing the Architecture Easier when layers are clearly structured MVC Pattern Business logic should be fully reusable Persistency Persistency Business logic Business logic Transition Controller Presentation Presentation Presentation View 35
  • 79. Persistency on a Fat Client 1 or only a few ID lastname firstname 1 Henderson Joe active transactions 2 Levinson Mark 3 McLachlan Sarah per client Database Each client holds its own copy 1 Concurrency & Joe 1 Henderson Joe Isolation on Henderson 1 Joe Client 1 Database level Henderson Client 1 Client 1 36
  • 80. Persistency on a Web Server Many active transactions ID lastname firstname 1 Henderson Joe 2 Levinson Mark 3 McLachlan Sarah Server holds 1 copy per session Database Concurrency in 1 Image or DB 1 1 Joe Joe Joe Henderson Henderson Henderson Isolation on Web Server Server / Session todomatic.com todomatic.com todomatic.com level Details of Joe Henderson Details of Joe Henderson Details of Joe Henderson 37
  • 81. Persistency on a Web Server Connection Pooling Parallel Transactions Isolation on Image Level Multithreading All supported by current Frameworks 38
  • 82. Accessing Backend Systems CICS, Host-programs etc. Requests may not block the server Multithreading Last Resort: Replace existing library with TCP/IP based communications 39
  • 83. Another Interaction model HTML is different than a local GUI Server Round-Trip vs. instant Event handling Validation Error Reporting HTML knows no Datatypes, only text 40
  • 84. Possible Solutions JavaScript-based Ajax-calls for server-side Validation in the validation Browser Faster Slower, many requests Server-side validation validation only necessary implemented on the server Type info needs to be Type info only on the sent to the browser server 41
  • 85. Other Topics Access Control Many fat client apps use DB password of current user User management and access control needs to be implemented 42
  • 86. Other Topics Performance Server Smalltalk and Seaside can handle several hundred requests per second on a normal PC Overall performance depends on application code more than SST/ Seaside 43
  • 87. Other Topics Production Logging Error reporting Health checks Performance measurement and reporting 44
  • 88. Other Topics Availability Scheduled Downtimes for Maintenance Tasks DB Reorganization Installing Fixpacks New releases Database Migrations Most important for Internet Apps 45
  • 89. Deployment scenario Seaside Seaside Seaside Seaside Image Image Image Image Sticky Sessions Static Files HTTP Server with Load Balancing Images (e.g. Apache with mod_proxy_balancer or mod_rewrite) CSS Media... 46
  • 90. How to start a conversion project? Build a prototype (3-4 developers) Choose a few dialogs of your app Some easier ones to start with ca. 2 complex ones to see if possible Address architectural risks ~2 months to make a decision
  • 91. Advantages of a conversion project? Reuse existing Smalltalk Know-How Reuse existing business code Adopt corporate Design Standards seamless visual integration Keep the Pace of Smalltalk Make Teams‘ strengths visible
  • 92. Questions? Contact details: objektfabrik Joachim Tuchel Fliederweg 1 71640 Ludwigsburg, Germany email: jtuchel@objektfabrik.de http://www.objektfabrik.de
  • 93. u o y k n ! a g h in T n te ! s e li id r s o a f e S y jo n E

Editor's Notes