cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

How to return failure from a Program Object with a log

Former Member
0 Likes
765

I would like to write a Java JAR file that implements IProgramBase (or IProgramBaseEx). These interfaces require that your class implement one method

void run(...) throws SDKException { ... }

. And therein lies the problem, the method can only return

void

and can only throw an

SDKException

.

The program I need to write may fail, and I would want someone to know that that has occurred. However, even if I throw an exception from within my program and use

System.out.println(...)

, the program's status returns success, while the log contains the exception message and stack trace.

I have managed to catch my exceptions and attempt to throw an SDK exceptoin, such as

SDKException.UnexpectedException(Throwable ex)

. However, all that results in is the program's status set to Failed (which is one thing that I want) and the very generic error message

An unexpected exception has occurred

. Even though the UnexpectedException takes a Throwable as an "inner" exception, the inner exception stack trace and/or error message is never displayed anywhere. Worse, there is no log file to access to see any stack traces in addition to the primary (outer) exception.

Is it even possible to tell Business Objects that a program object should return a status of Failed and have a log file for JAR-generated failures (as opposed to Business Objects failing to run the program object at all)?

Regards,

CS.

View Entire Topic
Former Member
0 Likes

Robert:

Again, thanks for the information.

I didn't realize, when I first asked about logging, that SAP includes its own logging facility, which would probably be easier to use/integrate with my Java program object.

I can't remember my username/password for the SAP Service Marketplace, so I haven't been able to look up that KB article, but as soon as I get access again, I'm going to check it out.

In the meantime, I tried adding a log to the program object via the SAP Logging facility:


Logger LOG = Logger.getInstance("com.my.package.name.MyClass");

, but evidently, that's not enough to "attach" it to the program object.

I did look up a successful program instance (which had some stuff logged) in the Query Builder facility and did note that the Program object, itself, had the log file associated with it in its SI_FILES collection. However, the name was (obviously) auto-generated, and I'm not sure how to "coerce" Business Objects into adding a log file (using the SAP Logging facility) to the program object. It seems that if your program object fails, anything you write to stdout is just dropped, as if it doesn't matter. Having said that, I wonder what would change if I wrote to stderr instead? Hmm, never thought of that. I'll reply here when I try it out, out of curiosity.

Anyway, any small code snippet anyone could provide would be helpful. This is definitely something that should be better documented by SAP.

Thanks Robert for your help, and TIA to anyone else who may reply.

Regards,

CS

Former Member
0 Likes

I don't believe it is possible to achieve what you describe. When an instance fails, the si_files property, i.e. the standard out file for program objects, is discarded. You can verify this by looking at the properties for a failed scheduled report. There is nothing stored on the output FRS because the output would be garbage since something bad happened. A program object is just another scheduleable object so it follows the same rules.

If you want to always log output from your programs, use a logger as you did in your last post and configure the output to write to some location the server has access to. That gives you the failed status and a log of what your program did to get to that point.

I've grappled with this issue before and finally settled on this crazy solution which works just fine for my needs. The only reason I wanted a program to fail was to make use of the email on failure feature of XI so I know that it failed. To meet that requirement, I do not allow the program objects to ever show a status of "failed" so I always have access to the standard out contents by clicking on the instance time. If an exception occurs, I have the last 100 lines of the log file emailed to me (or whomever cares) with a 5 email maximum per instance to prevent my inbox from being flooded. This can be done using Log4j, but I happen to use slf4j plus Logback.

Former Member
0 Likes

Ryan:

Thanks for your insight. I feared that what you said just might be the case.

That said, I wonder, then, if the KB article Robert pointed out above would help. I'm envisioning now, that the only possbile way to achieve this is to log everything using log4j (especially since Logger is completely undocumented in official SDK documentation for Business Objects) and attempt, in a catch-clause to add the log file from log4j to the program object (by implementing IProgramBaseEx).

Hopefully I will get access to the KB soon to find out about using log4j with my program object and I will test this scenario.

Thanks again.

Regards,

CS

Former Member
0 Likes

Attaching the log file to the instance is an interesting idea. Even if that works, I wonder if InfoView would display a hyperlink for that instance since it is officially "failed".

Former Member
0 Likes

Well, attaching a file to the SI_FILES collection on the programInfoObject parameter of the IProgramBaseEx.run method did not work. It looks like a couple of things are happening under the hood that make what I want to happen impossible.

I created a PrintStream object and performed println's on that, instead of System.out. Once I encountered an exception in my catch clause, I output the requisite lines to System.out. Then I "logged" more messages to my make-shift log file. Next, I attempted to add the file to the programInfoObject's SI_FILES collection and saved the object. Finally, I exited with System.exit(1).

When viewing the instance's properties, there was no hyperlink for a log file. Furthermore, viewing the instance in Query Builder, there was no file in the SI_FILES collection. I wondered what would happen if i exited with System.exit(0), instead, using the same steps as outlined above. The program object returned success (not totally surprising) and the log file contained only those lines written to System.out.

So, it appears that, under the hood, Business Objects will write the output from System.out to a text file and add it to the SI_FILES collection of the program object instance upon successful completion. If the instance's status is anything but Success, then the System.out data is not appended to the SI_FILES collection of the program object instance. Furthermore, it looks like that this collection is cleared when a System.exit(1) is encountered (after outputting the appropriate PROCPROGRAM:PROGRAM_ERROR text).

EDIT: 2011-09-08 - The above paragraph is exactly what Ryan Gordon was saying in a previous reply on this thread. His answer, while no more or less heplful than anyone else's, is exactly the solution for me in this situation, since it is closes to what I want. Hence, I have awarded him full points. But thank you Robert, too, for providing the information you did. (BTW, I did finally get my Service Marketplace ID/Password figured out!!)

Furthermore, I tried exiting the program with System.exit(1) without outputting PROCPROGRAM:PROGRAM_ERROR to the standard output stream (and the other requisite text). The program status was still successful (and thus, the contents of the standard output stream was saved as a log file for the program object instance).

So, what I'm trying to do: have a program return Failed and have a log file attached to the instance regarding any informational and/or error messages while the program was running--is impossible. All in all, this was a very poor design decision for this functionality. Who wouldn't want to know why their program object failed? Furthermore, who wouldn't want that information stored with the program object instance? Instead, this information must be logged externally from the system.

Thank you all for your help. The posts you all submitted will, no doubt, be helpful in one way or another.

Edited by: codeguru on Sep 8, 2011 12:17 PM - Giving credit where credit is due. Thank you all!