<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Franz</title>
    <description>The latest articles on DEV Community by Franz (@f345345dfg).</description>
    <link>https://dev.to/f345345dfg</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3671581%2F5f7f5670-e10e-4728-861f-ef8b79ab638c.png</url>
      <title>DEV Community: Franz</title>
      <link>https://dev.to/f345345dfg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/f345345dfg"/>
    <language>en</language>
    <item>
      <title>Building a tested calculator in the Uniface 10 IDE</title>
      <dc:creator>Franz</dc:creator>
      <pubDate>Sun, 20 Sep 2026 10:15:30 +0000</pubDate>
      <link>https://dev.to/f345345dfg/building-a-tested-calculator-in-the-uniface-10-ide-c73</link>
      <guid>https://dev.to/f345345dfg/building-a-tested-calculator-in-the-uniface-10-ide-c73</guid>
      <description>&lt;p&gt;Uniface is one of those tools you rarely read about, but that still runs a surprising amount of business software. I work with it regularly, and I wanted a small, self-contained project to try out a few things properly: a clean structure, input validation and - the part you almost never see in Uniface examples - automated tests.&lt;/p&gt;

&lt;p&gt;The result is a calculator with a modern flat look, about 25 functions (basic arithmetic, powers, roots, trigonometry, logarithms, rounding, memory, history) and a test service with 69 test cases.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgqbfcmrvvs3h3bo18skb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgqbfcmrvvs3h3bo18skb.png" alt=" " width="624" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everything here was built with &lt;strong&gt;Rocket Uniface 10 Community Edition (10.4)&lt;/strong&gt;, so you can follow along for free.&lt;/p&gt;

&lt;h2&gt;
  
  
  The architecture in one picture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CALC_FRM (Form)          CALC_SVC (Service)           CALC_TEST_SVC (Service)
 - fields &amp;amp; buttons   ---&amp;gt;   - public operations    &amp;lt;---  - exec -&amp;gt; RUN_ALL
 - checks empty fields       - all math                   - 69 test cases
 - shows errors              - validation                 - PASS/FAIL via putmess
 - history                   - returns 0 / -1 + text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most important decision: &lt;strong&gt;the form does not calculate anything&lt;/strong&gt;. It collects input, calls the service and displays the result. That is what makes the logic testable at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: A modeled entity without a database
&lt;/h2&gt;

