This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 29658

Summary: pushing Next button on first New Wizard panel fails
Product: qa Reporter: Mikhail Romanov <mromanov>
Component: JellytoolsAssignee: issues@qa <issues>
Status: CLOSED INVALID    
Severity: blocker    
Priority: P1    
Version: 3.x   
Hardware: PC   
OS: Windows ME/2000   
Issue Type: DEFECT Exception Reporter:

Description Mikhail Romanov 2002-12-19 20:57:19 UTC
Bug occurs in Nevada 021218 build on 2 processor
P4 machine.

When NewWizardOperator is created by calling this
static method
 
NewWizardOperator.invoke(node, tmplPath)

then pushing of Next button occured inside this
method on the first panel after selecting
corresponding template node fails to work for me
in 90% of cases. Looks like it happens on all fast
machines when button is pushed before
initialization of all components on the panel is
completed. Thus one need either to wait until all
components are initialed or just insert "sleep"
before pushing buttons (or doing any other
operations on any components) on panels with
multiple complex components.
Comment 1 Jiri Skrivanek 2002-12-20 11:56:11 UTC
I cannot reproduce it on our machines. I need more info about the
failure. Could you attach stack trace of exception, screenshot or test
log? What JDK version do you use?
Comment 2 Mikhail Romanov 2002-12-20 21:45:17 UTC
It happens for me almost each time. However the following code works
fine for me (it's a Shura's recomendation):

    public static NewWizardOperator invoke(Node node, String
templatePath) {
        if(node == null || templatePath == null ||
templatePath.equals("")) {
            throw new JemmyException("Cannot accept null parameters.");
        }
        new NewTemplateAction().perform(node);
        ChooseTemplateStepOperator ctso = new
ChooseTemplateStepOperator();
        ctso.verify();
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        ctso.selectTemplate(templatePath);
        ctso.next();
Comment 3 Jiri Skrivanek 2003-01-02 11:26:58 UTC
We can add verify() method into NewWizardOperator. But I don't know
why it fails without it. It shouldn't fail because jemmy should wait
until Next button is enabled before it tries to click on it. Please,
could you attach or send me stack trace of exception and jemmy log
file. I want to investigate why it fails.
Comment 4 Mikhail Romanov 2003-01-02 19:06:34 UTC
The problem is that one can never know for sure that once button is
added to the panel, it already has all required listeners registered
for it for proper work. Here is the possible scenario which will fail:

- create JButton
- add it to JPanel

---> at this moment Jemmy finds the button and posts event to event
queue; however no listeners are added to the button yet, so the event
is just ignored

- add listeners to JButton 

---> this is the correct time to post the event ...

Calling verify won't solve the problem, but it'll increase the
probability, that all required listeners are added to the components
(so actually it's a kind of "smart" timeout in this case).
Comment 5 Alexandre Iline 2003-01-02 22:28:17 UTC
All right, it's not that simple.

I've done some research through openide and core sources:
listener is always added prior to adding of a button on
container:
//from NbPresenter.java
for (int i = 0; i < currentPrimaryButtons.length; i++) {
    modifyListener(currentPrimaryButtons[i], buttonListener, 
true); // add button listener
    panelForPrimary.add(currentPrimaryButtons[i]);
}

Listener itself can not add any problem either:
//from WizardDescriptor.Listener
public void actionPerformed (ActionEvent ev) {
    if (ev.getSource () == nextButton) {
        panels.nextPanel ();
        ...
    }
    ...
}

However there is a possibility that next panel has not been 
created yet
//from WizardDescriptor.ArrayIterator
public synchronized void nextPanel () {
    if (index + 1 == panels.length) throw new 
java.util.NoSuchElementException ();
    index++;
}

But, in this case, some exception should be visible somewhere, 
shouldn't it?

Misha, do you see anything like that?


Generally, in order to understand if "verify()" invocation is a 
full solution
(or just a "smart timeout") we need to understand what's going on.
I'm afraid that could be done only by source code analysis.


Comment 6 Mikhail Romanov 2003-01-03 02:21:56 UTC
Today, after some experiments around this problem, I've got the
following exception in the output (probably it can help you in
searching the root of the problem):

org.netbeans.jemmy.JemmyException: Exception in
java.awt.event.MouseEvent event dispatching
	at org.netbeans.jemmy.QueueTool.invokeAndWait(Unknown Source)
	at org.netbeans.jemmy.QueueTool.invokeSmoothly(Unknown Source)
	at org.netbeans.jemmy.drivers.input.EventDriver.dispatchEvent(Unknown
Source)
	at
org.netbeans.jemmy.drivers.input.MouseEventDriver.dispatchEvent(Unknown
Source)
	at
org.netbeans.jemmy.drivers.input.MouseEventDriver.clickMouse(Unknown
Source)
	at org.netbeans.jemmy.drivers.buttons.ButtonMouseDriver.push(Unknown
Source)
	at org.netbeans.jemmy.operators.AbstractButtonOperator.push(Unknown
Source)
	at org.netbeans.jellytools.WizardOperator.next(Unknown Source)
	at org.netbeans.jellytools.NewWizardOperator.invoke(Unknown Source)
	at
util.gui.dialogs.NewWizardCommonDialog.<init>(NewWizardCommonDialog.java:33)
	at
util.gui.dialogs.ejb.NewWizardCommonEJB.<init>(NewWizardCommonEJB.java:29)
	at
util.gui.dialogs.ejb.NewWizardEntityBean.<init>(NewWizardEntityBean.java:29)
	at util.gui.toolkits.ejb.EJBToolkit.createEntityEJB(EJBToolkit.java:70)
	at util.gui.toolkits.ejb.EJBToolkit.createEJB(EJBToolkit.java:54)
	at util.j2ee.assembly.J2EEAssembler.assemble(J2EEAssembler.java:93)
	at util.j2ee.J2EEApplication.assemble(J2EEApplication.java:63)
	at common.SITest.assemble(SITest.java:94)
	at ri.deployment.RIDeploymentTest.start_test(RIDeploymentTest.java:38)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:324)
	at util.TestExecutor.run(TestExecutor.java:134)
	at
ri.deployment.RIDeploymentXTestFS.testRIDeploymentAccountFS(RIDeploymentXTestFS.java:24)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:324)
	at junit.framework.TestCase.runTest(TestCase.java:166)
	at junit.framework.TestCase.runBare(TestCase.java:140)
	at org.netbeans.jellytools.JellyTestCase.runBare(Unknown Source)
	at junit.framework.TestResult$1.protect(TestResult.java:106)
	at junit.framework.TestResult.runProtected(TestResult.java:124)
	at junit.framework.TestResult.run(TestResult.java:109)
	at junit.framework.TestCase.run(TestCase.java:131)
	at org.netbeans.junit.NbTestCase.run(NbTestCase.java:76)
	at junit.framework.TestSuite.runTest(TestSuite.java:173)
	at junit.framework.TestSuite.run(TestSuite.java:168)
	at
