Brothel Locator Web Service In COBOL

My last article on How To Create A JSON Web Service in ASP.NET did not attract much interest so it is time to step it up a notch. To make this article more interesting I’m going to create a new web service in Fujitsu NetCOBOL. As far as I know, there are no examples on the Internet on how to do anything meaningful with the .NET Framework using the COBOL language. Although you can use many programming languages with .NET nobody really uses anything other than C# and VB.NET.

Let’s suppose your company has senior management who often travel to Germany. Most of your expertise is in the COBOL programming language because the company has been using COBOL for years. And lets assume any new work must be done in COBOL as well to maintain the corporate IT culture. The executive puts in a request for a web service to help him find brothels while in Germany. You already have a web service that supplies him with client addresses from a contact database. He can’t easily find information on brothels in Germany because he does not read German so you’ll be maintaining a database of their locations.

Below is the database schema that we will be using for a database named Laufhaus with one table named ErosCenters:

column_name data_type numeric_precision character_maximum_length is_nullable column_default
ID int 10   NO  
BrothelName nvarchar   255 YES  
Street nvarchar   255 YES  
City nvarchar   255 YES  
PostalCode nvarchar   6 YES  
Phone nvarchar   25 YES  
Link nvarchar   255 YES  
Latitude nvarchar   50 YES  
Longitude nvarchar   50 YES  

Fujitsu NetCOBOL supplies an utility program which will add the necessary XML nodes to your web.config file for the database connection. This program will error until you run another utility program to update the machine.config. This was not well documented. Run the following command first: C:\Program Files\Common Files\Fujitsu NetCOBOL for .NET Runtime V3.0\Runtime\x86>setupconfig.exe /install

This will add the following section to your web.config file:

   1: <fujitsu.cobol>
   2:     <runtime>
   3:         <sqlSettings>
   4:             <connectionScope>
   5:                 <add key="@SQL_CONNECTION_SCOPE" value="APPLICATION_DOMAIN" />
   6:             </connectionScope>
   7:             <serverList>
   8:                 <server name="SERVER1" type="adonet" description="SERVER1">
   9:                     <add key="@SQL_DATASRC" value="LocalSqlServer" />
  10:                     <add key="@SQL_USERID" value="sa" />
  11:                     <add key="@SQL_PASSWORD" value="HIFDOBLHCFAPANBFLOJCNNMLDDHO" />
  12:                 </server>
  13:             </serverList>
  14:             <sqlDefaultInf>
  15:                 <add key="@SQL_DATASRC" value="LocalSqlServer" />
  16:                 <add key="@SQL_USERID" value="sa" />
  17:                 <add key="@SQL_PASSWORD" value="HIFDOBLHCFAPANBFLOJCNNMLDDHO" />
  18:             </sqlDefaultInf>
  19:         </sqlSettings>
  20:     </runtime>
  21: </fujitsu.cobol>

