Hi,
tl;dr;
Is there a way to either intercept ERROR and keep it from crashing the NAS, or can I configure the NAS to not even STOP when it sees any exception?
The details:
We have a product which uses C/AL to read from tables and perform CRUD operations. With the 2013 R2 much of our product broke. We tracked it down to the ERROR function. In our code units, we using ERROR to trigger exceptions and catch them in our .NET server, and pass them to another client.
The problem in R2 is that ERROR stops the NAS and causes our client to disconnect. When ERROR gets called, I see 3 entries is the event log:
Warning: Exception.NavNCLDialogException ID 218
Error: NAV Application Server session has failed and will be restarted. Reason Type NavNCLDialogException ID 221
Information: NAV Application is scheduled to start with the following configuration. ID 219
I was able to work around much of this by triggering events from the code units into our .NET. But there's still an issue when we hit existing code. For instance, if I try to insert a record that already exists, that table's INSERT throws ERROR, killing the server. Yes, the server restarts, but only so many times (limited by the config) and not fast enough to process thousands of rows we may be dealing with.
So. Is there a way to either intercept ERROR and keep it from crashing the NAS, or can I configure the NAS to not even STOP when it sees an exception?
I had submitted a ticket with ms regarding this issue, but they said it was working as expected and couldn't help.
Thanks,
0
Comments
I don't know if that still works in 2013, but in older versions you could wrap your critical code in an extra codeunit and try to invoke it by IF Codeunit.RUN THEN.
Another way would be to run your code in a separate session using the STARTSESSION functionality (one of the features from NAV2013 that I love most). This is basically how the Job Queue functionality works; it separates everything out in separate sessions to prevent the main session to die.
The main issue remains, of course: If the NAS process itself hits an error, it dies.
Microsoft - Dynamics NAV
I'll try pushing the call out to a separate session, then inspecting its output.
Thanks
what i have right now is one code unit that does all of the CRUD. Say it has 4 methods inside. Like (forgive me, this is mostly pseudo code):
CrudUnit.Create(record)
CrudUnit.Retrieve(record)
CrudUnit.Update(record)
CrudUnit.Delete(record)
I'm calling this from a higher level method, which gets instructions from .NET. This is done via case statement.
CASE command of
'create':
CrudUnit.Create(record);
end
and so on
i assume that at the top class, I need to spin the session and inspect the output, but what's that syntax when I'm calling a method on a codeunit, not just a codeunit?
OK := STARTSESSION(1, CODEUNIT::"CrudUnit", record);
how do i specify which method to call?? or do i have to break out the methods to smaller code units?
thanks,
thanks for all of the help.
Previously, my InsertRecord method looked like this:
RecRef.OPEN(tableName); //this is a RecordRef
RecRef.INIT;
OtherCodeUnit.FillValuesInRecord(RecRef);
//this line failed, with the 3 items in the event log killing the server:
RecRef.INSERT(TRUE);
I tried changing this last line to:
IF NOT RecRef.INSERT(TRUE) THEN
//some .NET code to handle errors through my stack. this doesn't throw.
This still seems to break. In the event log, I get only one entry, the 'warning' from before:
Warning Exceptions.NavNCLDialogException. Event Id 218.
I would actually be okay with this BUT the server appears to stop responding. I'm doing potentially hundreds of rows in quick succession and both the CAL debugger and my client code disconnect from the NAS after one execution.
I wasn't able to figure out the STARTSESSION using a recordref. Is there another solution or am I doing something wrong?
Again, when it's all said and done, I'm trying to HANDLE errors. My test case is intentionally creating bogus records so I can iron out this code.
Thanks!!
Trap those with STARTSESSION and not kill the server
or
do I need to go into that code and handle the errors at that level??
Thanks
RecordRef.INSERT(TRUE);
the line that kills my stack is
Table 5054 Contact Business Relation
The only code of mine that's getting called is the initial RecordRef.INSERT(TRUE);
How do I handle the error that far down and keep it from killing the whole stack? I tried wrapping it like
IF RecordRef.INSERT(TRUE) THEN
but that didn't work. The lower ERROR still tries to pop the dialog. I can't seem to handle that one.
thanks so much.
Also, you could use the STARTSESSION function. But in both cases you need to make sure that your "main thread" keeps running after one of your "child threads" hits an error.
Is your initial starting codeunit for NAS single instance?
Yes, I believe this is all a single instance.
Thank you for the help and the patience. I'm not a cal dev. I'm a .net dev (:
Back to your issue, I think if you just wrap your code into a separate session then maybe NAS will stay alive but your C/AL code to create certain records won't finish properly. So, your records are not created. I guess that's not what you would expect.
How does your solution work in detail? Is it a single instance codeunit with timer trigger? How is your .net component instantiated? How is the initial request started? How does the process workflow look like?
Thanks a bunch for the help.