[Glass] GsDevKit Server Blocks for Thin Client appications ... pre-announcement

Pierre CHANSON via Glass glass at lists.gemtalksystems.com
Wed Apr 29 15:42:27 PDT 2015


Thanks again Dale !

here are three small examples using these blocks in the roassal workspace
of tODE:  https://vimeo.com/126435220

I highlight here the server blocks in red.

The first one is a Mondrian view of the class Collection (server side) with
all it's subclasses.
The classes are processed in the block and stocked statically on the
variable "classes".

--------------------------------------------------------------------------------------------------------------------------------------
| b classes |
classes := shell onServerDo:[Collection withAllSubclasses collect: [ :c | c
name -> {(c superClass name). ((c instVarNamed: #methDicts asString)
numElements)}]].

b := RTMondrian new.
b shape circle.
b nodes: classes.
b edges connectFrom: [:e | classes detect: [ :c | c name = e value first ]
ifNone:[ nil ]] .

b shape bezierLineFollowing: [:e | classes detect: [ :c | c name = e value
first ] ifNone:[ nil ]];
     color: (Color blue alpha: 0.2).


b normalizer
    normalizeSize: [:e | e value second ] using: #sqrt;
    normalizeColor: [:e | e value second ] using: (Array with: Color green
with: Color red) using: #sqrt.
b layout cluster.
b build.
b view open
--------------------------------------------------------------------------------------------------------------------------------------

The second script use the RTExploraBuilder to do the same process, but this
time the builder call dynamically the server on clics (we are using the oop
of objects).

--------------------------------------------------------------------------------------------------------------------------------------
| builder |
    builder := RTExploraBuilder new.
    builder shape circle
        size: 30;
        color: (Color blue alpha: 0.5);
        if: [ :cls |
            (shell onServerDo: [ (Object _objectForOop: (cls value))
subclasses size]) = 0 ] fillColor: (Color red alpha: 0.5).
    builder
        layout: [RTClusterLayout new horizontalGap: 80];
        onClickExplore: [ :cls |
            shell onServerDo: [ ((Object _objectForOop: (cls value))
subclasses collect: [:c | c asString -> c asOop]) asArray ]
            ];
        withPopup: [:cls | cls key];
        dragChildren;
        node: (shell onServerDo: [Collection asString -> Collection asOop]);
        open.
--------------------------------------------------------------------------------------------------------------------------------------


The last script is about users. This need the last version of Roassal. We
present some selection menus, a button and a radar Chart. Created with the
RTMenuBuilder the button add a new user on the server with the
characteristics selected in the other menus and present the characteristics
of the added users on a Kiviat chart on the view.

--------------------------------------------------------------------------------------------------------------------------------------
|nameMenus privilegeMenus groupMenus|
    v := RTView new.

    kiv := RTKiviatBuilder new view: v.
    n := RTMultiLinearColorForIdentity new objects: (kiv objects).
    kiv shape circle color: [ :value | n rtValue: value kiviatNode named];
size: 10.


    kiv addMetric: [ :v | v second size] max: 5 title: 'groups'.
    kiv addMetric: [ :v | v third size] max: 5 title: 'privileges'.
    kiv addMetric: [ :v | v first size] max: 10 title: 'name'.


    kiv activatePolygons.
    kiv build.

    b := RTMenuBuilder new view: v.

    nameMenus := Array with: ('Henri'->[:m |]) with: ('Bob'->[:m |]) with:
('Robert'->[:m |]).
    groupMenus := Array with: ('Subscribers'->[:m |])
with:('Publishers'->[:m |]).
    privilegeMenus := Array with: ('ObsoleteStatistics'->[:m |])
with:('UserPassword'->[:m |]) with:('SessionAccess'->[:m |]).


    b menu: 'add User' callback: [
        |name groups privileges |

        name := (nameMenus detect: [ :m | m selected ]) name.
        groups := (groupMenus select: [:m | m selected]) collect: [:g | g
name].
        privileges := (privilegeMenus select: [:m | m selected])  collect:
[:p | p name].
        shell onServerDo: [
            AllUsers addNewUserWithId: name password: ''
defaultObjectSecurityPolicy: nil privileges: privileges inGroups: groups .
            System commitTransaction.].
        kiv addDynamicObject: (Array with: (name) with: (groups) with:
(privileges))
].

    nameMenus := b menu: 'user' subcheckmenus: nameMenus background: (Color
red alpha: 0.3).
    RTMenuGroup on: nameMenus.
    nameMenus first selected: true.


    groupMenus := b menu: 'groups' subcheckmenus: groupMenus background:
(Color blue alpha: 0.3).
    groupMenus first selected: true.


    privilegeMenus := b menu: 'privileges' subcheckmenus: privilegeMenus
background: (Color green alpha: 0.3).

    privilegeMenus first selected: true.

    b view open.
--------------------------------------------------------------------------------------------------------------------------------------

 Pierre




2015-04-23 19:58 GMT+02:00 Mariano Martinez Peck via Glass <
glass at lists.gemtalksystems.com>:

>
>
> On Wed, Apr 22, 2015 at 1:53 AM, Richard Sargent <
> richard.sargent at gemtalksystems.com> wrote:
>
>> Mariano,
>>
>> Depending on what you mean by "execute stuff on server Y", 3.2 includes
>> something called GsExternalSession. It it capable of executing Smalltalk
>> specified in  Block on a separate session against the same stone or a
>> different one.
>>
>> It doesn't support copying object graphs, but if your definition of
>> execute stuff has limited requirements for exchanging data, it could be
>> what you are looking for.
>> See the 3.2 documentation for details.
>>
>
> Good to know too. Thanks Richard.
>
>
>>  On Apr 21, 2015 7:01 PM, "Mariano Martinez Peck via Glass" <
>> glass at lists.gemtalksystems.com> wrote:
>>
>>>
>>>
>>> On Thu, Apr 16, 2015 at 2:23 AM, Dale Henrichs via Glass <
>>> glass at lists.gemtalksystems.com> wrote:
>>>
>>>>  A GsDevKit Server Block[1] is a block that is written in-line in
>>>> client Smalltalk, but is executed in GemStone. For example the following
>>>> expression is executed in a standard Pharo workspace:
>>>>
>>>>   | shell x y |
>>>>   shell := TDShell forSessionNamed: 'devKit'.
>>>>   x := 3.
>>>>   y := 4.
>>>>   shell onServerDo: [ x + y ].
>>>>
>>>
>>>
>>> Dale,
>>>
>>> I know (because I already asked a few months/years ago) that from a
>>> stone X you can do a remote login on stone Y and execute stuff in Y. But
>>> now I wonder....could server blocks also work for gemstone-gemstone? (my
>>> gut feelings tell me that yes) I mean, could I run the above code from
>>> GemStone itself?   That would automatically resolve all the remote login
>>> stuff and the ston serialization.
>>>
>>> Thanks in advance,
>>>
>>>
>>>
>>>> and the `[3 + 4 ]` block is executed in GemStone using the `devKit`
>>>> session description to log into the stone. The temp vars x and y referenced
>>>> in the server block and defined in Pharo are shipped across the wire to
>>>> GemStone along with block source where the block source is compiled and
>>>> executed. The result is then shipped back across the wire and returned as
>>>> the result of #onServerDo: message in Pharo. Pharo execution can continue
>>>> on using the result. STON[2] is used to serialize the objects that are
>>>> shipped across the wire.
>>>>
>>>> For any of you familiar with underpinnings of GemTools, Jade or tODE,
>>>> this is not necessarily ground-breaking technology, however, exposing this
>>>> capability to developers just may be.
>>>>
>>>> It has been a long standing crime that developers in the Pharo
>>>> community choose to use  MongoDB and MySQL over GemStone, but frankly the
>>>> problem is that (until now) we have not had a simple client-based solution
>>>> for adding GemStone-based persistence for native Pharo applications - the
>>>> pharo developers have not really had a choice.
>>>>
>>>> Being able to embed server blocks in client code certainly qualifies as
>>>> simple. Solution(?), well that remains to be seen, but I am optimistic.
>>>>
>>>> As a more concrete example, here's Pharo workspace code that uses
>>>> NeoCSV running in Pharo to load stone objects in a Dictionary in GemStone:
>>>>
>>>>   'NeoCSVBenchmark.csv' asFileReference
>>>>   readStreamDo: [ :stream |
>>>>   | reader converter buffer bufCnt numRecords records |
>>>>   converter := [ :string | NeoNumberParser parse: string ].
>>>>   reader := NeoCSVReader on: (ZnBufferedReadStream on: stream).
>>>>   reader
>>>>     recordClass: NeoCSVTestObject;
>>>>     addIntegerField: #'x:';
>>>>     addIntegerField: #'y:';
>>>>     addIntegerField: #'z:'.
>>>>   buffer := Array new: 1000.
>>>>   bufCnt := 0.
>>>>   [ reader atEnd ]
>>>>     whileFalse: [
>>>>       bufCnt := bufCnt + 1.
>>>>       buffer at: bufCnt put: reader next.
>>>>       bufCnt = buffer size
>>>>         ifTrue: [
>>>>           numRecords := bufCnt.
>>>>           records := buffer.
>>>>           DevKitShell
>>>>             onServerDo: [
>>>>               1 to: numRecords do: [ :index |
>>>>                 | record |
>>>>                 record := records at: index.
>>>>                 NeoCSVDictionary at: record x put: record ].
>>>>               System commitTransaction.
>>>>               nil ].
>>>>           bufCnt := 0 ] ] ].
>>>>    DevKitShell onServerDo: [ System commitTransaction ]
>>>>
>>>> The code ships 1000 instances of NeoCSVTestObject at a pop to GemStone.
>>>> Using the above technique, one can easily arrange to store some pretty
>>>> large object graphs in GemStone ... Efficient queries based on standard
>>>> Smalltalk can be written on the client and transparently performed in
>>>> GemStone (see the GsDevKitServerBlocks doc[1] for the complete example).
>>>>
>>>> Server blocks do not duplicate the functionality GemBuilder for
>>>> Smalltalk[6][7] which provides transparent replication and maintenance of
>>>> objects between the client and server. With server blocks you end up with
>>>> disconnected copies of server objects.
>>>>
>>>> Because of this disconnect, I think the best way to architect an
>>>> application using server blocks, is to plan on "executing all business
>>>> logic" on the server --- If you are using an MVC pattern, the M would
>>>> primarily be managed on the server while the VC would be managed on the
>>>> client.
>>>>
>>>> As an application evolves, the code can migrate back and forth between
>>>> client and server as needed.
>>>>
>>>> Most of the server blocks code leverages tODE and has been in use for
>>>> several years. The code that spelunks in the block structure and extracts
>>>> the _value_ of temp variables is only a couple of days old and has some
>>>> pretty rough edges (notice the odd placement of temp variables and
>>>> declarations in the above example).
>>>>
>>>> The server-side debugger and inspectors, etc. will use tODE (at least
>>>> for now) ...  in the server blocks doc[1] I demonstrate an
>>>> #exportClassToServer: to illustrate the potential to share code in weird
>>>> and wonderful ways between the client and server.
>>>>
>>>> If you have the interest/opportunity to take this code for a spin, let
>>>> me know. I have written instructions[5] for installing the experimental
>>>> Roassal Visualization code[4] (GemStone and Pharo3.0 or Pharo4.0) for
>>>> Pierre Chanson and those instructions can be used for doing work with
>>>> GsDevKit
>>>> Server Blocks. There are a handful of obvious things that need to be
>>>> done:
>>>>   - connection pools
>>>>   - coordinated client/server debuggers
>>>>   - client-side exception handlers for server errors
>>>>   - more???
>>>> and if folks express interest in start to do exploratory work with
>>>> server blocks, then I will make time to provide support.
>>>>
>>>> I am hoping to have something to announce by Smalltalks in November,so
>>>> it would be useful if some experienced GemStoners tried things out before
>>>> then...
>>>>
>>>> I do have to finish up the documentation for GsDevKitHome 1.0.0 and
>>>> tODE 0.1.0 and I'm also committed to doing some work on the 3.3 GemStone
>>>> release, so we'll see how that goes:)
>>>>
>>>> I also think that server blocks can be very useful for the "develop in
>>>> Pharo, deploy in GemSstone" crowd, since it will be possible to write
>>>> "pharo-based scripts" to perform server-side tasks ...
>>>>
>>>> Questions or comments?
>>>>
>>>> Dale
>>>>
>>>> [1]
>>>> https://github.com/GsDevKit/gsDevKitHome/blob/dev/docs/articles/gsDevKitServerBlocks.md
>>>> #gsdevkit-server-blocks
>>>> [2] https://github.com/GsDevKit/ston#ston---smalltalk-object-notation
>>>> [3] https://vimeo.com/123261640
>>>> [4]
>>>> https://github.com/GsDevKit/gsDevKitHome/tree/dev/projects/roassal#roassal-visualization
>>>> [5]
>>>> https://github.com/GsDevKit/gsDevKitHome/blob/dev/projects/roassal/devBootstrap.md
>>>> [6] http://gemtalksystems.com/products/gbs-vw/
>>>> [7] http://gemtalksystems.com/products/gbs-va/
>>>>
>>>> _______________________________________________
>>>> Glass mailing list
>>>> Glass at lists.gemtalksystems.com
>>>> http://lists.gemtalksystems.com/mailman/listinfo/glass
>>>>
>>>>
>>>
>>>
>>> --
>>> Mariano
>>> http://marianopeck.wordpress.com
>>>
>>> _______________________________________________
>>> Glass mailing list
>>> Glass at lists.gemtalksystems.com
>>> http://lists.gemtalksystems.com/mailman/listinfo/glass
>>>
>>>
>
>
> --
> Mariano
> http://marianopeck.wordpress.com
>
> _______________________________________________
> Glass mailing list
> Glass at lists.gemtalksystems.com
> http://lists.gemtalksystems.com/mailman/listinfo/glass
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.gemtalksystems.com/mailman/private/glass/attachments/20150430/c64e7cb2/attachment-0001.html>


More information about the Glass mailing list