org.netbeans.xtest.junit.JUnitTestRunnerExt.run(JUnitTestRunnerExt.java:249)
	at
org.netbeans.xtest.junit.JUnitTaskExt.executeInVM(JUnitTaskExt.java:482)
	at org.netbeans.xtest.junit.JUnitTaskExt.execute(JUnitTaskExt.java:304)
	at org.netbeans.xtest.junit.JUnitTaskExt.execute(JUnitTaskExt.java:280)
	at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:166)
	at org.apache.tools.ant.Task.perform(Task.java:319)
	at org.apache.tools.ant.Target.execute(Target.java:309)
	at org.apache.tools.ant.Target.performTasks(Target.java:336)
	at org.apache.tools.ant.Project.executeTarget(Project.java:1306)
	at org.netbeans.xtest.AntRunner.run(AntRunner.java:76)
	at org.netbeans.xtest.AntRunner.main(AntRunner.java:27)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:324)
	at
org.openide.execution.ThreadExecutor.executeClass(ThreadExecutor.java:116)
	at
org.openide.execution.ThreadExecutor$TERunnable.run(ThreadExecutor.java:183)
	at
org.netbeans.core.execution.RunClassThread.run(RunClassThread.java:118)
Inner exception:
java.lang.NullPointerException
	at
com.sun.forte4j.j2ee.ejb.wizard.CreateSessionEJBWizard.current(CreateSessionEJBWizard.java:74)
	at
com.sun.forte4j.j2ee.ejb.wizard.GenericEJBWizard.removeChangeListener(GenericEJBWizard.java:49)
	at
org.openide.loaders.TemplateWizardIterImpl.setIterator(TemplateWizardIterImpl.java:65)
	at
org.openide.loaders.TemplateWizard.setTemplateImpl(TemplateWizard.java:165)
	at
