Saturday, January 6, 2018

Setup Orchard Code Snippet

Setup code snippet:
  1. Clone the library repository (https://github.com/Lombiq/Orchard-Dojo-Library.git) to C:\MyDev\Lib
  2. Tools|Code Snippets Manager ..., Language: CSharp, Add.., choose folder C:\MyDev\Lib\Orchard-Dojo-Library\Library\Utilities\VisualStudioSnippets

Reference: https://orcharddojo.net/orchard-resources

Tuesday, August 1, 2017

mORMot on FHIR - Part 2 - ORM

In this blog, I want to try out some ORM feature of mORMot first.

Fist step, we save the Echo project from previous part to ORM project, and make a copy of SampleData.pas from mORMot's sample 01 to ORM's project folder, add this unit to the project:

Open SampleData.pas, we can see a class TSQLSampleRecord is defined, we can then add this class to the model when a TSQLModel is created so that the model now has one table/class:

Run the application and it has no problem. But we don't see where the table is created as the data server is a memory server, no persistence to any media, it is better to change the server to one of real database server, for convenience, we will use the default Sqlite database server.

The default Sqlite server class is TSQLRestServerDB, so we change the class TECHOServer to inherit from TSQLRestServerDB:

TECHOServer = class (TSQLRestServerDB)
  published
    procedure Echo(Ctxt: TSQLRestServerURIContext);
  end;
And the parameters for creating such a server is different from TSQLRestServerFullMemory, we just need to tell the server where the database file is:
aServer := TECHOServer.Create(aModel,
    ChangeFileExt(ExeVersion.ProgramFileName,'.db3'));
We can then ask the server to create the schema for us:
TSQLRestServerDB(aServer).CreateMissingTables;
That is it! (of cause, you need to add use units as we have changed the class)

After running the application, we can check the database file and there is the table created:


As you can see, without doing any explicit mapping configuration, the database schema is created automatically.

Saturday, July 29, 2017

mORMot on FHIR - Part 1 - RESTful Echo

My goal is to use Delphi mORMot framework to implement a FHIR server.

So what are FHIR and mORMot?

FHIR stands for Fast Health Interoperability Resource, a framework focussed on exchanging health data via RESTful API, thus a FHIR server is normally a RESTful server.

mORMot is a Delphi framework that has features such as ORM an SOA etc, it supports REST service out of the box.

So why mORMot for FHIR?

mORMot is all about REST server, i.e., provides service via RESTful API, taking request and returning response in JSON format, it matches what a FHIR server is doing perfectly.

So how easy can we build up a RESTful server in mORMot to take a JSON request and return a JSON response?

I strongly recommend you to download mORMot source code by using Git client so that you can update the source code easily as it is still being updated actively. So I save the source code in "C:\MyDev\mORMot\Git Version". We will start with a new console project:



and save it as ECHO project:


 The goal of this project is to build a server that can echo a HTTP post. First, we need to define a RESTful server:

TECHOServer = class (TSQLRestServerFullMemory)
  published
    procedure Echo(Ctxt: TSQLRestServerURIContext);
  end;
And the implementation of Echo is quite simple, assigning the input to output and returning HTTP 200 to client:
procedure TECHOServer.Echo(Ctxt: TSQLRestServerURIContext);
  begin
    Ctxt.Call.Outbody := Ctxt.Call.InBody;
    Ctxt.Call.OutStatus :=200;
  end;
Then we need to start the RESTful server, as mORMot ties data model, data server and HTTP server together, thus we need to initialize a model and a server before we start a HTTP server:
aModel := TSQLModel.Create([],'service');
  try
    aServer := TECHOServer.Create(aModel);
    try
      aHTTPServer := TSQLHttpServer.Create('7878',aServer,'+',useHttpApiRegisteringURI);
      write('Press [Enter] to close the server.');
      try
        readln;
      finally
        FreeAndNil(aHTTPServer);
      end;
    finally
      FreeAndNil(aServer);
    end;
  finally
    FreeAndNil(aModel);
  end;

And the whole souce code is as simple as below (less than 50 lines):
program Echo;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  mORMot,
  mORMotHttpServer;

type
  TECHOServer = class (TSQLRestServerFullMemory)
  published
    procedure Echo(Ctxt: TSQLRestServerURIContext);
  end;
  procedure TECHOServer.Echo(Ctxt: TSQLRestServerURIContext);
  begin
    Ctxt.Call.Outbody := Ctxt.Call.InBody;
    Ctxt.Call.OutStatus :=200;
  end;

var
  aModel: TSQLModel;
  aServer : TECHOServer;
  aHTTPServer: TSQLHttpServer;

begin
  aModel := TSQLModel.Create([],'service');
  try
    aServer := TECHOServer.Create(aModel);
    try
      aHTTPServer := TSQLHttpServer.Create('7878',aServer,'+',useHttpApiRegisteringURI);
      write('Press [Enter] to close the server.');
      try
        readln;
      finally
        FreeAndNil(aHTTPServer);
      end;
    finally
      FreeAndNil(aServer);
    end;
  finally
    FreeAndNil(aModel);
  end;
end.
Compile and run it:

Now it is time to test it:



 It works!

As you can see, use mORMot to build a RESTful server it pretty simple.

In the next part, I will try to deserialize the input JSON so that we can use the resource as an object internally.






Tuesday, April 4, 2017

Experience with NHAPI is not so happy–how to get a list of group name?

NHapi is a port of the original project HAPI.

NHapi allows Microsoft .NET developers to easily use an HL7 2.x object model. This object model allows for parsing and encoding HL7 2.x data to/from Pipe Delimited or XML formats. A very handy program for use in the health care industry.

With 7 years experience of developing HL7 related applications (HL7 messaging and integration), I have found that in reality, people do not always conformant with HL7’s specification, thus there are always something more or less in the actual HL7 message than what the specification says. This makes the static object model sometime not able to represent the HL7 it is processing, to solve this problem, Terser is introduced to read values from the HL7 regardless the static structure of a particular version of HL7. Terser uses path to locate a particular value. The path consists of segment, field and component, sub component. Unfortunately, the segment consists of group and the name of segment, but group are vary from version to version of HL7, for example, a PRD of REF^I12 in version 2.3.1 is under group PROVIDER, but it is not in any group in version 2.4. Another problem is that I have not been able to find a document in which tells you what groups are in a type of message for each version of HL7, this then leaves you only way to figure out is by guessing. After I have gain more experience of NHAPI, I now can use following code to print out a whole path picture of a specified message:

static void PrintNames(string ident,IStructure s)
        {
            Console.Write(ident);
            Console.Write(s.GetStructureName());
            if (! (s is IGroup))
            {
                Console.WriteLine("");
                return;
            }
            Console.WriteLine("(Group)");

            IGroup g = (IGroup)s;
            foreach (var sn in (g.Names))
            {               
                IStructure ss = g.GetStructure(sn);
                if (ss is IGroup)
                {
                  
                    PrintNames(ident + "    ", ss);
                }
                else
                {
                    Console.Write(ident + "    ");
                    Console.WriteLine(sn);

                }
                //Console.WriteLine("");
            }
        }

 

Call it with

REF_I12 r= new REF_I12;

PrintNames(“”,r)

we can get the path tree:

REF_I12(Group)
    MSH
    RF1
    AUTHORIZATION_CONTACT(Group)
        AUT
        CTD
    PROVIDER(Group)
        PRD
        CTD
    PID
    NK1
    GT1
    INSURANCE(Group)
        IN1
        IN2
        IN3
    ACC
    DG1
    DRG
    AL1
    PROCEDURE(Group)
        PR1
        AUTHORIZATION_CONTACT(Group)
            AUT
            CTD
    OBSERVATION(Group)
        OBR
        NTE
        RESULTS_NOTES(Group)
            OBX
            NTE
    PATIENT_VISIT(Group)
        PV1
        PV2
    NTE

Friday, February 3, 2017

Create multiple folders with command "MD"

The other day, I was trying to create a folder "SQL Server" but I was missing the quotes, so I issued command "md sql server" in the CMD window, then I used "cd sql server" to change the current directly but failed, with a "dir", I found there were two new folders "sql" and "server" instead of "sql server". If you check the help of the command "md" (I checked with Windows 10), there is no such usage in it. It seems that it is an undocumented and nice feature! If the folder contains space, you just need to double quoted your folder's name such as:
    md "folder 1" "folder 2" 

Thursday, October 27, 2016

Expierence of Enhancing existing projects with mORMot

The original blog with the same title is from one of the mORMot author here

What I want to add to the list are:
  1. You can use SynZip to replace your Zip library. In my case, I use Abbrevia component set for Zip and Unzip, but Abbrevia contains many units and if only the Zip and Unzip of functionality are used, it might be worth to using much more small SynZip
  2. You can replace your base64 routines with mORMot's as it is much faster when the data to be encode/decode is big

Thursday, October 6, 2016

A disadvantage of UPX

UPX (Ultimate Packer for Executables) is a free and open source executable packer (https://en.wikipedia.org/wiki/UPX). It makes your executable smaller thus speed up the loading and transfering. I have been using it for many years and have had no problem at all until few day ago I discovered an serious issue with it.

When UPX compress your executable, it not only compress the code inside the executable, but also compress the resource data in the executable, thus the resource data becomes not readable for other applications, one scenario is that you compile message table into your executable and use this executable as the resource file for some settings such as use it as the value of "EventMessageFile" for defining your own Event Log source in the Windows registry, unfortunately, if you do so, firstly, the Event Log view will not find the descriptions for your event's ID and category, secondly it might crash your Windows Event Log service and even worse, the service might not be able to recover even its Recovery setting has been set up.

You can reproduce what I have say in following steps:

  1. Download UPX from https://github.com/upx/upx/releases/tag/v3.91 (latest release at the time this blog is written)
  2. Find an Event Log source from within "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application",  whose EventMessageFile is an EXE and it has some events you can see them in Event Viewer
  3. Use UPX to compress the EXE you have found in step 2
  4. Restart the Event Log viewer if it is open
  5. Check the event then you can see that the first sentence is something lik "The description for Event ID xxx from source yyy cannot be found"
  6. Try to filter on current log to show event only from that chosen source, the event view might crashes because the Windows Event Log service has crashed by now in some cases.