[GLASSFISH-20234] autoundeploy directory-deployed application successful, then autodeploy it again false Created: 09/Apr/13  Updated: 20/Dec/16  Resolved: 08/May/13

Status: Resolved
Project: glassfish
Component/s: deployment
Affects Version/s: 4.0_dev
Fix Version/s: 4.1

Type: Bug Priority: Major
Reporter: sonky2 Assignee: Jeremy_Lv
Resolution: Won't Fix Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Decompression hello.war to a directory named hello, copy the directory hello to autodeploy dir, and then rm it.It is deployed and undeployed. But next it is deployed false when I copy the directory hello to autodeploy dir again.



 Comments   
Comment by Jeremy_Lv [ 09/Apr/13 ]

sonky2:

Can you list your detailed steps so that we can reproduce on our sides?

I have tried to use the autodeploy and seems it is normal as scenario. Here's my steps:
1). Copy the Hello folder to the directory of autodeploy and the application deployed successfully as the file test_sample1_deployed generated.
2). Delete all of the related files on the directory of autodeploy including the file exists in the .autodeploystatus.
3). execute the step1 again and the application deployed successfully.

BTW: the env. I have reproduced is as follows:
OS: Win7
java version: jdk1.7.0_12
glassfish: latest version of gfv4.0

Thanks.

Jeremy

Comment by sonky2 [ 10/Apr/13 ]

Jeremy:

Here's my steps:
1). Copy the hello folder to the directory of autodeploy and the application deployed successfully and the file hello_deployed generated.
2). Delete the hello folder on the directory of autodeploy. Then the file hello_undeployed generated, the file exists in the .autodeploystatus.
But the related directories on the directory of domain1\generated and domain1\applications__internal still exist.
3). execute the step1 again and the application deployed failed and the file hello_deployFailed generated.

UndeployCommand.java

File sourceFile = new File(source.getURI());
if (!source.exists()) {
logger.log(Level.WARNING, "Cannot find application bits at " +
sourceFile.getPath());
// remove the application from the domain.xml so at least server is
// in a consistent state
try

{ deployment.unregisterAppFromDomainXML(appName, target); }

catch(TransactionFailure e)

{ logger.warning("Module " + appName + " not found in configuration"); }

return;
}

I find in the UndeployCommand.java, source.exists() is false when I autoundeploy a directory-deployed application. So execute autoundeploy only execute "deployment.unregisterAppFromDomainXML(appName, target);",then return.

the env.
OS: Win7
java version: jdk1.7.0
glassfish: glassfish-4.0-b83-ml.zip

Thanks.

sonky2

Comment by Jeremy_Lv [ 10/Apr/13 ]

sonky2:

Thanks for listing the detailed steps, I can reproduce under your list steps. I found you have find the reason why it is failed in undeployment, I will make some changes later..

Thanks

Jeremy

Comment by Jeremy_Lv [ 10/Apr/13 ]

Here's my modification about UndeployCommand.java

UndeployCommand.java
Index: UndeployCommand.java
===================================================================
--- UndeployCommand.java	(revision 61278)
+++ UndeployCommand.java	(working copy)
@@ -304,7 +304,7 @@
             }
 
             File sourceFile = new File(source.getURI());
-            if (!source.exists()) {
+            if (!source.exists() && !deployment.isRegistered(appName)) {
                 logger.log(Level.WARNING, "Cannot find application bits at " +
                     sourceFile.getPath());
                 // remove the application from the domain.xml so at least server is

I have test it as manual and it run successfully.

I will run the QL tests and dev tests later to make sure whether the changes is fine.

Comment by Jeremy_Lv [ 10/Apr/13 ]

Here's result of the QL tests:

testng-summary:
     [echo]    [testng]
     [echo]    [testng] ===============================================
     [echo]    [testng] QuickLookTests
     [echo]    [testng] Total tests run: 117, Failures: 0, Skips: 0
     [echo]    [testng] ===============================================
     [echo]    [testng]
[INFO] Executed tasks
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8:58.602s
[INFO] Finished at: Wed Apr 10 16:03:55 KST 2013
[INFO] Final Memory: 25M/234M
Comment by Jeremy_Lv [ 10/Apr/13 ]

Hong:
Cc: Michael

I have also run the dev tests on my local win7 platform and all of the tests passed. I think the changes will be fine.

pl. consider to see whether the changes wil be checked into the v4.0 or v4.0.1

Thanks

Jeremy.

Comment by Jeremy_Lv [ 10/Apr/13 ]

The issue also can be reproduced as following steps:
1). asadmin deploy /home/Hello
2). Delete the Hello folder in the disk of /home
3). asadmin undeploy Hello
4). Copy the Hello folder to the /home disk
5). asadmin deploy /home/Hello
6). Failed in deploying the Hello.

