How to execute a void method automatically when a breakpoint is hit? - java

I'm using latest IntelliJ IDEA Ultimate 16 EAP. I have some code in a library that initializes an object with some setters:
X createSomething() {
X x = new X();
x.setY(z);
return x; // breakpoint on this line
}
I'm looking to modify this returned value's state from the debugger: calling x.setY(y). I tried with conditions, because I want it to happen on every hit of the breakpointstopping at the breakpoint and using the "Evaluate Expression" window is unfeasible.
It's not possible to do this in any of the normal object oriented ways (e.g. overriding that method), nor it is possible to capture the result outside the method and modify it there because it's deep within many calls.
Here are my tries that all failed due to no support for those language features in the debugger. They failed with a dialog asking "Would you like to stop at the breakpoint?". The language level is fixed at Java 6-7 because I'm developing for Android.
Try 1: Call the method
Problem processing VM event:
Breakpoint: 'Line 9 in ClassName.createSomething() (package)'
Error: Failed to evaluate breakpoint condition 'x.setY(y)'
Reason: Boolean value expected
Also tried variants like: x.setY(y); false;, but it needs to be an expression.
Try 2: Call the method using lambda
Problem processing VM event:
Breakpoint: 'Line 9 in ClassName.createSomething() (package)'
Error: Failed to evaluate breakpoint condition '() -> { x.setY(y); return false; }'
Reason: Lambdas evaluation is not supported
Try 3: Call the method to have a boolean expression
Problem processing VM event:
Breakpoint: 'Line 9 in ClassName.createSomething() (package)'
Error: Failed to evaluate breakpoint condition 'new java.util.concurrent.Callable<Boolean>() { #Override public Boolean call() { x.setY(y); return false; } }.call()'
Reason: Anonymous class evaluation is not supported
Try 4: Call a static method (working workaround)
I found a workaround that I want to share, but I'm still looking for a better solution if anyone knows one: that doesn't require recompiling and restarting.
Create a method in a class:
public class SomeClass {
public static boolean fixX(X x) {
x.setY(y);
return false; // don't actually stop on the breakpoint
}
}
In the breakpoint condition add
full.pkg.SomeClass.fixX(x)
This works, but any time you want to modify the condition you'll have to restart the app. Parametrized fixX(x, changeAbleY) is a solution to that.
Make sure to disable or remove the breakpoint to prevent headaches by modified behavior when debugging unrelated issues.

Steps:
Right click on the breakpoint
A tool popup will open, in that popup click on "More" link at the bottom then a window will open.
Now check "Log evaluated expression" checkbox in that window and enter your method call in the given text box e.g methodName().
Click OK and start debugging.
When the breakpoint will hit your method will get called before that line's execution.
Reference: https://www.jetbrains.com/idea/help/configuring-breakpoints.html
Screenshot: Screenshot of breakpoint configuration window.
IntelliJ has a feature to add "Watches" where you can execute your void method but that's manual, not automatic.

Related

How to implement/setup BPMN2 diagram with two successive exclusive gateways

I have a BPMN2 diagram with two successive exclusive gateways. In my first gateway, I have two expression condition types for the yes and no lines:
${enoughDrinks}
${notenoughDrinks}
Following this exclusive gateway, I have a second exclusive gateway with the same yes and no lines and an additional third line "other option". My problem is: how do I have to set this up? When I run the process and get to the no line of the "Enough drinks" gateway, I get an error for the boolean expression condition of the second gateway:
Unknown property used in expression: ${otherOption}. Cause: Cannot resolve identifier 'otherOption'
I have declared the variable in the execute method of my class that implements the JavaDelegate class:
public void execute(DelegateExecution execution) throws Exception {
boolean otherOption = (Boolean)execution.getVariable("otherOption");
execution.setVariable("otherOption", otherOption);
}
Below is the BPMN diagram and the red arrow points to the problematic line.
Maybe the general question is: if it is even possible to have to successive exclusive gateways without a user task inbetween?
Since you do not seem to have any service tasks defined the in your process: where is the delegate executed?
Try to add it as a "start" listener to the 2nd gateway

InvalidStackFrameException After Calling Method via ObjectReference#invokeMethod

