#1 mORMot 1 » mutlithread and sicPerUser variables » 2013-04-28 09:35:26

LoPiTaL
Replies: 1

Hi everyone!
I have a doubt about handling multithreads, lets see:

I have defined an interface-based service with sicPerUser mode.
The class implementing this service contains a variable of a class inheriting from TSQLRecord for cache purposes.
This service has two methods, one to update (it just assigns several RawUTF8s from the incoming record to that variable) and one to retrieve the information from that variable.

My doubt is, is this a correct way to handle this? Or should I use critical sections when updating / retrieving the data? Or should I use a completely different aproach?

I post also a bit of the code of the update procedure:

  FInformation.Name:=FRecord.FName;
  FInformation.NickName:=FRecord.FNickName;
  FInformation.BirthDate:=FRecord.FBirthDate;
  FInformation.EMail:=FRecord.FEmail;

where all the vars are RawUTF8 but the BirthDate, which is TDateTime.

The retrieving procedure is similar but reversed (FRecord.FName:=FINformation.Name; ....).

Best regards,
LoPiTaL

#2 Re: mORMot 1 » How to use sicPerUser, sicPerSession, sicPerGroup in the client? » 2013-04-16 17:28:14

Thank you! It works fine now.

Another question (I don't open a new thread since it is related).

When creating the perUser instance, the ServiceContext is still not initialized, so it is not possible to retrieve the context information at creation time.
This can be solved by initializing SErviceContext before creating the instance in the "TServiceFactoryServer.ExecuteMethod", moving the following lines:

    ThreadServer := @ServiceContext;
    //WR := TJSONSerializer.CreateOwnedStream;  //This one is not related, and should be kept where it is
    try
      with ThreadServer^ do begin
        Factory := self;
        Session := @Ctxt;
      end; // RunningThread is already set at thread initialization

to the beginning of the method, and the following to the end:

    finally
      with ThreadServer^ do begin
        Factory := nil;
        Session := nil;
      end;
      //WR.Free; //This one is not related, and should be kept where it is
    end;

This can be done? Or there is any other consideration?

If so, then it may be usefull to have the context info at instance creation time, i.e. for initializing data for caching, and using it without the need of checking in all the interface methods if the data is nil or not.

Best regards,
LoPiTaL

#4 Re: mORMot 1 » How to use sicPerUser, sicPerSession, sicPerGroup in the client? » 2013-04-15 12:51:01

Hi all!
I have both client and server in sicPerUser. The error is not a contract mismatch.

The problem is when calling the Get function from the service factory, which always returns False.

I copy and paste here the code of that function, in the "mORMot.pas" file, so I can show you:

function TServiceFactoryClient.Get(out Obj): Boolean;
var O: TInterfacedObjectFake;
begin
  result := false;
  if Self=nil then
    exit;
  case fInstanceCreation of
  sicShared:
    O := TInterfacedObjectFake(fSharedInstance);
  sicSingle, sicClientDriven:
    O := TInterfacedObjectFake(CreateFakeInstance);
  else exit;
  end;
  pointer(Obj) := @O.fVTable;
  O._AddRef;
  result := true;
end;

In it, it is clear that it will return an interface only when the instance creation is of type sicShared, sicSingle or sicClientDriven. Any other option will go to the "else" part of the case and return False.

My code to get the interface is as follows, as I stated in the first post:

 //With sicShared works fine, with sicPerUser returns always false
  if FClient.Services.GUID(IMyINterfaceCreatedWithSicPerUser).Get(LMyInterface) then begin
    //Work with interface
  end;

Note that if I change to sicShared (of course, in both client and server) it works fine, so the register of the interface is correctly done both, in the server and in the client.

So I am guessing that I should retrieve the interface to work with with another method, but it is not stated in the documentation nor I have found it around the code.

Best regards,
LoPiTaL

#5 mORMot 1 » How to use sicPerUser, sicPerSession, sicPerGroup in the client? » 2013-04-14 15:08:43

LoPiTaL
Replies: 8

Hi everyone!
I have been playing a bit with interface-based services using a Delphi client. But I was always doing tests with sicShared (the default creation mode).
Now I am trying to stop "playing", and start to do actual work, so now I need an interface-based service with sicPerUser mode instead.

How can I work with this from the Delphi client? I am trying to do the same as with sicShared, but the result is always False:

  //With sicShared works fine, with sicPerUser returns always false
  if FClient.Services.GUID(IMyINterfaceCreatedWithSicPerUser).Get(LMyInterface) then begin
    //Work with interface
  end;

I have seen that the "Get" procedure returns True only if the creation mode is sicShared, sicClientDriven or sicSingle. With any other creation mode, it returns False. So, which is the correct way to work with this creation modes?

Best regards,
LoPiTaL

#6 Re: mORMot 1 » User registration and autentication » 2013-04-10 21:31:16

As expected, it works perfectly fine, thank you.

Best regards,
LoPiTaL

#7 Re: mORMot 1 » User registration and autentication » 2013-04-04 06:38:55

Ok, I will try it. Thank you for your quick answer.

Best regards,
LoPiTaL

#8 mORMot 1 » User registration and autentication » 2013-04-03 18:44:51

LoPiTaL
Replies: 3

Hi everyone,
I think this is already answered, but I cannot find anything I can use.

My situation: I want to provide a server where anybody, via a web interface, can register a new user. Afterwards, the user will log in with his registered user name, and from here, all operations will be done logged in.
Since I am using a web interface for everything, I am going to use only the interface-based services as the interface with the server. Internally, these services will comunicate with the database layer to perform whatever.

About the security, everything must be secured (using the framework security options), but the registration of a new user, which, since there is no user yet, it cannot be secured.

So I am guessing that I will need two TSQLRestServerDB: one with the users database, the one which will handle the security and provide the interface needed for the application; and another TSQLRestServerDB which provides the actual application's database, this is right?
Also, to allow the users to register a new user without security, I may need a third server, this can be just a TSQLRestServerFullMemory, which will provide the interface needed for the creation of new users, with the HandleSecurity parameter set to false.

At the HTTP layer, I will use only one TSQLHttpServer with the two user handling servers passed in the creator.

Do all of this make sense? Or am I confused?

Best regards,
LoPiTaL

#9 Re: mORMot 1 » Smart Mobile Studio mORMot class server » 2013-02-24 18:16:40

Finally!
After a bussy week and a hard time with the SMS' RTTI I have prepared a new release of the client.
The ORM part is pretty similar to the Delphi's one, it is not required to autogenerate anything on this part. Everything is managed through the RTTI, and it works pretty fine big_smile. It even can be shared with the Delphi server with some {$IFDEF}s.
The interface-based service is similar to the previous release, so here the autogeneration is requiered until the SMS RTTI supports functions and interfaces also.

I have prepared also a new project, SMSTests, meant to be the test bench of the features of the client. In it, all the features are tested: ORM, interface-based services, connection / disconnection, blobs and dates; everything in both behaviours, synchronously and assynchronous.
The old project, mORMotSampleProject, remains as it was, and it is an easy way to get started with the client.

About the tests, I have tried it with the SMS client, Firefox and Chrome and it worked fine on them. The problem was with internet explorer, which sometimes works fine, sometimes does not work at all (the most times). I don't know why...

Best regards,
LoPiTaL

#10 Re: mORMot 1 » Smart Mobile Studio mORMot class server » 2013-02-15 15:43:47

Interesting the RTTI for SMS!!
In Delphi, the mORMot only uses properties for the records definitions, so maybe this can be all what is needed for the ORM part!! No more need for autogenerating it....
This weekend I will try it.

About the other part, interface-based services, we would need there the methods / functions RTTI to be able to work with it without autogenerating, but anyway, it looks pretty interesting.

I hope this weekend to have prepared the test project and the basic usage project, and maybe among some of the RTTI tests.

Best regards,
LoPiTaL

#11 Re: mORMot 1 » Smart Mobile Studio mORMot class server » 2013-02-12 11:30:32

warleyalex wrote:

I'd like to test this functionality, but seems that I have do add functions (AddComplex, Accum, LongCall) at proj n.14.

The modified interface for that project adding the other functions is also included in the rar package of the SMS project. Just replace the default one by the modified one, recompile, and reexecute the server.

ab: I have found that TDateTime and TBytes (blob) will need a special treatment in the autogenerated code. Both are already working in the ORM side, but I want to try them in the interface-based part before publishing anything. Hopefully today or tomorrow I will publish it. I tell you, so you can wait a bit more before begining the autogenerating procedure.

Also I want to prepare a little Delphi and SMS projects to be used as a Test Framework (TDD ? big_smile ) and let the sample SMS project easy to understand, just connecting to the samples 4 and 14 as they are right now, because the SMS project is begining to be quite dificult to follow.

Best regards,
LoPiTaL

#12 Re: mORMot 1 » Smart Mobile Studio mORMot class server » 2013-02-10 18:34:06

Hi again!
I have almost both, date/times and blobs working.
I can convert from TDateTime to string an viceversa, and the same for the blobs in Base64 encoding.

But I can't make them work when transmitting to the server. I have several questions about it:
1. How is the TDateTime transmitted when used in a query, when it is appended to the URI?
I.e. I want to transmit Date<=:(2013-03-10):
and I actually transmit
  Date%3C=:(%27%C2%B1%C2%BF%C3%AF2013-03-10%27)
Is it correct?

2. How is the TDateTime transmitted when used in a record object, this is, when it is transmitted in the BODY of the request? Right now, I have got it transmited as a float (directly the TDateTime variable). Is it correct?

Best regards,
LoPiTaL

#13 Re: mORMot 1 » Smart Mobile Studio mORMot class server » 2013-02-10 11:42:27

Ok, I have implemented the Variant2string function, used in the SQLFormat function, so its behaviour is pretty similar to the mORMot one's. The main difference is that in the SMS are not supported Pointers, Classes nor Currency. Thus, it is only supported strings, integer, float and boolean.
Pointers will not be supported (since SMS itself does not support them).
Classes I don't see the need of them in a SQL query, so I haven't implemented it...
Currency is not supported directly in SMS, and since it is just a float number (or int64, don't remember), SMS detects the Variant type as one of those, so it is not possible to generate it. But since it can be done manually before calling the SQLFormat function it is not a big problem (just follow the mORMot implementation).

Best regards,
LoPiTaL

#14 Re: mORMot 1 » Smart Mobile Studio mORMot class server » 2013-02-10 00:22:50

ab wrote:

The animated circle which is displayed as popup on web pages, when something is happening in the background.
If your service is expected to take some time, it could be a good idea to show such an animation.

Yes, there is a class "TW3CustomAnimation" which can be set up to spin an image like that one. I haven't explored too much, so maybe there is something more suitable...

The only problem with this is that it can be done only when connected using assynchronous mode, because the synchronous mode hangs the UI.
To make this possible, I have implemented the assynchronous interface-based service, so now everything can be done assynchronously and the UI stays responsive.

NOTE that I have changed the Intf_Services file!!!

Also I have changed a bit the working of the assynchronous mode making the callbacks per query instead of globally: since the user can press several buttons at a time, the callbacks can be changed while in the query, so now each callback is stored in the HTTP object instead of storing it in the client to prevent the changing of the callback while waiting the answer from the server.
I have also added a new function (LongCall) to test this functionality, and it works pretty fine.

Tomorrow I will implement the SQLFormat.

Best regards,
LoPiTaL

#15 Re: mORMot 1 » Smart Mobile Studio mORMot class server » 2013-02-08 19:09:01

ab wrote:

But using blocking communication just does make sense and is much easier to work with.

I though that also, so I will not modify any more the interface-based services.

ab wrote:

How do you add a "waiting spinner" in SMS? Is there anything "native"?

What do you mean?

ab wrote:

No problem about class external(JObject) - it was just a weird syntax, but when generated as JavaScript, it will use a plain javascript object - so no speed penalty.

big_smile Yes, it is a bit weird, but it does the trick: inheritance and checking in compile time in a JavaScript object - just perfect big_smile

ab wrote:

About session closing, what about the window.onbeforeunload event?

Maybe, I have to check it.

ab wrote:

Could you refresh your source code (including "array of const" version of SQLFormat), so that I will work on the wizard generation?

It is done. Tomorrow I will try to implement the features you have, this is, use integers, strings and so on, and not only strings.

When I have something new, I will tell you, but it is almost done, apart from the SQLFormat function and the disconnecting process, isn't it?.

Best regards,
LoPiTaL

#16 Re: mORMot 1 » Smart Mobile Studio mORMot class server » 2013-02-08 15:17:22

Hi ab!

1. The "array of const" is buggie, the compiler throws an exception, so I put it aside when I was working in that function. Nevertheless, I returned now to it, and digging a bit (and with more knowledge of the inners of SMS now than then) I have found a workaround, so I will implement it as "array of const". In fact, I have got it already working (but passing all the items to string big_smile ).

2. The record is not usable, since there are no pointers in SMS, then you cannot typecast a record to any other kind. So you cannot declare any function expecting a generic record, so the parsing from record to variant MUST be always done with asm end sections.... It is not usefull.
The variant can be used without more problems.

I have chosen to use "class external (JObject)" because I have got the code mistakes thrown by the compiler, and not in runtime, being less error prone. Since it is supposed (now) to be an autogenerated code, it should not contain any errors, but still, I think is clearer to use the class externals. Why don't you like this kind of classes?

3. It is because the calling is done in a synchronous mode. In fact, the interface-based services MUST be run in synchronous mode.
I know that javascript is asynchronous, but the Javascript object used to perform HTTP queries (XMLHttpRequest) supports also synchronous mode (https://developer.mozilla.org/en-US/doc … s_Requests). I don't know where the trick is, but it works and it is supported by every web browser...

About my implementation, in TmORMotClient, there is a property called Assynchronous. If this is set, then the query is performed asynchronously: it returns from the function without having the response.
Also there is an "internal handler", which is set in all the class methods and is where the next code of the function will be executed. Then, when the internal handler is called, this handler calls the external one, that is where the user's code handling the result of the query must be placed.
If this variable is not set, then the internal handler is called inmediately after the query, performs the internal operations and return without calling the external handler.

I.e:

function TmORMotClient.AddRecord(ARecord: TmORMotRecord): Boolean;
  //Internal handler. This method will be called both, in synch and in asynch mode.
  function AddedRecord(AResponse: string): Boolean;
  var
    LVariant: Variant;
  begin
    //Process the response
    REsult:=False;
    if (AResponse <> '') then begin
      LVariant:=JSON2Variant(AResponse);
      if ErrorReturned(LVariant) then begin
        //Error handler is always executed, both in synch and in asynch
        CallErrorHandler(JmORMotError(LVariant));
        Exit;
      end;
    end;

    //External handler is only executed if in asynch mode (the app is not waiting the function's result, so we must call it explicitly).
    CallExternalHandler();
    Result:=True;
  end;

var
  LData: string;
  LResponse: string;
begin
  Result:=False;
  LData:=JObject2JSON(ARecord[0]);

  //Prepare asynchronous callback
  FOnQueryCallBackInternal:=
  procedure(AResponse: string)
  begin
    AddedRecord(AResponse);
  end;

  //Perform the post
  LResponse:=Post(ARecord.TableName, LData);

  //If we are in synchronous mode, call manually the internal handler and return.
  if not FAssynchronous then
    Result:=AddedRecord(LResponse);
end;

A bit tricky, but this way both types of connections are supported, but for the interface-based services!!
Maybe I should refactor the interface-based services a bit more to support it also, though I don't see any advantage in making asynchronous calls in this part of the framework.
What do you think?

Best regards,
LoPiTaL

#17 Re: mORMot 1 » Smart Mobile Studio mORMot class server » 2013-02-07 23:26:33

Ok, so it is here!
I have uploaded to Dropbox a new version with the changes we talked.
Changes mainly are:
  . Renamed *Server by *Client.
  · Added assynchronous / synchronous queries.
  · Refactored the methods / interfaces for the interfaced-based services usage. Now it can be used directly interfaces, being the weird TMethod / JMethod pair hidden.
  · Modified the TmORMotRecord class, so now it have functions like FillPrepare, FillOne, CreateAndFillPrepare, etc... The pair TmORMotRecord / JmORMOtRecord is hidden also.
  · Added and handled sicClientDriven life time.

Several notes:
  · Since the shutdown of SMS is not guaranteed to be executen by the web browser, it is necessary the usage of timeouts in the server to manage unclosed connections and clientDriven instances not freed (I guess this is already implemented, but just confirming it).
  · I have modified the definition in the interface of the DemoProject4, in order to have an interface with var parameters and class parameters. Also the new definition is meant to be created with sicClientDriven, so the Accum method is usefull.
  · SMS does not support out parameters.
  · The interface retrieving must be done by name, but this shouldn't be a problem since the name will be autogenerated big_smile
  · Be warning! Both projects (4 and 14) works with "localhost" as server name, but nº 4 uses port 8080 and nº 14 888, so choose the correct one for each project.

ab:
  The autogenerated requiered code is the one found in the two Intf_* units (Intf_ORM.pas and Intf_Services.pas). I tried to be as rigid as possible with the names, always naming the same way things related (ICalculator, TCalculator, JCalculator, JCalculator_Add....). Please, tell me if the code is OK and if it is possible to automate.
Note the "weird" declaration of the var parameters in the JSON struct (i.e. "_VAR_SumResult"). It must be this way (begining with _VAR_), so SMS can detect which variables are "var" and return the correct values.

Any question, problem or suggestion, don't hesitate to ask.
Best regards,
LoPiTaL

#18 Re: mORMot 1 » Smart Mobile Studio mORMot class server » 2013-02-07 21:06:07

Sorry for my delay, but I have been refactoring the code a bit, combining both projects so only one copy of the library must be maintained. Also it seems more to the original mORMot code, with calls like FillPrepare, FillOne, GetService, etc...
The ORM part is already working fine, and almost all the interface-based services part. I am testing now with var and class parameters (out parameters are not supported by SMS).
In any time now, I will have the code and will share with you.

Best regards,
LoPiTaL

#19 Re: mORMot 1 » Smart Mobile Studio mORMot class server » 2013-02-03 14:08:06

Perfect! I like the idea.
I'm going to work on it when I arrive home.
When I have something,  I will tell you, so you can continue with the second step.

Best regards, 
LoPiTaL

#20 Re: mORMot 1 » Smart Mobile Studio mORMot class server » 2013-02-02 19:24:52

ab wrote:

I wanted to allow some quick HTTP browsing of the available ORM classes, method-based services and interface-based services, from any browser.
For ORM classes and interface-based services, no need to read the source code, just create the SMS/C# wrapper classes from the RTTI available at runtime on the server.

Ok, this is the piece of the puzzle I wasn't seeing, so I needed some parser or external .exe to generate the RTTI of the interfaces. But the RTTI is already in the server!... Nice!

ab wrote:

We may had an option to the server (with command line or external config file), or enable the feature only if the server is run within the Delphi IDE (which could make sense, and seems to be secure).

I think it would be better if implemented as a method only executable by the administrator, using the security features of the server. It would be a demonstration of the security of the server, and would be perfectly integrated in it.

ab wrote:

Did you see that I've added logging on console feature (with colors) to mORMot?
I found it very easy to debug interactively client remote access, e.g. from SMS applications.

Nop, I haven't got my computer with me, so I haven't got access to Delphi nor SMS today. On Monday I will check it big_smile

ab wrote:

I'm quite confident we are able to publish some mORMot servers process very easily to work with SMS, with no external .js files (needed e.g. if you want to access to DataSnap or RemObjects).

Any help and feedback is welcome.

Whatever you need, please, don't hesitate to ask!
After doing the changes to the SMS unit we talked on the previous post, I am going to try to create an interface-based service on the server which returns the interface-methods of the server as a SMS unit. If it can be possible, the work with SMS will be very very simplified and even error proven!

When I have something, I will tell you big_smile

warleyalex wrote:

Just a word.

If you want to do an app in a web site where you have complete control over the way everything is, and indeed have to manually do everything, then SMS looks good, but Jquery wouldn't be a better choice? You can perform all CRUD operations, you can handle security and it's able to execute remote methods.

warleyalex, yes, working with SMS is just like a wrapper to javascript (and then, also a wrapper for Jquery, as it is at top of javascript). The problem then, is that you have to know two completely different languages: Javascript and Delphi. With SMS, you only need to know Delphi to work in both sides. You have Delphi for the server, Delphi for stand-alone clients and now, Delphi for the web. When we finish what we have been talking here, then you won't need to do anything manually, the security will be managed by the mORMotClient class, and the CRUD operations and the remote methods will be handled by the auto-generated classes, so the working with the web-clients will be simplified.

Best regards,
LoPiTaL

#21 Re: mORMot 1 » Smart Mobile Studio mORMot class server » 2013-02-02 13:53:20

Hi Ab! I also think that the code can be improved. I published it as I get it working, so it actually can be improved.
If you don't mind, I can try to help you with that, since I have already touched the SMS RTL.

ab wrote:

I would like to enhance the SmartMobileStudio side code, in order to be able to directly use a class with a method for interface-based services, and perhaps make cleaner the CRUD access.

This is a bit hard. Since SMS does not have RTTI, the class (or interface) can not be defined just as in Delphi and be registered with the client.
I think that it would be possible to prepare an executable, that can be compiled before the server and launched in the "On After Compilation" event of the server, that could be used to generate an SMS unit with the classes / interfaces ready to be used with the client class in SMS and the mORMot server.
In fact, it should only prepare a class with a private inher class. The outer class (being also interfaced with the server's interface in the case of the interface-based services) will have the declared server methods. The inner class should be the currently "external" class, to be used as the JSON generator / parser.

About the CRUD access, I think that the aproach should be very similar, but the difference here is that the outer class may be the very same to all records (since the methods are the same), just changing the inner class to the correct "external" class.
Of course, from the user's point of view, this would be all invisible (all JSON fields and so being private) and he will only see the declared server methods.

What do you think?

Edit: I was looking now to the SynProject page, and I have seen that it has a built-in Delphi parser. Can it be used in the executable I was talking about? So it would not be necessary to recompile the exe all the times, just passing to it the source files as parameters and it can parse them and generate the corresponding units. The only needed step would be to call the executable in the "On After Compilation" event of the server.

ab wrote:

I will probably also rename mORMotServer.pas into mORMotClient.pas, and all *Server names into *Client, since it is a client class.

Yes, the *server sufix was just refering "connect to server", but yes, it should be client. This is an easy change. big_smile

ab wrote:

And include a compiled .html file within the corresponding sample folders.

This can be done just including the compiled .html generated by the SMS compiler. I removed it just to save space, I thought that everybody could just compile it and regenerate it, but I can include it.

Now I haven't got my computer, but the next week I will be working on all of this.

Best regards,
LoPiTaL

#22 Re: mORMot 1 » Smart Mobile Studio mORMot class server » 2013-01-30 17:10:34

ab wrote:

THTMLHeaders class is a nice idea, but is also slower than expected, since breaking some implementation patterns of mORMot (like temporary memory allocations, and conversion between string<->RawUTF8)

Ok, I got it.

ab wrote:

I suppose http://synopse.info/fossil/info/aa1fa79b05 should do the trick.

Yes! It works perfectly fine now!! Tried in IE 9, Firefox 18.0.1 and Chrome 24.0

Feel free to add the SMS units to the repository!

Best regards,
LoPiTaL

#23 Re: mORMot 1 » Smart Mobile Studio mORMot class server » 2013-01-30 13:59:34

ab wrote:

I've added TSQLHttpServer.AccessControlAllowOrigin property to handle cross-site AJAX requests via cross-origin resource sharing (CORS).
http://synopse.info/fossil/info/9d97879a75

Sorry, it does not work.
If you reply with the "Access-Control-Allow-Origin: *" header, then all "read" methods will work (this is, GET and OPTIONS). Even the browser does not query for the access control (does not send an OPTIONS method), just send it and accepts it if that header exists.

But when you want to send a POST or like, then the OPTIONS query is sent with a header called "Access-Control-Request-Headers", which contains the requiered headers to be CORS accessible. The server MUST response to that query with another header called "Access-Control-Allow-Headers", which contains an EXACT match of the requiered headers that contained the OPTIONS query.

With this implementation, only CONNECT, DISCONNECT and LIST will work. You cannot ADD, DELETE or UPDATE records.

If you look at my implementation, you will see that when I prepare the headers to be sent, all are constant, in exception of the "Access-Control-Allow-Headers", which I take from the LHeadersIn.

Just wondering, why don't take the THTMLHeaders class and use it within the TSQLHTTPServer? It is just a stringlist and simplifies the work with HTTP headers A LOT. It can parse directly all the headers with the Text property, and after working with them, retrieve them again with the same property.

Best regards,
LoPiTaL

#24 Re: mORMot 1 » Smart Mobile Studio mORMot class server » 2013-01-30 08:06:53

Hi!
Under Chrome it seems to work perfectly fine. Under IE it also worked fine.
In Firefox, I have tried in versions 13.0, 14.0 and 18.0 (the updater didn't let me chose any other version sad ) and also it has worked. Can you try with a newer version of firefox?

Best regards,
LoPiTaL

#25 Re: mORMot 1 » Smart Mobile Studio mORMot class server » 2013-01-29 20:53:14

Hi everyone!
Thanks for all the answers!


Roberto Schneiders wrote:

I'm not able to compile in version 1.1.0.371 Smart Mobile Studio :
Syntax Error: There's no accessible member with name "properties"! [line: 613, column: 20, file: mORMotServer]

I have uploaded a new version that solves the problem with the properties field (it was introduced in 1.1.0.372). Now the projects compiles in 1.1.0.371+.

Roberto Schneiders wrote:

Interesting. Apparently only works in Internet Explorer.
In Chrome just does not work. In Firefox the following message appears:
This site () is requesting data storage on your computer for offline use

Doing some tests I have found that Internet Explorer ignores the CORS directives (probably it ignores only the different ports part), while the others follows the CORS as is. Due to this, it work only in IE and not in the others.
To solve this, check the following:
  · You must be using, as the project samples servers, the provided TSQLRestServerDB_CORS class instead of TSQLRestServerDB or TSQLRestServerFullMemory or any other, in order to do cross site access (although the cross site is limited to the port). This class is in the HTTPHelpers.pas unit (this unit is for Delphi, not for SMS).
  · Be sure to have the lattest (today) version of the repository, or at least, correct manually the following bug (they are only a couple of pointers, easy to workaround): http://synopse.info/fossil/info/91f8f3ec6f

I also found an inconvenient with Firefox: encodeURL() does not encode the simple quotes, while the browser does, doing the signature invalid. I solved it in the newly updated version.

I tried in IE 9, Firefox 18.0.1 and Chrome 24.0, and it works in all three. The only problem was in IE 9, that if I use the IP address instead of 'localhost', it does not work; with 'localhost', it worked fine. With the other two, no more problems.

Roberto Schneiders wrote:

This site () is requesting data storage on your computer for offline use

Yes, this is normal. It appeared also to me.

ab wrote:

I'll also check TSQLRestServerDB_CORS, since it is also on the roadmap.

It is a very very basic implementation of the CORS, just allowing ALL connections from EVERYWHERE. Since the security is handled by the server, this is not really a problem, but it would be nice to be able to choose from where and so...
There is also a nice class to work with headers, making really easy the work with them, and not having to play with Pos, length and so in a single string.

ab wrote:

This is legend.... dary!

Thank you big_smile

ab wrote:

Could we integrate it directly in the official mORMot source tree?

Of course! I uploaded it with that in mind. Check that you have my lattest upload (to check it, look in the JavascriptHelpers.pas file and see if there is a function called 'VariantProperties')

ab wrote:

I still can't understand why SMS uses this awful XML .opp format.
Just unmaintainable for any serious project.

Yeahh I know! And if you choose to use external files, the files MUST be placed in the same folder as the project, useless anyway!!! sad

Thank you for all your comments!! I am glad you liked it!

Best regards,
LoPiTaL

#26 mORMot 1 » Smart Mobile Studio mORMot class server » 2013-01-29 14:21:37

LoPiTaL
Replies: 57

Hi everyone!
I have developed a Smart Mobile Studio class which is able to connect to the mORMot server, and I wanted to share it with you.
The class is able to:
· Handle security.
· Perform all the CRUD operations (delete, update, add and get) with ORM records.
· It is able to execute remote methods, including the usage of var and out parameters.

The SMS projects consists in:
    - mORMotServer: which is where the mORMot connector resides.
    - Computation: helper computation functions, crc32 and SHA256, extracted from mORMot's blog page:
       http://blog.synopse.info/post/2012/04/1 … JavaScript
    - JavaScriptHelpers: which contains several low-level functions.

Due to the lack of RTTI in SMS, the definition of the server methods and the ORM records are a bit strange, requiering in both cases two records instead of one (or one interface), but it is still pretty straight forward.

In the package, there are two samples, one using the "Project 4 server" sample that comes with the mORMot framework, to demonstrate the hability to work with ORM records; and another using the "Project 14 server", to demonstrate the hability to execute remote methods.

Also, it is included a unit called HTTPHelpers.pas, which contains a very basic class inherited from TSQLRestServerDB, TSQLRestServerDB_CORS, which implements CORS access control, thus enabling access to the server from different domain and port. This is useful when working from Smart Mobile Studio and testin the javascript application from the web browser. Without this, it won't work. Just replace your TSQLRestServerDB with TSQLRestServerDB_CORS, and that's all.

Requiered versions:
· SmartMobileStudio: 1.1.0.372 (or higher)
· mORMot framework: today's one, 10:47 - 2013-01-29,  9bae7dc630

Link (I am unable to upload it to the forum):
https://www.dropbox.com/s/um7p1j2bwow5q … 0Smart.rar

Best regards,
LoPiTaL

#27 mORMot 1 » DELETE with SELECT URI parameter error » 2013-01-20 14:30:57

LoPiTaL
Replies: 1

Hi everyone.
I am trying to send an HTTP DELETE with a select parameter in its URI to the server, in order to be able to delete more than one record at once.
Looking into the code, I have found this:

// ModelRoot/TableName?WhereClause to delete members
SQLWhere := Trim(UrlDecode(URI.Parameters));

in the URI method of TSQLRestServer class, in the 'mDELETE' case statement.

The problem is that the URI parameters, if logged as a user, is not only the where clause, but also the signature, like this:

'Name=:(''NameToDeleteEveryRecordFromIt''):&session_signature=000000410000000837DEB7E6'

so the generated variable SQLWhere is invalid, containing the where clause desired (Name=:(''NameToDeleteEveryRecordFromIt''):), but also the other URI parameters (&session_signature=000000410000000837DEB7E6).

I think that the parsing of the SQL where parameter should be done the same way as any other parameter, using:

UrlDecodeValue(URI.Parameters,'WHERE=',SQLWhere,@URI.Parameters);

so the URI should be "ModelRoot/TableName?where=WhereClause" instead of "ModelRoot/TableName?WhereClause".

Of course, this will make a breaking change, because the previous DELETE calls will not work with the new implementation; but without it, I think it is impossible to delete multiple records at once (most part of the time, the clients will be logged in, thus session_signature will always be appened).

Best regards,
LoPiTaL

#28 Re: mORMot 1 » Interfaced based services or direct access to database? » 2013-01-06 20:17:34

ab wrote:

I've written some new blog article, which may help you, from the architectural point of view.
See http://blog.synopse.info/post/2013/01/0 … and-mORMot

Starting point of it was your question here.
Thanks!

I have never thought that my question was so deep big_smile I am going to read your article right now!

ab wrote:

Note that in order to serialize the TDatabaseRecord records as pure JSON, you would need to code the writer and reader rountines by hand, whereas it is already included with TSQLPerson.

So this is really important if I am using an AJAX client, and didn't want to write too much code... I have read the SAD document before starting (quite strange in me big_smile), but when I began to write the code I forget about this detail (is really extense the SAD document....). So, I think that the best way to go is using directly the access to the database where the coding to standard JSON is already implemented and I have only to code the AJAX part.

Best regards,
LoPiTaL

#29 Re: mORMot 1 » Interfaced based services or direct access to database? » 2013-01-04 13:36:48

Hi ab, thank you for your quick and detailed answer.

ab wrote:

It has been optimized a lot (e.g. with a cache and other nice features), so I do not think reinventing a CRUD / database service is worth the prize. You have secure access to the ORM classes, with user/group attributes.

Yes, this is what I thought and what made me doubt.

ab wrote:

In fact, architecturally speaking, your question faces another point: the layer separation.

I didn't thought about it, but it is interesting. I will have this into account in the future

ab wrote:

Don't be afraid of writing some translation layers between TSQLRecord and records (i.e. entities and value objects). It will be very fast, on the server side.  If your service interfaces are cleaner, don't hesitate. But if it tends to enforce you writing a lot of wrapping code, forget about it.

Ok. I get the point.

Thank you very much for the answer! It has been very explanatory.

Best regards,
LoPiTaL

#30 mORMot 1 » Interfaced based services or direct access to database? » 2013-01-04 12:42:34

LoPiTaL
Replies: 6

Hi everyone!
I am a bit new to this framework and to the technologies related, so maybe my question is a bit stupid, but I couldn't find any suitable answer anywhere.

I have wroten a test server (using TSQLRestServerDB), which has a service that provides basic access to the database as follows:

  TDatabaseRecord=record
    Name: string;
    Age: integer;
  end;
  TDatabaseRecordArray=array of TDatabaseRecord;

  IDatabaseService=interface(IInvokable)
    ['{9ABC8235-5102-4C02-8469-0BCA606C1CF0}']
    function Add(const ARecord: TDatabaseRecord): integer;
    procedure Delete(AIndex: integer);
    procedure List(var ARecords: TDatabaseRecordArray);
  end;

The class implementing this service uses a class inherited from TSQLRecord to access the database. This class has similar parameters to the record TDatabaseRecord.

TSQLPerson = class(TSQLRecord)
  private
    FName: RawUTF8;
    FAge: integer;
  published
    property Age: integer read FAge write FAge;
    property Name: RawUTF8 read fName write fName;
  end;

The client uses the interface to connect to the server and everything works OK.

But then I thought, why don't use the TSQLPerson class directly in the client, so it can access directly to the database bypassing all the process the service has to do?

It worked also, of course.

So my question is: which way is better? Are the services meant to be used like this? Is it safer to access directly to the database from clients? I started with the services way thinking that may be more secure the usage of services instead of direct accessing. But since the framework already has a lot of security functionalities maybe I am overloading the server without achieving anything...

Note that my clients will be AJAX basically, not Delphi clients (don't know if it is relevant).

Best regards,
LoPiTaL

Board footer

Powered by FluxBB