&lt;p&gt;A Uniface form needs at least one entity - if you try to compile a form without one, you get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error: 1017 - Compiling a component without entities is not allowed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a calculator there is no table, so I created a &lt;strong&gt;modeled entity that is not in the database&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Model: &lt;code&gt;CALCULATOR_MDL&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Entity: &lt;code&gt;CALCULATOR_DMY&lt;/code&gt; (Database Behavior: &lt;em&gt;Not in Database&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Fields: &lt;code&gt;NUMBER1&lt;/code&gt;, &lt;code&gt;NUMBER2&lt;/code&gt;, &lt;code&gt;RESULT&lt;/code&gt; - data type Numeric&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You will see warnings like &lt;code&gt;1065 - Field ... might be truncated on output to DBMS&lt;/code&gt; and &lt;code&gt;1072 - Scaling ... changed to 8&lt;/code&gt; when compiling. Since the entity is never written to a database, they are harmless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: The form
&lt;/h2&gt;

&lt;p&gt;Create a &lt;strong&gt;Non-modal Form&lt;/strong&gt; (&lt;code&gt;CALC_FRM&lt;/code&gt;), drag the entity into it and add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the three modeled fields for input and result,&lt;/li&gt;
&lt;li&gt;non-modeled fields for &lt;code&gt;CALCULATION&lt;/code&gt; (last calculation), &lt;code&gt;MEMORY&lt;/code&gt; and &lt;code&gt;HISTORY&lt;/code&gt; (multi-line edit box),&lt;/li&gt;
&lt;li&gt;one &lt;strong&gt;Command Button&lt;/strong&gt; per function (&lt;code&gt;BTN_ADD&lt;/code&gt;, &lt;code&gt;BTN_SQRT&lt;/code&gt;, &lt;code&gt;BTN_SIN&lt;/code&gt;, ...).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The button caption is the field's &lt;strong&gt;Initial Value&lt;/strong&gt; (&lt;code&gt;+&lt;/code&gt;, &lt;code&gt;√x&lt;/code&gt;, &lt;code&gt;sin&lt;/code&gt;, ...). The flat look comes entirely from the widget properties, for example for the blue operator buttons:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BACKCOLOR=#2563EB; FORECOLOR=#FFFFFF; BACKCOLORFILL=flat;
BACKCOLORHOVER=#1D4ED8; BACKCOLORSELECT=#1E40AF; FONT=SANSLARGE
TOOLTIPTEXT=Add: Number 1 + Number 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Grey buttons for functions, indigo for memory, red for "C" - three or four colour groups are enough to make an old-school form look surprisingly current.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: The logic lives in a service
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;CALC_SVC&lt;/code&gt; is a plain Service component. Every function is a public operation with the same shape:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public operation DIVIDE
params
   numeric pA : IN
   numeric pB : IN
   numeric pResult : OUT
   string pError : OUT
endparams
   pError = ""
   if (pB = 0)
      pError = "Division by 0 is not possible."
      return -1
   endif
   pResult = pA / pB
   return 0
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The convention is simple: &lt;strong&gt;return 0 on success, -1 on error, and put a readable message into &lt;code&gt;pError&lt;/code&gt;&lt;/strong&gt;. The caller never has to know which error happened - it just shows the text.&lt;/p&gt;

&lt;p&gt;Unary functions (&lt;code&gt;SQRT&lt;/code&gt;, &lt;code&gt;SIN&lt;/code&gt;, &lt;code&gt;FACTORIAL&lt;/code&gt;, ...) have the same signature without &lt;code&gt;pB&lt;/code&gt;. Shared helpers such as the sine/cosine series or the natural logarithm are private &lt;code&gt;entry&lt;/code&gt; blocks inside the service, so both &lt;code&gt;LN&lt;/code&gt; and &lt;code&gt;LOG&lt;/code&gt; use the same code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public operation LOG
params
   numeric pA : IN
   numeric pResult : OUT
   string pError : OUT
endparams
variables
   numeric vLn
endvariables
   pError = ""
   if (pA &amp;lt;= 0)
      pError = "The logarithm is only defined for numbers greater than 0."
      return -1
   endif
   call NATURAL_LOG(pA, vLn)
   pResult = vLn / 2.302585092994045684
   return 0
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To keep the project self-contained, I implemented the transcendental functions myself in ProcScript: Taylor series for sine and cosine (after normalising the angle to -180..180 degrees), a series for &lt;code&gt;ln&lt;/code&gt; after scaling the argument into 0.5..2, "halve, expand, square back" for &lt;code&gt;e^x&lt;/code&gt;, and Newton's method for square roots. It is a nice exercise, and the tests below show whether the approximations are good enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: A button trigger
&lt;/h2&gt;

&lt;p&gt;Each button's &lt;code&gt;detail&lt;/code&gt; trigger follows the same pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;trigger detail
throws
variables
   numeric vResult
   string vError
endvariables
   call VALIDATE_INPUT
   if ($status &amp;lt; 0)
      return 0
   endif
   if (NUMBER1.CALCULATOR_DMY = "" | NUMBER2.CALCULATOR_DMY = "")
      message/error "Please enter both numbers."
      return 0
   endif
   activate "CALC_SVC".ADD(NUMBER1.CALCULATOR_DMY, NUMBER2.CALCULATOR_DMY, vResult, vError)
   if ($status &amp;lt; 0)
      message/error vError
      return 0
   endif
   RESULT.CALCULATOR_DMY = vResult
   call LOG_CALCULATION($concat(NUMBER1.CALCULATOR_DMY, " + ", NUMBER2.CALCULATOR_DMY, " = ", RESULT.CALCULATOR_DMY))
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After &lt;code&gt;activate&lt;/code&gt;, &lt;code&gt;$status&lt;/code&gt; holds the return value of the operation, so the -1 from the service arrives directly in the form.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;LOG_CALCULATION&lt;/code&gt; is a component entry that rounds the result for display, writes it into &lt;code&gt;CALCULATION&lt;/code&gt; and prepends it to &lt;code&gt;HISTORY&lt;/code&gt;. In a Uniface multi-line field, &lt;code&gt;%%^&lt;/code&gt; is the line separator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HISTORY.CALCULATOR_DMY = $concat(vText, "%%^", HISTORY.CALCULATOR_DMY)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: The input validation trap
&lt;/h2&gt;

&lt;p&gt;This one surprised me. Type &lt;code&gt;2-1&lt;/code&gt; into a numeric field and &lt;strong&gt;tab out&lt;/strong&gt; - Uniface rejects it and keeps the focus in the field. Fine.&lt;/p&gt;

&lt;p&gt;But type &lt;code&gt;2-1&lt;/code&gt; and &lt;strong&gt;click a button directly&lt;/strong&gt;, and the trigger runs anyway. The field's raw text is still &lt;code&gt;2-1&lt;/code&gt;, while the numeric value used in the calculation is &lt;code&gt;2&lt;/code&gt;. So &lt;code&gt;ln(2-1)&lt;/code&gt; happily returned &lt;code&gt;0.693...&lt;/code&gt; - the logarithm of 2.&lt;/p&gt;

&lt;p&gt;The fix is an explicit check before every calculation. The service has a &lt;code&gt;VALIDATE_NUMBER&lt;/code&gt; operation that walks through the raw string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;while (vPos &amp;lt;= vLen)
   vChar = pValue[vPos:1]
   if ($scan("0123456789", vChar) &amp;gt; 0)
      vDigits = vDigits + 1
   elseif (vChar = ".")
      vDots = vDots + 1
   elseif (vChar != "-" | vPos != 1)
      pError = $concat(pLabel, " is not a valid number. Use digits, one dot as decimal separator and an optional leading minus sign.")
      return -1
   endif
   vPos = vPos + 1
endwhile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The form calls it for both fields in its &lt;code&gt;VALIDATE_INPUT&lt;/code&gt; entry. Accepted: &lt;code&gt;42&lt;/code&gt;, &lt;code&gt;-3.5&lt;/code&gt;. Rejected: &lt;code&gt;2-1&lt;/code&gt;, &lt;code&gt;2,5&lt;/code&gt;, &lt;code&gt;1.5.2&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;abc&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Tests in ProcScript
&lt;/h2&gt;

&lt;p&gt;You don't need a test framework for this. A test service with an &lt;code&gt;exec&lt;/code&gt; operation is enough, because &lt;strong&gt;Compile &amp;amp; Test&lt;/strong&gt; on a service runs &lt;code&gt;exec&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public operation exec
   activate $instancename.RUN_ALL()
   return $status
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two small helper entries do the assertions. &lt;code&gt;CHECK_VALUE&lt;/code&gt; compares with a tolerance (the series only approximate), &lt;code&gt;CHECK_ERROR&lt;/code&gt; expects a negative status:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;entry CHECK_VALUE
params
   string pName : IN
   numeric pExpected : IN
   numeric pActual : IN
   numeric pStatus : IN
   numeric pTests : INOUT
   numeric pFailures : INOUT
endparams
variables
   numeric vDiff
endvariables
   pTests = pTests + 1
   vDiff = pActual - pExpected
   if (vDiff &amp;lt; 0)
      vDiff = 0 - vDiff
   endif
   if (pStatus &amp;lt; 0 | vDiff &amp;gt; 0.000001)
      pFailures = pFailures + 1
      putmess $concat($concat("FAIL: ", pName, " (expected ", pExpected), $concat(", got ", pActual, ")"))
   else
      putmess $concat("PASS: ", pName)
   endif
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A test case is then three lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;activate "CALC_SVC".SIN(30, vResult, vError)
vStatus = $status
call CHECK_VALUE("SIN 30", 0.5, vResult, vStatus, vTests, vFailures)

activate "CALC_SVC".TAN(90, vResult, vError)
vStatus = $status
call CHECK_ERROR("TAN 90", vStatus, vTests, vFailures)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The suite covers every operation with normal values, edge cases and expected errors - for example &lt;code&gt;ROUND(-2.5, 0) = -3&lt;/code&gt;, &lt;code&gt;LOG(0.01) = -2&lt;/code&gt;, &lt;code&gt;10! = 3628800&lt;/code&gt;, division by zero, &lt;code&gt;0 ^ -1&lt;/code&gt;, &lt;code&gt;2 ^ 0.5&lt;/code&gt; (only whole-number exponents are supported), &lt;code&gt;FACTORIAL(2.5)&lt;/code&gt; and all the validation strings above.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;putmess&lt;/code&gt; output ends up in the session log (&lt;code&gt;log\ide_&amp;lt;pid&amp;gt;.log&lt;/code&gt; in your Uniface user folder):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PASS: ADD 2 + 3
PASS: DIVIDE 1 / 0 (error expected)
PASS: SIN 30
...
PASS: VALIDATE 2-1 (error expected)
Calculator: 69 tests, 0 failures
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One caveat worth knowing: a &lt;code&gt;CHECK_ERROR&lt;/code&gt; test would also pass if the service could not be activated at all. That is acceptable here because dozens of &lt;code&gt;CHECK_VALUE&lt;/code&gt; tests would fail in the same situation - but if you write a suite that only checks errors, test the activation separately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pitfalls I ran into
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;$concat&lt;/code&gt; has an argument limit.&lt;/strong&gt; A call with seven arguments failed with &lt;code&gt;1000 - Syntax error (Wrong number of arguments)&lt;/code&gt;. Nesting two &lt;code&gt;$concat&lt;/code&gt; calls fixes it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;askmess&lt;/code&gt; vs. &lt;code&gt;message/error&lt;/code&gt;.&lt;/strong&gt; &lt;code&gt;askmess&lt;/code&gt; without options shows a Yes/No dialog - odd for an error. &lt;code&gt;message/error&lt;/code&gt; shows a proper error box with OK.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The script editor has two sections.&lt;/strong&gt; Each object in &lt;em&gt;Write Script&lt;/em&gt; has a &lt;em&gt;Declarations&lt;/em&gt; and a &lt;em&gt;Script&lt;/em&gt; section. If you select all and paste a trigger, it can end up in &lt;em&gt;Declarations&lt;/em&gt;. Paste into the &lt;em&gt;Script&lt;/em&gt; section.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't touch the repository while the IDE is running.&lt;/strong&gt; The Community Edition keeps its repository in a local SQLite file (&lt;code&gt;dbms\usys.db&lt;/code&gt;). Editing it with an external tool while the IDE was open made the IDE hang, and it would not start again until I restored a backup. Make every change through the IDE - or at least close it first and keep a copy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;None of this is exotic - it is the same separation you would use in any other stack: UI in one place, logic in a service with a clear contract, and tests that call the service directly. What I like is how little Uniface needs for it: no framework, no plugins, just a service with an &lt;code&gt;exec&lt;/code&gt; operation and &lt;code&gt;putmess&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you are maintaining Uniface applications, the pattern scales: move logic out of form triggers into services one piece at a time, and put a test service next to each one before you change anything.&lt;/p&gt;

&lt;p&gt;How do you test your Uniface code - or do you? I would be curious to hear about other approaches in the comments.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclosure: This article was created with the help of AI&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>uniface</category>
      <category>lowcode</category>
      <category>testing</category>
      <category>legacy</category>
    </item>
    <item>
      <title>Working with Uniface Lists Using `putitem` and `getitem`</title>
      <dc:creator>Franz</dc:creator>
      <pubDate>Mon, 14 Sep 2026 19:18:46 +0000</pubDate>
      <link>https://dev.to/f345345dfg/working-with-uniface-lists-using-putitem-and-getitem-387d</link>
      <guid>https://dev.to/f345345dfg/working-with-uniface-lists-using-putitem-and-getitem-387d</guid>
      <description>&lt;p&gt;In Uniface ProcScript, &lt;code&gt;putitem&lt;/code&gt; adds or replaces list items, while &lt;code&gt;getitem&lt;/code&gt; copies an item into a variable. This example uses an indexed list, with positions starting at &lt;strong&gt;1&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build, read, and update a list
&lt;/h2&gt;

&lt;p&gt;Add this operation to your component’s &lt;strong&gt;Script&lt;/strong&gt; section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public operation LIST_DEMO
variables
  string vMonths, vMonth
endvariables

vMonths = ""

; Append three items.
putitem vMonths, -1, "January"
putitem vMonths, -1, "February"
putitem vMonths, -1, "March"

; Read the second item: February.
getitem vMonth, vMonths, 2
putmess vMonth

; Replace the second item, then read it again.
putitem vMonths, 2, "April"
getitem vMonth, vMonths, 2
putmess vMonth

return 0
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected message output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;February
April
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Remember these rules
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;putitem vList, -1, value&lt;/code&gt; appends an item.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;putitem vList, 2, value&lt;/code&gt; replaces the second item. A position beyond the list’s end creates empty intermediate items.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getitem vValue, vList, 2&lt;/code&gt; reads the second item without removing it. Index &lt;code&gt;-1&lt;/code&gt; reads the last item.&lt;/li&gt;
&lt;li&gt;After &lt;code&gt;getitem&lt;/code&gt;, &lt;code&gt;$status &amp;gt; 0&lt;/code&gt; indicates the copied item’s position. If no item was copied, &lt;code&gt;$status&lt;/code&gt; is &lt;code&gt;0&lt;/code&gt; and the target is empty. Check the status immediately when handling a potentially missing item.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use &lt;code&gt;putitem&lt;/code&gt; to construct the list instead of typing ordinary semicolons: Uniface uses special list separators.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Creating a Service in Uniface 10 — Step by Step</title>
      <dc:creator>Franz</dc:creator>
      <pubDate>Mon, 14 Sep 2026 19:15:21 +0000</pubDate>
      <link>https://dev.to/f345345dfg/creating-a-service-in-uniface-10-step-by-step-2gp7</link>
      <guid>https://dev.to/f345345dfg/creating-a-service-in-uniface-10-step-by-step-2gp7</guid>
      <description>&lt;p&gt;This short guide shows how to create and name a service component in the Uniface IDE. You need an existing project and write access to your development repository.&lt;/p&gt;

&lt;p&gt;The steps are based on Rocket Uniface 10 Community Edition 10.4.03, patch 021, on Windows 11.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Open your project
&lt;/h2&gt;

&lt;p&gt;Open your project in the Uniface IDE, for example through &lt;strong&gt;Recent Objects&lt;/strong&gt; on the start page. In the project editor, select &lt;strong&gt;Define Project&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Select the Service template
&lt;/h2&gt;

&lt;p&gt;Open &lt;strong&gt;Templates&lt;/strong&gt; on the left and find &lt;strong&gt;Component: Service&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Select this exact template. &lt;strong&gt;Component: Entity Service&lt;/strong&gt; and &lt;strong&gt;Modeled Component: Service&lt;/strong&gt; are different templates.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Add the component
&lt;/h2&gt;

&lt;p&gt;Right-click &lt;strong&gt;Component: Service&lt;/strong&gt; and select &lt;strong&gt;Insert into Structure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The IDE adds a new component to the project with an automatically generated name, such as &lt;strong&gt;UCSVC_1&lt;/strong&gt;. The name may differ in your repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Name your service
&lt;/h2&gt;

&lt;p&gt;Double-click the new component to open it, then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select &lt;strong&gt;Define Structure&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Right-click the top-level component row.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Rename&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Enter a name, such as &lt;strong&gt;HELLO_SERVICE&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Press Enter to confirm.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Choose a name that is not already used in your repository. Check that the new name appears in the component structure and editor tab, then save your changes using the IDE’s Save action.&lt;/p&gt;

&lt;p&gt;Your service component is now created and named, ready for you to add its implementation.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>🖥️ The DEC-VAX: The Machine That Changed Computing History</title>
      <dc:creator>Franz</dc:creator>
      <pubDate>Wed, 31 Dec 2025 10:16:01 +0000</pubDate>
      <link>https://dev.to/f345345dfg/the-dec-vax-the-machine-that-changed-computing-history-50kf</link>
      <guid>https://dev.to/f345345dfg/the-dec-vax-the-machine-that-changed-computing-history-50kf</guid>
      <description>&lt;h2&gt;
  
  
  🎯 What Was the DEC-VAX?
&lt;/h2&gt;

&lt;p&gt;The DEC-VAX (Virtual Address Extension) was a family of 32-bit minicomputers developed by Digital Equipment Corporation (DEC). The first model, the VAX-11/780, was introduced on October 25, 1977, and shipped starting in 1978. This groundbreaking computer transformed DEC from a $700 million company into a $14 billion powerhouse that seriously challenged even IBM.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 The Birth of a Legend
&lt;/h2&gt;

&lt;p&gt;Gordon Bell, who now works at Microsoft's research division, recognized back in 1972 that the PDP-11 minicomputer wouldn't survive the decade due to its 16-bit address space limitation. In 1975, he started working with a team of engineers to develop a computer with 32-bit addressing that remained compatible with the older PDP-11 minicomputers.&lt;/p&gt;

&lt;p&gt;The first system shipped in 1978 to Carnegie Mellon University in Pittsburgh, followed by CERN in Switzerland and a German Max Planck Institute. 📦&lt;/p&gt;

&lt;h2&gt;
  
  
  💻 Technical Innovation
&lt;/h2&gt;

&lt;p&gt;The VAX-11/780 ran on the VMS operating system (VAX Version 1 contained approximately one million lines of code) and featured innovative capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Built-in error correction (Error Correction and Detection Code; ECC)&lt;/li&gt;
&lt;li&gt;✅ Virtual memory support&lt;/li&gt;
&lt;li&gt;✅ 32-bit architecture breaking the 16-bit barrier&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⌨️ The VT100 Terminal Legacy
&lt;/h2&gt;

&lt;p&gt;Around 1976, DEC introduced the VT100, an affordable and robust ASCII terminal whose command set remains the de-facto standard for terminal emulation programs today. These terminals, featuring the iconic &lt;strong&gt;gold-colored key&lt;/strong&gt;, were used alongside VAX systems and shaped an entire generation of developers.&lt;/p&gt;

&lt;p&gt;Fun fact: This is why Uniface still uses the "Gold Key" concept! 🔑&lt;/p&gt;

&lt;h2&gt;
  
  
  📈 Market Dominance
&lt;/h2&gt;

&lt;p&gt;By the 1980s, DEC had become the world's second-largest computer manufacturer by revenue, right behind IBM. The company evolved a comprehensive computer family with various subfamilies - advances in chip technology miniaturized the electronics while prices steadily declined.&lt;/p&gt;

&lt;p&gt;DEC's predecessor system, the PDP-11, had already achieved remarkable success with over 600,000 units sold. The VAX family continued this legacy throughout the 1980s. 🌍&lt;/p&gt;

&lt;h2&gt;
  
  
  🔚 The End of an Era
&lt;/h2&gt;

&lt;p&gt;In 1992, the death knell rang for VAX systems when DEC introduced the RISC CPU "21064" (codename: Alpha) - a 64-bit RISC processor, in contrast to the 32-bit CISC architecture of VAX computers. With the retirement of the VAX, a significant chapter in computing history came to an end.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎓 Legacy Impact
&lt;/h2&gt;

&lt;p&gt;The VAX systems influenced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modern operating system design (VMS concepts live on in OpenVMS)&lt;/li&gt;
&lt;li&gt;Terminal standards (VT100 emulation)&lt;/li&gt;
&lt;li&gt;Enterprise computing architecture&lt;/li&gt;
&lt;li&gt;Developer workflows and tooling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding the VAX era helps us appreciate why certain "legacy" systems work the way they do today! 🏛️&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you worked with VAX systems or encountered their legacy in modern software? Share your stories in the comments! 💬&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This article was created with the assistance of AI to research and compile historical information about DEC-VAX systems.&lt;/p&gt;

</description>
      <category>history</category>
      <category>retrocomputing</category>
      <category>legacy</category>
      <category>hardware</category>
    </item>
    <item>
      <title>🔑 The Gold Key in Uniface - A Relic from the VAX Era</title>
      <dc:creator>Franz</dc:creator>
      <pubDate>Wed, 31 Dec 2025 10:07:00 +0000</pubDate>
      <link>https://dev.to/f345345dfg/the-gold-key-in-uniface-a-relic-from-the-vax-era-3mf2</link>
      <guid>https://dev.to/f345345dfg/the-gold-key-in-uniface-a-relic-from-the-vax-era-3mf2</guid>
      <description>&lt;h2&gt;
  
  
  🤔 What is the Gold Key?
&lt;/h2&gt;

&lt;p&gt;The Gold Key is a special key in Uniface that modifies the behavior of subsequently typed characters. This function originates from the original development of Uniface on DEC-VAX machines, whose terminals actually had a &lt;strong&gt;gold-colored or yellow key&lt;/strong&gt; on the keyboard.&lt;/p&gt;

&lt;p&gt;A true piece of computing history! 🖥️✨&lt;/p&gt;

&lt;h2&gt;
  
  
  ⌨️ How to Use the Gold Key Today
&lt;/h2&gt;

&lt;p&gt;On Microsoft Windows, there are several options:&lt;/p&gt;

&lt;h3&gt;
  
  
  Standard Mapping
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Numeric Keypad&lt;/strong&gt;: &lt;code&gt;+&lt;/code&gt; (Plus key on the numpad)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Without Numpad&lt;/strong&gt;: &lt;code&gt;Ctrl + Shift + F1&lt;/code&gt; (press simultaneously)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web Applications&lt;/strong&gt;: &lt;code&gt;\&lt;/code&gt; (Backslash)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💡 Practical Use Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Enter Special Characters 📝
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Gold Key + ;&lt;/code&gt; (semicolon) creates a Gold-semicolon, which serves as a &lt;strong&gt;subfill separator&lt;/strong&gt; in Uniface lists&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Wildcard Search 🔍
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Gold + *&lt;/code&gt; for data query profiles &lt;/p&gt;

&lt;h3&gt;
  
  
  3. Structure Editor Functions ⚡
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Gold + R&lt;/code&gt; = Retrieve&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Gold + ,&lt;/code&gt; = Find Again&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🛠️ Configuration
&lt;/h2&gt;

&lt;p&gt;Gold Key combinations are defined with &lt;code&gt;^GOLD_BASE_SET&lt;/code&gt; and are available by default in all keyboard translation tables.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎯 Conclusion
&lt;/h2&gt;

&lt;p&gt;The Gold Key may seem antiquated at first glance, but it remains an integral part of Uniface operation today. A perfect example of how legacy systems carry their history with them! 🚀&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Do you have more Uniface tips? Share them in the comments! 💬&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This article was created with the assistance of AI to research and compile information about Uniface's Gold Key functionality.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>tooling</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🔌 MySQL Connector in Uniface 10.4: A Developer's Guide</title>
      <dc:creator>Franz</dc:creator>
      <pubDate>Tue, 23 Dec 2025 09:02:48 +0000</pubDate>
      <link>https://dev.to/f345345dfg/mysql-connector-in-uniface-104-a-developers-guide-2nmj</link>
      <guid>https://dev.to/f345345dfg/mysql-connector-in-uniface-104-a-developers-guide-2nmj</guid>
      <description>&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This blog post was created with AI assistance and is based on the official Uniface 10.4 documentation for the MySQL connector.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction: Why MySQL Integration Matters for Uniface Developers
&lt;/h2&gt;

&lt;p&gt;If you're working with Uniface 10.4, you're likely maintaining enterprise applications built with this powerful low-code platform. MySQL has become one of the most popular open-source relational database management systems, offering cost-effective data storage and compatibility with modern cloud platforms.&lt;/p&gt;

&lt;p&gt;Whether you're integrating with existing MySQL databases, modernizing legacy systems, or building new functionality, understanding the MySQL connector in Uniface is essential. This guide covers the core features, installation requirements, and practical setup based on official documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the MySQL Connector in Uniface?
&lt;/h2&gt;

&lt;p&gt;The MySQL DBMS connector is a database driver that enables Uniface applications to interact with MySQL database servers. It provides a bridge between Uniface's data model and MySQL's relational database structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Connector Information
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Connector Mnemonic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;MQL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQL Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stored Procedures Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Create Table Utility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Load Definitions Utility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Create Scripts Utility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Not Supported&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Understanding the Utilities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Create Table&lt;/strong&gt;: Allows you to generate MySQL tables directly from Uniface entity definitions in your application model&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load Definitions&lt;/strong&gt;: Enables reverse engineering—importing existing MySQL table structures into Uniface entities&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create Scripts&lt;/strong&gt;: Cannot generate standalone SQL script files (use alternative methods if needed)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Platform and Version Support
&lt;/h2&gt;

&lt;p&gt;The MySQL connector is available for Uniface 10.4 across multiple supported platforms. For the complete list of supported platforms and MySQL versions, consult the official &lt;a href="https://community.rocketsoftware.com/rocket-uniface-product-updates-108/uniface-product-availability-information-18191" rel="noopener noreferrer"&gt;Platform Availability Matrix&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation: The Critical Setup Steps ⚙️
&lt;/h2&gt;

&lt;p&gt;The MySQL connector requires proper configuration to function. Here's what you need to know:&lt;/p&gt;

&lt;h3&gt;
  
  
  Requirement: libmysql.dll
&lt;/h3&gt;

&lt;p&gt;To use the MySQL connector in Uniface, you must copy &lt;strong&gt;libmysql.dll&lt;/strong&gt; from your MySQL installation to your Uniface installation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Essential Step:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Locate libmysql.dll in your MySQL Connector/C installation folder&lt;/li&gt;
&lt;li&gt;Copy it to: &lt;code&gt;&amp;lt;Uniface Installation&amp;gt;\common\bin\&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  ⚠️ The 32-bit vs. 64-bit Compatibility Issue
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;This is critical:&lt;/strong&gt; The 32-bit and 64-bit versions of libmysql.dll are &lt;strong&gt;not binary compatible&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You must ensure:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If running &lt;strong&gt;32-bit Uniface&lt;/strong&gt; → copy the &lt;strong&gt;32-bit&lt;/strong&gt; libmysql.dll&lt;/li&gt;
&lt;li&gt;If running &lt;strong&gt;64-bit Uniface&lt;/strong&gt; → copy the &lt;strong&gt;64-bit&lt;/strong&gt; libmysql.dll&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using the wrong architecture will result in library loading errors. Always verify which version of Uniface you're running before copying the DLL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring the MySQL Connector in Uniface
&lt;/h2&gt;

&lt;p&gt;Configuration is handled through Uniface's assignment files (&lt;code&gt;.asn&lt;/code&gt; files). The specific syntax and options depend on your Uniface configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic Setup Process
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Open your assignment file&lt;/strong&gt; in the Uniface IDE or text editor&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Define the logical database path&lt;/strong&gt; with the MQL mnemonic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configure connection parameters&lt;/strong&gt; (hostname, database name, credentials)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test the connection&lt;/strong&gt; before deploying&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For detailed configuration options and parameters specific to your environment, refer to the official Uniface 10.4 documentation on database connector configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supported Features in Detail
&lt;/h2&gt;

&lt;h3&gt;
  
  
  SQL Support
&lt;/h3&gt;

&lt;p&gt;The MySQL connector supports SQL statements, allowing you to execute queries directly from Uniface applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stored Procedures
&lt;/h3&gt;

&lt;p&gt;MySQL stored procedures are fully supported. You can call existing stored procedures from Uniface and handle their results. This is useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex business logic encapsulated in the database&lt;/li&gt;
&lt;li&gt;Performance-critical operations&lt;/li&gt;
&lt;li&gt;Reusing existing database code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Important consideration:&lt;/strong&gt; When working with stored procedures, ensure proper error handling on both the Uniface and MySQL sides.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important Naming Considerations
&lt;/h2&gt;

&lt;p&gt;When using MySQL with Uniface, be aware of naming rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uniface requires uppercase names in the application model definition&lt;/li&gt;
&lt;li&gt;MySQL has reserved words that cannot be used for table or entity names&lt;/li&gt;
&lt;li&gt;Always check the official documentation for reserved words in your MySQL version&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Scenarios
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating Tables from Uniface
&lt;/h3&gt;

&lt;p&gt;Use the Create Table utility when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're building a new application with a database&lt;/li&gt;
&lt;li&gt;You want tables generated automatically from your entity model&lt;/li&gt;
&lt;li&gt;You need consistent naming and structure across entities&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Importing Existing Database Structures
&lt;/h3&gt;

&lt;p&gt;Use Load Definitions when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're integrating with an existing MySQL database&lt;/li&gt;
&lt;li&gt;You need to reverse-engineer database schema into Uniface entities&lt;/li&gt;
&lt;li&gt;You're migrating from another system to Uniface&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Troubleshooting Tips
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Connection Issues
&lt;/h3&gt;

&lt;p&gt;If Uniface cannot load the MySQL connector:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verify libmysql.dll is in &lt;code&gt;&amp;lt;Uniface&amp;gt;\common\bin\&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Check that the DLL architecture matches your Uniface installation (32-bit or 64-bit)&lt;/li&gt;
&lt;li&gt;Ensure all required files are properly copied&lt;/li&gt;
&lt;li&gt;Verify database connectivity settings in your assignment file&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Library Loading Errors
&lt;/h3&gt;

&lt;p&gt;Common error messages indicate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Missing libmysql.dll&lt;/li&gt;
&lt;li&gt;Architecture mismatch (32-bit/64-bit)&lt;/li&gt;
&lt;li&gt;Missing dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Naming and Reserved Words
&lt;/h3&gt;

&lt;p&gt;If table creation fails:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check for reserved MySQL keywords in your entity names&lt;/li&gt;
&lt;li&gt;Review naming rules in the Uniface documentation for MySQL&lt;/li&gt;
&lt;li&gt;Ensure compliance with both Uniface and MySQL naming conventions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  U_VERSION Mechanism for Locking
&lt;/h2&gt;

&lt;p&gt;The MySQL connector supports the U_VERSION mechanism, which is recommended for improving locking performance in concurrent environments. Consult the Uniface documentation for implementation details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for MySQL Integration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Configuration Management
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Store connection credentials securely&lt;/li&gt;
&lt;li&gt;Use the Platform Availability Matrix to verify version compatibility&lt;/li&gt;
&lt;li&gt;Test all database operations thoroughly before production deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Development Workflow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Design your data model&lt;/strong&gt; in Uniface first&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generate tables&lt;/strong&gt; using Create Table utility, or&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Import existing schema&lt;/strong&gt; using Load Definitions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test SQL statements&lt;/strong&gt; and stored procedure calls&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy with proper configuration&lt;/strong&gt; management&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Using Stored Procedures Effectively
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Keep procedures focused on specific business logic&lt;/li&gt;
&lt;li&gt;Document procedure parameters and expected results&lt;/li&gt;
&lt;li&gt;Handle errors appropriately in both database and Uniface layers&lt;/li&gt;
&lt;li&gt;Test procedures independently before integration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Referential Integrity
&lt;/h2&gt;

&lt;p&gt;MySQL connector supports referential integrity management. Review the documentation for how to properly implement and maintain referential integrity constraints in your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The MySQL connector in Uniface 10.4 provides robust support for integrating MySQL databases with your enterprise applications. Key points to remember:&lt;/p&gt;

&lt;p&gt;✅ Always match the libmysql.dll architecture (32-bit/64-bit) to your Uniface installation&lt;br&gt;
✅ Use Create Table for forward engineering and Load Definitions for reverse engineering&lt;br&gt;
✅ MySQL stored procedures are fully supported&lt;br&gt;
✅ Follow Uniface naming rules and avoid MySQL reserved words&lt;br&gt;
✅ Consult the Platform Availability Matrix for version compatibility&lt;br&gt;
✅ Test thoroughly before production deployment&lt;/p&gt;

&lt;p&gt;By following these guidelines and referring to the official documentation, you can successfully integrate MySQL with your Uniface 10.4 applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  Sources and References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Uniface 10.4 MySQL Connector Documentation (December 15, 2025)&lt;/li&gt;
&lt;li&gt;Rocket Software Platform Availability Matrix&lt;/li&gt;
&lt;li&gt;Rocket Uniface Community Documentation&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Have you integrated MySQL with Uniface? What challenges did you encounter? Share your experiences in the comments!&lt;/strong&gt; 💬&lt;/p&gt;

</description>
      <category>mysql</category>
      <category>uniface</category>
      <category>legacysystems</category>
      <category>databaseconnector</category>
    </item>
    <item>
      <title>🔐 Connecting Uniface 10.4 to LDAP Servers: A Complete Guide</title>
      <dc:creator>Franz</dc:creator>
      <pubDate>Tue, 23 Dec 2025 08:43:36 +0000</pubDate>
      <link>https://dev.to/f345345dfg/connecting-uniface-104-to-ldap-servers-a-complete-guide-5abc</link>
      <guid>https://dev.to/f345345dfg/connecting-uniface-104-to-ldap-servers-a-complete-guide-5abc</guid>
      <description>&lt;p&gt;&lt;strong&gt;Subtitle:&lt;/strong&gt; &lt;em&gt;Unlock the power of Directory Services in your Uniface applications with the 10.4 LDAP Connector.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the world of enterprise development, applications rarely live in isolation. They need to talk to other systems, and one of the most common requirements is authentication and user management. This is where &lt;strong&gt;LDAP&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;p&gt;If you are a Uniface developer working with version 10.4, you have a powerful tool at your disposal: the &lt;strong&gt;Uniface LDAP Connector&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this guide, we will break down exactly how to configure, use, and troubleshoot this connector, with a &lt;strong&gt;special deep dive into the &lt;code&gt;addbase&lt;/code&gt; option&lt;/strong&gt;. Whether you are a veteran dealing with legacy systems or a modern developer integrating new directories, this guide is for you! 🚀&lt;/p&gt;




&lt;h2&gt;
  
  
  1. What is LDAP? (A Quick Refresher) 📚
&lt;/h2&gt;

&lt;p&gt;Before we dive into the code, let's clarify a few terms for those who might be new to this specific domain.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;LDAP (Lightweight Directory Access Protocol):&lt;/strong&gt; Think of LDAP as a highly optimized, digital phonebook. It is a protocol used to access and manage distributed directory information services over an IP network. It's "Lightweight" because it was designed as a simpler alternative to the older, heavier &lt;strong&gt;X.500&lt;/strong&gt; standard.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;X.500:&lt;/strong&gt; This was the original "granddaddy" of directory standards. It was comprehensive but very complex and heavy on network resources. LDAP kept the directory structure of X.500 but streamlined the way we talk to it.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;IPv6:&lt;/strong&gt; You might see references to this in networking docs. It stands for "Internet Protocol version 6." It's the modern address system for the internet, replacing the older IPv4. Uniface and modern LDAP servers fully support IPv6, ensuring your application is future-proof.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;In simple terms:&lt;/strong&gt; If your company uses Microsoft Active Directory (AD) or OpenLDAP to store user passwords and emails, you use LDAP to talk to it.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The Uniface LDAP Connector 🔌
&lt;/h2&gt;

&lt;p&gt;Uniface doesn't treat LDAP like a weird external service; it treats it &lt;strong&gt;like a database&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is the magic of the Uniface architecture. You define an Entity (table) in your model, map it to an LDAP Object Class (like &lt;code&gt;person&lt;/code&gt; or &lt;code&gt;organizationalUnit&lt;/code&gt;), and use standard Uniface ProcScript commands (&lt;code&gt;retrieve&lt;/code&gt;, &lt;code&gt;store&lt;/code&gt;, &lt;code&gt;delete&lt;/code&gt;) to manipulate data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Capabilities:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  ✅ &lt;strong&gt;Authentication:&lt;/strong&gt; Verify user credentials (bind).&lt;/li&gt;
&lt;li&gt;  ✅ &lt;strong&gt;CRUD Operations:&lt;/strong&gt; Create, Read, Update, and Delete directory entries.&lt;/li&gt;
&lt;li&gt;  ✅ &lt;strong&gt;SSL/TLS Support:&lt;/strong&gt; Secure your connection (essential for production).&lt;/li&gt;
&lt;li&gt;  ✅ &lt;strong&gt;Hierarchy Management:&lt;/strong&gt; Navigate the tree structure of a directory.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Configuration and Setup ⚙️
&lt;/h2&gt;

&lt;p&gt;The connection behavior is controlled by the &lt;code&gt;USYS$LDP_PARAMS&lt;/code&gt; setting in your assignment file (usually &lt;code&gt;.asn&lt;/code&gt;). You configure this in the &lt;code&gt;[DRIVER_SETTINGS]&lt;/code&gt; section.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Assignment File Syntax
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[DRIVER_SETTINGS]&lt;/span&gt;
&lt;span class="err"&gt;USYS$&lt;/span&gt;&lt;span class="py"&gt;LDP_PARAMS&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;addbase=on, searchscope=sub, identifier case=lower, logon timeout=10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Options Reference
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Recommended Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;addbase&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;(See Deep Dive below)&lt;/strong&gt; Controls automatic DN concatenation.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;on&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;identifier case&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Determines if field names are case-sensitive.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;lower&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;logon timeout&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;How long (in seconds) to wait for the server to accept a login.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;10&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nulldefault&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Controls if empty fields are saved as &lt;code&gt;NULL&lt;/code&gt; or empty strings.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;N&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;searchscope&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Defines how deep the search goes (&lt;code&gt;base&lt;/code&gt;, &lt;code&gt;one&lt;/code&gt;, or &lt;code&gt;sub&lt;/code&gt;).&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sub&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;stepsize&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Controls batch fetching size. Higher values = better performance.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;50&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tls server validation&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Checks if the server's certificate is valid.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;on&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  4. Deep Dive: The &lt;code&gt;addbase&lt;/code&gt; Option 🕵️‍♂️
&lt;/h2&gt;

&lt;p&gt;One of the most useful (but often misunderstood) settings in the LDAP driver is &lt;code&gt;addbase&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What does it do?
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;addbase&lt;/code&gt; option controls whether Uniface automatically appends the &lt;strong&gt;Base DN&lt;/strong&gt; (Distinguished Name) defined in your path to the names you use in your ProcScript code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;addbase=on&lt;/code&gt; (Default/Recommended):&lt;/strong&gt; Uniface saves you typing. You only need to provide the "Relative" Distinguished Name (RDN).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;addbase=off&lt;/code&gt;:&lt;/strong&gt; You are in full control but must provide the &lt;strong&gt;full&lt;/strong&gt; Distinguished Name for every operation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example in Action
&lt;/h3&gt;

&lt;p&gt;Imagine your Base DN is &lt;code&gt;dc=example,dc=com&lt;/code&gt; and you want to search for a user named &lt;code&gt;jdoe&lt;/code&gt; inside the &lt;code&gt;users&lt;/code&gt; container.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With &lt;code&gt;addbase=on&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; You write cleaner code:
read (U_NAME = "cn=jdoe,ou=users")

; Uniface actually sends this to the server:
; "cn=jdoe,ou=users,dc=example,dc=com"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;With &lt;code&gt;addbase=off&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; You must write the full path every time:
read (U_NAME = "cn=jdoe,ou=users,dc=example,dc=com")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  When should you turn it OFF?
&lt;/h3&gt;

&lt;p&gt;You might want to set &lt;code&gt;addbase=off&lt;/code&gt; if your application needs to access objects strictly &lt;strong&gt;outside&lt;/strong&gt; of your defined Base DN, or if you are dynamically constructing complex DNs that might not follow the standard hierarchy of your main tree. For 95% of use cases, keeping it &lt;code&gt;on&lt;/code&gt; reduces bugs and makes code more readable.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Practical Use Cases &amp;amp; Code Examples 💻
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Scenario A: User Login (Authentication)
&lt;/h3&gt;

&lt;p&gt;Instead of writing complex API calls, you simply try to "log on" to the LDAP path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; Trigger: Detail Button (Login)
variables
  string vUsername, vPassword
endvariables

vUsername = FIELD_USER
vPassword = FIELD_PASS

; Format: $logon(Path, Username, Password)
$logon("LDAP_PATH", vUsername, vPassword)

if ($status &amp;lt; 0)
  message/error "Login Failed! Check credentials."
else
  message/info "Welcome, %%vUsername! 🔓"
endif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Scenario B: Searching for a User
&lt;/h3&gt;

&lt;p&gt;Assume you have modeled an entity named &lt;code&gt;INETORGPERSON&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; Trigger: Read
read
if ($status &amp;lt; 0)
   message/info "No users found."
endif
; Note: With addbase=on, the search is automatically 
; restricted to your Base DN subtree.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. Platform-Specific Notes &amp;amp; Troubleshooting 🚧
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Linux vs. Windows 🐧🪟
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Windows:&lt;/strong&gt; Uses the built-in Windows Secure Channel (Schannel). It usually "just works" if your machine trusts the domain controller.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Unix/Linux:&lt;/strong&gt; You often need to explicitly point to your certificate bundle using the &lt;code&gt;tls ca file&lt;/code&gt; option.

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Example:&lt;/em&gt; &lt;code&gt;USYS$LDP_PARAMS = tls ca file=/etc/ssl/certs/ca-bundle.crt&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Common Pitfalls
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;"Table not found":&lt;/strong&gt; Your Uniface Entity name must match the LDAP Object Class exactly.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Slow Searches:&lt;/strong&gt; If &lt;code&gt;addbase=on&lt;/code&gt; and &lt;code&gt;searchscope=sub&lt;/code&gt; are set on the root of a massive directory, you might timeout. Try narrowing your Base DN in the path definition (e.g., &lt;code&gt;ou=london,dc=company,dc=com&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Connection Refused:&lt;/strong&gt; Check firewall rules and ensure IPv6 isn't blocking you if your server is configured for IPv4 only.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  7. Conclusion ✅
&lt;/h2&gt;

&lt;p&gt;The Uniface 10.4 LDAP connector bridges the gap between your sturdy legacy logic and modern directory services. By correctly utilizing options like &lt;code&gt;addbase&lt;/code&gt;, you can write cleaner, more maintainable code that integrates seamlessly with enterprise identity systems.&lt;/p&gt;

&lt;p&gt;Go ahead and integrate that directory! Happy coding! 👩‍💻👨‍💻&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Transparency Note: This article was created with AI assistance to help structure technical documentation effectively.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>uniface</category>
      <category>ldap</category>
      <category>addbase</category>
      <category>integration</category>
    </item>
    <item>
      <title>🔐 Mastering LDAP Integration in Uniface 10.4: The Native Way</title>
      <dc:creator>Franz</dc:creator>
      <pubDate>Tue, 23 Dec 2025 08:35:35 +0000</pubDate>
      <link>https://dev.to/f345345dfg/mastering-ldap-integration-in-uniface-104-the-native-way-1ala</link>
      <guid>https://dev.to/f345345dfg/mastering-ldap-integration-in-uniface-104-the-native-way-1ala</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was created with AI assistance, synthesizing official Rocket Uniface 10.4 documentation with practical implementation patterns.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Connecting legacy enterprise applications to modern directory services is a classic integration challenge. While many developers attempt to build complex wrappers or external call-outs, Uniface 10.4 provides a native &lt;strong&gt;LDAP Connector (LDP)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This connector is powerful because it allows you to treat a hierarchical Directory Service almost exactly like a relational database. This guide will show you how to configure and use it correctly using native ProcScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  📚 What is LDAP? (For the Uninitiated)
&lt;/h2&gt;

&lt;p&gt;Before we dive into code, let's clarify the terminology:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;LDAP (Lightweight Directory Access Protocol)&lt;/strong&gt;: Think of it as a specialized database optimized for &lt;strong&gt;reading&lt;/strong&gt; data. Unlike a standard SQL database that balances reading and writing, LDAP is designed for scenarios where you write once (create a user) but read millions of times (verify a login).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;X.500&lt;/strong&gt;: This is the "grandparent" standard. It defined the comprehensive model for directory services. LDAP was created as a lighter, more efficient way (via TCP/IP) to access X.500 directories. Uniface supports both pure LDAP and X.500 gateways.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;IPv6&lt;/strong&gt;: The modern version of the Internet Protocol. The Uniface LDAP connector is fully compatible with IPv6 addresses (e.g., &lt;code&gt;[2001:db8::1]&lt;/code&gt;), ensuring your application is future-proof.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔌 The Uniface Approach: Driver, Not Service
&lt;/h2&gt;

&lt;p&gt;A common misconception is that you "call" LDAP like a web service. In Uniface, you don't. You use the &lt;strong&gt;LDP driver&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This means you interact with LDAP using standard Uniface I/O commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;retrieve&lt;/code&gt; to search for users.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;open&lt;/code&gt; to authenticate.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;store&lt;/code&gt; to update attributes (if permissions allow).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🛠️ Step 1: Configuration (The ASN File)
&lt;/h2&gt;

&lt;p&gt;The magic happens in the Assignment File (&lt;code&gt;.asn&lt;/code&gt;). You need to define the driver and map a logical path to your LDAP server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[SETTINGS]&lt;/span&gt;
&lt;span class="c"&gt;; Load the LDAP driver (ensure the version matches your install, e.g., U3.0 or similar)
&lt;/span&gt;&lt;span class="err"&gt;USYS$&lt;/span&gt;&lt;span class="py"&gt;LDP&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;LDP&lt;/span&gt;

&lt;span class="c"&gt;; Enable debug logging - crucial for seeing what happens under the hood!
&lt;/span&gt;&lt;span class="py"&gt;LDAP_DEBUG&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;1&lt;/span&gt;
&lt;span class="py"&gt;LDAP_TIMEOUT&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;10&lt;/span&gt;

&lt;span class="nn"&gt;[PATHS]&lt;/span&gt;
&lt;span class="c"&gt;; Syntax: $PATH_NAME = LDP:ServerName:Port:BaseDN
; 'BaseDN' is the root folder where your search begins.
&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="py"&gt;AD_PROD&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;LDP:ad.company.com:389:DC=company,DC=com&lt;/span&gt;

&lt;span class="c"&gt;; For SSL/TLS (LDAPS), typically use port 636
&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="py"&gt;AD_SECURE&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;LDP:ad.company.com:636:DC=company,DC=com&lt;/span&gt;

&lt;span class="nn"&gt;[ENTITIES]&lt;/span&gt;
&lt;span class="c"&gt;; Map your Uniface entities to the logical path
&lt;/span&gt;&lt;span class="py"&gt;USER.AD&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$AD_PROD&lt;/span&gt;
&lt;span class="py"&gt;GROUP.AD&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$AD_PROD&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📝 Step 2: The Data Model
&lt;/h2&gt;

&lt;p&gt;LDAP is hierarchical, but Uniface is relational. We bridge this gap by mapping:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;LDAP Class&lt;/strong&gt; ➡️ &lt;strong&gt;Uniface Entity&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Distinguished Name (DN)&lt;/strong&gt; ➡️ &lt;strong&gt;Primary Key&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In your Uniface Model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Create an entity (e.g., &lt;code&gt;USER&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;  Create a field &lt;code&gt;DN&lt;/code&gt; (String, approx C256) and mark it as the &lt;strong&gt;Primary Key&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  Create fields for attributes you want (e.g., &lt;code&gt;CN&lt;/code&gt;, &lt;code&gt;MAIL&lt;/code&gt;, &lt;code&gt;TELEPHONENUMBER&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Important:&lt;/strong&gt; The field names in Uniface must match the LDAP attribute names (case-insensitive in Uniface, but usually lowercase in LDAP schema).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  💻 Step 3: Practical Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use Case A: User Authentication (The Login)
&lt;/h3&gt;

&lt;p&gt;To check a password, we don't need a complex query. We simply try to &lt;strong&gt;open a connection&lt;/strong&gt; using the specific user's credentials. If the server accepts the connection, the password is correct.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;operation user_login
params
    string p_username : IN
    string p_password : IN
endparams

variables
    string v_connection_string
endvariables

    ; Construct the dynamic path string
    ; Syntax: LDP:Host:Port:BaseDN|Username|Password
    ; Note: Active Directory often requires 'domain\user' or 'user@domain'
    v_connection_string = "LDP:ad.company.com:389:DC=company,DC=com|%%p_username|%%p_password"

    ; Attempt to open the path
    ; The 'b' flag is best practice here to skip table verification checks
    open v_connection_string, "b"

    if ($status &amp;lt; 0)
        ; Connection refused (Wrong password, account locked, or server down)
        return -1
    endif

    ; Security Best Practice: Close the connection immediately!
    ; You don't want to keep a session open with the user's privileges.
    close v_connection_string

    return 1 ; Success
endoperation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use Case B: Finding a User (The Search)
&lt;/h3&gt;

&lt;p&gt;To find a user, use the standard &lt;code&gt;retrieve&lt;/code&gt; command. Uniface translates your profile fields into an LDAP filter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;operation find_employee
params
    string p_search_name : IN
endparams

    clear/e "USER"

    ; Set the search profile
    ; This translates to an LDAP filter like (cn=Smith*)
    CN.USER = "%%p_search_name%%*"

    ; Execute the search
    retrieve/e "USER"

    if ($status &amp;lt; 0)
        message "Error or no data found: %%$status"
        return
    endif

    ; Loop through results
    setocc "USER", 1
    while ($status &amp;gt; 0)
        putmess "Found: %%CN.USER - %%MAIL.USER"
        setocc "USER", $orc + 1
    endwhile
endoperation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🐧 Platform Specifics: Linux vs. Windows
&lt;/h2&gt;

&lt;p&gt;While the ProcScript code stays the same, the environment setup differs slightly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Windows 🪟
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Certificates:&lt;/strong&gt; The connector typically uses the Windows Certificate Store. If your organization uses a private CA for LDAPS, ensure the Root CA is installed in the Windows Trusted Root store.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Authentication:&lt;/strong&gt; Integration with Active Directory is usually seamless.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Linux 🐧
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Certificates:&lt;/strong&gt; You must explicitly tell the driver where to find certificates if they aren't in the standard OpenSSL location. Add this to your &lt;code&gt;.asn&lt;/code&gt; file:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[SETTINGS]&lt;/span&gt;
&lt;span class="py"&gt;LDAP_CACERTFILE&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/etc/pki/tls/certs/ca-bundle.crt&lt;/span&gt;
&lt;span class="py"&gt;LDAP_CERTFILE&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/path/to/client-cert.pem&lt;/span&gt;
&lt;span class="py"&gt;LDAP_KEYFILE&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/path/to/client-key.pem&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ⚡ Troubleshooting &amp;amp; Best Practices
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;"Table Not Found" (-13):&lt;/strong&gt; This is the most common error. It usually means your &lt;strong&gt;Base DN&lt;/strong&gt; is incorrect. If Uniface looks in &lt;code&gt;OU=Sales&lt;/code&gt; but the user is in &lt;code&gt;OU=IT&lt;/code&gt;, it won't find the "table" (object).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Performance:&lt;/strong&gt; Never do a &lt;code&gt;retrieve&lt;/code&gt; without setting a profile field (like &lt;code&gt;CN&lt;/code&gt; or &lt;code&gt;SAMACCOUNTNAME&lt;/code&gt;). An unbounded search attempts to download the &lt;em&gt;entire&lt;/em&gt; directory, which will time out or crash your application.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Encoding:&lt;/strong&gt; LDAP v3 uses &lt;strong&gt;UTF-8&lt;/strong&gt;. Ensure your Uniface application handles Unicode correctly, otherwise, characters like &lt;code&gt;é&lt;/code&gt; or &lt;code&gt;ü&lt;/code&gt; in names will appear corrupted.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Read-Only Mindset:&lt;/strong&gt; While &lt;code&gt;store&lt;/code&gt; commands exist, AD permissions are complex. It is generally safer and easier to use Uniface for &lt;strong&gt;reading/authenticating&lt;/strong&gt; and use specialized tools (or PowerShell scripts invoked by Uniface) for creating accounts.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🏁 Conclusion
&lt;/h2&gt;

&lt;p&gt;The Uniface LDAP connector eliminates the need for external DLLs or Java wrappers. By understanding that LDAP is just another "database" to Uniface, you can use the standard commands you already know (&lt;code&gt;open&lt;/code&gt;, &lt;code&gt;retrieve&lt;/code&gt;) to build secure, integrated enterprise applications.&lt;/p&gt;

&lt;p&gt;Happy coding! 🚀&lt;/p&gt;

</description>
      <category>uniface</category>
      <category>ldap</category>
      <category>integration</category>
      <category>legacy</category>
    </item>
    <item>
      <title>Connecting Uniface 10.4 to LDAP Servers: A Complete Guide 🔐</title>
      <dc:creator>Franz</dc:creator>
      <pubDate>Tue, 23 Dec 2025 08:27:13 +0000</pubDate>
      <link>https://dev.to/f345345dfg/connecting-uniface-104-to-ldap-servers-a-complete-guide-2f3f</link>
      <guid>https://dev.to/f345345dfg/connecting-uniface-104-to-ldap-servers-a-complete-guide-2f3f</guid>
      <description>&lt;p&gt;&lt;em&gt;This article was created with AI assistance to provide accurate technical documentation for the developer community.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you're working with legacy enterprise systems, you've probably encountered the challenge of integrating directory services. Today, I'll walk you through the &lt;strong&gt;Uniface 10.4 LDAP Connector&lt;/strong&gt; - a powerful tool that bridges the gap between your Uniface applications and enterprise directory services.&lt;/p&gt;

&lt;h2&gt;
  
  
  📚 Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is LDAP?&lt;/li&gt;
&lt;li&gt;Understanding the Uniface LDAP Connector&lt;/li&gt;
&lt;li&gt;Supported Features and Operations&lt;/li&gt;
&lt;li&gt;Real-World Use Cases&lt;/li&gt;
&lt;li&gt;Configuration and Setup&lt;/li&gt;
&lt;li&gt;Platform-Specific Considerations&lt;/li&gt;
&lt;li&gt;Best Practices and Common Issues&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is LDAP? 🤔
&lt;/h2&gt;

&lt;p&gt;Before diving into the Uniface connector, let's understand what LDAP actually is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LDAP (Lightweight Directory Access Protocol)&lt;/strong&gt; is an industry-standard protocol used to access and manage directory information services over a network. Think of it as a specialized database optimized for read-heavy operations, storing information in a hierarchical tree structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Concepts:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;📖 X.500 Standard&lt;/strong&gt;: LDAP was originally designed as a lightweight alternative to the X.500 Directory Access Protocol (DAP). While X.500 required the heavy OSI protocol stack, LDAP runs directly over TCP/IP, making it much more practical for modern networks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🌳 Hierarchical Structure&lt;/strong&gt;: Data in LDAP is organized like a tree, with a root at the top and branches leading to individual entries (called "Distinguished Names" or DNs).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔍 Common Operations&lt;/strong&gt;: LDAP supports standard operations including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Search&lt;/strong&gt;: Query the directory for specific entries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bind&lt;/strong&gt;: Authenticate a user (verify credentials)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add&lt;/strong&gt;: Create new directory entries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modify&lt;/strong&gt;: Update existing entries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delete&lt;/strong&gt;: Remove entries from the directory&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why Use LDAP?
&lt;/h3&gt;

&lt;p&gt;LDAP is perfect for centralized authentication in enterprise environments. Instead of managing user credentials separately in each application, you maintain a single source of truth. Applications like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jenkins 🛠️&lt;/li&gt;
&lt;li&gt;Kubernetes ☸️&lt;/li&gt;
&lt;li&gt;OpenVPN 🔒&lt;/li&gt;
&lt;li&gt;Atlassian products (Jira, Confluence) 📊&lt;/li&gt;
&lt;li&gt;Samba file servers 📁&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...all commonly integrate with LDAP directories for user authentication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Uniface LDAP Connector 🔌
&lt;/h2&gt;

&lt;p&gt;The Uniface LDAP connector (mnemonic: &lt;strong&gt;LDP&lt;/strong&gt;) enables Uniface applications to communicate with LDAP servers seamlessly. This includes both standalone LDAP servers and X.500 Directory System Agents with an LDAP gateway.&lt;/p&gt;

&lt;h3&gt;
  
  
  Technical Specifications:
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Specification&lt;/th&gt;
&lt;th&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Connector Mnemonic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;LDP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Protocol Version&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;LDAP V3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Windows Implementation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native LDAP (32-bit and 64-bit)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Unix/Linux Implementation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;OpenLDAP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Connection Types&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;TCP (unencrypted) and TLS (encrypted)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Unicode Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full Unicode range (independent of $DEF_CHARSET)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Important IPv6 Note 🌐
&lt;/h3&gt;

&lt;p&gt;The LDP connector supports &lt;strong&gt;IPv6 through hostname resolution&lt;/strong&gt; using DNS or the local hosts file. However, direct IPv6 address input is not yet available. This means you'll need to configure DNS entries or host file entries for IPv6-enabled LDAP servers rather than using literal IPv6 addresses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Instead of using literal IPv6 address
ldap://[2001:db8::1]:389  ❌

# Use hostname resolution
ldap://ldap-server.example.com:389  ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Supported Features and Operations 🛠️
&lt;/h2&gt;

&lt;p&gt;The Uniface LDAP connector provides comprehensive functionality within the limitations of the LDAP protocol:&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Capabilities:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;✅ Read Operations&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieve individual entries by Distinguished Name (DN)&lt;/li&gt;
&lt;li&gt;Access specific attributes from directory entries&lt;/li&gt;
&lt;li&gt;Handle multi-valued attributes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;✅ Write Operations&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create new entries in the LDAP directory&lt;/li&gt;
&lt;li&gt;Update existing entries (modify attributes)&lt;/li&gt;
&lt;li&gt;Delete entries from the directory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;✅ Search Operations&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Execute complex search queries with filters&lt;/li&gt;
&lt;li&gt;Search across subtrees or single levels&lt;/li&gt;
&lt;li&gt;Return specific attributes or complete entries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;✅ Connection Management&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Establish secure connections using TLS&lt;/li&gt;
&lt;li&gt;Authenticate using credentials stored in .asn files&lt;/li&gt;
&lt;li&gt;Close connections gracefully&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Configuration Through .asn Files 📝
&lt;/h3&gt;

&lt;p&gt;All connection settings are stored in Uniface assignment files (.asn). This includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server address and port&lt;/strong&gt;: Where to connect&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Base DN&lt;/strong&gt;: The starting point in the directory tree&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication credentials&lt;/strong&gt;: Username and password for binding&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connection parameters&lt;/strong&gt;: Timeout values, SSL/TLS settings&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real-World Use Cases 💼
&lt;/h2&gt;

&lt;p&gt;Let's explore practical scenarios where the Uniface LDAP connector shines:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Enterprise Single Sign-On (SSO)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;: A large organization uses Uniface applications for business operations and needs centralized authentication.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; Example: Authenticate user against LDAP
operation AuthenticateUser
  parameters
    string vUsername
    string vPassword
  endparameters

  variables
    string vDN
    string vResult
  endvariables

  ; Build Distinguished Name
  vDN = "uid=%%vUsername%%,ou=users,dc=company,dc=org"

  ; Attempt LDAP bind
  activate "LDAP_AUTH".bind(vDN, vPassword)

  ; Check result
  if ($status = 0)
    putmess "Authentication successful"
  else
    putmess "Authentication failed"
  endif

end ; AuthenticateUser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. User Profile Synchronization
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;: Automatically sync user information from Active Directory to Uniface application entities.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; Example: Retrieve user details from LDAP
operation GetUserProfile
  parameters
    string vUsername
  endparameters

  variables
    string vEmail
    string vFullName
    string vDepartment
  endvariables

  ; Search for user
  retrieve LDAP_USER, 1
    where (LDAP_USER.UID = vUsername)

  if ($status = 0)
    ; Map LDAP attributes to variables
    vEmail = LDAP_USER.MAIL
    vFullName = LDAP_USER.CN
    vDepartment = LDAP_USER.DEPARTMENT
  endif

end ; GetUserProfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Dynamic Group Management
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;: Query LDAP groups to determine user permissions dynamically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-world benefit&lt;/strong&gt;: Instead of maintaining duplicate group memberships in your Uniface database, query LDAP at runtime to check if users belong to specific groups (e.g., "Administrators", "Finance_Staff", "ReadOnly_Users").&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration and Setup ⚙️
&lt;/h2&gt;

&lt;p&gt;Here's how to configure the Uniface LDAP connector step by step:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Configure the .asn File
&lt;/h3&gt;

&lt;p&gt;Create or edit your assignment file with LDAP settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[DRIVER_SETTINGS]&lt;/span&gt;
&lt;span class="c"&gt;; Define the LDAP connector
&lt;/span&gt;&lt;span class="py"&gt;LDAP_DRIVER&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;LDP&lt;/span&gt;

&lt;span class="nn"&gt;[ENTITIES]&lt;/span&gt;
&lt;span class="c"&gt;; Map your Uniface entities to LDAP structure
&lt;/span&gt;&lt;span class="py"&gt;LDAP_USER&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;LDAP_DRIVER, ou=users,dc=company,dc=com&lt;/span&gt;
&lt;span class="py"&gt;LDAP_GROUP&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;LDAP_DRIVER, ou=groups,dc=company,dc=com&lt;/span&gt;

&lt;span class="nn"&gt;[LDAP_DRIVER]&lt;/span&gt;
&lt;span class="c"&gt;; Connection parameters
&lt;/span&gt;&lt;span class="py"&gt;Server&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;ldap.company.com&lt;/span&gt;
&lt;span class="py"&gt;Port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;389&lt;/span&gt;
&lt;span class="c"&gt;; For TLS/SSL connection use port 636
&lt;/span&gt;
&lt;span class="c"&gt;; Base DN for searches
&lt;/span&gt;&lt;span class="py"&gt;BaseDN&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;dc=company,dc=com&lt;/span&gt;

&lt;span class="c"&gt;; Bind credentials (authentication)
&lt;/span&gt;&lt;span class="py"&gt;BindDN&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;cn=uniface_service,ou=service_accounts,dc=company,dc=com&lt;/span&gt;
&lt;span class="py"&gt;BindPassword&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;YourSecurePassword&lt;/span&gt;

&lt;span class="c"&gt;; Connection options
&lt;/span&gt;&lt;span class="py"&gt;Timeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;30&lt;/span&gt;
&lt;span class="py"&gt;Version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Define Entity Keys
&lt;/h3&gt;

&lt;p&gt;Each LDAP entity in your Uniface model needs a unique identifier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[LDAP_USER]&lt;/span&gt;
&lt;span class="c"&gt;; Define the key attribute
&lt;/span&gt;&lt;span class="py"&gt;Key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;uid&lt;/span&gt;

&lt;span class="c"&gt;; Map Uniface fields to LDAP attributes
&lt;/span&gt;&lt;span class="py"&gt;UID&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;uid&lt;/span&gt;
&lt;span class="py"&gt;EMAIL&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;mail&lt;/span&gt;
&lt;span class="py"&gt;FULL_NAME&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;cn&lt;/span&gt;
&lt;span class="py"&gt;FIRST_NAME&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;givenName&lt;/span&gt;
&lt;span class="py"&gt;LAST_NAME&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;sn&lt;/span&gt;
&lt;span class="py"&gt;DEPARTMENT&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;ou&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Enable TLS/SSL (Recommended) 🔒
&lt;/h3&gt;

&lt;p&gt;For production environments, always use encrypted connections:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[LDAP_DRIVER]&lt;/span&gt;
&lt;span class="py"&gt;Server&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;ldaps.company.com&lt;/span&gt;
&lt;span class="py"&gt;Port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;636&lt;/span&gt;
&lt;span class="py"&gt;SSL&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
&lt;span class="c"&gt;; or for STARTTLS on port 389
&lt;/span&gt;&lt;span class="py"&gt;UseTLS&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Security Best Practice&lt;/strong&gt;: Never store credentials in plain text in production .asn files. Use environment variables or encrypted configuration management tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Test the Connection
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; Test LDAP connectivity
operation TestLDAPConnection
  variables
    string vResult
  endvariables

  ; Attempt to open connection
  activate "LDAP_DRIVER".open

  if ($status = 0)
    putmess "LDAP connection successful!"
    activate "LDAP_DRIVER".close
  else
    putmess "Connection failed: %%$status%%"
  endif

end ; TestLDAPConnection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Platform-Specific Considerations 🖥️
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Linux/Unix Requirements
&lt;/h3&gt;

&lt;p&gt;On Linux systems, the LDAP connector requires the OpenLDAP package to be installed:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debian/Ubuntu:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;slapd ldap-utils libldap-2.4-2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Red Hat/CentOS:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;openldap openldap-clients openldap-servers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;SUSE/openSUSE:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;zypper &lt;span class="nb"&gt;install &lt;/span&gt;openldap2 openldap2-client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;⚠️ Important&lt;/strong&gt;: Make sure you install the OpenLDAP version that is current for your operating system version. Outdated packages may have security vulnerabilities or compatibility issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Windows Considerations
&lt;/h3&gt;

&lt;p&gt;Windows systems use the native LDAP implementation (Wldap32.dll), which is included with the operating system. No additional packages are required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Active Directory Integration&lt;/strong&gt;: When connecting to Microsoft Active Directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[AD_DRIVER]&lt;/span&gt;
&lt;span class="py"&gt;Server&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;ad.company.local&lt;/span&gt;
&lt;span class="py"&gt;Port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;389&lt;/span&gt;
&lt;span class="c"&gt;; Use Windows domain format for bind DN
&lt;/span&gt;&lt;span class="py"&gt;BindDN&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;COMPANY&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;uniface_service&lt;/span&gt;
&lt;span class="c"&gt;; or UPN format
&lt;/span&gt;&lt;span class="py"&gt;BindDN&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;uniface_service@company.local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Platform Independence ✨
&lt;/h3&gt;

&lt;p&gt;One of LDAP's greatest strengths is its platform independence. Unlike Active Directory (which is Windows-centric), LDAP works seamlessly across:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows Server environments&lt;/li&gt;
&lt;li&gt;Linux/Unix systems&lt;/li&gt;
&lt;li&gt;macOS&lt;/li&gt;
&lt;li&gt;Mixed heterogeneous networks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes the Uniface LDAP connector ideal for organizations with diverse infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices and Common Issues 🎯
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Security Best Practices 🔐
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Always Use TLS/SSL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Never send credentials over unencrypted connections in production:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;; ❌ Insecure
&lt;/span&gt;&lt;span class="py"&gt;Port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;389&lt;/span&gt;
&lt;span class="py"&gt;SSL&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;no&lt;/span&gt;

&lt;span class="c"&gt;; ✅ Secure
&lt;/span&gt;&lt;span class="py"&gt;Port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;636&lt;/span&gt;
&lt;span class="py"&gt;SSL&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Use Service Accounts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create dedicated LDAP service accounts for Uniface applications with minimal required privileges:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Example: Create restricted service account
dn: cn=uniface_service,ou=service_accounts,dc=company,dc=com
objectClass: inetOrgPerson
cn: uniface_service
sn: Service Account
userPassword: {SSHA}encrypted_hash_here
description: Uniface application authentication service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Implement Connection Pooling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Reuse LDAP connections where possible to reduce overhead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; Keep connection open for multiple operations
activate "LDAP_DRIVER".open

; Perform multiple operations...
; ... retrieve user 1
; ... retrieve user 2
; ... search groups

; Close when done
activate "LDAP_DRIVER".close
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Common Issues and Solutions 🔧
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Issue 1: Authentication Failures
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Symptoms&lt;/strong&gt;: Bind operations fail with "Invalid credentials" error&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common Causes&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Incorrect BindDN format&lt;/li&gt;
&lt;li&gt;Expired service account password&lt;/li&gt;
&lt;li&gt;Insufficient permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Test credentials manually&lt;/span&gt;
ldapsearch &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; ldap://server:389 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="s2"&gt;"cn=uniface_service,ou=service_accounts,dc=company,dc=com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-W&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="s2"&gt;"dc=company,dc=com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"(objectClass=*)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Issue 2: Connection Timeouts
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Symptoms&lt;/strong&gt;: Operations hang or timeout&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common Causes&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Firewall blocking LDAP ports (389, 636)&lt;/li&gt;
&lt;li&gt;Network latency&lt;/li&gt;
&lt;li&gt;LDAP server overloaded&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;; Increase timeout values
&lt;/span&gt;&lt;span class="nn"&gt;[LDAP_DRIVER]&lt;/span&gt;
&lt;span class="py"&gt;Timeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;60&lt;/span&gt;
&lt;span class="py"&gt;NetworkTimeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Issue 3: SSL/TLS Certificate Errors
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Symptoms&lt;/strong&gt;: "Certificate verification failed" errors&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common Causes&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Self-signed certificates not trusted&lt;/li&gt;
&lt;li&gt;Expired certificates&lt;/li&gt;
&lt;li&gt;Hostname mismatch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Add CA certificate to trusted store (Linux)&lt;/span&gt;
&lt;span class="nb"&gt;sudo cp &lt;/span&gt;ldap-ca-cert.pem /usr/local/share/ca-certificates/
&lt;span class="nb"&gt;sudo &lt;/span&gt;update-ca-certificates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Issue 4: Character Encoding Problems
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Symptoms&lt;/strong&gt;: Special characters (ä, ö, ü, ß, é, ñ) displayed incorrectly&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: The Uniface LDAP connector uses Unicode exclusively. Ensure your .asn file specifies UTF-8 encoding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[SETTINGS]&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="py"&gt;NLS_ENCODING&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;UTF-8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Issue 5: Performance Issues with Large Directories
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Symptoms&lt;/strong&gt;: Slow search operations&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Use indexed attributes and implement pagination:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; Use paged results for large searches
operation SearchUsersWithPaging
  variables
    numeric vPageSize
    string vCookie
  endvariables

  vPageSize = 100

  ; Implement paging logic
  ; (pseudocode - actual implementation varies)

end ; SearchUsersWithPaging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing and Debugging Tips 🔍
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Use LDAP Browser Tools&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tools like Apache Directory Studio or JXplorer help you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visualize directory structure&lt;/li&gt;
&lt;li&gt;Test search filters&lt;/li&gt;
&lt;li&gt;Verify attribute names&lt;/li&gt;
&lt;li&gt;Check permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Enable Verbose Logging&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[SETTINGS]&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="py"&gt;LDAP_DEBUG&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;1&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="py"&gt;TRACE&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;ALL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Test with Command-Line Tools&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Test basic connectivity&lt;/span&gt;
ldapsearch &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; ldap://server:389 &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="s2"&gt;"dc=company,dc=com"&lt;/span&gt;

&lt;span class="c"&gt;# Test TLS&lt;/span&gt;
ldapsearch &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; ldap://server:389 &lt;span class="nt"&gt;-ZZ&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="s2"&gt;"dc=company,dc=com"&lt;/span&gt;

&lt;span class="c"&gt;# Test authentication&lt;/span&gt;
ldapsearch &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; ldap://server:389 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="s2"&gt;"cn=user,dc=company,dc=com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-W&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; &lt;span class="s2"&gt;"dc=company,dc=com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion 🎉
&lt;/h2&gt;

&lt;p&gt;The Uniface 10.4 LDAP Connector is a powerful integration tool that brings enterprise-grade directory services to your legacy applications. By understanding its capabilities and following best practices, you can:&lt;/p&gt;

&lt;p&gt;✅ Implement centralized authentication&lt;br&gt;&lt;br&gt;
✅ Reduce administrative overhead&lt;br&gt;&lt;br&gt;
✅ Improve security posture&lt;br&gt;&lt;br&gt;
✅ Enable SSO capabilities&lt;br&gt;&lt;br&gt;
✅ Integrate seamlessly with existing infrastructure  &lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;LDAP is a protocol&lt;/strong&gt;, not a product - it works across platforms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;X.500 compatibility&lt;/strong&gt; means broad directory support&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TLS/SSL is mandatory&lt;/strong&gt; for production environments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IPv6 support&lt;/strong&gt; requires DNS hostname resolution&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform-specific requirements&lt;/strong&gt; vary (OpenLDAP on Linux, native on Windows)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Next Steps 🚀
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Review your organization's LDAP directory structure&lt;/li&gt;
&lt;li&gt;Install required OpenLDAP packages (Linux)&lt;/li&gt;
&lt;li&gt;Configure your .asn file with connection parameters&lt;/li&gt;
&lt;li&gt;Test authentication in a development environment&lt;/li&gt;
&lt;li&gt;Implement proper error handling&lt;/li&gt;
&lt;li&gt;Plan migration strategy for production&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Resources 📚
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.rocketsoftware.com/bundle/uniface_104/" rel="noopener noreferrer"&gt;Uniface 10.4 Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.openldap.org/doc/" rel="noopener noreferrer"&gt;OpenLDAP Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://datatracker.ietf.org/doc/html/rfc4511" rel="noopener noreferrer"&gt;LDAP RFC 4511&lt;/a&gt; - Protocol Specification&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.itu.int/rec/T-REC-X.500/" rel="noopener noreferrer"&gt;X.500 Standard Overview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Have you integrated Uniface with LDAP?&lt;/strong&gt; Share your experiences, challenges, or tips in the comments below! 💬&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Note: This guide is based on Uniface 10.4 documentation. Always refer to your specific version's documentation and consult with your system administrators before implementing changes in production environments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>uniface</category>
      <category>ldap</category>
      <category>enterprisedevelopment</category>
      <category>legacysystems</category>
    </item>
    <item>
      <title>Uniface 10.4 &amp; Informix: Decoding Error Messages 🔍</title>
      <dc:creator>Franz</dc:creator>
      <pubDate>Tue, 23 Dec 2025 08:08:39 +0000</pubDate>
      <link>https://dev.to/f345345dfg/uniface-104-informix-decoding-error-messages-24e2</link>
      <guid>https://dev.to/f345345dfg/uniface-104-informix-decoding-error-messages-24e2</guid>
      <description>&lt;p&gt;Hey developers! 👋&lt;/p&gt;

&lt;p&gt;If you work with &lt;strong&gt;Uniface 10.4&lt;/strong&gt; and &lt;strong&gt;Informix&lt;/strong&gt;, you know that robust error handling is key. Sometimes, the message frame shows you an error, but it can be confusing. Is it Uniface? Is it the Connector? Is it the Informix database itself?&lt;/p&gt;

&lt;p&gt;In this post, I will help you understand the different types of error messages and give you a &lt;strong&gt;cheat sheet&lt;/strong&gt; for the specific Connector return values.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;🤖 This blog post was created with the help of an AI assistant, based on the official Uniface documentation.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Two Types of Messages 📧
&lt;/h2&gt;

&lt;p&gt;First, you need to spot the difference between a &lt;strong&gt;Connector&lt;/strong&gt; error and a native &lt;strong&gt;Informix&lt;/strong&gt; error. They look different in the message frame.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Connector Errors
&lt;/h3&gt;

&lt;p&gt;These are errors generated by the Uniface driver itself (before or during communication with the database).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Syntax:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Connector {ERROR|WARNING} (Number): Message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Informix Errors
&lt;/h3&gt;

&lt;p&gt;These come directly from the DBMS. They include the SQLSTATE and SQLCODE.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Syntax:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Informix {ERROR|WARNING|NO DATA} (SQLSTATE: sqlstate ): Message SQLCODE sqlcode: Message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The $dberror Variable 🕵️
&lt;/h2&gt;

&lt;p&gt;When an error happens, Uniface stores the last error code in the &lt;code&gt;$dberror&lt;/code&gt; variable. This is what you check in your ProcScript code.&lt;/p&gt;

&lt;p&gt;Here is the breakdown of what the values in &lt;code&gt;$dberror&lt;/code&gt; mean:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Success, no error. Everything worked perfectly. ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&amp;lt; 0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Error detected by Informix. A negative number means the DBMS reported an issue. 🔴&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;20–29&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Connector errors. A positive number in this range means the Connector found an issue. 🟠&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Connector Error Cheat Sheet 📝
&lt;/h2&gt;

&lt;p&gt;If you see a positive number in &lt;code&gt;$dberror&lt;/code&gt; between 20 and 29, it is one of these specific Connector issues. Keep this list handy!&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;$dberror&lt;/th&gt;
&lt;th&gt;Message&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The requested function/mode is not supported.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;21&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The specified database environment name is too long.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;22&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The connector can fetch by primary key only.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;23&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No more cursors could be allocated.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;24&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No more statements could be allocated.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Connector deleted/updated more or less than 1 row.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;26&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The parsed SQL statement was not a select.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;27&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;An illegal request was received by the connector.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;28&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Already logged on to a database.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;29&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Unrecognized option for open database.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Examples in Action 🚀
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Example 1: Success (Error 0)
&lt;/h3&gt;

&lt;p&gt;You fetch a record successfully from the Informix database.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Result in &lt;code&gt;$dberror&lt;/code&gt;&lt;/strong&gt;: &lt;code&gt;0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Message&lt;/strong&gt;: No error message appears.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example 2: Already Logged On (Error 28)
&lt;/h3&gt;

&lt;p&gt;Your code tries to open a connection to the database, but your path is already open.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Result in &lt;code&gt;$dberror&lt;/code&gt;&lt;/strong&gt;: &lt;code&gt;28&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Message&lt;/strong&gt;: &lt;code&gt;Connector ERROR (28): Already logged on to a database.&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example 3: Informix Error (Negative Value)
&lt;/h3&gt;

&lt;p&gt;The Informix DBMS reports an error (for example, a syntax error in your SQL or a constraint violation).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Result in &lt;code&gt;$dberror&lt;/code&gt;&lt;/strong&gt;: A negative number (example: &lt;code&gt;-201&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Message&lt;/strong&gt;: &lt;code&gt;Informix ERROR (SQLSTATE: 42000): ... SQLCODE -201: ...&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Quick Tips 💡
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  ✨ Always check &lt;code&gt;$dberror&lt;/code&gt; after database operations.&lt;/li&gt;
&lt;li&gt;  ✨ If &lt;code&gt;$dberror&lt;/code&gt; is positive and between 20–29, use the table above to find the cause.&lt;/li&gt;
&lt;li&gt;  ✨ If &lt;code&gt;$dberror&lt;/code&gt; is negative, contact Informix documentation for the SQLCODE meaning.&lt;/li&gt;
&lt;li&gt;  ✨ Look at both the error &lt;strong&gt;number&lt;/strong&gt; and the &lt;strong&gt;message&lt;/strong&gt; to debug faster.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Next time you see an error in the message frame, check the syntax first. Is it "Connector" or "Informix"? If it is a Connector error, use the table above to quickly find the cause!&lt;/p&gt;

&lt;p&gt;Happy coding! 💻✨&lt;/p&gt;

</description>
      <category>uniface</category>
      <category>informix</category>
      <category>dberror</category>
      <category>database</category>
    </item>
    <item>
      <title>Uniface 10.4 + Informix: Simple Guide to Data Packing 📦</title>
      <dc:creator>Franz</dc:creator>
      <pubDate>Tue, 23 Dec 2025 08:02:54 +0000</pubDate>
      <link>https://dev.to/f345345dfg/uniface-104-informix-simple-guide-to-data-packing-4n9d</link>
      <guid>https://dev.to/f345345dfg/uniface-104-informix-simple-guide-to-data-packing-4n9d</guid>
      <description>&lt;p&gt;&lt;em&gt;🤖 This blog post was created with the help of an AI assistant and is based on the Uniface 10.4 documentation about “Informix Data Packing”.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When you use Uniface 10.4 with an Informix database, every field in your model has a packing code. This packing code tells Informix how the data is stored in the database. 😊&lt;/p&gt;

&lt;p&gt;In this article, you see how Uniface packing codes map to Informix storage formats, in simple language and with small examples. This can help you avoid strange data problems when you design or debug your application. 💡&lt;/p&gt;




&lt;h2&gt;
  
  
  What is data packing?
&lt;/h2&gt;

&lt;p&gt;In Uniface, each field has a data type and a packing code, for example &lt;code&gt;C10&lt;/code&gt; or &lt;code&gt;I4&lt;/code&gt;. The packing code controls how the data is stored physically in the Informix table (for example as &lt;code&gt;CHAR&lt;/code&gt;, &lt;code&gt;VARCHAR&lt;/code&gt;, &lt;code&gt;DECIMAL&lt;/code&gt; or &lt;code&gt;DATE&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The Informix connector uses a fixed mapping from the Uniface packing code to the Informix storage format. This means that the same packing code always results in the same Informix data type.&lt;/p&gt;

&lt;h3&gt;
  
  
  Very small example
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;C10&lt;/code&gt; in Uniface → stored as &lt;code&gt;CHAR(10)&lt;/code&gt; in Informix.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;I4&lt;/code&gt; in Uniface → stored as &lt;code&gt;INTEGER&lt;/code&gt; in Informix.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;D&lt;/code&gt; in Uniface → stored as &lt;code&gt;DATE&lt;/code&gt; in Informix.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the table is created in Informix, this mapping is fixed for that column unless you change the table definition with SQL. So choosing the right packing code is important already in the Uniface model.&lt;/p&gt;




&lt;h2&gt;
  
  
  Character and text fields 📝
&lt;/h2&gt;

&lt;p&gt;Many Uniface packing codes become simple character types in Informix. These are used for names, codes, flags and other text data that is not extremely large.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;B&lt;/strong&gt;, &lt;strong&gt;B1-B5&lt;/strong&gt; → stored as &lt;code&gt;CHAR&lt;/code&gt; in Informix (for example for boolean-like fields stored as &lt;code&gt;Y&lt;/code&gt;/&lt;code&gt;N&lt;/code&gt; or &lt;code&gt;0&lt;/code&gt;/&lt;code&gt;1&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;C1-C*&lt;/strong&gt; → stored as &lt;code&gt;CHAR&lt;/code&gt; (fixed-length character fields).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;R1-R*&lt;/strong&gt; → stored as &lt;code&gt;CHAR&lt;/code&gt; (often used for raw codes).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;(S)A1-A9&lt;/strong&gt; → stored as &lt;code&gt;CHAR&lt;/code&gt; (short strings).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;(S)A11-A40&lt;/strong&gt; → stored as &lt;code&gt;CHAR&lt;/code&gt; (longer strings).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;T&lt;/strong&gt;, &lt;strong&gt;T1-T2&lt;/strong&gt; → stored as &lt;code&gt;CHAR&lt;/code&gt; (small text or time-related codes).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;U1-U*&lt;/strong&gt; → stored as &lt;code&gt;CHAR&lt;/code&gt; (Unicode string handled as character data by the connector).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;VC1-VC255&lt;/strong&gt;, &lt;strong&gt;VR1-VR255&lt;/strong&gt;, &lt;strong&gt;VU1-VU255&lt;/strong&gt; → stored as &lt;code&gt;VARCHAR&lt;/code&gt; (variable-length text).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;VC256-VC*&lt;/strong&gt;, &lt;strong&gt;VR256-VR*&lt;/strong&gt;, &lt;strong&gt;VU256-VU*&lt;/strong&gt; → stored as &lt;code&gt;CHAR&lt;/code&gt; (because of size limits in the Informix driver).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example: customer name
&lt;/h3&gt;

&lt;p&gt;Imagine a field &lt;code&gt;CUSTOMER.NAME&lt;/code&gt; defined as &lt;code&gt;C40&lt;/code&gt; in Uniface. The Informix connector will create this as &lt;code&gt;CHAR(40)&lt;/code&gt; in the database.&lt;/p&gt;

&lt;p&gt;If you change it later to &lt;code&gt;VC40&lt;/code&gt;, Uniface would map it to &lt;code&gt;VARCHAR(40)&lt;/code&gt;, which can save space but may behave differently in indexes and comparisons. So plan your character packing codes with your DBA rules in mind.&lt;/p&gt;




&lt;h2&gt;
  
  
  Numbers and money 💰
&lt;/h2&gt;

&lt;p&gt;For numeric fields, the Uniface packing code controls whether Informix uses &lt;code&gt;INTEGER&lt;/code&gt;, &lt;code&gt;SMALLINT&lt;/code&gt;, &lt;code&gt;DECIMAL&lt;/code&gt;, &lt;code&gt;FLOAT&lt;/code&gt; or &lt;code&gt;MONEY&lt;/code&gt;. This is important for precision and performance.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;I1-I2&lt;/strong&gt; → &lt;code&gt;SMALLINT&lt;/code&gt; (small integers).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;I3-I4&lt;/strong&gt; → &lt;code&gt;INTEGER&lt;/code&gt; (normal integers, for example IDs or counters).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;I8&lt;/strong&gt; → &lt;code&gt;FLOAT&lt;/code&gt; (large numeric values stored as floating point).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;F&lt;/strong&gt; → &lt;code&gt;DECIMAL&lt;/code&gt; (fixed-point numeric, generic &lt;code&gt;F&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;F4&lt;/strong&gt; → &lt;code&gt;REAL&lt;/code&gt; (4-byte floating point).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;F8&lt;/strong&gt; → &lt;code&gt;FLOAT&lt;/code&gt; (8-byte floating point).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;M1-M4&lt;/strong&gt; → &lt;code&gt;MONEY&lt;/code&gt; (monetary values).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;N1-N32&lt;/strong&gt; → &lt;code&gt;DECIMAL&lt;/code&gt; (numeric with different sizes and precision).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;(N)C1-32&lt;/strong&gt; → &lt;code&gt;DECIMAL&lt;/code&gt; (numeric values packed with a &lt;code&gt;C&lt;/code&gt; packing, but stored as decimal).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;O1-O32&lt;/strong&gt;, &lt;strong&gt;P1-P16&lt;/strong&gt;, &lt;strong&gt;Q1-Q16&lt;/strong&gt; → &lt;code&gt;DECIMAL&lt;/code&gt; (different decimal ranges and precisions).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example: invoice amount
&lt;/h3&gt;

&lt;p&gt;For an invoice amount, a typical choice in Uniface is &lt;code&gt;M2&lt;/code&gt; (money with 2 decimals). The Informix column will then be of type &lt;code&gt;MONEY&lt;/code&gt;, which keeps the decimal places stable and is easy to sum in SQL.&lt;/p&gt;

&lt;p&gt;If you used a floating type like &lt;code&gt;F8&lt;/code&gt; instead, Informix would store it as &lt;code&gt;FLOAT&lt;/code&gt;, which can introduce rounding issues for financial calculations. So for prices and totals, it is safer to use &lt;code&gt;M*&lt;/code&gt; or &lt;code&gt;N*&lt;/code&gt; (decimal) instead of &lt;code&gt;FLOAT&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dates and times ⏰
&lt;/h2&gt;

&lt;p&gt;Date and time fields have special mappings because Informix has dedicated date and datetime types. Using the correct packing code here makes your queries simpler and more efficient.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;D&lt;/strong&gt;, &lt;strong&gt;D1-D11&lt;/strong&gt; → &lt;code&gt;DATE&lt;/code&gt; (calendar date without time).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;E&lt;/strong&gt;, &lt;strong&gt;E1-E8&lt;/strong&gt;, &lt;strong&gt;E10&lt;/strong&gt; → &lt;code&gt;DATETIME YEAR TO SECOND&lt;/code&gt; (full date and time down to seconds).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;T3&lt;/strong&gt; → &lt;code&gt;DATETIME YEAR TO SECOND&lt;/code&gt; (time-related packing that maps to datetime).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example: order date vs. timestamp
&lt;/h3&gt;

&lt;p&gt;For an &lt;code&gt;ORDER_DATE&lt;/code&gt; field, a simple &lt;code&gt;D&lt;/code&gt; is often enough and becomes &lt;code&gt;DATE&lt;/code&gt; in Informix. For an audit field like &lt;code&gt;LAST_UPDATE&lt;/code&gt;, you can use &lt;code&gt;E&lt;/code&gt; so that Informix stores &lt;code&gt;DATETIME YEAR TO SECOND&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This way you can easily select all rows from today or sort by the exact update time in SQL. It also keeps the storage compact and index-friendly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Serial, byte and text fields 📂
&lt;/h2&gt;

&lt;p&gt;Some Uniface packings are used for special Informix types like serial numbers, byte data and text data. These are important for technical IDs, blobs and large documentation fields.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;(S)A10&lt;/strong&gt; → &lt;code&gt;SERIAL&lt;/code&gt; (auto-increment integer, often used as technical primary key).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;SR1-SR*&lt;/strong&gt; → &lt;code&gt;BYTE&lt;/code&gt; (binary data, for example PDF or image stored as blob).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;SC1-SC*&lt;/strong&gt; → &lt;code&gt;TEXT&lt;/code&gt; (large text stored as a TEXT blob).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;SU1-SU*&lt;/strong&gt; → &lt;code&gt;TEXT&lt;/code&gt; (Unicode text stored in a TEXT-like way by the connector).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example: document storage
&lt;/h3&gt;

&lt;p&gt;If you have a field &lt;code&gt;DOCUMENT.FILE_CONTENT&lt;/code&gt; with packing &lt;code&gt;SR1&lt;/code&gt;, Informix will store it as &lt;code&gt;BYTE&lt;/code&gt;. This is good for binary files like PDFs.&lt;/p&gt;

&lt;p&gt;For a field &lt;code&gt;DOCUMENT.LONG_COMMENT&lt;/code&gt; with packing &lt;code&gt;SC1&lt;/code&gt;, Informix will store it as &lt;code&gt;TEXT&lt;/code&gt;. This is better for long user comments or descriptions that can be larger than normal &lt;code&gt;VARCHAR&lt;/code&gt; limits.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this mapping matters in real projects 🧠
&lt;/h2&gt;

&lt;p&gt;The mapping between Uniface packing codes and Informix storage formats is not just a technical detail. It affects how indexes work, how much disk space you use and how easy it is to write SQL queries.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  If you choose a &lt;code&gt;CHAR&lt;/code&gt; packing for a field that changes a lot in length, your table may waste space and become slower.&lt;/li&gt;
&lt;li&gt;  If you choose a floating type (&lt;code&gt;F4&lt;/code&gt;, &lt;code&gt;F8&lt;/code&gt;, &lt;code&gt;I8&lt;/code&gt;) for monetary values, you may get rounding problems in reports.&lt;/li&gt;
&lt;li&gt;  If you use &lt;code&gt;TEXT&lt;/code&gt; or &lt;code&gt;BYTE&lt;/code&gt; for fields that you often filter in &lt;code&gt;WHERE&lt;/code&gt; clauses, you may not be able to index them easily.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A good practice is to create a small test table where you define one column for each packing code that you plan to use. Then you can check the real Informix types with tools like &lt;code&gt;dbschema&lt;/code&gt; or your favorite database browser and adjust your Uniface model before you go to production. ✅&lt;/p&gt;




&lt;p&gt;Uniface 10.4 and Informix give you a flexible and powerful combination for business applications. When you understand how packing codes map to Informix storage formats, you can design models that are both safe and efficient. 🚀&lt;/p&gt;

</description>
      <category>database</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Uniface 10.4 + Informix: Simple Guide to Stored Procedures 🚀</title>
      <dc:creator>Franz</dc:creator>
      <pubDate>Sun, 21 Dec 2025 06:58:31 +0000</pubDate>
      <link>https://dev.to/f345345dfg/uniface-104-informix-simple-guide-to-stored-procedures-3ogd</link>
      <guid>https://dev.to/f345345dfg/uniface-104-informix-simple-guide-to-stored-procedures-3ogd</guid>
      <description>&lt;p&gt;&lt;em&gt;🤖 This blog post was created with the help of an AI assistant and is based on the official Uniface 10.4 documentation for “Informix Stored Procedures”.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When you build Uniface applications on Informix, performance matters. One simple way to speed up basic database operations is to use stored procedures generated by the Uniface Informix connector (INF).&lt;/p&gt;




&lt;h2&gt;
  
  
  What is a stored procedure? 🤔
&lt;/h2&gt;

&lt;p&gt;A stored procedure is one or more SQL statements that are already parsed and compiled and stored in the Informix database. Because of this, Informix can execute them immediately without parsing the SQL text again each time.&lt;/p&gt;

&lt;p&gt;Compared to sending raw SQL from your application, stored procedures can be faster and more consistent for common operations.&lt;/p&gt;




&lt;h2&gt;
  
  
  How the INF connector uses stored procedures
&lt;/h2&gt;

&lt;p&gt;The INF connector can create stored procedures automatically when it creates the base tables in Informix. These procedures handle the most basic I/O operations: insert, fetch, update, delete, and select.&lt;/p&gt;

&lt;p&gt;To enable this behavior, you must set the &lt;code&gt;procs&lt;/code&gt; connector option in the Uniface assignment file for Informix. Without this option, Uniface does not create or use these Informix stored procedures.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stored procedures created by INF 🔧
&lt;/h2&gt;

&lt;p&gt;For each table (let’s call it &lt;code&gt;table_name&lt;/code&gt;), the connector can create several procedures with specific suffixes. Here are the most important ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;table_name_E&lt;/code&gt; – Existence check. This procedure checks if &lt;code&gt;table_name&lt;/code&gt; already has the expected procedures.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;table_name_I&lt;/code&gt; – Insert a row into &lt;code&gt;table_name&lt;/code&gt;. This one is &lt;strong&gt;not&lt;/strong&gt; created for tables that contain segmented fields.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;table_name_F&lt;/code&gt; – Fetch all nonsegmented fields in one row of &lt;code&gt;table_name&lt;/code&gt; using a specific primary key, and optionally lock the row.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;table_name_U&lt;/code&gt; – Update one row in &lt;code&gt;table_name&lt;/code&gt; based on the primary key, or the primary key plus the &lt;code&gt;U_VERSION&lt;/code&gt; field. This is also not created for tables that contain segmented fields.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;table_name_D&lt;/code&gt; – Delete a row in &lt;code&gt;table_name&lt;/code&gt; based on the primary key, or the primary key plus &lt;code&gt;U_VERSION&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;table_name_S&lt;/code&gt; – Select nonsegmented fields for all rows of &lt;code&gt;table_name&lt;/code&gt;, using a select cache for better performance.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;table_name_S#&lt;/code&gt; – Select nonsegmented fields using a specific index number &lt;code&gt;#&lt;/code&gt;, again using the select cache. The connector generates one stored procedure for each index that is used in such select operations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, Uniface can generate extra stored procedures to enforce referential integrity, depending on your settings and table relationships.&lt;/p&gt;




&lt;h2&gt;
  
  
  Segmented fields and stored procedures 📦
&lt;/h2&gt;

&lt;p&gt;Informix supports segmented fields (for example, large text or byte data stored in separate locations). The INF connector has special rules for these fields.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The connector never uses stored procedures to manipulate segmented fields.&lt;/li&gt;
&lt;li&gt;  For tables that contain segmented fields, the connector does &lt;strong&gt;not&lt;/strong&gt; create the insert (&lt;code&gt;_I&lt;/code&gt;) or update (&lt;code&gt;_U&lt;/code&gt;) procedures.&lt;/li&gt;
&lt;li&gt;  The other procedures (&lt;code&gt;_F&lt;/code&gt;, &lt;code&gt;_D&lt;/code&gt;, &lt;code&gt;_S&lt;/code&gt;, &lt;code&gt;_S#&lt;/code&gt;) are still created but they only work with nonsegmented fields.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For read, write, and update operations that involve segmented fields, the connector falls back to dynamic SQL instead of using stored procedures.&lt;/p&gt;




&lt;h2&gt;
  
  
  Serial fields and the serial insert option 🔁
&lt;/h2&gt;

&lt;p&gt;Informix also supports serial fields (auto-increment numeric values). In Uniface, the behavior for tables with serial fields depends on the connector options.&lt;/p&gt;

&lt;p&gt;If the &lt;code&gt;serial insert&lt;/code&gt; option is turned on together with the &lt;code&gt;procs&lt;/code&gt; option, the INF connector changes its behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  For tables that contain serial fields, the connector does &lt;strong&gt;not&lt;/strong&gt; use the insert stored procedure.&lt;/li&gt;
&lt;li&gt;  Instead, it uses dynamic SQL to execute the write request, so that serial values are handled correctly.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Example: Simple customer table 🧑‍💻
&lt;/h2&gt;

&lt;p&gt;Let’s look at a small example. Imagine a table called &lt;code&gt;customer&lt;/code&gt; with a primary key &lt;code&gt;customer_id&lt;/code&gt;, no segmented fields, and no serial fields.&lt;/p&gt;

&lt;p&gt;With the &lt;code&gt;procs&lt;/code&gt; option enabled, you can expect the INF connector to create procedures like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;customer_I&lt;/code&gt; – Insert a new customer row.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;customer_F&lt;/code&gt; – Fetch one customer row by primary key (and optionally lock it).&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;customer_U&lt;/code&gt; – Update an existing customer row using the primary key (and possibly &lt;code&gt;U_VERSION&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;customer_D&lt;/code&gt; – Delete a customer row using the primary key (and possibly &lt;code&gt;U_VERSION&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;customer_S&lt;/code&gt; – Select all customer rows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In your Uniface component, the connector can call these stored procedures internally when you do normal store, read, or update operations. You do not have to call the procedures manually; Uniface does it for you based on your configuration.&lt;/p&gt;




&lt;h2&gt;
  
  
  When should you enable stored procedures? 💡
&lt;/h2&gt;

&lt;p&gt;Using the &lt;code&gt;procs&lt;/code&gt; option makes most sense when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  You want better performance for common CRUD operations on Informix.&lt;/li&gt;
&lt;li&gt;  Your tables mainly use nonsegmented fields (or you are fine with dynamic SQL for the segmented ones).&lt;/li&gt;
&lt;li&gt;  You like a clear, predictable mapping between Uniface I/O and Informix stored procedures.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have many segmented fields or very complex SQL logic, you may still rely more on dynamic SQL or custom SQL statements. But for standard, frequent operations, the generated stored procedures are a clean and efficient solution.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final thoughts 😊
&lt;/h2&gt;

&lt;p&gt;Uniface 10.4 and Informix work well together when you use the INF connector options correctly. With the &lt;code&gt;procs&lt;/code&gt; option, you get a set of ready-made stored procedures that speed up basic I/O.&lt;/p&gt;

&lt;p&gt;Add in the special behavior for segmented and serial fields, and you have a flexible setup: fast where possible, dynamic where necessary.&lt;/p&gt;

&lt;p&gt;Happy coding with Uniface and Informix! 🚀&lt;/p&gt;

</description>
      <category>database</category>
      <category>sql</category>
      <category>performance</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
