You are not logged in.
Arnold, I would like to thank you for your comments here and apologize for the lack of knowledge in the framework, I'm still new to mormot, but I'll get there. Digging around the framework I discovered the properties:
TServiceFactoryServer's SetWholeOption([???])
optResultAsJsonObjectWithoutResult or optResultAsJsonObject
I just put the optResultAsJsonObjectWithoutResult option and the json I wanted was already returned the way I needed it.
function Busca(pId: Int64; var abc: TDTOProjeto; out pProjeto: TDTOProjeto; out pPaineis: TDTOPaineis): TServiceCustomStatus;
{
"abc": {
"RowID": 1,
"Nome": "Projeto c",
"DataCriacao": "2023-03-18T12:34:09",
"UltimaAlteracao": "2023-03-18T12:34:09",
"IdCriador": 5,
"Paineis": []
},
"pProjeto": {
"RowID": 1,
"Nome": "Projeto c",
"DataCriacao": "2023-03-18T12:34:09",
"UltimaAlteracao": "2023-03-18T12:34:09",
"IdCriador": 5,
"Paineis": [
{
"RowID": 1,
"Nome": "painel a",
"DataCriacao": "2023-03-20T10:08:48",
"UltimaAlteracao": "2023-03-20T10:08:48",
"IdCriador": 5,
"IdProjeto": 1
}
]
},
"pPaineis": [
{
"RowID": 1,
"Nome": "painel a",
"DataCriacao": "2023-03-20T10:08:48",
"UltimaAlteracao": "2023-03-20T10:08:48",
"IdCriador": 5,
"IdProjeto": 1
}
],
"Result": 0
}long live the mormot!
I world like a copy too please. Cannyou put on github?
I can do this into component, or i will need call manually into application when using the component?
i have commented the picture (GIF) that was registred. the error happen yet
I removed TGifImage of matrixes too
const
PicturesExt: array[0..4] of TFileName =
('jpg','jpeg','png','tif','tiff');
PictureClasses: array[0..4] of TGraphicClass =
(TJpegImage,TJpegImage,TPngImage,TTiffImage,TTiffImage);
....
procedure TGDIPlus.RegisterPictures;
var
i: integer;
begin
SendDebug('register!');
// launch Gdip.RegisterPictures to initialize the GDI+ library if necessary
if (Self=nil) and (Gdip=nil) then
begin
SendDebug('gdipo criando!');
Gdip := TGDIPlus.Create('gdiplus.dll');
end;
// register JPG and PNG pictures as TGraphic
if GetClass('TTiffImage')=nil then
begin
RegisterClass(TJpegImage);
RegisterClass(TPngImage);
//RegisterClass(TGifImage); <<<<<<<<<<<<
RegisterClass(TTiffImage);
for i := 0 to high(PicturesExt) do
TPicture.RegisterFileFormat(PicturesExt[i],
PictureName(PictureClasses[i]),PictureClasses[i]);
end;
end;AB,
Do you still provide any support for SynGDI Plus?
I have created a ThumbView component that uses the GR32 lib. In this component I put:
uses
Windows, Messages, Math, SysUtils, Classes, Controls, Types,
StdCtrls, Dialogs, Contnrs, CommCtrl, ActiveX, Graphics, Forms,
GR32_Image, GR32, GR32_Transforms, GR32_RangeBars, GR32_Blend,
SynGdiPlus,
BackgroundWorker;
....
//initialization
// Gdip.RegisterPictures;
end.When I install the component without this initialization I can close delphi without any problems.
but if i uncomment that initialization Gdip.RegisterPictures, when I close delphi I get the following message

