How can I get stacktrace for Adobe AIR global runtime errors in non-debug mode? - air

The new version AIR gives us the ability to globally capture run time errors and handle them. The problem is that it doesn't have the stacktrace or any helpful information about the error other than the error id and error message and name. For example it may tell me that a null pointer exception has happened but it will not tell me where or which method or anything. The debug version of the runtime gives us all of that but when the app is deployed to customers it is not running on the debug version so none of the useful information is available. I was wondering if this group has any suggestions on how to enable better logging of errors in an AIR app for better supportability of the product. Any suggestions?

I have a little hack to get line numbers too. :)
make a listener to get uncaught errors. I do it in my main class:
private function addedToStageHandler(event:Event):void {
loaderInfo.uncaughtErrorEvents.addEventListener( UncaughtErrorEvent.UNCAUGHT_ERROR, uncaughtErrorHandler );
}
for example my listener with error.getStackTrace():
private function uncaughtErrorHandler( event:UncaughtErrorEvent ):void
{
var errorText:String;
var stack:String;
if( event.error is Error )
{
errorText = (event.error as Error).message;
stack = (event.error as Error).getStackTrace();
if(stack != null){
errorText += stack;
}
} else if( event.error is ErrorEvent )
{
errorText = (event.error as ErrorEvent).text;
} else
{
errorText = event.text;
}
event.preventDefault();
Alert.show( errorText + " " + event.error, "Error" );
}
Add additional compiler argument: -compiler.verbose-stacktraces=true
Create the release build.
now the little hack:
Mac:
Go to the installation location where you have your .app file. Right click and choose show package content. Navigate to Contents ▸ Resources ▸ META-INF ▸ AIR. There you can find a file called hash. Duplicate the hash file and rename it to debug. Open the debug file with some text editor and remove the content. Done now you get the stack trace + line numbers.
Windows:
Browse to its install directory in a file explorer. Navigate to {app-folder}▸META-INF▸AIR▸. Here you can find a file called hash. Duplicate the hash file and rename it to debug. Open the debug file with some text editor and remove the content. Done now you get the stack trace + line numbers.
If you can't find the hash file, just create an empty file without file extension and call it debug.
Tested with Air 3.6!

No way until new version of AIR supports it. It doesn't now because of performance issues, rendering global handler almost useless. I'm waiting for it too, because alternative is logging everything yourself, and this is very time consuming.

The compiler option:
compiler.verbose-stacktraces=true
should embed stack information even in a non-debug build.

About the compiler option.
I develop with IntelliJ IDEA 14. In my build options i have also "Generate debuggable SWF". Maybe thats the reason why its working. Check my attachment.
Grettings

Related

Howto tell PowerBuilder to pass options to a JVM when starting?