I am currently working on an Eclipse plugin which enhances the debugging possibilities. During the debugging session, I invoke a Scala method via com.sun.jdi.ObjectReference#invokeMethod like that:
public int callMethod_Reactive_Level(final ObjectReference o) throws InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException, InvocationException {
final Method m = apiValues.getMethod_Reactive_level(o); // com.sun.jdi.Method
final IntegerValue intVal = (IntegerValue) o.invokeMethod(thread, m, new LinkedList<Value>(), ObjectReference.INVOKE_SINGLE_THREADED);
return intVal.intValue();
}
After doing that, a call to org.eclipse.debug.core.model.IVariable#getValue leads to an InvalidStackFrameException. The whole error message is:
Status ERROR: org.scala-ide.sdt.debug code=5010 Exception while retrieving variable's value com.sun.jdi.InvalidStackFrameException
The message Exception while retrieving variable's value is shown when I inspect a variable in the variables view after calling a method as shown above.
Any idea how this problem can be solved? I do not understand why this is so problematic, since the JDI explicitely provides the possibility to do that.
Update: Since it may be a bug in the Scala IDE, there is a discussion and a tutorial how to reproduce the issue in the Scala IDE dev group.
The error message seems to come from the Scala IDE implementation of IVariable.getValue. It delegates to the JDI StackFrame.getValue, which throws. According to the docs, this can happen "if this stack frame has become invalid. Once the frame's thread is resumed, the stack frame is no longer valid."
My guess is that executing an invokeMethod on the same thread invalidates the stack frame.

IzPack ProcessPanel using executeclass not giving desired onSuccess/onFail behavior

I'm following the IzPack documentation use case Executing a Java Class with ProcessPanel and am running into some difficulty achieving the desired behavior from the onSuccess and onFail elements and could use some clarification from someone more familar with IzPack 4.3.5.
I've defined a java condition, process.panel.condition, that I want to use to control the availability of the next and previous buttons on the process panel after the run method in my Java class has been invoked. This run method assigns true or false to the static field, ConditionBoolean, underlying the process.panel.condition condition.
My expectation is that when process.panel.condition is true, I'd like the previous button to become disabled and the next button enabled. When process.panel.condition is false, I'd like the complement to occur- previous becomes enabled and next becomes disabled.
Instead what appears to be happening is that the previous button assignment is working but the next button is always made enabled.
Can anyone point out why I'm seeing this behavior and how I should go about changing my approach to achieve my desired behavior?
Below are the xml definitions and associated Java class referenced in the executeclass element.
<conditions>
<condition type="java" id="process.panel.condition">
<java>
<class>MyClass</class>
<field>ConditionBoolean</field>
</java>
<returnvalue type="boolean">True</returnvalue>
</condition>
</conditions>
Process spec xml as follows:
<processing>
<job name="Step 1">
<executeclass name="MyClass">
<arg>...</arg>
</executeclass>
</job>
<onFail previous="false" next="false" />
<onSuccess condition="!process.panel.condition" previous="true" next="false" />
<onSuccess condition="process.panel.condition" previous="false" next="true" />
</processing>
And the MyClass implementation:
import com.izforge.izpack.util.AbstractUIProcessHandler;
public class MyClasss {
public static boolean ConditionBoolean;
public void run(AbstractUIProcessHandler handler, String[] args) {
ConditionBoolean = false;
try {
...
ConditionBoolean = true;
} catch (Throwable e) {
handler.logOutput(e.getMessage(), false);
}
}
}
I've never seen a non-built-in condition id to have dots. So it might be a bug with izpack, considering it still has various weird bugs. Consider changing the id to something like "processPanelCondition".
After digging through the IzPack issues, I found IzPack-238, Installation will be treated as successfull [sic] even if a process in the ProcessPanel returns a boolean value of false, which pointed out that IzPack would report success after invoking a run method with a void return type.
This issue was then patched in version 4.2.1 to allow the run method to have a boolean return value that indicates whether or not the run method completed successfully. Despite the issue being resolved back in 2009-02, the documentation refered to in the question was not updated.
After switching the return value of the run method from void to boolean, and returning the outcome, I was able to resolve my problem.

why selenium.isConfirmationPresent() returns true after using chooseCancelOnNextConfirmation