You can create a ASP.NET web service using COBOL as the language. It took me hours of experimentation to figure out how to turn a simple “Hello World” demo program into an actual web service. I had to work through how to make the database connection, how to return XML instead of a string, how to return multiple records, how to create an .NET object within COBOL, and how to call an object method. It was a hell of a lot of fun though to work in COBOL. As you can see this program is far more wordy than an equivalent program in C# would be.

   1: IDENTIFICATION DIVISION.
   2: CLASS-ID. CLASS-THIS AS "Service" INHERITS CLASS-WEBSERVICE
   3:     CUSTOM-ATTRIBUTE CA-WEBSERVICE CA-WEBSERVICEBINDING.
   4: ENVIRONMENT DIVISION.
   5: CONFIGURATION SECTION.
   6: SPECIAL-NAMES.
   7:     CUSTOM-ATTRIBUTE CA-WEBSERVICE
   8:       CLASS CLASS-WEBSERVICEATTRIBUTE
   9:       PROPERTY PROP-NAMESPACE IS N"http://www.williamsportwebdeveloper.com"
  10:     CUSTOM-ATTRIBUTE CA-WEBSERVICEBINDING
  11:       CLASS CLASS-WEBSERVICEBINDINGATTR
  12:       PROPERTY PROP-CONFORMSTO IS PROP-BASICPROFILE1_1 OF ENUM-WSIPROFILES
  13:     CUSTOM-ATTRIBUTE CA-WEBMETHOD
  14:       CLASS CLASS-WEBMETHODATTRIBUTE
  15:     .
  16: REPOSITORY.
  17:     CLASS CLASS-STRING AS "System.String"
  18:     CLASS CLASS-WEBMETHODATTRIBUTE AS "System.Web.Services.WebMethodAttribute"
  19:     CLASS CLASS-WEBSERVICE AS "System.Web.Services.WebService"
  20:     CLASS CLASS-WEBSERVICEATTRIBUTE AS "System.Web.Services.WebServiceAttribute"
  21:     CLASS CLASS-WEBSERVICEBINDINGATTR AS "System.Web.Services.WebServiceBindingAttribute"
  22:     CLASS CLASS-SQLPROCEDURE AS "Microsoft.SqlServer.Server.SqlProcedureAttribute"
  23:     CLASS CLASS-XML AS "System.Xml.XmlDocument"
  24:     CLASS CLASS-STRING-BUILDER AS "System.Text.StringBuilder"
  25:     ENUM ENUM-WSIPROFILES AS "System.Web.Services.WsiProfiles"
  26:     PROPERTY PROP-BASICPROFILE1_1 AS "BasicProfile1_1"
  27:     PROPERTY PROP-CONFORMSTO AS "ConformsTo"
  28:     PROPERTY PROP-NAMESPACE AS "Namespace"
  29:     .
  30: OBJECT.
  31: DATA DIVISION.
  32: WORKING-STORAGE SECTION.
  33: 01 MSG                  PIC X(1200).
  34: 01 WK-BROTHEL-NAME      PIC X(255).
  35: 01 WK-STREET            PIC X(255).
  36: 01 WK-CITY              PIC X(255).
  37: 01 WK-POSTAL-CODE       PIC X(6).
  38: 01 WK-PHONE             PIC X(255).
  39: 01 WK-LINK              PIC X(255).
  40: 01 WK-LATITUDE          PIC X(50).
  41: 01 WK-LONGITUDE         PIC X(50).
  42: 01 WK-STRING            OBJECT REFERENCE CLASS-STRING.
  43: 01 WK-STRING-BUILDER    OBJECT REFERENCE CLASS-STRING-BUILDER.
  44: PROCEDURE DIVISION.
  45:  
  46: METHOD-ID. NEW.
  47: PROCEDURE DIVISION.
  48:     *> Uncomment the following line if using designed components.
  49:     *> INVOKE SELF "InitializeComponent".
  50: END METHOD NEW.
  51:  
  52: METHOD-ID. GET-BROTHELS AS "GetBrothels" CUSTOM-ATTRIBUTE CA-WEBMETHOD.
  53: DATA DIVISION.
  54: WORKING-STORAGE SECTION.
  55: *> There must be enough fields for the number of columns.
  56:     EXEC SQL BEGIN DECLARE SECTION END-EXEC.
  57: 01 BROTHEL-LIST.
  58:   02 BROTHEL-NAME           PIC X(255).               
  59:   02 STREET                 PIC X(255).                      
  60:   02 CITY                   PIC X(255).             
  61:   02 POSTAL-CODE            PIC X(6).
  62:     02 PHONE                  PIC X(25).
  63:     02 LINK                   PIC X(255).
  64:     02 LATITUDE               PIC X(50).
  65:     02 LONGITUDE              PIC X(50).
  66: 01 NUMBER-OF-RECORDS    PIC S9(9) COMP-5.    
  67: 01 SQLINFOA.
  68:     02 SQLERRD              PIC S9(9) COMP-5 OCCURS 6 TIMES.
  69: 01 SQLSTATE                 PIC X(5).     
  70:     EXEC SQL END DECLARE SECTION END-EXEC.
  71: LINKAGE SECTION.
  72: 01 RET-VAL OBJECT REFERENCE CLASS-STRING.
  73: 01 RET-VAL-XML OBJECT REFERENCE CLASS-XML.
  74: PROCEDURE DIVISION RETURNING RET-VAL-XML.
  75:     EXEC SQL WHENEVER NOT FOUND GO TO :P-END END-EXEC.
  76:     EXEC SQL
  77:       DECLARE CUR1 CURSOR FOR SELECT BrothelName, Street, City, PostalCode, Phone, Link, Latitude, Longitude FROM ErosCenters          
  78:     END-EXEC.
  79:  P-START.
  80:     EXEC SQL CONNECT TO 'SERVER1' AS 'CNN1' END-EXEC.
  81:     EXEC SQL
  82:          SELECT COUNT(*) INTO :NUMBER-OF-RECORDS FROM ErosCenters 
  83:     END-EXEC.
  84:     EXEC SQL OPEN CUR1 END-EXEC.
  85:     *> CREATE AN STRING BUILDER OBJECT
  86:     INVOKE CLASS-STRING-BUILDER "NEW" RETURNING WK-STRING-BUILDER.
  87:     *> CALL THE OBJECT METHOD
  88:     SET WK-STRING TO "<ErosCenters>"
  89:     INVOKE WK-STRING-BUILDER "Append" USING BY VALUE WK-STRING.
  90:     PERFORM P-LOOP NUMBER-OF-RECORDS TIMES.
  91:  P-LOOP.
  92:     EXEC SQL
  93:         FETCH CUR1 INTO :BROTHEL-LIST
  94:     END-EXEC.
  95:     *> MOVE SQLERRD(3) TO MSG.
  96:     *> MOVE BROTHEL-LIST TO MSG.
  97:     MOVE BROTHEL-NAME TO WK-BROTHEL-NAME.
  98:     MOVE STREET TO WK-STREET.
  99:     MOVE CITY TO WK-CITY.
 100:     MOVE POSTAL-CODE TO WK-POSTAL-CODE.
 101:     MOVE PHONE TO WK-PHONE.
 102:     MOVE LINK TO WK-LINK.
 103:     MOVE LATITUDE TO WK-LATITUDE.
 104:     MOVE LONGITUDE TO WK-LONGITUDE.
 105:     *> CONSTRUCT XML STRING
 106:     SET WK-STRING TO CLASS-STRING::"Concat"(N"<Brothel><Name>" WK-BROTHEL-NAME N"</Name>").
 107:     INVOKE WK-STRING-BUILDER "Append" USING BY VALUE WK-STRING.   
 108:     SET WK-STRING TO CLASS-STRING::"Concat"(N"<Street>" WK-STREET N"</Street>").
 109:     INVOKE WK-STRING-BUILDER "Append" USING BY VALUE WK-STRING. 
 110:     SET WK-STRING TO CLASS-STRING::"Concat"(N"<City>" WK-CITY N"</City>").
 111:     INVOKE WK-STRING-BUILDER "Append" USING BY VALUE WK-STRING. 
 112:     SET WK-STRING TO CLASS-STRING::"Concat"(N"<PostalCode>" WK-POSTAL-CODE N"</PostalCode>").
 113:     INVOKE WK-STRING-BUILDER "Append" USING BY VALUE WK-STRING. 
 114:     SET WK-STRING TO CLASS-STRING::"Concat"(N"<Phone>" WK-PHONE N"</Phone>").
 115:     INVOKE WK-STRING-BUILDER "Append" USING BY VALUE WK-STRING.
 116:     SET WK-STRING TO CLASS-STRING::"Concat"(N"<Link>" WK-LINK N"</Link>").
 117:     INVOKE WK-STRING-BUILDER "Append" USING BY VALUE WK-STRING.
 118:     SET WK-STRING TO CLASS-STRING::"Concat"(N"<Latitude>" WK-LATITUDE N"</Latitude>").
 119:     INVOKE WK-STRING-BUILDER "Append" USING BY VALUE WK-STRING.
 120:     SET WK-STRING TO CLASS-STRING::"Concat"(N"<Longitude>" WK-LONGITUDE N"</Longitude></Brothel>").
 121:     INVOKE WK-STRING-BUILDER "Append" USING BY VALUE WK-STRING.
 122:  P-END.
 123:     SET WK-STRING TO "</ErosCenters>"
 124:     INVOKE WK-STRING-BUILDER "Append" USING BY VALUE WK-STRING.
 125:     EXEC SQL CLOSE CUR1 END-EXEC.
 126:     EXEC SQL ROLLBACK WORK END-EXEC.
 127:     EXEC SQL DISCONNECT DEFAULT END-EXEC.      
 128:     *> INVOKE SELF "GetData" .
 129:     *> CREATE AN XMLDOCUMENT OBJECT
 130:     INVOKE CLASS-XML "NEW" RETURNING RET-VAL-XML.
 131:     *> CALL THE OBJECT METHOD
 132:     SET WK-STRING TO WK-STRING-BUILDER::"ToString".
 133:     INVOKE RET-VAL-XML "LoadXml" USING BY VALUE WK-STRING. 
 134: END METHOD GET-BROTHELS.
 135:  
 136: METHOD-ID. GET-DATA AS "GetData".
 137: PROCEDURE DIVISION.
 138:     MOVE "Hello" & " World" TO MSG.
 139: END METHOD GET-DATA. 
 140:  
 141: END OBJECT.
 142: END CLASS CLASS-THIS.