What I want to do?
I want to create and consume java objects in PowerBuilder and call methods on it. This should happen with less overhead possible.
I do not want to consume java webservices!
So I've a working sample in which I can create a java object, call a method on this object and output the result from the called method.
Everything is working as expected. I'm using Java 1.8.0_31.
But now I want to attach my java IDE (IntelliJ) to the running JVM (started by PowerBuilder) to debug the java code which gets called by PowerBuilder.
And now my question.
How do I tell PowerBuilder to add special options when starting the JVM?
In special I want to add the following option(s) in some way:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
The JVM is created like following:
LONG ll_result
inv_java = CREATE JavaVM
ll_result = inv_java.CreateJavaVM("C:\Development\tms java\pbJavaTest", FALSE)
CHOOSE CASE ll_result
CASE 1
CASE 0
CASE -1
MessageBox ( "", "jvm.dll was not found in the classpath.")
CASE -2
MessageBox ( "", "pbejbclient90.jar file was not found." )
CASE ELSE
MessageBox ( "", "Unknown result (" + String (ll_result ) +")" )
END CHOOSE
In the PowerBuilder help I found something about overriding the static registry classpath. There is something written about custom properties which sounds like what I'm looking for.
But there's no example on how to add JVM options to override default behavior.
Does anyone have a clue on how to tell PowerBuilder to use my options?
Or does anyone have any advice which could guide me in the right direction?
Update 1
I found an old post which solved my initial issue.
If someone else want to know how it works take a look at this post:
http://nntp-archive.sybase.com/nntp-archive/action/article/%3C46262213.6742.1681692777#sybase.com%3E
Hi, you need to set some windows registry entries.
Under HKEY_LOCAL_MACHINE\SOFTWARE\Sybase\Powerbuilder\9.0\Java, there
are two folders: PBIDEConfig and PBRTConfig. The first one is used when
you run your application from within the IDE, and the latter is used
when you run your compiled application. Those two folders can have
PBJVMconfig and PBJVMprops folders within them.
PBJVMconfig is for JVM configuration options such as -Xms. You have to
specify incremental key values starting from "0" by one, and one special
key "Count" to tell Powerbuilder how many options exists to enumerate.
PBJVMprops is for all -D options. You do not need to specify -D for
PBJVMProps, just the name of the property and its value, and as many
properties as you wish.
Let me give some examples:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Sybase\PowerBuilder\9.0\Java\PBIDEConfig\PBJVMprops]
"java.security.auth.login.config"="auth.conf"
"user.language"="en"
[HKEY_LOCAL_MACHINE\SOFTWARE\Sybase\PowerBuilder\9.0\Java\PBRTConfig\PBJVMconfig]
"0"="-client"
"1"="-Xms128m"
"2"="-Xmx512m"
"Count"="3"
[HKEY_LOCAL_MACHINE\SOFTWARE\Sybase\PowerBuilder\9.0\Java\PBRTConfig\PBJVMprops]
"java.security.auth.login.config"="auth.conf"
"user.language"="en"
Regards,
Gokhan Demir
But now there's another issue...
PB isn't able to create EJB Proxies for my sample class which is really simple with java 1.8.0_31. They were created with the default version, which is 1.6.0_24.
public class Simple
{
public Simple()
{
}
public static String getValue()
{
return "blubber";
}
public int getInt32Value()
{
return 123456;
}
public double getDoubleVaue()
{
return 123.123;
}
public static void main(String[] args)
{
System.out.println(Simple.getValue());
}
}
The error is the following. :D
---------- Deploy: Deploy of project p_genapp_ejbclientproxy (15:35:18)
Retrieving PowerBuilder Proxies from EJB...
Generation Errors: Error: class not found: (
Deployment Error: No files returned for package/component 'Simple'. Error code: Unknown. Proxy was not created.
Done.
---------- Finished Deploy of project p_genapp_ejbclientproxy (15:35:19)
So the whole way isn't a option because we do not want to change the JAVA settings in PB back and forth just to generate new EJB Proxies for changed JAVA objects in the future...
So one option to test will be creating COM wrappers for JAVA classes to use them in PB...

Index was outside the bounds of the array in #Scripts.Render

For each controller have a folder (with the same name controler), and for each action a script file.
For each file is creating a bundle following the pattern: "~/Scripts/Controllers/{controller-name}/{filename-without-extension}"
bundles.IncludePerFile(new DirectoryInfo(server.MapPath("~/Scripts/Controllers")), "~/Scripts/Controllers/{0}/{1}",
(dir,file) => string.Format("~/Scripts/Controllers/{0}/{1}", dir, Path.GetFileNameWithoutExtension(file)), "*.js");
IncludePerFile is an extension method I created to perform this task
Then one bundle for: ~/Scripts/Controllers/processos/pasta should exist!
And to confirm this:
So far so correct! The bundle exists!
Running app
When I run the application, the following error occurs:
Full image
Wrongly and inefficient to repair the error:
If I change this:
#Scripts.Render("~/Scripts/Controllers/processos/pasta")
to this:
#Scripts.Render("~/Scripts/Controllers/processos/pasta.js")
No error is generated. But the file is not minified since there is effectively a bundle. (I have already put in release mode and published application!)
Full error
Index was outside the bounds of the array.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.IndexOutOfRangeException: Index was outside the bounds of the array.
Source Error:
Line 3: #section js {
Line 4: #*#Scripts.Render("~/Scripts/Controllers/processos/Pasta.js", "~/Scripts/Controllers/processos/display.js")*#
Line 5: #Scripts.Render("~/Scripts/Controllers/processos/pasta")
Line 6: #Scripts.Render("~/Scripts/Controllers/processos/display.js")
Line 7:
Source File: w:\Clients\creditoimobiliariobb\sistema\src\CreditoImobiliarioBB\CreditoImobiliarioBB.Web\Views\processos\display.cshtml Line: 5
Stack Trace:
[IndexOutOfRangeException: Index was outside the bounds of the array.]
System.String.get_Chars(Int32 index) +0
Microsoft.Ajax.Utilities.CssParser.Append(Object obj, TokenType tokenType) +402
Microsoft.Ajax.Utilities.CssParser.AppendCurrent() +74
Microsoft.Ajax.Utilities.CssParser.SkipToClose() +744
Microsoft.Ajax.Utilities.CssParser.SkipToEndOfStatement() +232
Microsoft.Ajax.Utilities.CssParser.ParseRule() +574
Microsoft.Ajax.Utilities.CssParser.ParseStylesheet() +1235
Microsoft.Ajax.Utilities.CssParser.Parse(String source) +897
Microsoft.Ajax.Utilities.Minifier.MinifyStyleSheet(String source, CssSettings settings) +419
System.Web.Optimization.CssMinify.Process(BundleContext context, BundleResponse response) +302
System.Web.Optimization.Bundle.ApplyTransforms(BundleContext context, String bundleContent, IEnumerable`1 bundleFiles) +207
System.Web.Optimization.Bundle.GenerateBundleResponse(BundleContext context) +355
System.Web.Optimization.Bundle.GetBundleResponse(BundleContext context) +104
System.Web.Optimization.BundleResolver.GetBundleContents(String virtualPath) +254
System.Web.Optimization.AssetManager.EliminateDuplicatesAndResolveUrls(IEnumerable`1 refs) +435
System.Web.Optimization.AssetManager.DeterminePathsToRender(IEnumerable`1 assets) +1029
System.Web.Optimization.AssetManager.RenderExplicit(String tagFormat, String[] paths) +75
System.Web.Optimization.Scripts.RenderFormat(String tagFormat, String[] paths) +292
System.Web.Optimization.Scripts.Render(String[] paths) +51
I've had the same error in this question: StyleBundle Index was outside the bounds of the array
And answer is pretty simple: you have to update your Microsoft Web Optimization & WebGrease packages (at this time 1.1.2 & 1.6.0 versions)
I would verify that all the elements of your
IncludePerFile(new DirectoryInfo(server.MapPath("~/Scripts/Controllers")), "~/Scripts/Controllers/{0}/{1}",
(dir,file) => string.Format("~/Scripts/Controllers/{0}/{1}", dir, Path.GetFileNameWithoutExtension(file)), "*.js")
are putting in the created bundles exactly what you think they're putting in.
I got this error at run time when the wrong type of file is included within a bundle. i.e.
#Styles.Render("~/bundles/myStyleBundle");
actually contains a JavaScript file.
I had the same problem and when I tried different checking I found out that there is a selector in my css file like this that cause the problem:
.glyphicons-icon _:-o-prefocus,
.glyphicons-icon {
background-image: url(../images/glyphicons.png);
}
it seems that Microsoft.Ajax.Utilities.CssParser has a problem with _: css selector. I removed the line and it's working.
I just ran into a similar problem. I am using VS 2013 and MVC 5 and was updating to Bootstrap v3.0.1 in order to use a theme from Bootswatch. I updated everything using the latest Bootstrap download and the site seemed to work fine. I then grabbed the CSS for Slate from the Bootswatch site and used it in the new stylesheet, changed it in the StyleBundle and built solution. When I ran it, I got the "Index was outside the bounds of the array" error. Switch back to bootstrap.css and it worked fine.
I then used NuGet Package Manager to update all my packages... I had just installed VS 2013 and not yet updated everything. Rebuilt the solution and wallah, it works great. So I would up vote the updating your packages answser.
You may need to update some of your nuget libraries. Try updating WebGrease
I'm using
#Scripts.Render()
For me it was an issue with the backtik in JS file.
Sample 1
let something = `some text
bla bla
`;
Above code thrown this exception
Index and length must refer to a location within the string.
Sample 2
let something = `some text
bla bla`;
Now it works well, so do not keep the closing backtik at the beginning new line ...

JFrame in remote between JDK 5 (Server) and 6 (Client - VisualVM)

So I have a little trouble on the opening of a JFrame. I searched extensively on the net, but I really can not find a solution ...
I explained the situation:
I need to develop an application that needs to retrieve information tracking application while meeting new safety standards. For that I use JMX that allows monitoring and VisualVM to see these information.
I therefore I connect without problems (recently ^ ^) to JMX since VisualVM.
There is thus in a VisualVM plugin for recovering information on MBean, including those on Methods (Operations tab in the plugin).
This allows among others to stop a service or create an event.
My problem then comes when I try to display a result of statistics.
In fact, I must show, at the click of a button from the list of methods in the "Operations", a window with a table in HTML (titles, colors and everything else).
For that I use a JFrame:
public JFrame displayHTMLJFrame(String HTML, String title){
JFrame fen = new JFrame();
fen.setSize(1000, 800);
fen.setTitle(title);
JEditorPane pan = new JEditorPane();
pan.setEditorKit(new HTMLEditorKit());
pan.setEditable(false);
pan.setText(HTML);
fen.add(pan);
return fen;
}
I call it in my method:
public JFrame displayHtmlSqlStatOK_VM(){
return displayHTMLJFrame(displaySQLStat(sqlStatOK, firstMessageDate), "SqlStatOK");
}
The method must therefore giving me back my JFrame, but she generates an error:
Problem invoking displayHtmlSqlStatOK_VM : java.rmi.UnmarshalException: error unmarshalling return; nested
exception is:
java.io.InvalidClassException: javax.swing.JFrame; local class incompatible: stream classdesc serialVersionUID =
-5208364155946320552, local class serialVersionUID = -2386951414768123374
I saw on the internet that this was a version problem (Serialization), and I believe strongly that it comes from the fact that I have this:
Server - JDK5 <----> Client (VisualVM) - JDK6
Knowing that I can not to change the server version (costs too important ...) as advocated by some sites and forums.
My question is as follows:
Can I display this damn window keeping my current architecture (JDK5 server side and client side JDK6)?
I could maybe force the issue? Tell him that there's nothing bad that can run my code? Finally I'm asking him but he does not answer me maybe to you he will tell you ... (Yes I crack ^^).
Thank you very much to those who read me and help me!
If you need more info do not hesitate.
EDIT
The solution to my problem might be elsewhere, because in fact I just want a table with minimal formatting (this is just for viewing application for an for an officer to have his little table him possibly putting critical data in red...).
But I have nowhere found a list of types that I can return with VisualVM ... This does not however seem to me too much to ask.
After I had thought of a backup solution, which would be to create a temporary HTML file and open it automatically in the browser, but right after that is perhaps not very clean ... But if it can work ^^
I am open to any area of ​​research!
It looks like you are sending instance javax.swing.JFrame over the JMX connection - this is a bad idea.
Well good I found myself, as a great :)
Thank you bye!
..........
Just kidding of course I will give the solution that I found ^ ^
So here's what I did:
My display to be done on the client (normal...) my code to display a JFrame that I had set up on the server was displayed obviously ... On the server xD
I didn't want to change the customer (VisualVM) to allow users maximum flexibility. However I realized that to display my HTML table to be rendered usable (with colors and everything) I had to change the client (as JMX does not support the type JFrame as type back an operation).
My operation running from the MBeans plugin for VisualVM, it was necessary that I find the source code for it to say "Be careful if you see that I give you the HTML you display it in a JFrame".
Here is my approach:
- Get the sources
The link SVN to get sources VisualVM is as follows:
https: //svn.java.net/svn/visualvm~svn/branches/release134
If like me you have trouble with the SVN client includes in NetBeans because you are behind a proxy, you can do it by command line:
svn --config-option servers:global:http-proxy-host=MY_PROXY_HOST --config-option servers:global:http-proxy-port=MY_PROXY_PORT checkout https: //svn.java.net/svn/visualvm~svn/branches/release134 sources-visualvm
Putting you on your destination folder of course (cd C:\Users\me\Documents\SourcesVisualVM example).
- Adding the platform VisualVM
NetBeans needs the platform VisualVM to create modules (plugins) for it. For this, go to "Tools" -> "NetBeans Platforms".
Then click "Add Platform ..." at the bottom left of the window and select the folder to the bin downloaded at this address: http:// visualvm.java.net/download.html
You should have this:
http://img15.hostingpics.net/pics/543268screen1.png
- Adding sources in the workspace (NetBeansProjects)
Copy/paste downloaded sources (SVN from the link above) to your NetBeans workspace (by default in C:\Users\XXX\Documents\NetBeansProjects).
- Ouverture du projet du plugin MBeans
In NetBeans, right click in the Project Explorer (or go to the menu "Files") and click "Open Project ...".
You will then have a list of projects in your workspace.
Open the project "mbeans" found in "release134" -> "Plugins", as below:
http://img15.hostingpics.net/pics/310487screen2.png
- Changing the file "platform.properties"
To build plugin you must define some variables for your platform.
To do this, open the file platform.properties in the directory release134\plugins\nbproject of your workspace.
Replace the content (by changing the paths compared to yours):
cluster.path=\
C:\\Program Files\\java6\\visualvm_134\\platform:\
C:\\Program Files\\java6\\visualvm_134\\profiler
# Deprecated since 5.0u1; for compatibility with 5.0:
disabled.clusters=
nbjdk.active=default
nbplatform.active=VisualVM_1.3.4
suite.dir=${basedir}
harness.dir= C:\\Program Files\\NetBeans 7.1.2\\harness
- Changing the class XMBeanOperations
To add our feature (displaying an HTML table), you must change the class that processes operations, namely the class XMBeanOperations in package com.sun.tools.visualvm . modules.mbeans.
At line 173, replace:
if (entryIf.getReturnType() != null &&
!entryIf.getReturnType().equals(Void.TYPE.getName()) &&
!entryIf.getReturnType().equals(Void.class.getName()))
fireChangedNotification(OPERATION_INVOCATION_EVENT, button, result);
By :
if (entryIf.getReturnType() != null &&
!entryIf.getReturnType().equals(Void.TYPE.getName()) &&
!entryIf.getReturnType().equals(Void.class.getName())) {
if (entryIf.getReturnType() instanceof String) {
String res = result + "";
if (res.indexOf("<html>") != -1) {
JFrame frame = displayHTMLJFrame(res, button.getText());
frame.setVisible(true);
}
else
fireChangedNotification(OPERATION_INVOCATION_EVENT, button, result);
} else
fireChangedNotification(OPERATION_INVOCATION_EVENT, button, result);
}
With the method of creating the JFrame that you place above "void performInvokeRequest (final JButton button)" for example:
// Display a frame with HTML code
public JFrame displayHTMLJFrame(String HTML, String title){
JFrame fen = new JFrame();
fen.setSize(1000, 800);
fen.setTitle(title);
JEditorPane pan = new JEditorPane();
pan.setEditorKit(new HTMLEditorKit());
pan.setEditable(false);
pan.setText(HTML);
fen.add(pan);
return fen;
}
We can see that we already did a test on the return type, if it is a String which is returned, if the case, if we see in this string the balise , then we replace the result of the click by opening a JFrame with the string you put in, what makes us display our HTML code!
- Creating a .nbm
The file .nbm is the deployment file of your plugin. Simply right-click your project (in the Project Explorer) and click on "Create NBM".
Your file .nbm will be created in the folder "build" the root of your project.
- Installing the plugin in VisualVM
To install your plugin, you must just go in VisualVM, go into "Tools" -> "Plugins" tab and then "Downloaded", click "Add Plugins ...". Select your plugin .nbm then click "Install". Then follow the instructions.
Useful Sources
http: //docs.oracle.com/javase/6/docs/technotes/guides/visualvm/
http: //visualvm.java.net/"]http://visualvm.java.net/
http: //visualvm.java.net/api-quickstart.html (Créer un plugin VisualVM avec NetBeans)
Thank you very much for your help Tomas Hurka ;)

PHP Error handling: die() Vs trigger_error() Vs throw Exception

In regards to Error handling in PHP -- As far I know there are 3 styles:
die()or exit() style:
$con = mysql_connect("localhost","root","password");
if (!$con) {
die('Could not connect: ' . mysql_error());
}
throw Exception style:
if (!function_exists('curl_init')) {
throw new Exception('need the CURL PHP extension.
Recomplie PHP with curl');
}
trigger_error() style:
if(!is_array($config) && isset($config)) {
trigger_error('Error: config is not an array or is not set', E_USER_ERROR);
}
Now, in the PHP manual all three methods are used.
What I want to know is which style should I prefer & why?
Are these 3 drop in replacements of each other & therefore can be used interchangeably?
Slightly OT: Is it just me or everyone thinks PHP error handling options are just too many to the extent it confuses php developers?
The first one should never be used in production code, since it's transporting information irrelevant to end-users (a user can't do anything about "Cannot connect to database").
You throw Exceptions if you know that at a certain critical code point, your application can fail and you want your code to recover across multiple call-levels.
trigger_error() lets you fine-grain error reporting (by using different levels of error messages) and you can hide those errors from end-users (using set_error_handler()) but still have them be displayed to you during testing.
Also trigger_error() can produce non-fatal messages important during development that can be suppressed in production code using a custom error handler. You can produce fatal errors, too (E_USER_ERROR) but those aren't recoverable. If you trigger one of those, program execution stops at that point. This is why, for fatal errors, Exceptions should be used. This way, you'll have more control over your program's flow:
// Example (pseudo-code for db queries):
$db->query('START TRANSACTION');
try {
while ($row = gather_data()) {
$db->query('INSERT INTO `table` (`foo`,`bar`) VALUES(?,?)', ...);
}
$db->query('COMMIT');
} catch(Exception $e) {
$db->query('ROLLBACK');
}
Here, if gather_data() just plain croaked (using E_USER_ERROR or die()) there's a chance, previous INSERT statements would have made it into your database, even if not desired and you'd have no control over what's to happen next.
I usually use the first way for simple debugging in development code. It is not recommended for production. The best way is to throw an exception, which you can catch in other parts of the program and do some error handling on.
The three styles are not drop-in replacements for each other. The first one is not an error at all, but just a way to stop the script and output some debugging info for you to manually parse. The second one is not an error per se, but will be converted into an error if you don't catch it. The last one is triggering a real error in the PHP engine which will be handled according to the configuration of your PHP environment (in some cases shown to the user, in other cases just logged to a file or not saved at all).

selenium.captureEntirePageScreenshot does not work but selenium.captureScreenshot works

I'm running Selenium with TestNG using Eclipse and Selenium RC. I used the command:
selenium.captureEntirePageScreenshot("\\test.png","");
but got the following error:
com.thoughtworks.selenium.SeleniumException: ERROR: Command execution failure. Please search the forum at http://clearspace.openqa.org for error details from the log window. The error message is: Component returned failure code: 0x80520001 (NS_ERROR_FILE_UNRECOGNIZED_PATH) [nsILocalFile.initWithPath]
Can someone please suggest why this error is occuring? I have already tried the following:
1)Replaced "" (String kwargs parameter) with "background=#CCFFDD"
2)Running in Firefox in chrome mode
3)Changed the path to the following values and I'm still getting the error:
"\test.jpg",
"c:\test.jpg",
"c:\test.png",
"c:\folder1\test.png", (folder1 exists)
"c:\folder1\test.jpg",
4)Tried with - selenium.captureScreenshot("\test.png"); and it works fine but it does not solve my purpose and I dont want to use awt.
Can someone please suggest what could be wrong?
Thanks,
Mugen
Better yet...
I ran into a similar issue, where I only had access to a relative path instead of an absolute one. Here is the solution I came up with:
public void saveScreenshot(String methodName) {
if (methodName == null) {
methodName = String.valueOf(System.currentTimeMillis());
}
File f = new File("reports" + File.separator + methodName + ".jpg");
selenium.captureEntirePageScreenshot(f.getAbsolutePath(), "");
}
Which will put a screen shot of the entire page into the reports directory that is relative to the project. I am using the method name as the file name, or the current time if null is sent to the method.
Try this:
String path = System.getProperty("user.dir");
selenium.captureEntirePageScreenshot(path + "\\test.png", "");
To whomsoever it may concern,. the problem was solved after I kept fiddling with the code for a while and restarted my system. I came to know that captureEntirePageScreenshot works only on absolute paths so I made sure I kept trying with just that.
I got it working after looking at this page.
http://ashishbhatt.wordpress.com/2010/02/03/using-captureentirepagescreenshot-with-selenium/