[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