I am having a code like the following
selenium.chooseCancelOnNextConfirmation();
selenium.click("deleteRequest");// confirm dialog will be displayed on clicking the button
System.out.println("is confirmation present "+selenium.isConfirmationPresent());
Eventhough i am using selenium.chooseCancelOnNextConfirmation(), please let me know why selenium.isConfirmationPresent() returns true.
But selenium.isConfirmationPresent() returns false after
selenium.getConfirmation();
Is it mandatory to use selenium.getConfirmation(), as i am not able to do further processing. It says
com.thoughtworks.selenium.SeleniumException: ERROR: There was an unexpected Confirmation! [Are you sure to delete selected request(s)?]
com.thoughtworks.selenium.HttpCommandProcessor.throwAssertionFailureExceptionOrError(HttpCommandProcessor.java:97)
at com.thoughtworks.selenium.HttpCommandProcessor.doCommand(HttpCommandProcessor.java:9
This is the expected behaviour. chooseCancelOnNextConfirmation() dictates the behaviour of getConfirmation(). Calling getConfirmation() effectively "consumes" the confirmation popup. You must use getConfirmation or verifyConfirmation before continuing your test, as any other Selenium command will fail if you do not handle the popup with a getConfirmation call.
By default, the confirm function will
return true, having the same effect as
manually clicking OK. This can be
changed by prior execution of the
chooseCancelOnNextConfirmation
command. If an confirmation is
generated but you do not get/verify
it, the next Selenium action will
fail.
So your code could be:
selenium.chooseCancelOnNextConfirmation();
selenium.click("deleteRequest")
selenium.getConfirmation();

What is this java.awt.event error?

ANSWER:
If you ever see these lines and are mistified like I was, here's what they mean.
Thread[AWT-EventQueue-0] (Suspended (exception NullPointerException))
EventDispatchTread.run() line: not available [local variables unavailable]
It's not that the variables are unavailable because they are lurking behind a shroud of mystery in a library somewhere dank. No no, they just went out of scope! It's still your fault, you still have to find the null, and no you can't blame the library. Important lesson!
QUESTION:
One of the most frustrating things for me, as a beginner is libraries! It's a love/hate relationship: On the one hand they let me do things I wouldn't normally understand how to do with the code that I do understand, on the other hand because I don't completely understand them, they sometimes throw a wrench in code that is otherwise working fine! It's because I don't understand the errors that can occur when using these libraries, because I didn't write them, and because eclipse doesn't give me a great deal to go with when one of imports starts acting up...
So here's the problem: I've been working with java.awt.event to handle a bunch of JButtons on the screen for this and that. I get an error when I use one of the buttons I've made. The error is:
Thread[AWT-EventQueue-0] (Suspended (exception NullPointerException))
EventDispatchTread.run() line: not available [local variables unavailable]
What does this mean? What could be causing it? I'm embarrassed to post code, but if you can stand to try to decipher my terrible style, here is the method that seems to cause this error to be thrown.
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
String name;
code...
if(cmd.equals("Play")) {
name = field.getText();
card = getCard(name);
if(card != null) {
if(rules.zoneHasCard(card, rules.hand)) {
display.updateStatusMessage(rules.play(card));
field.setText("");
display.updateHand(rules.zoneList("hand"));
display.updateDiscard(rules.zoneList("Discard")); // This is the error here! The discard Zone was empty!
}
else {
field.setText("You do not have " + card.getName());
field.selectAll();
}
}
else {
field.setText("That cardname is unused");
field.selectAll();
}
}
}
Welcome to the complexity of writing GUI code.
When you run a Swing program, a background thread called the Event Dispatch Thread is created. When the user clicks on a JButton, for example, JButton creates and fires an event using this Event Dispatch Thread. Hence the name: it's the thread that dispatches events!
Your code:
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
String name;
// more code...
}
is called by this Event Dispatch Thread, so your code can handle the event.
Somewhere within your code you are trying to do something with a variable that is currently equal to null. The error message is telling you, "hey while running some code on the event dispatch thread, I encountered a NullPointerException" in your code.
Why are you not receiving more info? Possibly you configured Eclipse not to include debug info when compiling?
For now, I recommend adding some lines to your actionPerformed method to show the state of variables:
System.out.println("field = " + field);
System.out.println("rules = " + rules);
System.out.println("display = " + display);
See if this shows you any nulls.
Even if the NullPointerException comes from a library, the stack trace will show which line of your code called that library. But only if you've configured Eclipse to generate debugging info.
In the longer term, work through the Sun's Swing Tutorial to learn more about these issues.
Any method call on a null object will raise a null pointer exception.
In your code, rules, name or display could be null and cause an exception.
Use a debugger (such as the one included in the eclipse IDE) and set a breakpoint at the start of the actionPerformed() method, then step through it line by line to see when a variable you try to invoke a method on is null.
Just don't stop reading the stack trace after two lines. Somewhere in the stack trace you'll recognise the name of one of the classes/methods which you did write. Start looking there. (btw, people spend way to much time inside debuggers :-))
You might have forgotten to actually set an ActionCommand.
In the ActionEvent API Doc there's a note regarding possible null results of getActionCommand().

Categories

Resources