Instead of a C# using namespace, you must alias a class in the REPOSITORY section. You define your string variables in the WORKING-STORAGE SECTION. Line 80 is where the database connection is being made. Then there is a query to determine how many records there are which tells you how many times to perform a routine. The database fields are moved to working storage strings which are then concatenated with XML tags. As you can see, just getting COBOL to build a string is hard work. A XmlDocument is created on line 130 and its LoadXml method is called to load the string that was built. This is what the web service returns.

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <ErosCenters>
   3:   <Brothel>
   4:     <Name>Laufhaus Vitalia</Name>
   5:     <Street>Helene-Wessel-Bogen 16</Street>
   6:     <City>Munich</City>
   7:     <PostalCode>80939</PostalCode>
   8:     <Phone>+49 (0) 89 35818865</Phone>
   9:     <Link>http://www.laufhaus-vitalia.de</Link>
  10:     <Latitude>48.197147</Latitude>
  11:     <Longitude>11.592529</Longitude>
  12:   </Brothel>
  13:   <Brothel>
  14:     <Name>Maison d'envie</Name>
  15:     <Street>Danziger Strasse 61</Street>
  16:     <City>Berlin</City>
  17:     <PostalCode>10435</PostalCode>
  18:     <Phone>030 417 259 20</Phone>
  19:     <Link>http://www.danziger61.de</Link>
  20:     <Latitude>52.540201</Latitude>
  21:     <Longitude>13.422267</Longitude>
  22:   </Brothel>
  23:   <Brothel>
  24:     <Name>Laufhaus Eros</Name>
  25:     <Street>Ulmer Strasse 16</Street>
  26:     <City>Goppingen</City>
  27:     <PostalCode>73107</PostalCode>
  28:     <Phone>07161-50 60 180</Phone>
  29:     <Link>http://wwwlaufhaus-eros.de</Link>
  30:     <Latitude>48.699458</Latitude>
  31:     <Longitude>9.663935</Longitude>
  32:   </Brothel>
  33: </ErosCenters>

