Optimisation of SOAP Requests - Using Stored Procedures
Cadcorp GeognoSIS runs as a Web Service; it allows client applications to contact it using SOAP messages. (eg ASP.NET web pages or Visual Basic applications).
But communication stress happens with each use of the Cadcorp GeognoSIS API:
- Packaging up arguments into an XML document
- Transporting it to Cadcorp GeognoSIS
- Unpacking
- Then doing the same in reverse with whatever Cadcorp GeognoSIS returns.
For eg, consider the following simple fragment of code:
Dim allNames as String = ""
Dim nItems as Integer = sis.Scan("items", myOverlay, "", "")
For I = 0 to nItems
Dim name = sis.GetListItemStr("items", "_name$")
allNames = allNames & "," & name
Next
If the scan finds 100 items, a total of 101 messages will be sent– this is costly when the client runs on the same server as Cadcorp GeognoSIS but potentially disastrous when the two are communicating over a busy network.
How can stored procedures help?
With this option, you simply create your own API methods for GeognoSIS and bundle a large amount of work into a single procedure.
The code shown above can become just such a procedure. Although Cadcorp GeognoSIS has the same amount of work to do, the number of messages between client and Cadcorp GeognoSIS is reduced to just one.
This also means other client applications can use the same enhancements making them more reliable and maintainable.
In Cadcorp GeognoSIS Manager, click on View for any instance.
Expand the Stored Procedures option to see available options:
Select .NET ENGINE and click on Create Programming File in the top right.
This will open the Programming File dialog:
Fill in the form and press Submit to create the required Programming File; the file will be saved in C:\Program Files\Cadcorp GeognoSIS 9\StoredProcedures\WM9\DotNet
Stored procedures are defined in DLLs.
These DLLs are in the StoredProcedures/DotNet folder inside Cadcorp GeognoSIS.
When the service is started, it reads all the DLLs present and incorporates all valid procedures and classes into its API.
In Visual Studio:
- Select a Visual Basic Class Library project.
- Add a reference to the stored procedure base classes.
- These are contained in C:\Program Files\Cadcorp SIS Desktop 9\StoredProcedures\DotNet\Development\GeognoSIS\StoredProcedures.dll.
- Change the project’s output path to the DotNet folder.
If Cadcorp.GeognoSIS.StoredProcedures.dll does not already exist, use these steps to create it.
- Open GeognoSIS Manager, right-click .NET Engine and select All Tasks > Create programming files.
- The Create Programming Files dialog will be displayed, as shown above.
- Leave all Parameter Values blank and click OK.
- Cadcorp.GeognoSIS.StoredProcedures.dll is now created in C:\Program Files (x86)\Cadcorp GeognoSIS 9.0\StoredProcedures\DotNet\Development.
Visual Studio will have created a file Class1.vb for you. To the file header, add:
Imports Cadcorp.GeognoSIS.StoredProcedures
Now you make this class recognisable to Cadcorp GeognoSIS so you can start creating stored procedures.
Note: The name of the class is not relevant to Cadcorp GeognoSIS:
Public Class Class1
Inherits GeognoSIS;
Public Sub New(ByVal invoke As Invoke)
' No need to do anything other than call base class constructor MyBase.New(invoke)
End Sub
End Class
Cadcorp GeognoSIS considers the class valid for generating stored procedures if
- It is public
- It inherits from the class GeognoSIS and
- Has a public single-argument constructor as in this example.
Invalid classes are simply ignored.
If the class is valid, all its public methods will become part of the Cadcorp GeognoSIS API.
So as a very simple example you can add to this class:
Public Function HelloWorld() As String
Return "Hello World"
End Function
Build the class library, stop and restart Cadcorp GeognoSIS and start a browser pointing at http://localhost:4326/GeognoSIS/GeognoSIS.wsdl. Somewhere in this file you will find an entry corresponding to a new API method called SP_HelloWorld(). You can now use this method just as you would any of Cadcorp GeognoSIS’s built-in ones.
Note: Stored procedures always have the prefix SP_ added, which means it is not possible to replace any built-ins.
If two classes define stored procedures with the same name, you cannot predict which one will take precedence.
Stored procedures CAN use Cadcorp GeognoSIS’s built-in methods; your class inherits the entire Cadcorp GeognoSIS API and you just call these methods as you might in a client application.
This allows you to build up sequences of API calls into a single one.
For eg you might wish to extend LoadSwd() so that critical data layers are not accidentally exposed as editable to a web application.
To do this, first build your constants file as before and include in your project. Then add your new method:
Public Sub LoadSafeSwd(ByVal filename As String)
LoadSwd(filename)
Dim nOverlays As Integer = GetInt(SIS_OT_WINDOW, 0, "_nOverlay&")
For i As Integer = 0 To nOverlays – 1
If (GetInt(SIS_OT_OVERLAY, i, "_status&") = SIS_EDITABLE)
Then SetInt(SIS_OT_OVERLAY, i, "_status&", SIS_HITTABLE)
End If
Next
End Sub
Again rebuild the project, stop and restart Cadcorp GeognoSIS and your method will appear in the service description WSDL file.
TIP: Iterations through overlays and items are ideal for turning into stored procedures because of the potential saving of messages. In this example, a typical SWD of 20 overlays would take 42 messages if written in the client application but only 1 in a stored procedure.
Sometimes it is useful to gather together different pieces of information about an overlay (or an item) and return them as a group.
To do this, you can create classes that contain the information; these are then returned from your stored procedure.
One common task is to retrieve all the overlays within an SWD. To do this, add a class which represents an overlay to Class1.vb:
<Serializable()> Public Class OverlayInfo
Public Name As String Public Number As Integer Public Status As Integer
Public Sub New()
End Sub
Public Sub New(ByVal name As String, ByVal number As Integer, _
ByVal status As Integer)
Me.Name = name
Me.Number = number
Me.Status = status
End Sub
End Class
Cadcorp GeognoSIS considers the class valid as a datatype if it is:
- Public
- Serializable and
- Has a zero-argument constructor.
This must be explicitly provided if you have defined any other constructors in the class.
User Defined Type fields which are NotSerialized, Static, or Const are not exposed to clients. If a field is ReadOnly or non-Public AND is not any of these 3 types, it will be considered invalid and not available to Stored Procedures.
You can define methods in the class and use them inside the stored procedure but again these DO NOT become part of the GeognoSIS API.
You can now use this type to pass information between Cadcorp GeognoSIS and its clients.
For eg, add this method to Class1:
Public Function GetOverlayDetails() As OverlayInfo()
Dim nOverlays = GetInt(SIS_OT_WINDOW, 0, "_nOverlay&")
' Build an array of overlay information
Dim array(nOverlays) As OverlayInfo
' Populate each overlay in turn
For i As Integer = 0 To nOverlays - 1
Dim name = GetStr(SIS_OT_OVERLAY, i, "_name$")
Dim status = GetInt(SIS_OT_OVERLAY, i, "_status&")
array(i) = New OverlayInfo(name, i, status)
Next
Return array
End Function
Once again compile and restart Cadcorp GeognoSIS.
In addition to our stored procedures, the WSDL file defines a class UDT_ClassLibrary1_OverlayInfo with three members: Name, Number and Status.
Note: Here the client-side class name is prefixed both with UDT_ (User Defined Type) and the namespace that the class is defined in. In Visual Basic the namespace is the project name; in C# it is as defined by the namespace keyword.
Our client code can use this class just like any other – for example to generate a list of visible overlays:
Dim overlays() As UDT_ClassLibrary1_OverlayInfo = sis.GetOverlayDetails()
For I as Integer = 0 to overlays.Length
If (overlays(i).Status > SIS_INVISIBLE) Then
Response.Write(overlays(i).Name)
End If
Next
Essentially this is the same procedure as .NET.
You simply use the Java programming file com.cadcorp.geognosis.storedprocedures.jar and create .jar files containing the stored procedures.
Remember however:
- The environment variable PATH must include the folder which contains the Java Virtual Machine jvm.dll.
- You must copy the programming file into the main Stored Procedures folder. (This happens automatically when Visual Studio builds a .NET project.)
TIP: You can create your own data types to represent common concepts (such as an overlay) and populate them with as much information as required. This produces readable and intuitive code in your clients as well as passing a lot of information in a single message.
The following data types can be used:
- for procedure parameters
- to return types
- for User Defined Type (UDT) field types
In C#:
- bool
- byte
- Cadcorp.GeognoSIS.StoredProcedures.SisExtent
- Cadcorp.GeognoSIS.StoredProcedures.SisMimeType
- Cadcorp.GeognoSIS.StoredProcedures.SisVector
- double
- float
- int
- long
- short
- string
- System.DateTime
- void
void is used as a return type only. It does not apply to VB.NET, where you replace Function by a Sub routine (sub) instead.
Also included are one-dimensional arrays of the above data types. There are no artificial limits to the number of UDTs and stored procedures. The limit is the available RAM.
A binary string search is performed to find the definitions of UDTs and stored procedures used in a SOAP request.
Theoretically each additional stored procedure makes the method lookup of stored procedures and non-stored procedures "system" SOAP requests marginally slower.
It would require a vast number of stored procedures to be created before this delay becomes noticeable.
This is also true for UDTs except their number only affects stored procedures that use UDTs or built in types.
Note: The stored procedures can use null pointers as parameters and as return values.
Note on Cadcorp GeognoSIS communication speed with client
In GeognoSIS 9, communication speed has been significantly improved compared to older versions.
A .asmx service also uses wrapped Document/literal SOAP messages.
The SOAP style is selected by the new 'type' parameter added to GeognoSIS.wsdl.
When a web reference is added to a VS project, the service URL can be specified in the following ways:
http://localhost:4326/GeognoSIS/GeognoSIS.wsdl
http://localhost:4326/GeognoSIS/GeognoSIS.wsdl?type=RpcEncoded
http://localhost:4326/GeognoSIS/GeognoSIS.wsdl?type=DocumentLiteral
If the type argument is missing DocumentLiteral will be used by default.