Robert Cemper · Jul 6, 2020 go to post

Just found an example:

Class Demo.Loan.BankUS Extends Ens.BusinessProcess [ ClassType = persistent, ProcedureBlock ]
{ /// 2 modes: Queue, InProc
Parameter INVOCATION = "Queue"; Property CreditRating As %Integer; Property PrimeRate As %Numeric; Method OnRequest(
    request As Demo.Loan.Msg.Application,
    Output response As Demo.Loan.Msg.Approval) As %Status
{
    Set $ZT="Trap",tSC=$$$OK
    Do {
        $$$TRACE("received application for "_request.Name)
        #;
        If $zcrc(request.Name,2)#5=0 {
            Set response = ##class(Demo.Loan.Msg.Approval).%New()
            Set response.BankName = "BankUS"
            Set response.IsApproved = 0
            $$$TRACE("application is denied because of bank holiday")
            Quit
        }
        #;
        Set tRequest = ##class(Demo.Loan.Msg.PrimeRateRequest).%New()
        Set tSC = ..SendRequestAsync("Demo.Loan.WebOperations",tRequest,1,"PrimeRate")
        #;
        Set tRequest = ##class(Demo.Loan.Msg.CreditRatingRequest).%New()
        Set tRequest.TaxID = request.TaxID
        Set tSC = ..SendRequestAsync("Demo.Loan.WebOperations",tRequest,1,"CreditRating")
        #;
        Set tSC = ..SetTimer("PT15S")
        #;
        Quit
    While (0)
Exit
    Quit tSC
Trap
    Set $ZT="",tSC=$$$EnsSystemError Goto Exit
} /// Handle a 'Response'
Method OnResponse(
    request As Ens.Request,
    ByRef response As Ens.Response,
    callrequest As Ens.Request,
    callresponse As Ens.Response,
    pCompletionKey As %String) As %Status
{
    Set $ZT="Trap",tSC=$$$OK
    Do {
        If pCompletionKey="PrimeRate" {
            Set ..PrimeRate = callresponse.PrimeRate
        Elseif pCompletionKey="CreditRating" {
            Set ..CreditRating = callresponse.CreditRating
        }
        Quit
    While (0)
Exit
    Quit tSC
Trap
    Set $ZT="",tSC=$$$EnsSystemError Goto Exit
} Method OnComplete(
    request As Ens.Request,
    ByRef response As Ens.Response) As %Status
{
    Set $ZT="Trap",tSC=$$$OK
    Do {
        Set response = ##class(Demo.Loan.Msg.Approval).%New()
        Set response.BankName = "BankUS"
        Set tIsUsCitizen=($zcvt($tr(request.Nationality,"."),"u")="USA")||($zcvt($tr(request.Nationality,"."),"u")="US")
        If ('tIsUsCitizen)||(..CreditRating<50) {
            Set response.IsApproved = 0
            $$$TRACE("application is denied")
        Else {
            Set response.IsApproved = 1
            Set response.InterestRate = ..PrimeRate+2+(5*(1-(..CreditRating/100)))
            $$$TRACE("application is approved for "_response.InterestRate_"%")
        }
        Quit
    While (0)
Exit
    Quit tSC
Trap
    Set $ZT="",tSC=$$$EnsSystemError Goto Exit
}
Storage Default
{
 <Data name="BankUSDefaultData">
   <Subscript>"BankUS"</Subscript>
   <Value name="1">
      <Value>CreditRating</Value>
   </Value>
   <Value name="2">
      <Value>PrimeRate</Value>
   </Value>
 </Data>
 <DefaultData>BankUSDefaultData</DefaultData>
 <Type>%Library.CacheStorage</Type>
} }

 
Robert Cemper · Jul 6, 2020 go to post

#1)
- create a simple Business Process using the wizard
- compile it and see the resulting class and at least 4 related .int routines.
- then decide if you really want to do this all manually
the challenge is to properly use and service the methods you see in Ens.BusinessProcess

To make it easier you may install (or activate) the ENSDEMO namespace as an example (before IRIS. have no idea where it is gone)

#2)

you write.    ---transformation (written in DTL), but the code is manually written. ---

It might sufficient to put your code just into a CODE Block of a BP generated with the wizard.

Robert Cemper · Jul 6, 2020 go to post

My personal opinion:
WIN* is a nice Desktop OS good for mom and aunt Betty.  With an incredible paranoic approach. 
In post VMS times all *X (LinuX,AIX, OS X, Solaris(rip+), ***UNIX, ....)  are real server OS systems by nature.

Robert Cemper · Jul 6, 2020 go to post

Good observation.

Try run a "force" down of the image. For Caché it's .../bin/ccontrol force  <instance> 

The service calls itself always "Controller" .
I've seen such orphans rarely every now and then. but I don't have any explanation.
stopping it should allow a new start.  Check if there are other processes with Ensemble or Cache.exe

Robert Cemper · Jul 6, 2020 go to post

There's still alert.log - (not a big hope)
eventually, a Windows event logging may give a hint. - (less hope)

next emergency startup with -nostu

WRC = last chance

Robert Cemper · Jul 5, 2020 go to post

When I found it, I felt like Indiana Jones when he detected the Holy Grail.  smiley

Robert Cemper · Jun 29, 2020 go to post

Is it really %String or a subtype without MAXLEN or MALXEN disabled ?
I have done this in past and I know of some types just defined to remove MAXLEN =50

e.g. %Library.RawString, %Library.Text, ...

Robert Cemper · Jun 29, 2020 go to post

in class %Dictionary.CompiledProperty you have

if  a Property Parameter exists it is in this Array:  
But not all properties have MAXLEN  this is a %String

Robert Cemper · Jun 28, 2020 go to post

If you call routines or classes you should temporarily save your lines before execution
e.g.  ZS temp

Robert Cemper · Jun 28, 2020 go to post

use local routine. like:

a<tab>for i=1:1:100 {
<tab>/// do one line
<tab>///do something else
<tab>}
do a   ;to run it

to edit/show  your line use ZI, ZR, PRINT  

ATTENTION: you need a REAL terminal. 
WebTerm, Studio, .... just can process  single lines as they are only Terminal SIMULATIONS using eXECUTE command

Robert Cemper · Jun 23, 2020 go to post

 I see just nothing in SQL that relates to the error message.
my only wild guess: some NULL value results confuse the VB end.
You could eventually bypass it using NVL() function

SELECT NVL(PROE,'*'),NVL(DESP,'*),NVL(ID,0) FROM ZVBMAPEAMENTO.SVINFOUVND
WHERE JOB=1224 GROUP BY PROE
Robert Cemper · Jun 23, 2020 go to post

The most simple way to do it:
in  class Table.A have 
       Property TableB as Table.B;
in  class Table.B have
                  Property TableA as Table.A;

in your code it may look like this:

set objA=##class(Table.A).%OpenId(212)
set objB=##class(Table.B).%OpenId(99)
set objA.TableB=objB
set objB.TableA=objA
do objA.%Save(), objB.%Save()

You are free to index properties TableA or TableB according to your needs
and you can also use Implicit JOIN between these tables.  

Robert Cemper · Jun 23, 2020 go to post

Suggestion for a calculated Property:

Property SentTimeNEW As Ens.DataType.UTC [ Calculated, SqlComputed,
              
SqlComputeCode = { set {*}=$s({SentTime}<1842:"",1:{SentTime}) } ];
Robert Cemper · Jun 23, 2020 go to post

OK. I understand those records where created BEFORE you defined your new column.
I checked the internal code

$s(%val="":"",1:$zdatetime($zdTH($zdatetimeh(%val,3,,,,,,,,0),-3),3,,3))

This tells me:
- Your value is Not Empty 
- it has no valid time format, so it is trapped by the ERROR option and set to Zero  ==>> 1840-12-31 00:00:00

Suggestion:
- set value to NULL for old records.
or
- create your own data type for this case. 
or

- use a calculated Property  to trap the values

Robert Cemper · Jun 23, 2020 go to post

1840-12-31 00:00:00 is point Zero of internal time setting.
It applies as default to empty data type Ens.DataType.UTC

Robert Cemper · Jun 22, 2020 go to post

embedded SQL is probably an overkill for this formating.
Just convert it to the internal format, add what you need and assemble the pieces in COS

; set datein=201906192359
; set add=60    ;; seconds to add
set dh=$ZDH($e(datein,1,8),8)
set hh=$e(datein,9,10)
set mi=$e(datein,11,12)
set new=$ZTH(hh_":"_mi_":00",3)+add
set zdt=$zdt(new\86400+dh_","_(new#86400),3)
set dateout=$tr($e(zdt,1,*-3),"-: ")