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 46903 - Deployment error
Summary: Deployment error
Status: RESOLVED FIXED
Alias: None
Product: serverplugins
Classification: Unclassified
Component: Infrastructure (show other bugs)
Version: 4.x
Hardware: PC Windows XP
: P2 blocker (vote)
Assignee: Nam Nguyen
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-08-04 16:20 UTC by L Martinek
Modified: 2004-08-13 12:11 UTC (History)
0 users

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments
DeploymentException (996 bytes, text/plain)
2004-08-04 16:21 UTC, L Martinek
Details

Note You need to log in before you can comment on or make changes to this bug.
Description L Martinek 2004-08-04 16:20:24 UTC
[Build 200408021800, JDK 1.5.0]

Sometimes deployment fail. I don't know exact
reproducible steps yet, but it often happens to me
after finishing debugging and manually stopping
server. Next deployment fails with message
"Deployment error: Failed to start server
http://localhost:8084/. See ide log for details."
Comment 1 L Martinek 2004-08-04 16:21:13 UTC
Created attachment 16650 [details]
DeploymentException
Comment 2 Petr Jiricka 2004-08-04 19:19:23 UTC
There are some weird smells in the code. For example, if the user
cancels deployment, method _start() in ServerInstance returns false
(ServerInstance:446). Then startTarget() also returns false.

Then TargetServer.startTargets() returns false (TargetServer:389).

Then Deployment.deploy() gets false (Deployment:84) and then it throws
an exception (Deployment:91).

So, this nasty looking exception may be a consequence of the user
cancelling the dialog.

Or another smell is the threading code in ServerInstance.start().
Regardless of whether _start() succeeds, it always returns false ?!?
(ServerInstance:339).
Comment 3 L Martinek 2004-08-05 10:31:02 UTC
I have never canceled the dialog. I started execution or debugging of
the project and waited.
Comment 4 Pavel Buzek 2004-08-05 21:15:59 UTC
I can reproduce the ex when I debug, stop server and then run the
project. Thanks for the scanario!
I am looking into it.
Comment 5 Pavel Buzek 2004-08-05 21:43:05 UTC
> There are some weird smells in the code. For example, if the user
> cancels deployment, method _start() in ServerInstance returns false
> (ServerInstance:446). Then startTarget() also returns false.
> 
This is actually how it is supposed to behave!

> Then TargetServer.startTargets() returns false (TargetServer:389).

Perhaps the message should be different if the user stopped the
server, otherwise it is ok.

> 
> Then Deployment.deploy() gets false (Deployment:84) and then it throws
> an exception (Deployment:91).
> 
> So, this nasty looking exception may be a consequence of the user
> cancelling the dialog.
> 
> Or another smell is the threading code in ServerInstance.start().
> Regardless of whether _start() succeeds, it always returns false ?!?
> (ServerInstance:339).
> 

This code looks suspicious but it is not called here. 
The TS.startTargets calls SI.start(UI) - with parameter.
Comment 6 Pavel Buzek 2004-08-05 22:13:09 UTC
The problem is not reproducible 100%, it seems rather random.

My debug prints show that the problem spot is in checking the server
status after the plugin says the server has been started,
ServerInstance:441. The problem is that SI is caching the value of
isRunning!!! so it is sure to return false (and FAIL) if is checked
the value in the last 2000ms.
I tried removing the check for isRunning at 441 in SI and after that I
cannot reproduce the bug.

Nam has added this check in ver. 1.15 as part of IN=19137 which says:

> This will be done quietly without dialog for confirmation at this time.
> The implementation will rely on j2eeserver ModuleInstall.close() to
detect IDE exit.
> 
> This check in also fix:
> - infinite loop during silent start server in case of S1AS plugin.
> - clean up duplicate and unused entries in Bundle.properties
> - fix ServerStatusBar not to use invokeLater unecessarily
> 

I will let him comment on whether the check is really needed.
If it is I will add a new method 
private boolean checkRunning () which will no use the cached value.
Comment 7 Nam Nguyen 2004-08-05 23:51:32 UTC
The caching of state is for UI responsiveness reason. 
If the cache value is wrong for that 2 secs, I still don't see how it
can contribute to the scenario in either cases.  

Case 1: server stopped and cached value is running, the failure would
be later during deployment.  

Case 2: server is running and cached value says stopped,
SS.startDeploymentManager will be called.  Here if the plugin normally
just fire completed event and the cached state is in sync again.  If
plugin fire an error event then we got the problem.  But I think Libor
test case more likely fall into case 1 or the following plugin theory.

