Retreive Error Message Desc from BSFN from NER

nkuebelbeck

nkuebelbeck

VIP Member
I'm writing a NER and it's going to end up calling some business functions. Typically when I do this, I execute the function and then check for an error like so

SomeBusinessFunction
//
If SV Error_Status is equal to CO ERROR
// STAHP! but what was the error?
Else
// Ok to proceed
End If

Is there a method to retrieve the error and description of the error(s)?
 
Hi, that's a very grey question as there are several ways.

C++/NER can set the behaviour COM to an error state, and it's this that trips the SV Error flag that calling programs can check.

Also, most BSFNs have a DTAI or ERRC parameter that is set and fed back to the calling program.

Examples of COM in a NER
Set NER Error("0520", BF mnShipmentNumber_SHPN)

SetNERReturnCode(B0100044.SetNERReturnCode)
"2" -> idErrorStatus [GENLNG]


All error messages live on F9200 and F9203 (text)

Use N44H0130 Get Error Description to get the text for you :)

Hope that helps
 
Thanks, I've seen some functions return the DTAI or ERRC in a parameter and that works well, it's when it doesn't that I'd like to be able to pull the error. I'm not sure how/if that is possible. It's almost as if it's possible to set the behavior COM without setting an error?

Sorry for the vague question.
 
for example, If i execute F4113FSBeginDoc and leave all the parameters blank it will execute in error. The only parameter that indicates failure is cErrorCode and that is a '1'. Looking at the source code of that function I can see

if ( IsStringBlank(lpDS->szDocumentType) ){
bStopProcess = TRUE ;
ErrorLineID = IDERRszDocumentType_2 ;
jdeStrcpy ( (JCHAR *) szErrorID, (const JCHAR *) _J("0003") ) ;
}

this is an internal function variable error used later

if ( bStopProcess ) {
lpDS->cErrorCode = _J('1') ;
idReturnValue = ER_ERROR ;
if ( nSetError == 1 ){
jdeErrorSet ( lpBhvrCom, lpVoid, ErrorLineID, (JCHAR *) szErrorID, (LPVOID) NULL ) ;
}
}

So is it possible to read the jdeErrorSet after the function has finished executed?
 
As you see, the return code is whatever the function returns. The runtime engine maps it to Success = 0, Warning = 1, Error = 2

You can use the error retrieval APIs to traverse the internal list of errors after the function call.

Code:
jdeErrorSetToFirstEx(lpBhvrCom, lpVoid);
/* Get the first error */
lpErrorStruct = jdeErrorGetNextDDItemNameInfoEx (lpBhvrCom, lpVoid);
while (lpErrorStruct != NULL)
{
    /* do something with error */
    lpErrorStruct = jdeErrorGetNextDDItemNameInfoEx (lpBhvrCom, lpVoid);
}
For example, we use a generic function to write the errors to table so a calling process can display the error stack on a report.

Craig
 
As you see, the return code is whatever the function returns. The runtime engine maps it to Success = 0, Warning = 1, Error = 2

You can use the error retrieval APIs to traverse the internal list of errors after the function call.

Code:
jdeErrorSetToFirstEx(lpBhvrCom, lpVoid);
/* Get the first error */
lpErrorStruct = jdeErrorGetNextDDItemNameInfoEx (lpBhvrCom, lpVoid);
while (lpErrorStruct != NULL)
{
    /* do something with error */
    lpErrorStruct = jdeErrorGetNextDDItemNameInfoEx (lpBhvrCom, lpVoid);
}
For example, we use a generic function to write the errors to table so a calling process can display the error stack on a report.

Craig

When would you call the generic function to return only the errors for the current process? Are the error indexed somehow?

In my use case say I call the F4113FSBeginDoc in NER would I execute the generic function after the F4113FSBeginDoc?

F4113FSBeginDoc
//
If SV Error_Status is equal to CO ERROR
GenericFunctionError //assuming I've got to pass a parameter to limit the error to only the current calling NER?
Else
// Ok to proceed
End If

Thanks for the help
 
Yes, right after the failing function. The error list will be everything for the current seession. You can clear the list as well with jdeErrorClearEx(LPBHVRCOM lpBhvrCom, LPVOID lpVoid) if you want.
 
Yes, right after the failing function. The error list will be everything for the current seession. You can clear the list as well with jdeErrorClearEx(LPBHVRCOM lpBhvrCom, LPVOID lpVoid) if you want.