org.openide.loaders.TemplateWizard1.implStoreSettings(TemplateWizard1.java:492)
	at
org.openide.loaders.TemplateWizardPanel1.storeSettings(TemplateWizardPanel1.java:112)
	at org.openide.WizardDescriptor.updateState(WizardDescriptor.java:450)
	at
org.openide.loaders.TemplateWizard.updateState(TemplateWizard.java:571)
	at
org.openide.WizardDescriptor$Listener.actionPerformed(WizardDescriptor.java:991)
	at
javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1764)
	at
javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(AbstractButton.java:1817)
	at
javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:419)
	at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:257)
	at
javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:245)
	at java.awt.Component.processMouseEvent(Component.java:5093)
	at java.awt.Component.processEvent(Component.java:4890)
	at java.awt.Container.processEvent(Container.java:1566)
	at java.awt.Component.dispatchEventImpl(Component.java:3598)
	at java.awt.Container.dispatchEventImpl(Container.java:1623)
	at java.awt.Component.dispatchEvent(Component.java:3439)
	at
org.netbeans.jemmy.drivers.input.EventDriver$Dispatcher.launch(Unknown
Source)
	at org.netbeans.jemmy.QueueTool$QueueAction.run(Unknown Source)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:171)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:448)
	at
java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:197)
	at
java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
	at
java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:140)
	at java.awt.Dialog.show(Dialog.java:538)
	at org.netbeans.core.NbPresenter.superShow(NbPresenter.java:685)
	at org.netbeans.core.NbPresenter.run(NbPresenter.java:718)
	at org.openide.util.Mutex$1.run(Mutex.java:930)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:171)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:448)
	at
java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:197)
	at
java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:144)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:136)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:99)
Comment 7 Mikhail Romanov 2003-01-03 02:43:42 UTC
Please have a look at the inner exception.
I'm getting it very consistently on the recent Nevada FFJ build and I
belive it points on the real cause of the problem.
Comment 8 Jiri Skrivanek 2003-01-03 10:04:18 UTC
From the exception it seems that wizardPanels array in
CreateSessionEJBWizard.java is null at line 74. But it is a question
for responsible developer why.
Are you able to reproduce similar failure creating a different object
from template than EBJ (e.g. Java Classes|Main)? If not, please file a
bug againts EJB module with appropriate description.
Comment 9 Alexandre Iline 2003-01-04 01:42:33 UTC
We've performed a brainstorm with Misha, here is what's, probably, 
happening.

Exception happens on this line:
//from CreateSessionEJBWizard
    public WizardDescriptor.Panel current () {
        if (wizardPanels[getCurrentPanelIndex()] == null) { //this 
one (I)
            wizardPanels[getCurrentPanelIndex()] = 
                createWizardPanel (wizardPanelClasses 
[getCurrentPanelIndex()]);
        }
        ...
    }

It can only means that wizardPanels is null.

wizardPanels is initialized here:
//from CreateSessionEJBWizard
    protected void initialize () {
        wizState = new CreateEJBWizardState 
(CreateEJBWizardHelper.SESSION,
                                             "Session");        
//NOI18N
        wizState.setCurrentHelper (wizState.getHelper (CMT));

        wizardPanels = new WizardDescriptor.Panel 
[wizardPanelClasses.length]; //here (II)
        wizardPanels[0] = new CreateEJBPropsPanel (wizState);
    }

So, as we can see, by the time the button is pressed, 
CreateSessionEJBWizard.initialize() method has not performed yet.
This method is invoked during CreateSessionEJBWizard creation:
//from TemplateWizard
    private TemplateWizard (TemplateWizardIterImpl it) {
        super (it); //(III) we'll talk about it later
        
        this.iterator = it;
        
        // pass this to iterator
        iterator.initialize(this); //(IV) here!

        ...
    }

Buttons are added on panel here:
//from NbPresenter:
    protected final void initializeButtons() {
        ...
                    panelForPrimary.add(currentPrimaryButtons[i]); 
//here (V)
        ...
                    
panelForSecondary.add(currentSecondaryButtons[i]); //or here (V)
        ...
                    
currentButtonsPanel.add(currentPrimaryButtons[i], gbc); //or here 
(V)
        ...            
                    
currentButtonsPanel.add(currentSecondaryButtons[i], gbc); //or 
here (V)
        ...
    }

