You are not logged in.
Ok, I can confirm it works when including the directive: {$RTTI EXPLICIT FIELDS([vcPublic])}
as indicated in test.core.base.pas.
Pretty cool
Stable FPC (3.2.x) does not have this RTTI. You need the trunk (3.2.3) version - we support it.
Hmmm, is trunk not 3.3.1?
Using fpcupdeluxe on Windows, I installed fpc trunk and lazarus trunk.
About says fpc 3.3.1 and Lazarus 3.99
I also tried to install fpc fixes-3.2 and lazarus stable.
In that case it says fpc is version 3.2.3, and lazarus is 3.4
In both cases, serialization to json outputs base64 string, not "normal" json.
If I use Rtti.RegisterFromText, then in all cases (i.e. also 3.2.2) it outputs normal json.
Sample code: serialize record with RecordSaveJson/DynArraySaveJson
Hi,
Code snippet:
mormot service method returns base64 string on Lazarus
When visiting the url: http://localhost:11111/root/NotebookService.List
With Delphi returns:
{
"result": [
[
{
"ID": 9,
"Title": "New Notebook 1",
"GUID": "",
"CurrentNote": 0
},
{
"ID": 10,
"Title": "New Notebook 2",
"GUID": "",
"CurrentNote": 0
}, ...
With Lazarus (v3.4 fpc 3.2.2, installed with fpcupdeluxe) returns:
{"result":[["AA4GAAAAAAEAAAAAAAAADk5ldyBOb3RlYm9vayAxAAAAAAAAAAAAAgAAAAAAAAAOTmV3IE5vdGVib29rIDIAAAAAAAAAAAADAAAAAAAAAA5OZXcgTm90ZWJvb2sgMwAAAAAAAAAAAAQAAAAAAAAADk5ldyBOb3RlYm9vayA0AAAAAAAAAAAABQAAAAAAAAAOTmV3IE5vdGVib29rIDUAAAAAAAAAAAAGAAAAAAAAAA5OZXcgTm90ZWJvb2sgNgAAAAAAAAAAAA=="],200]}
I'm on Windows 10
What's your TJsonRecord definition in the second case?
The server is a descendant of TRestServerDB, using a standard sqlite db, in turn served by a TRestHttpServer. The client is an ajax javascript application, but you could also just say using postman, i.e sending get/post http requests to the server.
You can disable caching, but you would loose performance and stability.
Right, this is just for a particular debugging scenario, where the cache is getting in the way, or could be getting in the way, and I want to disable it temporarily. Stopping and restarting the application, can be slow, and it would just be faster if I can disable the cache. From the docs it sounds like it is at the "Database" or SQL level.
A TSynCache instance is instantiated within the TSQLDataBase internal global instance,
I seem to have missed it before, but now I see I can access the DB property of the server, so looks like I can disable with
constructor TSampleServer.Create(aModel: TOrmModel; const aDBFileName:
TFileName);
begin
inherited Create(AModel, ADBFileName, True);
Self.DB.UseCache := False;
works
Hi,
I am working on an ajax client. The server is using a standard sqlite db, and as part of debugging, I am manually making changes to the sqlite data, which mORMot does not detect. So repeated ajax requests to the server do not reflect the changes I am making. How to disable mormot caching?
Thanks
Not sure if I understand the word "export". Is it possible for a TRestServerFullMemory to use the Auth tables of a TRestServerDB instance?
If I try following code:
TPublicServer = class(TRestServerFullMemory)...
TDBServer = class(TRestServerDB)...
function CreateSampleModel: TOrmModel;
begin
result := TOrmModel.Create([TOrmSample, TAuthGroup, TAuthUser,
TOrmNote, TOrmNotebook]);
end;
// create servers
Model := CreateSampleModel;
DBServer := TDBServer.Create(Model,
ChangeFileExt(Executable.ProgramFileName, '.db'));
DBServer.db.Synchronous := smOff;
DBServer.db.LockingMode := lmNormal; //lmExclusive;
DBServer.server.CreateMissingTables;
PublicServer := TPublicServer.CreateWithOwnModel(
[TAuthGroup, TAuthUser], True
);
PublicServer.Server.RemoteDataCreate(TAuthUser, DBServer.OrmInstance);
I get error: Exception class ERestStorage with message 'Duplicated TRestOrmServerFullMemory.RemoteDataCreate(TAuthUser) as TRestStorageInMemory'.
With TRestServerFullMemory, as far as I can tell, there is no way for me to delay creation of external tables until after call to RemoteDataCreate..
Can RemoteDataCreate be used with TRestServerFullMemory, e.g. TRestServerFullMemory to use Auth tables from a TRestServerDB?
From docs it sounds like this is intended for a TRestServerDB to use tables from another TRestServerDB, but I'm not entirely sure. It does compile with TRestServerFullMemory though...
- use a separated TRestServerDB for the persistence, and a TRestServerFullMemory for the services publication;
1) With the current implementation, the service is inheriting from TInjectableObjectRest, and so has convenient and automatic access to the Server/DB instance. If there are 2 separate servers, how can I access the db server from the service method implementation, which is being defined for the memory server. i.e in TNotebookService.Update, Self.Server would be the TRestServerFullMemory. How to access a separate TRestServerDB instance?
2) Just to clarify, why you make this recommendation. I can see that in a more complex situation, it will be a good idea/more flexible setup. But in a simple "CRUD app" type of situation, where each server call is going to essentially make a call to the db layer, is there going to be an advantage to this setup?
Thanks
Thanks. I was looking for the right class instead of looking for the interface.
I was curious to know what "minimal debugging" you had done?
Looking at the source, I could see a number of nested classes, and "method redirection". So I think it would take considerable time to gain some familiarity with that part of the code. Hence, I'm curious if you have some tips to bypass that, as a first step ..
Thanks a lot for the info. I'm going to be away for a few days. I will follow up when I return...
Log when update called the first time:
20240421 11111121 ! + mormot.soa.client.TServiceFactoryClient(02a53968).InternalInvoke INotebookService.Update({ID:9,Title:"General"})
20240421 11111121 ! + mormot.rest.http.client.TRestHttpClientSocket(029d52c0).InternalUri POST
20240421 11111121 ! trace mormot.rest.http.client.TRestHttpClientSocket(029d52c0) InternalRequest POST calling THttpClientSocket(029bbfb0).Request
20240421 11111121 " + server.TSampleServer(029fc120).URI POST root/NotebookService.Update?session_signature=0009b4c900274a19f9436761 in=24 B
20240421 11111121 " call server.TSampleServer(029fc120) NotebookService.Update[{ID:9,Title:"General"}]
20240421 11111121 " DB server.TSampleServer(029fc120) prepared 258us mORMotNotesVCL.db SELECT ID,CreatedAt,ModifiedAt,Title,UserId FROM Notebook WHERE RowID=? [{id:2,detail:"SEARCH Notebook USING INTEGER PRIMARY KEY (rowid=?)"}]
20240421 11111121 " SQL server.TSampleServer(029fc120) 492us id=9 SELECT ID,CreatedAt,ModifiedAt,Title,UserId FROM Notebook WHERE RowID=?
20240421 11111121 " cache mormot.db.raw.sqlite3.TSqlDatabase(02a53628) mORMotNotesVCL.db cache flushed
20240421 11111121 " DB server.TSampleServer(029fc120) prepared 151us mORMotNotesVCL.db UPDATE Notebook SET ModifiedAt=?,Title=?,UserId=? WHERE RowID=? [{id:4,detail:"SEARCH Notebook USING INTEGER PRIMARY KEY (rowid=?)"}]
20240421 11111121 " SQL server.TSampleServer(029fc120) 4.22ms UPDATE Notebook SET ModifiedAt=:(135843590859):,Title=:('General'):,UserId=:(3): WHERE RowID=:(9):
20240421 11111121 " srvr User Interface POST root/NotebookService.Update=200 out=16 B in 5.85ms
20240421 11111121 " ret mormot.rest.server.TRestServerRoutingRest(032c4e70) {"result":[200]}
20240421 11111121 " - 00.005.985
20240421 11111121 ! clnt mormot.rest.http.client.TRestHttpClientSocket(029d52c0) POST root/NotebookService.Update?session_signature=0009b4c900274a19f9436761 status=200 len=16 state=0
20240421 11111121 ! - 00.007.824
20240421 11111121 ! ret mormot.soa.client.TServiceFactoryClient(02a53968) {"result":[200]}
20240421 11111121 ! - 00.008.093
Log when called the second time:
20240421 11112003 ! + mormot.soa.client.TServiceFactoryClient(02a53968).InternalInvoke INotebookService.Update({ID:9,Title:"Generalxxx"})
20240421 11112003 ! + mormot.rest.http.client.TRestHttpClientSocket(029d52c0).InternalUri POST
20240421 11112003 ! trace mormot.rest.http.client.TRestHttpClientSocket(029d52c0) InternalRequest POST calling THttpClientSocket(029bbfb0).Request
20240421 11112003 % + server.TSampleServer(029fc120).URI POST root/NotebookService.Update?session_signature=0009b4c900274a3b461dac76 in=27 B
20240421 11112003 % call server.TSampleServer(029fc120) NotebookService.Update[{ID:9,Title:"Generalxxx"}]
20240421 11112003 % srvr User Interface POST root/NotebookService.Update=404 out=16 B in 210us
20240421 11112003 % ret mormot.rest.server.TRestServerRoutingRest(032c5170) {"result":[404]}
20240421 11112003 % - 00.000.320
20240421 11112003 ! clnt mormot.rest.http.client.TRestHttpClientSocket(029d52c0) POST root/NotebookService.Update?session_signature=0009b4c900274a3b461dac76 status=404 len=16 state=0
20240421 11112003 ! - 00.003.037
20240421 11112003 ! trace mormot.rest.http.client.TRestHttpClientSocket(029d52c0) POST root/NotebookService.Update returned 404 (Not Found) with message {"result":[404]}
20240421 11112003 ! ret mormot.soa.client.TServiceFactoryClient(02a53968) {"result":[404]}
20240421 11112003 ! - 00.003.342
On second call, it's not that the db query fails, it's that the db layer is not being called.
I have prepared a sample project:
https://www.dropbox.com/scl/fi/8s8axgdc … sfbrl&dl=0
It's a delphi project.
Steps to reproduce:
1. Press Connect
2. Type in notebook title edit, then press Add, to add an entry. (e.g. General)
3. Click on the entry in the list box (this fills the notebook edit)
4. Modify the title. (e.g. Generalxxx)
5. Press Edit, this works as expected
repeat 3 and 4. This time it shows message "Error updating.. " etc.
Hi,
I've got a small app, based on the martin-doyle InterfacedBasedServices demo.
Here are some pertinent code snippets:
TNotebook = packed record
ID: TID;
Title: string;
end;
TNotebookArray = array of TNotebook;
INotebookService = interface(IInvokable)
['{644FEAD9-5DCC-4C61-9740-C6FE8AD2CDAB}']
function Add(var Notebook: TNotebook): TServiceCustomStatus;
function Get(const NotebookId: TID; var Notebook: TNotebook): TServiceCustomStatus;
function List(var Notebooks: TNotebookArray): TServiceCustomStatus;
function Update(const Notebook: TNotebook): TServiceCustomStatus;
function Delete(const NotebookId: TID): TServiceCustomStatus;
end;
TOrmNotebook = class(TOrm)
private
FCreatedAt: TCreateTime;
FModifiedAt: TModTime;
FTitle: string;
FUserId: TSessionUserId;
public
published
property CreatedAt: TCreateTime read FCreatedAt write FCreatedAt;
property ModifiedAt: TModTime read FModifiedAt write FModifiedAt;
property Title: string read FTitle write FTitle;
property UserId: TSessionUserId read FUserId write FUserId;
end;
function TNotebookService.Update(const Notebook: TNotebook): TServiceCustomStatus;
var
OrmNotebook: TOrmNotebook;
begin
OrmNotebook := TOrmNoteBook.Create;
try
if Self.Server.Orm.Retrieve(Notebook.ID, OrmNoteBook, True) then
begin
OrmNotebook.Title := Notebook.Title;
Self.Server.Orm.Update(OrmNotebook);
Result := HTTP_SUCCESS;
end
else
begin
Result := HTTP_NOTFOUND;
end;
finally
OrmNotebook.Free;
end;
end;
constructor TSampleServer.Create(aModel: TOrmModel; const aDBFileName:
TFileName);
begin
inherited Create(AModel, ADBFileName, True);
ServiceDefine(TNotebookService, [INotebookService], sicShared);
...
end;
The first time the client is calling NotebookService.Update, Orm.Retrieve returns true, so the update code executes. The second time it is called (a few seconds later), Orm.Retrieve returns false, so the result is HTTP_NOTFOUND. However, the input parameter, i.e. Notebook.ID is the same in both cases, so I don't understand why Orm.Retrieve returns false.
Any ideas why this is happening?
(The client is a vcl TRestHttpClient)
If your method returns HTTP_SUCCESS with no body, then the web server itself will return a HTTP_NOCONTENT.
So I take it you're referring to when the rsoHttp200WithNoBodyReturns204 flag has been set. If this flag is not set, (and you want to return NOCONTENT) then you need to use TServiceCustomAnswer.
I see, thanks for the info.
I did a bit more testing. The error occurs only with a return of HTTP_NOCONTENT. Other return values, such as HTTP_BADREQUEST, HTTP_FORBIDDEN don't cause a problem.
Hi,
In SOA by Interfaces with custom HTTP Status you mention that TServiceCustomStatus was added and can be used as a return type for interface methods:
It won't change anything for mORMot client/server communication - just for non-mORMot HTTP clients, they will be able to check the HTTP response code.
So I have a method like this:
INoteService = interface(IInvokable)
['{2B97D344-F806-4D6B-A3D9-56C61F9276BE}']
...
function Delete(const NoteId: TID): TServiceCustomStatus;
end;
TNoteService = class(TInjectableObjectRest, INoteService)
public
....
function Delete(const NoteId: TID): TServiceCustomStatus;
end;
function TNoteService.Delete(const NoteId: TID): TServiceCustomStatus;
begin
Result := HTTP_NOCONTENT;
Self.Server.Orm.Delete(TOrmNote, NoteId);
end;
If called from the mormot client: (vcl app)
NoteService.Delete(OrmNote.ID)
I get this error
Exception class EInterfaceFactory with message 'TInterfacedObjectFakeClient.FakeCall(INoteService.Delete) failed: 'Invalid returned JSON content: expects {result:...}, got ''. Process Project04InterfaceBasedClient.exe
If the delete method returns HTTP_SUCCESS, then there is no error.
I am doing this wrong?
Hi,
For an interface-based service is it possible for me to define the uri endpoint?
E.g. the service is defined as
ISampleService = interface...
So the uri is going to be at root/SampleService
Is there a setting to modify this so that the service enpoint is at root/Sample?
Ok... I found the cause of the problem:
procedure TRestServerLog.ComputeFileName;
begin
inherited ComputeFileName;
FFileName := StringReplace(FFileName, ' ', '_', [rfReplaceAll]);
end;
My path to the project is:
"C:\Delphi\Components Full\Database\mORMot2", so this code creates an invalid path, and I didn't notice this in the error message.
I imagine the code should actually just modify the log filename, not the full path.
@ab: Thanks for catching that. I didn't notice it.
@Thomas: My problem with your demo is that I get this error:
First chance exception at $75ADF932. Exception class EOSException with message 'TFileStreamEx.Create(C:\Delphi\Components_Full\Database\mORMot2\ex\ThirdPartyDemos\tbo\04-HttpServer-InterfaceServices\bin\TestRestServer_20240102_175743.log) failed as ERROR_PATH_NOT_FOUND'. Process TestRestServer.exe (5340)
It is occurring in mormot.core.os
constructor TFileStreamEx.CreateFromHandle(const aFileName: TFileName; aHandle: THandle);
begin
if not ValidHandle(aHandle) then
raise EOSException.CreateFmt('%s.Create(%s) failed as %s',
[ClassNameShort(self)^, aFileName, GetErrorText(GetLastError)]);
inherited Create(aHandle); // TFileStreamFromHandle constructor which own it
fFileName := aFileName;
end;
called from mormot.core.log TSynLog.CreateLogWriter.
I added this code to the server:
var
MainServer: TTestServerMain;
LogFamily: TSynLogFamily;
begin
{$IFDEF DEBUG}
ReportMemoryLeaksOnShutdown := True;
{$ENDIF}
LogFamily := SQLite3Log.Family;
LogFamily.Level := LOG_VERBOSE;
LogFamily.PerThreadLog := ptIdentifiedInOnFile;
LogFamily.EchoToConsole := LOG_VERBOSE;
LogFamily.NoFile := True;
But error still occurs. My assumption is that it is working on a different SynLog instance. Still not sure of the cause of the actual error..
I get the same error, whether SetUser is first, in the middle or last..
My code in client:
procedure TMainForm.FormCreate(Sender: TObject);
begin
Model := CreateSampleModel;
HttpClient := TRestHttpClient.Create('localhost', HttpPort, Model);
try
HttpClient.SetUser('User', 'synopse');
HttpClient.ServiceDefine([IExample], sicShared);
HttpClient.Services['Example'].Get(ExampleService);
except
On E: Exception do
MainTrace.Send(E.classname, E.Message)
end;
end;
Log file - shows that the auth works ok
20240102 13273442 # + server.TSampleServer(02604460).URI GET root/auth?username=User in=0 B
20240102 13273442 # srvr Method GET root/auth=200 out=77 B in 1.78ms
20240102 13273442 # ret mormot.rest.server.TRestServerRoutingRest(02de67c0) {"result":"ae7dd4354359d5ececc51861bfc1a9d6f1c6b877ad68dc4960941dba8bd0dcc7"}
20240102 13273442 # - 00.004.082
20240102 13273442 $ + server.TSampleServer(02604460).URI GET root/auth?username=User&password=85f078ed616bfdf0174407281f45772e91031b1fe3ba4ece40bd88894a5cd2e7&clientnonce=4a651701_463d3e15c1e23861227694e85890d00f in=0 B
20240102 13273443 $ DB server.TSampleServer(02604460) prepared 99us Project04InterfaceBasedServer.db SELECT ID,LogonName,DisplayName,PasswordHashHexa,GroupRights FROM AuthUser WHERE LogonName=? LIMIT 1 [{id:4,detail:"SEARCH AuthUser USING INDEX sqlite_autoindex_AuthUser_1 (LogonName=?)"}]
20240102 13273443 $ SQL server.TSampleServer(02604460) 1.60ms returned 1 row as 153 B SELECT ID,LogonName,DisplayName,PasswordHashHexa,GroupRights FROM AuthUser WHERE LogonName=:('User'): LIMIT 1
20240102 13273443 $ res mormot.db.raw.sqlite3.TSqlDatabase(0271a820) [{"ID":3,"LogonName":"User","DisplayName":"User","PasswordHashHexa":"67aeea294e1cb515236fd7829c55ec820ef888e8e221814d24d83b3dc4d825dd","GroupRights":3}]
20240102 13273443 $ DB server.TSampleServer(02604460) prepared 147us Project04InterfaceBasedServer.db SELECT ID,Ident,SessionTimeout,AccessRights FROM AuthGroup WHERE RowID=? [{id:2,detail:"SEARCH AuthGroup USING INTEGER PRIMARY KEY (rowid=?)"}]
20240102 13273443 $ SQL server.TSampleServer(02604460) 1.78ms id=3 SELECT ID,Ident,SessionTimeout,AccessRights FROM AuthGroup WHERE RowID=?
20240102 13273444 $ DB server.TSampleServer(02604460) prepared 71us Project04InterfaceBasedServer.db SELECT Data FROM AuthUser WHERE RowID=? [{id:2,detail:"SEARCH AuthUser USING INTEGER PRIMARY KEY (rowid=?)"}]
20240102 13273444 $ SQL server.TSampleServer(02604460) 1.70ms id=3 len=0 B SELECT Data FROM AuthUser WHERE RowID=?
20240102 13273444 $ auth mormot.rest.server.TAuthSession(026541d0) New [User] session User/805670 created at /-288230374541098224 running Mozilla/5.0 (Win x86; mORMot) HCS/2.1.5794 Project04InterfaceBasedClient/0 {Windows 10 64bit 19045}
20240102 13273444 $ srvr null Method GET root/auth=200 out=219 B in 22.12ms
20240102 13273444 $ ret mormot.rest.server.TRestServerRoutingRest(02de67c0) {"result":"805670+FC246362BC82654BC58AAE31301B27B4B41187C63123A9BC790B3FB1351286CA","logonid":3,"logonname":"User","logondisplay":"User","logongroup":3,"timeout":60,"server":"Project04InterfaceBasedServer","version":""}
20240102 13273444 $ - 00.025.008
20240102 13273444 % + server.TSampleServer(02604460).URI POST root/Example._contract_?session_signature=000c4b26006669c0f9a89362 in=2 B
20240102 13273445 % debug server.TSampleServer(02604460) TRestServerRoutingRest.Error: { "errorCode":400, "errorText":"Invalid URI" }
20240102 13273445 % srvr ? POST root/Example._contract_?session_signature=000c4b26006669c0f9a89362=400 out=49 B in 7.85ms
20240102 13273445 % ret mormot.rest.server.TRestServerRoutingRest(02de67c0) { "errorCode":400, "errorText":"Invalid URI" }
20240102 13273445 % - 00.012.346
20240102 13280023 " + server.TSampleServer(02604460).URI GET root/auth?userName=User&session=805670&session_signature=000c4b2600666a24c4f0fa26 in=0 B
20240102 13280024 " auth server.TSampleServer(02604460) Deleted session User:805670/1 from /-288230374541098224 soaGC=0
20240102 13280024 " srvr User Method GET root/auth=200 out=0 B in 21.90ms
20240102 13280025 " - 00.037.361
20240102 13284529 ! + mormot.rest.http.server.TRestHttpServer(026141f0).Destroy
20240102 13284529 ! http mormot.rest.http.server.TRestHttpServer(026141f0) {"THttpApiServer(0260c610)":{ApiVersion:"HTTP API 2.0",ServerName:"mORMot2 (Win)",ProcessName:"root",Options:["hsoThreadSmooting"],Router:{"TUriRouter(026f7140)":{Gets:1}},Cloned:false,RegisteredUrl:"http://+:11111/root/",MaxBandwidth:4294967295,MaxConnections:4294967295}} finalized for 1 server
20240102 13284529 ! + mormot.rest.http.server.TRestHttpServer(026141f0).Shutdown(true)
20240102 13284529 ! - 00.000.789
Hi,
I have run the martin-doyle\04-InterfacedBasedServices demo, and it works without problem.
Then I change the RestServer to require authentication, so I add the "True" parameter.
SampleServer := TSampleServer.Create(Model,
ChangeFileExt(Executable.ProgramFileName, '.db'), True);
Now when I run the client, I get the error:
TServiceFactoryClient.Create(): IExample interface or TRestClientRoutingRest routing not supported by server [{
"errorCode":400,
"errorText":"Invalid URI"
}]
It does not make a difference if I login or not (i.e. HttpClient.SetUser...)
Can anyone reproduce?
How to go about debugging/resolving?
I'm using Delphi 10.4. Problem occurs with Mormot 2.1, but I also tried latest source with same result.
Thanks
@mpv: Thanks for the info. I looked around a bit, and tried building the image with frolvlad/alpine-glibc - and it works without any issues!
There also is no need for the call to apk add.
So the dockerfile is
#FROM alpine:latest
FROM frolvlad/alpine-glibc:latest
#RUN apk add --no-cache libc6-compat sqlite-libs
WORKDIR /app
RUN mkdir data
RUN mkdir log
COPY /Project07Daemon /app/Project07Daemon
VOLUME ["/app/data","app/log"]
EXPOSE 11111
CMD ["/app/Project07Daemon", "--run"]
I did some investigation. Running Project02Server on an alpine image. First disabling all mormot code, and then enabling the units one by one.
mormot.core.base - no problem.
mormot.core.os - no problem.
mormot.core.log -> Problem occurs.
So looks like the problem lies in the InitializeUnit code there.
program Project02Server;
{$APPTYPE CONSOLE}
{$I mormot.defines.inc}
uses
{$I mormot.uses.inc}
SysUtils,
mormot.core.base,
mormot.core.os,
mormot.core.log{,
mormot.db.raw.sqlite3,
mormot.orm.core,
mormot.rest.http.server }
;
Hi,
I can build the docker image from the martin-doyle\07-HttpDockerORM example.
However, when I run it, I get a list of AV's as below:
rael@User-PC:/mnt/d/fpcupdeluxe/ccr/mormot2/ex/07-Docker$ docker run -p 11111:11111 project07daemon
An unhandled exception occurred at $00007FC608B45C4E:
EAccessViolation: Access violation
$00007FC608B45C4E
An unhandled exception occurred at $00007FC608B45B20:
EAccessViolation: Access violation
$00007FC608B45B20
An unhandled exception occurred at $00007FC608B45B20:
EAccessViolation: Access violation
$00007FC608B45B20
An unhandled exception occurred at $00007FC608B45B20:
EAccessViolation: Access violation
$00007FC608B45B20
An unhandled exception occurred at $00007FC608B45B20:
EAccessViolation:
$00007FC608B45B20
An unhandled exception occurred at $00007FC608B45C4E:
EAccessViolation:
$00007FC608B45C4E
Not particularly helpful..
Any hints?
I installed lazarus and fpc with fpcupdeluxe, selecting the "stable" option, and using latest mormot.
Do I perhaps need to install some fixes?
I'm running Windows 10 x64, and building the app and docker image in WSL ubuntu 22.04.2
Thanks
Hi,
Previously one could download the latest documentation as a PDF. Is this still available?
Also, is it possible to download the documentation as a number of PDF files, i.e. each chapter as a different file (there are now 30 chapters). This would make it easier to read through, and keep track of where I'm up to in the docs. (i.e. page 10 of chapter 4). I think this may have been available at one point..
Thanks
I'm trying to get up and running with a simple Websocket client example.
I would like to connect to the test echo websocket server @
wss://echo.websocket.org
(info at https://www.websocket.org/echo.html)
My code looks like this:
...
fWebSockets: THttpClientWebSockets;
proto: TWebSocketProtocolChat;
procedure OnFrameReceived(Sender: THttpServerResp;
const Frame: TWebSocketFrame);
...
procedure TForm1.btnConnect2Click(Sender: TObject);
var
msg: RawUTF8;
begin
fWebSockets := THttpClientWebSockets.Create;
fWebSockets.Open('echo.websocket.org', '80');
proto := TWebSocketProtocolChat.Create('echo', '', OnFrameReceived);
msg := fWebSockets.WebSocketsUpgrade('' {A}, '', True, false, proto);
if msg = '' then
Memo1.Lines.Add( 'ConnectToWebSockets: upgraded with protocol "EchoTest"')
else
Memo1.Lines.Add('Error: WebSocketsUpgrade: ' + msg);
end;
I keep on getting the result "Error: WebSocketsUpgrade: Invalid HTTP Upgrade Header".
I tried different things in {A}, e.g. echo.websocket.org, or wss://echo.websocket.org, I still get the same result.
Can anyone help me with this?
Thanks
I'm having trouble when calling fWebSockets.WebSocketsUpgrade
My code looks like this:
const
fServerURI = 'localhost';
var
fWebSocketsUri: RawUTF8;
msg: RawUTF8;
begin
fWebSockets := THttpClientWebSockets.Create;
fWebSockets.Open(fServerURI, '6800');
proto := TWebSocketProtocolChat.Create('aria2', '', OnFrameReceived);
fWebSocketsUri := StringToUTF8('ws://localhost:6800/jsonrpc');
msg := fWebSockets.WebSocketsUpgrade(fWebSocketsUri, '', True, false, proto);
if msg = '' then
Memo1.Lines.Add( 'ConnectToWebSockets: upgraded with protocol "aria2"')
else
Memo1.Lines.Add('Error: WebSocketsUpgrade: ' + msg);
end;
When fWebSockets.WebSocketsUpgrade is called I get an error:
"WebSocketsUpgrade: Invalid HTTP Upgrade Header"
Can you take a look, I prepared a demo project. To run the aria server just click on prompt.bat.
http://www.bauerapps.com/dev/AriaWebSocketsTest.zip
I will buy you a coffee...
Hi,
I have looked at this example of using a Websocket client: "WebSockets Client side" (https://synopse.info/forum/viewtopic.php?id=5291)
It shows using THttpClientWebSockets, and "upgrading" to use TWebSocketProtocolChat. Is this something that can only be used with a compatible mORMot Websockets server?
I am wanting to connect to an "aria2" websocket server. (It is an open source download manager. See https://aria2.github.io/manual/en/html/ … interface). Is this something I can do with mORMot websockets?
Thanks
Rael
Thanks.
There is a small typo there:
VirtualTableExternalRegister(fExternalModel,TSQLRecordPeopleExt,fProperties,'PeopleExternal');
We also customized the name of the external table, from its default 'PeopleExt' (computed by /timing/ TSQLRecord prefix from TSQLRecordPeopleExt) into 'PeopleExternal'.
Should be "trimming"
Hello,
Does mORMot allow to customize field names?
e.g.
TPerson
...
published
FirstName: RawUTF8;
LastName: RawUTF8;
...
In database to be represented as
first_name, last_name
Thanks
Rael
Hi,
That does not seem to work. I tried the following (using Project 02 with new database)
procedure TForm1.AddButtonClick(Sender: TObject);
var
Rec: TSQLSampleRecord;
begin
Rec := TSQLSampleRecord.Create;
try
// we use explicit StringToUTF8() for conversion below
// a real application should use TLanguageFile.StringToUTF8() in mORMoti18n
Rec.Name := StringToUTF8(NameEdit.Text);
Rec.Question := StringToUTF8(QuestionMemo.Text);
Rec.IDValue := 30; // <----
if Database.Add(Rec, true) = 0 then
ShowMessage('Error adding the data')
else
begin
NameEdit.Text := '';
QuestionMemo.Text := '';
NameEdit.SetFocus;
lblID.Caption := 'ID: ' + IntToStr(Rec.ID);
end;
finally
Rec.Free;
end;
end;
The added Rec.ID is 1, not 30 as I had set it.
Thanks for the info, that is interesting.
However, it does not answer the second issue: How do I supply a rec.ID to the server when syncing records from the client, since rec.ID is readonly?
Hi,
I would like to understand how to deal with the following type of scenario using mormot:
Offline client can create new records. Also, server can create new records.
At some point client and server will be synced.
Ordinarily, one would use a GUID as ID field for each record. (i.e. client and server need to be creating globally unique ids)
Also, when sending a record from client to server, one includes the ID in the record (i.e. not created at server.)
TSQLRecord.ID is int64, which is pretty large, so perhaps this could be used an an equivalent to GUID. (i.e a GUID is 16 bytes but only uses a restricted range for each byte (0-F). int64 is 8 bytes but could use a larger range..). However, more of a "problem" is that TSQLRecord.ID is read only, so one cannot achieve above requirement (of sending Record.ID to server).
So is the way to deal with such a situation to basically ignore the TSQLRecord.ID, and supply our own GUID field?
Thank you
Rael
AFAIR the Delphi Web Script JavaScript back-end has been released again under Open Source.
Do you have a reference for that information?
Trying to run Project 29 in SMS 2.2.2.4543
I run into a few problems:
When I open the project, I get an error: WebForm.pas not found
I delete the reference in WebForm.sproj.
Then need to remove:
<AlignText>1</AlignText>
from LoginForm.sfm
Then comment out some code in SmartTests.pas:
procedure TestsIso8601DateTime;
Then the project compiles. When I try to connect to server (from Sample 27) I get an error:
Impossible to connect to the server...
It does compile, but console shows:
"StartServer DB.Add(TSQLRecordPeople) Error"
1) Is that expected?
2) Is there a way to be notified when a reply occurs to a post?
Thanks.
Hi,
Just updated to latest version via Git.
I get these errors when I try to compile RegressionTestsServer.dpr from [Samples\27 - CrossPlatform Clients] in Delphi 7:
[Error] PeopleServer.pas(197): Ambiguous overloaded call to 'Add'
[Error] PeopleServer.pas(197): Incompatible types: 'Integer' and 'String'
[Error] PeopleServer.pas(197): Constant expression violates subrange bounds
[Error] PeopleServer.pas(197): Incompatible types: 'Integer' and 'String'
[Fatal Error] RegressionTestsServer.dpr(13): Could not compile used unit 'PeopleServer.pas'
Any suggestions?
Thanks
Rael
Ok I found answer to 2). I need to include third parameter = true.
1) Can anyone out there reproduce the problem I have mentioned?
2) @Arnaud: I tried to use TSQLRestServerDB instead of TSQLRestServerFullMemory so I may be able to better track what happens at the server.
I create with:
DB := TCustomServer.Create(Model, ChangeFileExt(paramstr(0),'.db3')); // inherits from TSQLRestServerDB
DB.CreateMissingTables();
When I inspect the db, no default users are created. Is that only for TSQLRestServerFullMemory ?
3) I did some tracing, it looks the the "errors" are occurring in the ORMTest calls to client.delete and client.update. The initial add/read operations work ok.
Project14ServerHttpWrapper was working with Project14Client.sproj.
I see Project14ServerHttpWrapper calls:
aServer := TSQLRestServerFullMemory.Create(aModel,'test.json',false,true);
RegressionTestsServer project calls:
DB := TCustomServer.Create(Model);
Should it not be loading the 'test.json' file (with user info) for the authentication to be working correctly?
Hi,
I am trying out this example, but run into a problem.
First I compile and run RegressionTestsServer (from "27 - CrossPlatform Clients").
(I copy the crossplatform units to the SMS libraries folder)
Then I run the WebForm.sproj (from "29 - SmartMobileStudio Client") and run it in the browser.
From the browser console it looks like the app is not working: Here is (part of) the output from Firefox:
no element found DropTable:1:1
no element found 16:1:1
no element found 32:1:1
no element found 48:1:1
no element found 64:1:1
no element found 80:1:1
no element found 82:1:1
no element found 96:1:1
no element found 112:1:1
no element found 128:1:1
no element found 144:1:1
no element found 160:1:1
no element found 164:1:1
no element found 176:1:1
no element found 192:1:1
GET
XHR
http://127.0.0.1:888/root/People/16 [HTTP/1.1 404 Not Found 5ms]
GET
XHR
http://127.0.0.1:888/root/People/32 [HTTP/1.1 404 Not Found 5ms]
GET
XHR
http://127.0.0.1:888/root/People/48 [HTTP/1.1 404 Not Found 5ms]
GET
XHR
http://127.0.0.1:888/root/People/64 [HTTP/1.1 404 Not Found 5ms]
GET
XHR
http://127.0.0.1:888/root/People/80 [HTTP/1.1 404 Not Found 4ms]
GET
XHR
http://127.0.0.1:888/root/People/96 [HTTP/1.1 404 Not Found 5ms]
GET
XHR
http://127.0.0.1:888/root/People/112 [HTTP/1.1 404 Not Found 4ms]
GET
XHR
http://127.0.0.1:888/root/People/128 [HTTP/1.1 404 Not Found 4ms]
GET
XHR
http://127.0.0.1:888/root/People/144 [HTTP/1.1 404 Not Found 5ms]
GET
XHR
http://127.0.0.1:888/root/People/160 [HTTP/1.1 404 Not Found 4ms]
GET
XHR
http://127.0.0.1:888/root/People/176 [HTTP/1.1 404 Not Found 5ms]
GET
XHR
http://127.0.0.1:888/root/People/192 [HTTP/1.1 404 Not Found 5ms]
The returned json from request is
{
"errorCode":403,
"errorText":"Forbidden"
}
So looks like there is an authentication problem?
In RegressionTestsServer.dpr I could not see any code where a user "User/synopse" is created...
Any hints of what is wrong?
Thanks
Rael
(Using latest mORMot and D7)
Sorry, I updated the ODBC driver and then it worked fine.
-Rael
Hi,
I'm trying to use Unidac Firebird in the "15 - External DB performance" example.
The unidac sqlite test works ok.
With firebird I encounter some errors. First it says:
"DescribeParams" is not a valid option name for InterBase UniProvider
so I commented this out in unit SynDBUniDAC (line 231).
Then when I try test it says:
EIBCError, I/O error for file "unidac firebird.1" Error while trying to open file. The system cannot find the file specified.
It seems like it cannot create database if it doesn't exist.
I'm using Unidac 6.1.5 and D7.
Any ideas?
(I tried Zeos firebird, and that test worked ok.)
Thanks
Rael
Hi,
I would like to try out sample 28 - Simple Restful ORM Server, using SQLite.
I change the ODBC connection to :
aProps := TODBCConnectionProperties.Create('',
'Driver={SQLite3 ODBC Driver};Database=C:\Temp\REST.db3', '', '');
I also got an error on this line:
// create tables or fields if missing
aRestServer.CreateMissingTables;
so I commented it out, not sure why the error occurs.
Then server compiles and runs ok. When I run the client it looks like something is not working since the output is:
Added TPerson.ID=0
Name read for ID=0 from DB = ""
and nothing gets added to the database.
What needs to be changed to get the example to work?
Thanks
Rael
Hi,
Sorry, I recall reading some sections on how to use the Mormot/SynCrossPlatformJSON classes for JSON, but now I do not recall how/where I found that info. Can you please point me to the relevant docs?
Thanks
Rael
Hi,
I'm just looking at these samples and have some questions.
For sample 02 & 03 (client)
I see
Database.Free;
But I could not see where the Database is created?
Also For sample 03 client,
where is the code/logic that connects the client to the server? I could not see any code related to this.
Thanks
Rael
ln 1121:
// you should call sqlite3.open() instead of sqlite3.open() for instance
I believe should be:
// you should call sqlite3.open() instead of sqlite3_open() for instance
(as in lin 2078)
-Rael