Thanks for the help. Is jdeErrorGetNextDDItemNameInfoEx documented in the API? I can't find any documentation
 
Here is a small little utility BSFN I wrote several years ago that will copy the current error stack to cache and let you iterate over the list. I use it quite a bit in UBEs to detect and display errors on a UBE as well as for situations like what you are talking about. I actually wrote an article in jdeTips on this if you have access to it it will explain a little more about how to use jdeErrorGetNextDDItemNameInfoEx and the attached BSFN as well as some "gotchas" with jdeErrorGetNextDDItemNameInfoEx.
 

Attachments

  • B59JDET1.zip
    5 KB · Views: 290
Here is a small little utility BSFN I wrote several years ago that will copy the current error stack to cache and let you iterate over the list. I use it quite a bit in UBEs to detect and display errors on a UBE as well as for situations like what you are talking about. I actually wrote an article in jdeTips on this if you have access to it it will explain a little more about how to use jdeErrorGetNextDDItemNameInfoEx and the attached BSFN as well as some "gotchas" with jdeErrorGetNextDDItemNameInfoEx.

this is very helpful. thank you very much
 
Here is a small little utility BSFN I wrote several years ago that will copy the current error stack to cache and let you iterate over the list. I use it quite a bit in UBEs to detect and display errors on a UBE as well as for situations like what you are talking about. I actually wrote an article in jdeTips on this if you have access to it it will explain a little more about how to use jdeErrorGetNextDDItemNameInfoEx and the attached BSFN as well as some "gotchas" with jdeErrorGetNextDDItemNameInfoEx.

Is this utility function free to use? I think this would be a slam dunk drop in solution for me.
 
I believe so yes. I can't, however, post the jdetips article. The source code I posted was just a copy of a function I wrote long before the article with the prefix "jdetips" added to all the function names. The article has a .par file you can import with the function and data structure objects and an example of how I use this function in UBEs. The jdetips "version" of the function is just a stripped down copy of the original - I simply copied the function I use here at my company, stripped off some dependencies on other custom jde functions/libs and removed some other general purpose error utility functions that were in the source and put the prefix on the function names to try and avoid any name collisions should someone want to import the objects in the .par file.

You could probably do a string replace on the prefix on the function names and replace it with what ever your organization uses. The code itself is pretty straight forward and simple. It's really just a simple wrapper around the jde APIs - barely more than "documentation" on how to use the JDE APIs.
 
I believe so yes. I can't, however, post the jdetips article. The source code I posted was just a copy of a function I wrote long before the article with the prefix "jdetips" added to all the function names. The article has a .par file you can import with the function and data structure objects and an example of how I use this function in UBEs. The jdetips "version" of the function is just a stripped down copy of the original - I simply copied the function I use here at my company, stripped off some dependencies on other custom jde functions/libs and removed some other general purpose error utility functions that were in the source and put the prefix on the function names to try and avoid any name collisions should someone want to import the objects in the .par file.

You could probably do a string replace on the prefix on the function names and replace it with what ever your organization uses. The code itself is pretty straight forward and simple. It's really just a simple wrapper around the jde APIs - barely more than "documentation" on how to use the JDE APIs.

I'm going to get this into my fat client and see if I can test.
 
I'm going to get this into my fat client and see if I can test.

Here is what I got. See any issues? (it appears to work)

00001 VA evt_cEndOfList_CHAR [CHAR] = "0"
00002 -F4113FSBeginDoc(XT4113Z1.F4113FSBeginDoc)
00003 -If SV Error_Status is equal to CO ERROR
00004 | -JDETipsViewErrorStackInit(B59JDET1.JDETipsViewErrorStackInit)
| VA evt_mnHandle_JOBS [JOBS] <- mnHandle [JOBS]
| VA evt_nWarningCount_INT01 [INT01] <- nWarningCount [INT01]
| VA evt_nErrorCount_INT01 [INT01] <- nErrorCount [INT01]
| VA evt_nTotalCount_INT01 [INT01] <- nTotalCount [INT01]
00005 | -While VA evt_cEndOfList_CHAR [CHAR] is equal to "0"
00006 | | -JDETipsViewErrorStackIterate(B59JDET1.JDETipsViewErrorStackIterate)
| | VA evt_mnHandle_JOBS [JOBS] -> mnHandle [JOBS]
| | VA evt_idCursorHandle_GENLNG [GENLNG] <- idCursorHandle [GENLNG]
| | VA evt_cCloseCursor_CHAR [CHAR] <> cCloseCursor [CHAR]
| | VA evt_szErrorID_DTAI [DTAI] <- szErrorID [DTAI]
| | VA evt_nErrorLevel [INT01] <- nErrorLevel [INT01]
| | VA evt_szErrorDesc_DL011 [DL011] <- szErrorMsg [DL011]
| | VA evt_cEndOfList_CHAR [CHAR] <- cEndOfList [CHAR]
00007 | | // do stuff with DTAI and DL011
00008 | End While
00009 | -JDETipsViewErrorStackFree(B59JDET1.JDETipsViewErrorStackFree)
| VA evt_mnHandle_JOBS [JOBS] -> mnHandle [JOBS]
00010 | -JDETipsClearErrorStack(B59JDET1.JDETipsClearErrorStack)
00011 -Else
00012 | // all is well proceed
00013 End If
 