initializeButtons() method is invoked as a result of 
PropertyChangeEvent processing:
//from NbPresenter:
    public void propertyChange(final 
java.beans.PropertyChangeEvent evt) {
        ...
        if 
(DialogDescriptor.PROP_OPTIONS.equals(evt.getPropertyName())) {
            initializeButtons(); //here (VI)
            update = true;
        } else if 
(DialogDescriptor.PROP_OPTION_TYPE.equals(evt.getPropertyName())) {
        ...
    }

The event is posted by PropertyChangeSupport class instance during 
creating of
WizardDescriptor:
//from NotifyDescriptor:
    protected void firePropertyChange(String propertyName, Object 
oldValue, Object newValue) {
        if (changeSupport != null) { //changeSupport is an 
instance of PropertyChangeSupport
            changeSupport.firePropertyChange(propertyName, 
oldValue, newValue); //here (VII)
        }
    }

//from NotifyDescriptor
    public void setOptions(Object[] newOptions) {
        Object[] oldOptions = options;
        options = newOptions;
        firePropertyChange(PROP_OPTIONS, oldOptions, newOptions); 
//here (VIII)
    }

//from WizardDescriptor:
    public WizardDescriptor (Iterator panels, Object settings) {
        ...
        nextButton.addActionListener (listener);
        previousButton.addActionListener (listener);
        finishButton.addActionListener (listener);
        cancelButton.addActionListener (listener);

        super.setOptions (new Object[] { previousButton, 
nextButton, finishButton, cancelButton }); //here (IX)
        ...        
    }

One important thing is that PropertyChangeSupport passes event to 
listeners directly - 
not through the EventQueue.

Finally, WizardDescriptor constructor is invoked from 
TemplateWizard cunstructor at (III) line.

Thus, buttons are displayed _before_ the array initialization,
and though it seems most unlikely, during the time between (III) 
and (IV) lines
(more exactly between (I) and (V) lines) Jemmy is able to find the
button and even push it.

Well, at least it is the only explanation we have.

This might be caused by using two-processor machine - I do not 
know about that.

So that's what's happening. 




Let's take a look on verify() method using.

Verify simply checks existing of all known subcomponents, and, 
particularly,
the templates tree. Now, if NewWizardOperator pushes button, it 
means that
it has already found a template tree and selected a template in it.
Which means that tree has already been displayed anyway.

So, although I do not know why verify() makes tests more stable, 
it's just
a workaround. 

Full solution would be to wait for the array to be initialized. 
May be it's possible, 
may be not - I am not aware if there are such public interface.
Anyway it is not a good solutions since we tie the implementation 
to internal
API.

Another solution whould be to implement a timeout: 
"NewWizardOperator.AfterWizardTimeout" or something like that,
so tester can set this timeout to nonzero value whenever he
executes tests on dual-processor machines.

I, personally, vote for this one, if anything.





Finally, we need to create a bug. It will have low priority,
bacause it is hardly reproducible, but it needs to be created,
because, theoretically, user can push the button very fast
(or, vise versa, NB will work very slow).

I even can propose a fix: actions performed in 
CreateSessionEJBWizard.initialize() 
need to be moved to constructor.

From where I sit, 
TemplateWizard.Iterator.initialize(TemplateWizard) method is 
designed
for the purposes of an Iterator initialization, when intialization 
needs to be done 
with knowledges about the TemplateWizard.

In GenericEJBWizard class (superclass of CreateSessionEJBWizard), 
initialize(TemplateWizard)
simply invokes initialize() which is wrong using of the design 
idea.

Comment 10 Jiri Skrivanek 2003-01-06 11:53:44 UTC
It is a great investigation. We should definitely create a bug. In
Issuzila such bugs have keyword T9Y (testability) and priority can be
from medium to high because automated tests are important.
If they fix the bug quickly, we don't need to do anything. If they
not, I would add a timeout as Shura suggested.
Comment 11 Alexandre Iline 2003-01-16 03:40:40 UTC
Misha, could you please tell us what's going on with that bug you 
opened against EJB?

Comment 12 Mikhail Romanov 2003-01-16 05:38:29 UTC
Looks like this bug was caused by improper initialization sequence in
S1S EJB wizards (bugs # 4797676 and 4799932).
Now, when wizard bug is fixed and integrated, I can not reproduce this
bug anymore. 

My suggestion is to close it as invalid (as it is S1S bug rather than
Jellytools bug).
Comment 13 Alexandre Iline 2003-01-16 05:52:29 UTC
It's a bug in S1S.