Thanks

Comment by sonky2 [ 10/Apr/13 ]

UndeployCommand.java
// now start the normal undeploying
this.name = appName;

ExtendedDeploymentContext deploymentContext = null;
try

{ deploymentContext = deployment.getBuilder(logger, this, report).source(source).build(); }

catch (IOException e) {
logger.log(Level.SEVERE, "Cannot create context for undeployment ", e);
report.setMessage(localStrings.getLocalString("undeploy.contextcreation.failed","Cannot create context for undeployment :

{0}

", e.getMessage()));
report.setActionExitCode(ActionReport.ExitCode.FAILURE);
return;
}

I have test it as your modification in glassfish-3.1.2.2.zip and it run still failed.

this time it generates hello_undeployFailed when I delete the hello folder on the directory of autodeploy,it print "java.lang.NullPointerException" in the line "deploymentContext = deployment.getBuilder(logger, this, report).source(source).build();" in server.log.

Comment by Jeremy_Lv [ 10/Apr/13 ]

sonky2:
Will the modification will throw the NPE in latest version of glassfish v4.0?

I haven't test it in glassfish-3.1.2.2.zip, if you need the modification about v3.1.2.2, I will take a look later...

Thanks

Jeremy

Comment by Jeremy_Lv [ 10/Apr/13 ]

sonky2:
I have test my modification in the latest version of gfv4 manually again but there's no NPE comes out... pl. check about the modification again..

Thanks

Jeremy

Comment by sonky2 [ 11/Apr/13 ]

Jeremy:

I'm developing app in glassfish-3.1.2.2.zip now,could you test the modification about v3.1.2.2 if you have the time.

Thanks

sonky2

Comment by Jeremy_Lv [ 11/Apr/13 ]

sonky2:

Yes, you are right, I have just test my modification in gf3.1.2.2 and it is failed in undeployment.

pl. wait for a moment so that I can find out the solution for gf3.1.2.2 for you

-Jeremy

Comment by Jeremy_Lv [ 12/Apr/13 ]

sonky2:

Sorry to reply you so later, Here's some changes related to the glassfish 3.1.2.2:

Bar.java
Index: admin/src/main/java/org/glassfish/deployment/admin/UndeployCommand.java
===================================================================
--- admin/src/main/java/org/glassfish/deployment/admin/UndeployCommand.java	(revision 58927)
+++ admin/src/main/java/org/glassfish/deployment/admin/UndeployCommand.java	(working copy)
@@ -243,7 +243,7 @@
             }
 
             File sourceFile = new File(source.getURI());
-            if (!source.exists()) {
+            if (!source.exists() && !deployment.isRegistered(appName)) {
                 logger.log(Level.WARNING, "Cannot find application bits at " +
                     sourceFile.getPath());
                 // remove the application from the domain.xml so at least server is
Index: common/src/main/java/com/sun/enterprise/deploy/shared/FileArchive.java
===================================================================
--- common/src/main/java/com/sun/enterprise/deploy/shared/FileArchive.java	(revision 58927)
+++ common/src/main/java/com/sun/enterprise/deploy/shared/FileArchive.java	(working copy)
@@ -239,9 +239,11 @@
     @Override
     public Collection<String> getDirectories() throws IOException {
         List<String> results = new ArrayList<String>();
-        for (File f : archive.listFiles()) {
-            if (f.isDirectory() && isEntryValid(f)) {
-                results.add(f.getName());
+        if(archive.exists()){
+            for (File f : archive.listFiles()) {
+                if (f.isDirectory() && isEntryValid(f)) {
+                    results.add(f.getName());
+                }
             }
         }
         return results;

I have run the QL tests and all of the tests passed.

Hope the changes will help you.

Thanks

-Jeremy

Comment by sonky2 [ 12/Apr/13 ]

Jeremy:

I have run the tests and all of the tests passed in glassfish 3.1.2.2.

Thank you very much

-sonky2

Comment by Hong Zhang [ 06/May/13 ]

Jeremy: the block in the UndeployCommand that you modified is intended to clean up this scenario: application bits are somehow removed, but the application is still registered in domain.xml. In this case, we want to clean up the domain.xml to make the server state consistent. In your proposed change, the new condition now changes the scenario (for application which is not registered in the domain.xml) which is not this block of coded intended to do.

Can you provide more details of your investigation on the cause for this reported use case? Looking at the UndeployCommand, the domain.xml will be cleaned up for normal case in this block anyways?

if (!report.getActionExitCode().equals(ActionReport.ExitCode.FAILURE)) {
// so far I am doing this after the unload, maybe this should be moved before...
try

{ // remove the "application" element deployment.unregisterAppFromDomainXML(appName, target); }

catch(TransactionFailure e)

{ logger.warning("Module " + appName + " not found in configuration"); }

BTW: The 3.1.2.* code base is owned by the sustaining org, any fix to that code base needs to go through support channel.

Comment by Jeremy_Lv [ 07/May/13 ]

Hong:
it is because the first autoundeploy doesn't unregister, So it will be failed during the second time of autodeployment, we can devided the steps as follows and then you may seem the reason:
1). asadmin deploy /home/Hello
2). Delete the Hello folder in the disk of /home
3). asadmin undeploy Hello
4). Copy the Hello folder to the /home disk
5). asadmin deploy /home/Hello
6). Failed in deploying the Hello.
After step 6 and the command will throw out the exception as follows:
remote failure: Error occurred during deployment: Application name Hello
is already in use. Please pick a different name.. Please see server.log for more
details.
Command deploy failed.

the key reason is because we haven't move execute the appRegistry.remove(appName); during the autoundeploy, when we deploy the same application the ApplicationLifecycle.deploy will execute the follow code:

        if (commandParams.origin == OpsParams.Origin.deploy && 
            appRegistry.get(appName) != null) {
            report.setMessage(localStrings.getLocalString("appnamenotunique","Application name {0} is already in use. Please pick a different name.", appName));
            report.setActionExitCode(ActionReport.ExitCode.FAILURE);
            return null;                
        }

So it will be failed in the second time to dseploy the same applications.

BTW: it will be execute the appRegistry.remove(appName); during the ApplicationLifecycle.undeploy. so I use the logical about deployment.isRegistered(appName) to see whether we need to call the ApplicationLifecycle.undeploy when it comes to this situation.

Comment by Jeremy_Lv [ 07/May/13 ]

If I just execute the appRegistry.remove(appName); to remove the appname, another exception about the context root will be thrown out:

remote failure: Error occurred during deployment: Exception while loading the ap
p : java.lang.Exception: Virtual server server already has a web module test_sam
ple5 loaded at /test_sample5 therefore web module test_sample5 cannot be loaded
at this context path on this virtual server. Please see server.log for more deta
ils.

So I think we should not only remove the application registered in domain.xml but also execute the ApplicationLifecycle.undeploy in this situation.

Comment by Hong Zhang [ 07/May/13 ]

I tried to reproduce the problem from my side and I see what the problem is now.
As the source directory does not exist for directory auto-undeploy case, the code went into that block which made it return too early and skip all the code to properly undeploy the application. To fix this and also continue accommodating the case that we tried to solve originally with this block, I think we could add the additional condition for checking "info". If "info" is non-null, it means the application is in memory and needs proper undeployment and should not go into this block and exit early.

bash-4.1$ svn diff
Index: UndeployCommand.java
===================================================================
--- UndeployCommand.java        (revision 61867)
+++ UndeployCommand.java        (working copy)
@@ -304,7 +304,7 @@
             }

             File sourceFile = new File(source.getURI());
-            if (!source.exists()) {
+            if (!source.exists() && info == null) {
                 logger.log(Level.WARNING, "Cannot find application bits at " +
                     sourceFile.getPath());
                 // remove the application from the domain.xml so at least server is

Let me know what you think.

Comment by Jeremy_Lv [ 08/May/13 ]

Hong:
I think the solution you have comments is better than me because the variable of info can judge more conditions than only check about the appname.

Comment by Hong Zhang [ 08/May/13 ]

Actually with some further testing/investigation today, I noticed the deployment infrastructure will not be able to always undeploy an application cleanly with its original source deleted. We can clean to the point we can, but it will require a server restart to ensure the server is in consistent state before any redeployment is attempted. For that reason, I have not committed the previous suggested change, and just enhanced the existing warning message to state a server restart is required for this kind of case (so code does not fail at an unexpected place with the source been deleted prior to undeployment).

I am going to close the bug as "won't fix" as this is not a supported feature and looking at the current code, the undeployment code cannot be enhanced easily to guarantee a proper undeployment for such case.

Comment by Jeremy_Lv [ 09/May/13 ]

I see. Here's some of my comments:
1).Althought it seems a little strange because the useful warning messages was thrown out on the undeploy operation but it is failed in deploying the same application. As this solution will not affect the original syntax about the deployment...

The issue is occured because we have deleted the related directory before clean the related info about the deployed application.
So it can be also reproduce as follow:
1). asadmin deploy test_sample.war
2). delete the directory of test_sample under domains/domain1/applications/test_sample
3). asadmin udneploy test_sample
4). asadmin deploy test_sample.war
After step4, it will be failed because of the application info isn't cleanup without restart the domain. We will continue to look into this if the syntax about this will change in the future.

Generated at Mon Feb 27 13:40:07 UTC 2017 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.