Appears to be good. One note. Sometimes a BSFN wont necessarily return ER_ERROR but will still throw an error, so sometimes I check for errors regardless of SV Error_Status.
 
Appears to be good. One note. Sometimes a BSFN wont necessarily return ER_ERROR but will still throw an error, so sometimes I check for errors regardless of SV Error_Status.

Sometimes a BSFN wont necessarily return ER_ERROR but will still throw an error <--This is not cool IMO. Either issue an error correctly or let it be a warning....
 
Everything was going fine until I tried to use this newly created error in a business function that was called from Business Services(BSSV).

I get the following error in the BSSV logs

Dec 9 08:32:42.850368 jdeobj.c1543 - 424/5 WRK:SOMEUSER_80000000_DConnector COB0000012 - GetProcAddress failed CCUSTOM function JDETipsViewErrorStackInit Error = 0

and the BSSV returns an ERROR 500.

I've testing the function locally on my fat client using object browser and it worked well.

I tried testing the BSSV locally via jdeveloper and the activeconsole.exe process bombs. Couldn't find any logs to why the process failed even after turning on as much debugging as I know how. So I had my CNC deploy the BSSV and that is how I that error message.

Thanks in advance for any help.
 
This looks like a BSSV issue and not necessarily anything specific to that specific BSFN - unless there is some error in the BSFN itself like a buffer overrun or something. I assume the BSFN has been built on the server? Anyway someone more familiar with configuring BSSV can probably help better than I.

Having said that, using this BSFN in a BSSV may not necessarily yield the results you might expect - not sure though since I have not test it in a a BSSV call. For more consistent results I suggest you create wrapper functions to the BSSNs you are calling and then check for errors inside those wrapper functions. In other words, under some situations jdeErrorGetNextDDItemNameInfoEx can't see the errors because the error stack gets cleared.

See https://www.jdelist.com/community/index.php?threads/48641/. I believe the same rules apply and you may run into the same issue with a BSSV as you would an APPL.
 
The BSSV is not directly called in the BSFN. I've created a wrapper around some other stock BSSV and inside the wrapper BSSV I check for Error Status and then execute the Init,Iterate,Clear functions.

So call stack might look something like this
BSSV Published Method
--WrapperBSFN(Executed by BSSV)
----JDE_BSFN (executed by the WrapperBSFN)
----IF ERROR
------INIT //this is where the error is thrown occurs
------WHILE-LOOP
-------ITERATE
------END WHILE-LOOP
------CLEARStack
----END IF ERROR
----//do more stuff
--END WRAPPER BSFN

My CNC indicated that the package build in fact did fail on one of 2 E1 servers (It failed on the AS400 and success on a Windows), so we are looking at finding some logs

The odd part is that this all built fine on my fat client and I was able to successfully execute the WrapperBSFN from ObjectBrowser
 
This looks like a BSSV issue and not necessarily anything specific to that specific BSFN - unless there is some error in the BSFN itself like a buffer overrun or something. I assume the BSFN has been built on the server? Anyway someone more familiar with configuring BSSV can probably help better than I.

Having said that, using this BSFN in a BSSV may not necessarily yield the results you might expect - not sure though since I have not test it in a a BSSV call. For more consistent results I suggest you create wrapper functions to the BSSNs you are calling and then check for errors inside those wrapper functions. In other words, under some situations jdeErrorGetNextDDItemNameInfoEx can't see the errors because the error stack gets cleared.

See https://www.jdelist.com/community/index.php?threads/48641/. I believe the same rules apply and you may run into the same issue with a BSSV as you would an APPL.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms683212(v=vs.85).aspx

Going to look through this BSFN and see if it's using WINAPI
 
Back
Top