Article
Eduard Lebedyuk · Dec 7, 2019 1m read

About %objlasterror

%objlasterror is a useful reference to the last error.

Every time $$$ERROR is called, %objlasterror is set to a result of this call.

It's important in cases where you want to convert exception to status:

Try {
   //  quality code
} Catch ex {
   Set sc = $g(%objlasterror, $$$OK)
   Set sc = $$$ADDSC(sc, ex.AsStatus())
}

Because AsStatus calls $$$ERROR under the wraps, the order is important, first you need to get %objlasterror and  convert exception after that.

For Java gateway this method of handling exceptions also works:

If ((ex.Name="<ZJGTW>") && $d(%objlasterror)) {
    Set sc = %objlasterror
} Else {
    Set sc = ex.AsStatus()
}
21
1 3 211 0

Replies

Just a quick note: when errors are processed consistently, e.g. each %Status have been returned is processed with $$$TOE or $$$ThrowOnError  or $$$ThrowStatus macro, this approach seems to be excessive, and `set sc=ex.AsStatus()` is just enough. E.g. 

ClassMethod GetDBProp(pDBname, ByRef pProp, pDivide = 1) As %Status
{
  try {
   new $namespace set $namespace="%SYS"
   set sc=1/pDivide ;potential <DIVIDE>
   $$$TOE(sc, ##Class(Config.Databases).Get(pDBname,.pProp))
  catch ex {
   set sc=ex.AsStatus()
  }
  quit sc
}

For me, unexpected %objlasterror is no more than a sign of inaccurate coding, when some %Status values are not processed.

Depends on a coding style.

I prefer not to use/propagate exceptions, but rather %Status.

It seems that try / catch paradigm encourages one to propagate exceptions. Otherwise it's easy to get a "style mix" that looks unpleasant, something like: 

   ...
   set sc=##Class(Config.Databases).Get(pDBname,.pProp)
   if 'sc goto gDBPropQ ; more characters to type and less expressive
  
  catch ex {
   set sc=ex.AsStatus()
  }
gDBPropQ
  quit sc
}

or 

  ...
  set sc=##Class(Config.Databases).Get(pDBname,.pProp)
  if 'sc return sc ; many exit points from one method contradicts
                   ; with reasonable principles of modular coding
 catch ex {
   set sc=ex.AsStatus()
 }
 return sc
}

All this stuff is just IMHO, just an attempt to be consistent.