I have The same problem. I remove line that registerclass tgif because my delphi são that is duplicated register class.
Then now when I closet The delphi I get a Access violation in rtl70.bpl
What u think Arnold?
What i can see about the code, all workflow abou soa via interfaces is internal. Then i think this idea is viable.
Good Morning Arnold,
I thought TServiceCustomStatus was only for non mormot clients.
Atualmente o mormot traz no result uma matriz com valores diversos. E não é possível ler isso de clientes não mormot. Veja isso.
TPaineis = array or TPainel
function BuscaPaineis(idProject: integer; out paineis: TPaineis): boolean;
// if I put an idProject that doesn't exist, for example, a Json arrives in this format:
{
"result" = [ [], false ]
}
// if I put an idProject that exists for example a Json arrives in this format:
{
"result" = [ [{"painel": 'painel1'}, {"painel": 'painel1'}], true ]
}A non-mormot client is expecting just an array of TPainel. Which is not the case with the true and false into array.
An example response that mormot could return and handle without impacting applications that use interface-based SOA could look like this:
function BuscaPaineis(idProject: integer; out paineis: TPaineis): boolean;
{
"result" = [{"painel": 'painel1'}, {"painel": 'painel1'}],
"return" = true
}I will further detail the problems I am trying to solve as I want to work with interface based SOA. But I need the mormot server to return the JSON in a way that can be read by any 3rd party application.
1) Return the custom HTTP code
2) The returned JSON should follow a pattern for when the result is 200..399.
3) When the return is 400..599 I need the returned JSON to follow an exception pattern with the proper error message. This type really should not be an exception, even though they are expected errors. They should not be logged or handled by the framework.
When I use TServiceCustomStatus I can return the statuscode that I want, great!
But when I return a code between 400...599 I have to return a Json with the reason for this error.
So I thought of TServiceCustomStatus as a record. And I adjusted the code so that anyone who wants to use Mormot and is not using a Mormot client.
Maybe a way to standardize this would be that every return from mormot would return
{
"<result> or <classname>": <Jsonobject> or <JsonArray>
"errormessage": "<empty> or <custom error message>" <<< not out parameter but a TServiceCustomStatus.ErroMessage field
"return" : <null is procedure> or <value of function result> <<< if function is TServiceCustomStatus then TServiceCustomStatus.Status
}
Without losing the cardinal TServiceCustomStatus obviously. HTTPStatus code would return TServiceCustomStatus.Status too.I'm asking this because my frontend tool (as well as many others) already evaluates the http statuscode to be able to direct the workflow to a success or error routine.
We don't always have control over the frontend that will be using our API, and some of these clients don't have the facility to change their programming.
I know someone here may say that it is the clients that should implement according to the API specification, but I have clients that use no-code tools that just receive the json and treat this json according to the returned http statuscode.
In summary. Your mormot clients would not have to change their programming at all, because if I have the following methods in the interface they would return the following json:
function TABC.FindOrder(Id: Integer; out Order: TOrder; out Items: TItems): TServiceCustomStatus;
{
"output1" or "order": { "id": 1, ... }
"output2" or "items": [{ "id": 10, ... }, { "id": 11, ... }, { "id": 12, ... }]
"errormessage": ""
"return" : 200 <<<< the same of HTTPStatus code returned
}
function TABC.FindOrder(Id: Integer; out Order: TOrder; out Items: TItems): boolean;
{
"output1" or "order": { "id": 1, ... }
"output2" or "items": [{ "id": 10, ... }, { "id": 11, ... }, { "id": 12, ... }]
"errormessage": ""
"return" : true <<<< HTTPStatus code always 200 if result <> TServiceCustomStatus
}To internaol SOA process, "errormessage" field would be ignored unless the programmer put an out errormessage in the parameters.
Hi, I make some changes in TServiceCustomStatus
and put a PR #160
What did u think?
Are u see some problem in my changes?
Hi guys I try. look this sample:
TPainel = class;
TPaineis = array of TPainel;
TProjeto = class(TOrm)
private
FPaineis: TPaineis;
published
property Paineis: TPaineis read FPaineis;
end;
TPainel = class(TOrm)
private
FIdProjeto: TProjeto;
published
property IdProjeto: TProjeto read FIdProjeto write FIdProjeto;
end;when I use this code
function TProjetoService.Busca(pId: Int64): TServiceCustomAnswer;
var
vProjeto: TProjeto;
vAuto: IAutoFree;
begin
vAuto := TOrm.AutoFree([@vProjeto, TProjeto]);
if not GlobalRepository.Orm.Retrieve(pId, vProjeto) then
Result := ReturnRecordNotFound
else
Result.Content := ObjectToJson(vProjeto);
end;I receive this:
{
"RowID": 1,
"Nome": "Projeto a",
"DataCriacao": 135770589581,
"UltimaAlteracao": 135770590233,
"IdCriador": 5,
"Paineis": "[{\"RowID\":1,\"Nome\":\"painel a\",\"DataCriacao\":0,\"UltimaAlteracao\":0,\"IdCriador\":5,\"IdProjeto\":1},{\"RowID\":2,\"Nome\":\"painel b\",\"DataCriacao\":0,\"UltimaAlteracao\":0,\"IdCriador\":5,\"IdProjeto\":1},{\"RowID\":3,\"Nome\":\"painel c\",\"DataCriacao\":0,\"UltimaAlteracao\":0,\"IdCriador\":5,\"IdProjeto\":1}]"
}I whould like this:
{
"Id": 1,
"Nome": "Projeto a",
"IdCriador": 5
"Paineis": [
{
"Id": 1,
"Nome": "painel a",
"IdCriador": 5,
"IdProjeto":1
},
{
"Id": 2,
"Nome": "painel b",
"IdCriador": 5,
"IdProjeto":1
},
{
"Id": 3,
"Nome": "painel c",
"IdCriador": 5,
"IdProjeto":1
}
]
}1) How orm method i should be use to RETRIEVE the object TProjeto with the array Paineis filled? There are some?
2) This model create 2 tables Painel and Projeto but fill just Projeto and create a string field into Projeto table to store all TPanel as json. How I can store projeto and painel in diferent tables, but yet so make the same RETRIEVE above?
Very fast, Very thanks.
In this sample TBO. What type of TOrmPhoneObjArray? and How I can get a person id=? and the orm bring the person with all phones?
Thanks. Phone is just a sample.
I will use this strategy for more complex classes. Order and OrderItem for sample.
I dont think that OrderItem shoud be saved into a blob into order table.
Reasons:
1) Will be dificult mount reports. because by default FastReport and others reports generators work with Datasets, then we need get the records master detail in tables.
2) A bussiness inteligence tool that work with database need get OrderItems to make the graphics. Imagine this stored in blobs.
3) How to find something into objects that are store in this field blob?
Sample1: I want bring all orders that have product "xyz" (where product is into a blob field)
Sample2: I want sum(orderitem.total) where product "xyz" in a period (where product is into a blob field)
4) I think that exist other reason that do not appear in my mind at the moment.
How u treat this? Store all objects as documents (nosql style)?
I see all documentation. But TOrmMany is to pivottable, and i dont have source and dest in this case.
I what just a property returning list of objects TPhone into person!
Or I dont understand very well how to use!
Remerber that Tperson 1 - (0..n) Tphone (on database are different tables)
Problem with this is that we have to treat all input/output parameters of service method, getting of Ctx. very hard work!
There are some other way?
I Have 2 tables in my database
Person (id, name)
Phone (id, idPerson, number)
1) How can i map this in mormot?
TPerson = class;
TPhone = class(TOrm);
private
FIdPerson: TPerson;
FNumber: RawUTF8;
published
property Number: RawUTF8 index 25 read FNumber write FNumber;
property IdPerson: TPerson read FIdPersonwrite FIdPerson;
TPerson = class(TOrm)
private
FNome: RawUTF8;
published
property Nome: RawUTF8 index 100 read FNome write FNome;
property Phones: ???????? read FPhones <<<< that property type can i use here? (need persist in 2 separated tables)
end;
2) How I can call retrieve on orm and bring some person (id=10 for sample) and all your Phones?
Hi All,
I see that when implementing services interface based the framework always return 200.
But we whould like return others httpstatus.
then we discover TServiceCustomAnswer. this resolve the httpstatus problem, but this return do not accept parameters out neither var
sample. What i would like do:
function TProjetoService.GetProjetoPaineis(out pProjeto: TOrmProjeto): TServiceCustomAnswer;
begin
if not FRestOrm.Retrieve(pProjeto.Id, pProjeto) then
Result := ReturnError(Format('(%s) '+cErrorRecordNotFound, [GetClassName]), HTTP_NOTFOUND)
// else following the course, will return 200 ok!!!!
end;
function TServiceBase.ReturnError(const pErrorMessage: RawUTF8; pStatus: cardinal): TServiceCustomAnswer;
var
vError: Variant;
begin
TDocVariant.New(vError);
vError.ErrorMessage := pErrorMessage;
vError.StatusCode := pStatus;
Result.Content := VariantSaveJson(vError);
Result.Status := pStatus;
end;
How we can do this? What the recomendation?
2) You have a set of TSynFilter and TSynValidate sub-classes available at ORM level.
Ok then, if by sample, I want validate a integer field at ORM Level, to just receive values > 5, what validate TSynValidate sub-classes i should be to use? TSynValidatePattern? I hate regular expressions. How u would do? should I be make others subclasses?
ti-pattern to let other projects make direct changes to the DB (******* I AGREE *******)
All right. Still talking about foreign key, constraints, and not null fields. Is there any way to intercept the creation of the table and fields in order to add these options to the database according to the reading via RTTI of the TOrm classes? I know that some types database does not have these options, but most databases have.
Maybe we can embedded some class on ORM that implement some interface where we could put things like foreign key, constraints, not null fields, descriptions etc...
I'm only saying this Arnold because many developers are so rooted in their old relational paradigms that they would find it very odd that the ORM framework doesn't provide this natively. Then we could offer the possibility for these people to see MORMOT as a tool they can trust. not that it makes a difference to you or me. do you understand?
What you think?
I start my study and develop with mormot, congratulations, excelent framework.
Some doubts.
1) I see on documentation that I can use TNullableXXX to treat nullables.
This is working on mormot2?
How ORM can create database field as "not null"? CreateMissingTables are creating all fields as "accept null"
2) Where I find the validators class to make things as:
- field is filled or is null (field integer or string).
- Length validator
- max and min values
- number interval
- etc... (i just see to ipvalidator email and some others)
3) Serious that framwork do not generate FK Keys?
This is a great problem when database is filled by others applications, or if the programmer need make changes on database directly.
how u grant the integrity in yours applications guys?
fábio você é brasileiro?
Hi Guys,
I starting develop mormot using mormot2.
I trying build a ticket system as prove of concept.
I had read this topics and I would like know why not can use PUT/DELETE with SOA interfaced based?
https://synopse.info/forum/viewtopic.php?id=1833
Congratulations for the Server.Route.Get/Post/Put/Delete article. I'm using this approach.
But do not works to DELETE/PUT
Server.Route.Get('/projeto/<id>', 'root/find/<id>'); // works
Server.Route.Delete('/projeto/<id>', 'root/delete/<id>'); // dont works
Why Route DELETE cannot get the instace of service and call your delete(id: integer) method as the GET does?
And some base classe that implements IInvokable could expose a virtual method called DoRequest(Ctxt: TRestServerUriContext)? so the programmer could be treat others situations not implemented by mormot!
What you think?
Can you post some few lines of code about:
1 - how to Send message strings? this is correct way?
FClient := TCrtSocket.Open('192.168.1.255', '12001', cslUDP);
if FClient.SockIn = nil then
FClient.CreateSockIn;
if FClient.Sock < 0 then
begin
ShowMessage('Socket not found!');
exit;
end;
FClient.SockSend(['Teste aaaaaaaaaaaaaaa']);
FClient.SockSendFlush; <<<< I neeed really this??????
lookin on wireshark i see :
41 2.147148 192.168.1.72 192.168.1.255 LLC 65 U F, func=UA; DSAP ISO Network Layer (OSLAN 2) Individual, SSAP 0x64 Response
Why Wireshark shows LLC instead UDP???????
2 - how to Send message steams?
3 - how to treat exceptions?
I need use UDP communication, but i dont see any sample about your use?
Can anyone here post a simple sample of client and server using this protocol??
Thanks