Passing object (input-output), with a dataset or TT, between

Posted by DenDuze on 30-Dec-2019 13:32

Hi,

Should it be possible to get the following working?

I have as class (serializable) that I instantiate on the client
In this instance I create some temp-table records (in a static defined temp-table)
I pass this instance from the client to the appserver
There I process the values of that static temp-table and as a result I create some dynamic temp-tables that I put in a dynamic dataset (that is all done in that  class that I passed to the appserver)
Now I pass that object (so with the dynamic created dataset/temp-tables back to the client.
There I want to display the records that I created on the server,
But this does not work? The object is valid but the dataset/temp-tables are not?
Is that because I use dynamic Temp-tables/dataset??
Is there some way to do this (I can't use static defined temp-tables because I do not know what data I need to send back)

Passing the records from the client to the server (with static temp-table) works well
But I can't manage to get that data from those dynamic created dataset on the client.

I guess I could try with input object (with the static temp-table with selection-criteria) and output dataset/dataset-handle but I think it would be better to contain that dataset/temp-tables in the class itself (if that can work!)

If possible: can someone give me some example on how to do this (or link to example)

Regards

Posted by Simon L. Prinsloo on 30-Dec-2019 14:42

With static temp-table I presume static as in a defined temp-table construct as opposed to a dynamic one, and not a static member of the class, i.e NOT "DEFINE STATIC TEMP-TABLE".

If you create a dynamic dataset and dynamic temp-tables, I assume the member holding it is a handle property of variable. The he help topic "Parameter passing syntax",  states that "Handle-based variables are serialized, but no information for reconstructing handle-based objects on the receiving side is serialized."

So in essence, the dynamic dataset and temp-tables cannot be reconstruced. You can however pass objects of type Progress.Json.ObjectModel.JsonObject and Progress.Json.ObjectModel.JsonArray.

I would therefore suggest that you change the handle member to be non-serializable and add a member of type JsonObject. On the server, you can then do this just before you return:

hDataset:WRITE-JSON("JsonObject", mJsonData, ?, ?, TRUE).

On the receiving end, you can do this when the call return, or, if the dataset handle is a property, in its GET() when it is not valid and the mJsonData member is valid:

CREATE DATASET hDataset.

hDataset:READ-JSON("JsonObject", mJsonData).

All Replies

Posted by Simon L. Prinsloo on 30-Dec-2019 14:42

With static temp-table I presume static as in a defined temp-table construct as opposed to a dynamic one, and not a static member of the class, i.e NOT "DEFINE STATIC TEMP-TABLE".

If you create a dynamic dataset and dynamic temp-tables, I assume the member holding it is a handle property of variable. The he help topic "Parameter passing syntax",  states that "Handle-based variables are serialized, but no information for reconstructing handle-based objects on the receiving side is serialized."

So in essence, the dynamic dataset and temp-tables cannot be reconstruced. You can however pass objects of type Progress.Json.ObjectModel.JsonObject and Progress.Json.ObjectModel.JsonArray.

I would therefore suggest that you change the handle member to be non-serializable and add a member of type JsonObject. On the server, you can then do this just before you return:

hDataset:WRITE-JSON("JsonObject", mJsonData, ?, ?, TRUE).

On the receiving end, you can do this when the call return, or, if the dataset handle is a property, in its GET() when it is not valid and the mJsonData member is valid:

CREATE DATASET hDataset.

hDataset:READ-JSON("JsonObject", mJsonData).

Posted by DenDuze on 30-Dec-2019 14:58

Hi Simon,

That was what I wanted to do if my test-scenario was not possible.

I was hoping that (because I used the object as input-output) that Progress would send the whole object, so with all records in all datasets/temp-tables that are created in that object, back to the client and that there I could retrieve the buffers from that dataset to get all data.

It looks like that does not work so will have to try the JsonObject approch.

Thanks

Posted by DenDuze on 30-Dec-2019 14:58

Hi Simon,

That was what I wanted to do if my test-scenario was not possible.

I was hoping that (because I used the object as input-output) that Progress would send the whole object, so with all records in all datasets/temp-tables that are created in that object, back to the client and that there I could retrieve the buffers from that dataset to get all data.

It looks like that does not work so will have to try the JsonObject approch.

Thanks

Posted by goo on 30-Dec-2019 15:04

Should be ok to pass a Dataset between client and server, so I wonder how you create the dataset and temp-tables and how you pass it?
 
//Geir Otto
 

Posted by DenDuze on 31-Dec-2019 07:23

Hi Otto,

I also thought that this would work because the dynamically created dataset belongs to the object so when I send the object back to the client I thought that all that information was also copied to there but ....

I can't see how to attach an example

- I instantiate the class on the client and fill the static defined temp-table with the needed info to find the DB-records

- I send the object to the server (input-output so after the filling of the dataset I expect that the object is returned to the client)

- On the server I create a dynamic dataset that hold the buffers of dynamically created temp-tables (below short version of the code)

create dataset this-object:phDs.

create query hquery.

hquery:forward-only.

assign i = 0.

for each ttTable:

 assign i           = i + 1

              v-YNcreated = false.

 // work with create so I can work generic and do not need to list all possible tables here

 create buffer hbufferDB for table ttTable.NMtableDB.        

 hquery:set-buffers(hbufferDB).

 hquery:query-prepare(substitute("for each &1 where &2", ttTable.NMtableDB, ttTable.INwhere)) no-error.

 hquery:query-open().

 do while hquery:get-next(no-lock):

   if not v-YNcreated then

     do:

       tt[i]:create-like(ttTable.NMtableDB).

       tt[i]:temp-table-prepare(substitute("tt&1", ttTable.NMtableDB)).

       hbuffer[i] = tt[i]:default-buffer-handle.

       this-object:phds:add-buffer(hbuffer[i]).

       assign v-YNcreated = true.

     end.    

   hbuffer[i]:buffer-create.

   hbuffer[i]:buffer-copy(hquery:get-buffer-handle).

 end.

 finally:

   delete object hBufferDB.

 end finally.

end.

@the meanwhile I'm trying to work with the jsonObject (but I would prefer that the way with the dynamically created dataset would work)

Regards

Posted by Laura Stern on 03-Jan-2020 12:43

Since the object’s property is a Handle, I believe we just serialization the Handle value when the object is sent back to the client.  But the DataSet with its TTs can be sent back via a parameter.  If you just added an output DataSet Handle parameter, the whole thing with the schema and all the records will be sent back to the client.

Posted by DenDuze on 03-Jan-2020 13:16

Hi Laura,

Yes I understand that but I thought that when you sent an instance of a class to the server as input-output that that object would be send back to the client with everything that belongs to that object. So also all datasets/buffers/tt's that are created/changed on the server.... but it looks like that does not work.(because they are dynamically created)

I changed it for now like Simon suggested, so with a static defined temp-table that holds a jsonObject instance with the content of the dataset taht is created on the server --> That works.

The only problem I still have is the fact that I have some memory leaks (datasets and temp-tables that should be destroyed but are not) - have to test further how to be sure that everything is cleaned up correctly.

Posted by Laura Stern on 03-Jan-2020 13:21

Ok.  Though why do you need a static TT to hold the jsonObject?  Why not just return the jsonObject on its own?  

Posted by DenDuze on 03-Jan-2020 13:38

Hi Laura,

I tried that with a property in that instance of type jsonObject but that also did not work.

Posted by DenDuze on 03-Jan-2020 13:40

or do you mean input <instance of the class>, output <instance of jsonobject>?

I liked the idea to just do a input-output <instance of the class> because all code regarding that object is on 1 place

Posted by Laura Stern on 03-Jan-2020 17:53

I wasn't really thinking that specifically.  Yes, input of one, output of the other should work.  But I would have thought that the input-output object case would work as well, where the jsonObject property is set before returning.  If it doesn't work, that seems wrong.

And just to address your original question/point:  Why doesn't setting the handle to your dynamically created Dataset send back all the records?  

First of all, for some handle types, it would be impossible to recreate the state of the handle back on the client.  Take the case of a socket object, for example.  So we would have to treat a TT or DataSet handle as a special case if we wanted to send back the contents/state and not just the handle value.  Inconsistency is usually not a good thing.

Secondly, what if we did serialize that back.  On the client, we could not use the same handle value(s), as they might conflict with existing handles already there.  So we'd have to create new ones. And then what if you sent that object back to the server again?  Do we again serialize all the records back to the server?  And if we did, once on the server, we'd again have to re-create the handles.  The original copy you had there would get "lost".  Is this all really what you want?  So the semantics of this operation are not clear and problematic.  And of course, you would lose the ability to just round-trip the handle value, which is what we do now.

Posted by Thomas Mercer-Hursh on 03-Jan-2020 18:03

While I understand that it would be easy if one could send an object back and forth, my instinct is to think that an object is too inherent to the operating context for it to make sense to send it to a different operating context.  It is one thing to send data, but an object is both data and operations.  One of the ways to look at this is to flip the original context, i.e., to just focus on the part about the server sending out an object.  One can see initially how this might be desirable with a 4GL client, but what if one then replaces that 4GL client with a web page or a smart device?  Sending the same data could easily make sense regardless of the client type, but sending the operations as well makes no sense.

Posted by DenDuze on 06-Jan-2020 06:44

I understand what you are saying and indeed I can see why it does not work like expected but still if you do not know that it works this way it is very confusing.

You have the data on the server before you go back to the client, no errors come up but on the end on the client you have nothing...

No problem, it works with that static temp-table

This thread is closed