I’ve used Eiffel for the .NET Framework but I would prefer COBOL since it can be used with the .NET Framework 2.0 and Visual Studio 2005. I learned COBOL in community college but never got the chance to use it professionally.

Please note that the brothel locator web service is intended as a joke. I just thought it would entice programmers to check out COBOL for the .NET Framework. My serious articles are often ignored. Nobody has actually requested this web service and it will not be used. It was purely a programming exercise. The nature of the data in the database is unimportant compared to the interesting choice of programming language and the technical challenge of making this work in COBOL.

This entry was posted in ASP.NET, COBOL, Programming and tagged , , , , . Bookmark the permalink.

5 Responses to Brothel Locator Web Service In COBOL

  1. Mack says:

    For god’s sake get the damn thing working! I want to use it!

    [Reply]

  2. Pingback: Brothel Locator Web Service In COBOL – Williamsport Web Developer … | Mobile Phone Street

  3. Pingback: Brothel Locator Web Service In COBOL – Williamsport Web Developer … | developer

  4. This is such a great resource, i understand you are providing the valiuable of information as well. JSON when communicating with web services as quality method. Nice article.

    [Reply]

  5. Emerson Lopes says:

    http://www.100coolthings.net

    OO Cobol (Windows e .Net) samples.

    have fun

    [Reply]

Leave a Reply

Your email address will not be published. Required fields are marked *