From the stack, I think that the possible reason is that the (tomcat
or as8) ProgressObject did not notify the StartProgressHandler.  I
remember there was a race condition where the plugin PO fire the
completed event too early even before the handler attached.  Could
this be the case?
Comment 8 Nam Nguyen 2004-08-06 00:11:19 UTC
I don't know how to explain Pavel observation about removing cached
value make the problem go away.  But if this really solve the problem,
I think that to have a private "realtime" method checkRunning to use
only for deployment is fine.
Comment 9 Pavel Buzek 2004-08-06 00:26:03 UTC
To explain better what I mean: it is the case 2. The server is stopped
and the cached value of isRunning is false. ServerInstance calls
StartServer.startDeploymentManager() and as soon as the server starts
and norifies the ServerInstance the ServerInstance will check the
isRunning() again -- I guess to make sure(?). If this happnes within
2000 ms of the last check the isRunning() will return false. If the
ServerInstance would ask StartServer at this point (e.g. if the 2000
ms time out expired, or just ignore the chache value) it would return
true, as it should be.

(ServerInstance, line 416.. with my comments started with //PB)

    private synchronized boolean _start(DeployProgressUI ui) {
        if (isRunning())
            return true;
 //PB: this.isRunning == false (the cache)
        DeployProgressUI.CancelHandler ch = getCancelHandler();
        ui.addCancelHandler(ch);
        
        try {
            StartServer ss = getStartServer();
            String errorMessage = checkStartDM(ss);
            if (errorMessage != null) {
                handleStartServerError(ui, errorMessage);
                return false;
            }
            
            ProgressObject po = ss.startDeploymentManager();
            
            ui.setProgressObject(po);
            po.addProgressListener(new StartProgressHandler());
            
            // wait until done or cancelled
            boolean done = sleep();
            if (! done) {
               
ui.addMessage(NbBundle.getMessage(ServerInstance.class,
"MSG_StartServerTimeout", url));
                return false;

//PB: done == true, ie. StartServer notified Server Instance 
//PB: that it has started succesfully

            } else if (! isRunning()) {
               ui.addMessage(NbBundle.getMessage(ServerInstance.class,
"MSG_StartedServerFailedPing", url));
                return false;
//PB: ^^ this is where it fails (IMO), the server was just 
//PB: started but the cache says it is not running!
//PB: when it failed it was here...
Comment 10 Nam Nguyen 2004-08-06 01:05:33 UTC
Well 2 secs is about the time required for an empty tomcat to start. 
Anyway, for bullet proof functionality, we can change the
StartProgressHandler.handleProgressEvent code to also remember the
ending state (FAILED or COMPLETED) so that we don't have to check
isRunning again.
Comment 11 Pavel Buzek 2004-08-06 17:22:46 UTC
Nam kindly offered to take this issue. Tx.
Comment 12 Nam Nguyen 2004-08-08 17:34:20 UTC
Depending on implementation of pinging the server
(StartServer.isRunning) sometimes it is not the best mechanism to
determine when starting server is successful.  Sometime
StartServer.isRunning just return false when
StartServer.startDeploymentManager already generate COMPLETED event.  

The integrated fix for this issue has the following improvements to
ServerInstance:

- Plainly rely on the plugin ProgressObject event COMPLETED to decide
when a start/debug/stop is done successfully.
- Precautious check for ProgressObject event COMPLETED even before
start waiting. (Sometimes plugin fire event COMPLETED event too fast
before listener attached.  Maybe this is not what happen to
start/stop/debug, but it happens in implementation of incremental deploy).
- Parameterize ServerInstance.isRunning and add isReallyRunning which
alway call StartServer.isRunning without relying on cahed value.
- Cleanup ServerInstance: eliminate unecessary methods that get in the
way of optimization.  Rearrange and streamline atomic calls:
_start/_stop/_debug.  All external calls now go through multiplexor
method SI.startTarget(Target target, DeployProgressUI ui, boolean
debugMode)
- Make sure event handlers are detached in finally blocks.
Comment 13 Nam Nguyen 2004-08-08 17:38:18 UTC
The fix consists of the following changes:

src/org/netbeans/modules/j2ee/deployment/impl/Bundle.properties;
new revision: 1.21; previous revision: 1.20
src/org/netbeans/modules/j2ee/deployment/impl/ServerInstance.java;
new revision: 1.27; previous revision: 1.26
src/org/netbeans/modules/j2ee/deployment/impl/ui/ServerStatusBar.java;
new revision: 1.10; previous revision: 1.9