I'm facing NullPointer exception on click on a button in GWT, Could someone suggest me how to go ahead and debug the issue ? I have posted the snippet of the code here.
I have a form which creates a movie ticket on create, cancel if user decides not to. On cancel it loads back to the first form successfully but parent form buttons throw null pointer exception on click.
Note: These parent buttons were works just fine if i don't load createMovie page.
createMovie.class
public void init( ClickListener listener )
{
// code ...
// ........
cancel.addClickListener( listener );
createMovie.add( header );
createMovie.add( table );
createMovie.setHeight( "663px" );
initWidget( createMovie );
}
In FocusWidget.class
public void addClickListener(ClickListener listener) {
if (clickListeners == null) {
clickListeners = new ClickListenerCollection();
sinkEvents(Event.ONCLICK);
}
clickListeners.add(listener);
}
// code
#Override
public void onBrowserEvent(Event event) {
switch (DOM.eventGetType(event)) {
case Event.ONCLICK:
if (clickListeners != null) {
clickListeners.fireClick(this); ------->>> LINE 102
}
break;
case Event.ONBLUR:
case Event.ONFOCUS:
if (focusListeners != null) {
focusListeners.fireFocusEvent(this, event);
}
break;
case Event.ONKEYDOWN:
case Event.ONKEYUP:
case Event.ONKEYPRESS:
if (keyboardListeners != null) {
keyboardListeners.fireKeyboardEvent(this, event);
}
break;
}
}
In ClickListenerCollection.class
public void fireClick(Widget sender) {
for (ClickListener listener : this) {
listener.onClick(sender);
}
}
Errors:
[ERROR] Uncaught exception escaped
java.lang.NullPointerException: null
at com.google.gwt.user.client.ui.ClickListenerCollection.fireClick(ClickListenerCollection.java:34)
at com.google.gwt.user.client.ui.FocusWidget.onBrowserEvent(FocusWidget.java:102)
at com.google.gwt.user.client.DOM.dispatchEventImpl(DOM.java:1308)
at com.google.gwt.user.client.DOM.dispatchEventAndCatch(DOM.java:1287)
at com.google.gwt.user.client.DOM.dispatchEvent(DOM.java:1255)
at sun.reflect.GeneratedMethodAccessor34.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
A NullPointerException means that you're trying to run something on a null object. (Well, not exactly, but that's basically it.)
First of all, learn how to read a stack trace. It's a very important skill. Basically, go down the stack until you find a file that is yours. In this case, it's FocusWidget:102. Since I don't know which line 102 is, I'll just guess.
Since you seem to be implying that the error is in that code snippet, and anything in the if statement can't be null since you're checking for it, my guess is that somehow the argument "listener" is null. I'm not sure, though. It'd be helpful if you could give us the entire block of code that's causing the issue, i.e. the scope around line 102.
Things i have done to fix,
I had cancel button in both forms (parent & child) and upon calling 'cancel' in createMovie.class ( child ) i was removing the parent form. So when i attempted to press 'cancel' in child form ( createMovie ) the listener was passing Null.
Fix
if ( childFormLoaded )
{
if ( panelsControl.containsPanel( createMovie.class.getName() ) )
panelsControl.removePanel( createMovie.class.getName() );
}
else
{
if ( panelsControl.containsPanel( ParentClass.class.getName() ) )
panelsControl.removePanel( ParentClass.class.getName() );
}
Related
I am getting an error when using a LogEventListener.
When I just print something, for example in the beforeEvent method, everything is fine, but when I set any action in any method, I get this error:
java.lang.StackOverflowError
at java.base/java.lang.String.replace(String.java:2173)
at com.codeborne.selenide.impl.SelenideElementDescriber.selector(SelenideElementDescriber.java:67)
at com.codeborne.selenide.impl.ElementFinder.elementCriteria(ElementFinder.java:137)
at com.codeborne.selenide.impl.ElementFinder.getSearchCriteria(ElementFinder.java:130)
at com.codeborne.selenide.impl.Alias$NoneAlias.getOrElse(Alias.java:43)
at com.codeborne.selenide.impl.WebElementSource.description(WebElementSource.java:60)
at com.codeborne.selenide.impl.SelenideElementProxy.invoke(SelenideElementProxy.java:81)
at jdk.proxy2/jdk.proxy2.$Proxy17.is(Unknown Source)
at com.bme.listeners.EventLogger.beforeEvent(EventLogger.java:16)
at com.codeborne.selenide.logevents.SelenideLogger.beginStep(SelenideLogger.java:121)
at com.codeborne.selenide.logevents.SelenideLogger.beginStep(SelenideLogger.java:57)
at com.codeborne.selenide.impl.SelenideElementProxy.invoke(SelenideElementProxy.java:81)**
Code:
public class EventLogger implements LogEventListener {
#Override
public void beforeEvent(LogEvent log) {
if(Selenide.$("path").is(visible)) {
System.out.println("Before Event");
}
}
#Override
public void afterEvent(LogEvent log) {
}
}
Can anyone help me understand?
My best guess as to the cause of this problem is that calling Selenide.$("path").is(visible) causes a log event to be generated. This would cause your listener gets called again, so Selenide.$("path").is(visible) gets called again, which causes another log event, so your listener gets called again, and so on and so on until the stack overflows. However, I don't have enough of your stacktrace to be sure. I would be more sure of this problem if you could include the stacktrace down as far as the second line in which com.bme.listeners.EventLogger.beforeEvent appears.
What might help is adding a boolean field to your listener that records whether it is currently logging an event, and does nothing if beforeEvent is called and this field is true:
public class EventLogger implements LogEventListener {
private boolean isCurrentlyLoggingAnEvent = false;
#Override
public void beforeEvent(LogEvent log) {
if (isCurrentlyLoggingAnEvent) {
// Prevent recursive call.
return;
}
isCurrentlyLoggingAnEvent = true;
try {
if(Selenide.$("path").is(visible)) {
System.out.println("Before Event");
}
}
finally {
isCurrentlyLoggingAnEvent = false;
}
}
#Override
public void afterEvent(LogEvent log) {
}
}
I've used a try-finally block to ensure that the field isCurrentlyLoggingAnEvent is always set back to false, even when an exception is thrown from within the try block.
If you plan to put any logic in afterEvent, you may want to consider doing something similar there.
I have an Eclipse RCP application which I am migrating from Eclipse 3.0 to 4.4, which works fine so far. Due to the migration, some menue entries (e.g. generic open file) were added, which I want to remove. This works so far, because I am calling hideActionset(...) in my perspectiveActivated() methods.
The menu entries disappear. But when I reset the perspective and then change the perspective, the menu entries appear again. I tried to fix this by calling hideActionSet(...) in my perspectiveChanged(...) methods, but they get called so often that I get a stackoverflow.
/**
* #see org.eclipse.ui.IPerspectiveListener#perspectiveActivated(org.eclipse.ui.IWorkbenchPage, org.eclipse.ui.IPerspectiveDescriptor)
*/
public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective)
{
if( perspective.getId().equals(m_PerspektivenID) || m_PerspektivenID.equals(STANDARDAKTION))
{
setEnabled( true );
}
else
{
setEnabled( false );
}
if(page != null)
{
page.hideActionSet("org.eclipse.ui.actionSet.keyBindings");
page.hideActionSet("org.eclipse.ui.actionSet.openFiles");
}
}
/**
* #see org.eclipse.ui.IPerspectiveListener#perspectiveChanged(org.eclipse.ui.IWorkbenchPage, org.eclipse.ui.IPerspectiveDescriptor, java.lang.String)
*/
public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, String changeId)
{
if(page != null)
{
page.hideActionSet("org.eclipse.ui.actionSet.keyBindings");
page.hideActionSet("org.eclipse.ui.actionSet.openFiles");
}
}
Here's a snipped of one of the two log-files that are being generated:
!ENTRY org.eclipse.equinox.event 4 0 2016-01-12 14:37:00.768
!MESSAGE Exception while dispatching event org.osgi.service.event.Event [topic=org/eclipse/e4/ui/model/ui/UIElement/widget/SET] to handler org.eclipse.e4.ui.services.internal.events.UIEventHandler#faec277
!STACK 0
java.lang.StackOverflowError
at java.util.HashMap.hash(HashMap.java:338)
at java.util.HashMap.containsKey(HashMap.java:595)
at java.util.Collections$SynchronizedMap.containsKey(Collections.java:2578)
at org.eclipse.e4.core.internal.contexts.EclipseContext.set(EclipseContext.java:347)
at org.eclipse.e4.ui.internal.services.ContextContextService.setEventCaching(ContextContextService.java:129)
at org.eclipse.e4.ui.internal.services.ContextContextService.deferUpdates(ContextContextService.java:86)
at org.eclipse.ui.internal.contexts.ContextService.deferUpdates(ContextService.java:92)
at org.eclipse.ui.internal.Perspective.removeActionSet(Perspective.java:362)
at org.eclipse.ui.internal.WorkbenchPage.hideActionSet(WorkbenchPage.java:2593)
at packagenane.classname.perspectiveChanged(BaseAction.java:146)
at org.eclipse.ui.internal.PerspectiveListenerList$4.run(PerspectiveListenerList.java:134)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.core.runtime.Platform.run(Platform.java:867)
at org.eclipse.ui.internal.PerspectiveListenerList.fireEvent(PerspectiveListenerList.java:58)
at org.eclipse.ui.internal.PerspectiveListenerList.firePerspectiveChanged(PerspectiveListenerList.java:131)
at org.eclipse.ui.internal.WorkbenchWindow.firePerspectiveChanged(WorkbenchWindow.java:1721)
at org.eclipse.ui.internal.WorkbenchPage.hideActionSet(WorkbenchPage.java:2596)
at packagenane.classname.perspectiveChanged(BaseAction.java:146)
at org.eclipse.ui.internal.PerspectiveListenerList$4.run(PerspectiveListenerList.java:134)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.core.runtime.Platform.run(Platform.java:867)
at org.eclipse.ui.internal.PerspectiveListenerList.fireEvent(PerspectiveListenerList.java:58)
at org.eclipse.ui.internal.PerspectiveListenerList.firePerspectiveChanged(PerspectiveListenerList.java:131)
at org.eclipse.ui.internal.WorkbenchWindow.firePerspectiveChanged(WorkbenchWindow.java:1721)
at org.eclipse.ui.internal.WorkbenchPage.hideActionSet(WorkbenchPage.java:2596)
at packagenane.classname.perspectiveChanged(BaseAction.java:146)
at org.eclipse.ui.internal.PerspectiveListenerList$4.run(PerspectiveListenerList.java:134)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
at org.eclipse.core.runtime.Platform.run(Platform.java:867)
at org.eclipse.ui.internal.PerspectiveListenerList.fireEvent(PerspectiveListenerList.java:58)
at org.eclipse.ui.internal.PerspectiveListenerList.firePerspectiveChanged(PerspectiveListenerList.java:131)
at org.eclipse.ui.internal.WorkbenchWindow.firePerspectiveChanged(WorkbenchWindow.java:1721)
at org.eclipse.ui.internal.WorkbenchPage.hideActionSet(WorkbenchPage.java:2596)
at packagenane.classname.perspectiveChanged(BaseAction.java:146)
at org.eclipse.ui.internal.PerspectiveListenerList$4.run(PerspectiveListenerList.java:134)
If you look at the stack trace you can clearly see that when you call WorkbenchPage.hideActionSet a new perspective changed event is being fired and perspectiveChanged is being called again while you are still in the first perspectiveChanged call.
One way to stop this is to have a flag in your perspectiveChanged method to detect that you are already dealing with a change.
Something like:
private boolean changeActive;
public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, String changeId)
{
if (changeActive) { // Don't do anything if already handling change
return;
}
changeActive = true;
if (page != null)
{
page.hideActionSet("org.eclipse.ui.actionSet.keyBindings");
page.hideActionSet("org.eclipse.ui.actionSet.openFiles");
}
changeActive = false;
}
I'm having a problem with my Java code.
I need to execute my doSomething() method, which includes code that manage also global variables. The problem is that the method is invoked twice (both mouseEvent and focusEvent of my JTable are fired at the same time).
How can I execute the doSomething() method only once at a time, in a sort of mutual exclusion ?
Thanks.
addMouseListener (new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
doSomething();
}
});
addFocusListener(new FocusAdapter() {
#Override
public void focusLost(FocusEvent e){
doSomething();
}
});
JTable cells contains String with length 1 or 2.
I need to apply a setValue method (or delete the String), in the exact moment the user stops the cell editing or he writes a 2 character String.
With those listeners I know the exact time to do the setValue or to inform the user that the first character he wrote doesn't exist. So in that way I wanted to block the user's action.
In other words, I need to control the user input in order to do a setValue or delete it. FocusLost tells me when the user clicks outside the JTable Component.
MouseClicked tells me when the user clicks in the JTable Component.
When mouseClicked is invoked and the JOptionPane appears, the cell automatically lose the focus, and so also the focusLost is invoked.
public void doSomething () {
// inEdit and tableCellEdited are the global variables
if ( inEdit && tableCellEdited != null ) {
String temp = "" + tableCellEdited.getDay();
String s = tableCellEdited.getValRenderer().trim();
if (s.length() > 2) s = s.substring(4);
if ( !s.trim().isEmpty() ) {
JOptionPane.showMessageDialog(getParent(),
"Code doesn't exist" , "Error: Code doesn't exist",JOptionPane.WARNING_MESSAGE);
tableCellEdited.setRendererValue(getUltimaGG(), false);
}
else {
tableCellEdited.setRendererValue(s, false);
setValueAt(tableCellEdited, getRowFromMat(tableCellEdited.getMat()), Integer.parseInt(temp.substring(6, 8)) );
}
clearProgrammazioneDueCaratteri();
}
}
repaint();
}
I am creating 2-3 checkbox field in my screen and adding those in a vertical field manager. Idea here is to disable other check box on click of another checkbox. but it is giving me stackoverflow error. I am posting my code here...
final CheckboxField[] checkBoxField = new CheckboxField[2];
checkBoxField[0] = cashCardCheckboxField;
checkBoxField[1] = creditDebitCardCheckboxField;
checkBoxField[0].setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
if(context != FieldChangeListener.PROGRAMMATIC){ //It means manually clicked by User
if(checkBoxField[0].getChecked()){
checkBoxField[0].setChecked(false);
}else{
checkBoxField[0].setChecked(true);
//Please wait Screen starts
// call here a user defined function to populate the drop down list
//Please wait Screen ends
}
}else{
checkBoxField[0].setChecked(false);
}
}
});
checkBoxField[1].setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
if(context != FieldChangeListener.PROGRAMMATIC){ //It means manually clicked by User
if(checkBoxField[1].getChecked()){
checkBoxField[1].setChecked(false);
}else{
checkBoxField[1].setChecked(true);
//Please wait Screen starts
// call here a user defined function to populate the drop down list
//Please wait Screen ends
}
}else{
checkBoxField[1].setChecked(false);
}
}
});
Thanks and Regards.
Solution
Try using this code. It allows you to create any number of checkboxes. When one is checked, the listener will uncheck all the other ones.
public class CheckBoxScreen extends MainScreen {
private CheckboxField checkBoxField[];
public CheckBoxScreen() {
super(MainScreen.VERTICAL_SCROLL | MainScreen.VERTICAL_SCROLLBAR);
checkBoxField = new CheckboxField[3];
checkBoxField[0] = new CheckboxField("one", true); // checked by default
checkBoxField[1] = new CheckboxField("two", false);
checkBoxField[2] = new CheckboxField("three", false);
FieldChangeListener listener = new CheckboxListener();
for (int i = 0; i < checkBoxField.length; i++) {
checkBoxField[i].setChangeListener(listener);
add(checkBoxField[i]);
}
}
private class CheckboxListener implements FieldChangeListener {
public void fieldChanged(Field field, int context) {
if (context != FieldChangeListener.PROGRAMMATIC) {
// user modified this field
CheckboxField checkbox = (CheckboxField)field;
if (checkbox.getChecked()) {
// uncheck the other checkboxes
for (int i = 0; i < checkBoxField.length; i++) {
if (checkBoxField[i] != checkbox && checkBoxField[i].getChecked()) {
checkBoxField[i].setChecked(false);
}
}
}
} else {
// nothing more to do here ... this time, fieldChanged() is being
// called as a result of calling setChecked() in the code.
}
}
}
}
Why Your Code Created a Stack Overflow
The fieldChanged() method gets called whenever a field has its properties modified. For a CheckboxField, that happens when the field is checked or unchecked. This can happen either because the user checks/unchecks the field, or because your code calls setChecked(boolean). This line:
if(context != FieldChangeListener.PROGRAMMATIC){ //It means manually clicked by User
is what allows the code inside fieldChanged() to determine if this call is occurring because the user changed the field, or because setChecked() was called by your code. Unfortunately, you have placed calls to setChecked() in all branches of the if statement, which causes setChecked() to be called both for user events, and when your code changes the fields.
In this code:
checkBoxField[0].setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
if(context != FieldChangeListener.PROGRAMMATIC){ //It means manually clicked by User
if(checkBoxField[0].getChecked()){
checkBoxField[0].setChecked(false);
}else{
checkBoxField[0].setChecked(true);
//Please wait Screen starts
// call here a user defined function to populate the drop down list
//Please wait Screen ends
}
}else{
checkBoxField[0].setChecked(false);
}
}
});
it is the last line (checkBoxField[0].setChecked(false);) that is causing problems. That else branch is reached after calling setChecked() in the "manually clicked" branch of the if statement. Once you call setChecked(false) again, you have modified the field programmatically. This will cause fieldChanged() to be called back again. And again. And again. This loop will never stop, until the program stack is full, and your app crashes.
So, if you see my code, you notice that I am not calling setChecked() in the programmatic branch of the if statement. Another problem in your code is that you don't have the correct logic to uncheck checkbox 1 when checkbox 0 is checked. But, that's only a functional bug. The recursive call to fieldChanged() is what caused the stack overflow.
Hope that helps.
I have a seemingly simple problem. I am working with imagebuttons inside a linearlayout which is inside a scrollview. I have set an onClickListener for one of the buttons which switches the color to red then transparent and then back again. I have tried calling performClick() and manually coding a routine to fire when a condition is met. The problem I am having is no matter how I try to do this the method(s) that are calling .setBackgroundColor() are all exiting when it's called. I don't even get to see a return statement in my Log. here is the code. I am sure this is a simple fix but I am not familiar very familiar with these things. Also I am not using any XML and would like to avoid it if possible so please keep that in mind when posting suggestions. Thanks in advance!
I will try to clarify what I am trying to accomplish. I am attempting to emulate the events that are fired during a click event WITHOUT a click event happening. I have tried this with performClick() and in the way I have here. In both cases I have the call to .setBackgroundColor() not firing and prematurely exiting the method that is calling it and it is called in.
After messing around a bit I found that the method will fire the setBackgroundColor() AND continue the method when I use Color.RED when it is already the color red. If I try any other colors it doesn't work. So it appears to not want to change the color in this fashion. Any ideas anyone?
here is the handler:
IBFireBall.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Log.d(TAG, "in onClick");
if (Fireball.activated) {
Fireball.activated = false;
AbilityWidget.IBFireBall.setBackgroundColor(0);
Log.d(TAG, "was activated");
} else {
Level.fireBall = new Fireball(context);
Fireball.activated = true;
AbilityWidget.IBFireBall.setBackgroundColor(Color.RED);
Log.d(TAG, "wasn't activated");
}
}
});
here is the other method Log only prints out 1 and 2:
public static void resetButton(String id) {
if (id.equals("Fireball")) {
if (Fireball.activated) {
Log.d(TAG,"inside resetbutton 1");
Fireball.activated = false;
Log.d(TAG,"inside resetbutton2" );
AbilityWidget.IBFireBall.setBackgroundColor(0);
Log.d(TAG,"inside resetbutton4" );
} else {
Level.fireBall = new Fireball(context);
Fireball.activated = true;
AbilityWidget.IBFireBall.setBackgroundColor(Color.RED);
Log.d(TAG, "wasn't activated");
}
}
}
1. First never use "=="`` to compare Objects, use.equals()`.
2. You are Not calling the resetButton() method from the onClick(), how will this method be invoked, if its not called.
It appears that the problem lies in threading. You can't update UI outside UI thread. Case closed :) I'll link some documentation on subject later.