cancel
Showing results for 
Search instead for 
Did you mean: 

Best Way to Uninstall a AMP Module

cgonzalez
Champ on-the-rise
Champ on-the-rise
Hi,

I have developed a amp module than extends Alfresco, it works fine,but now i want to uninstall it. How can i do that?

If have readed that there's no good way to do that.

Any tip?
1 ACCEPTED ANSWER

jpotts
World-Class Innovator
World-Class Innovator

Old thread, but in case it is helpful, in 5.x you can also use the Node Browser at /alfresco to browse the same path and delete exactly the module you need to.

View answer in original post

19 REPLIES 19

jbarmash
Champ in-the-making
Champ in-the-making
Yes, currently there is no way to uninstall an AMP.  

Check out this forum post for a workaround.  
http://forums.alfresco.com/viewtopic.php?f=36&t=11487&p=38155#p38155

Also, you can restore the backup file without the AMP that is made when you install the AMP. 

This is something that has been bothering me and some customers, so I just modified the Module Management Tool code to handle uninstalling AMPs.   I will work with engineering to make this part of the releases, but in the meantime, below is the patch information. 

The only file modified is ModuleManagementTool.java in projects\repository\source\java\org\alfresco\repo\module\tool\.

Index: ModuleManagementTool.java
===================================================================
— ModuleManagementTool.java   (revision 8575)
+++ ModuleManagementTool.java   (working copy)
@@ -77,8 +77,9 @@
     public static final String MODULE_DIR = "/WEB-INF/classes/alfresco/module";
     public static final String BACKUP_DIR = MODULE_DIR + "/backup";
    
-    /** Operations and options supperted via the command line interface to this class */
+    /** Operations and options supported via the command line interface to this class */
     private static final String OP_INSTALL = "install";
+    private static final String OP_UNINSTALL = "uninstall";
     private static final String OP_LIST = "list";
     private static final String OPTION_VERBOSE = "-verbose";
     private static final String OPTION_FORCE = "-force";
@@ -195,7 +196,7 @@
      * @param warFileLocation   the location of the WAR file into which the AMP file is to be installed.
      * @param preview           indicates whether this should be a preview install.  This means that the process of
      *                          installation will be followed and reported, but the WAR file will not be modified.
-     * @param forceInstall      indicates whether the installed files will be replaces reguarless of the currently installed
+     * @param forceInstall      indicates whether the installed files will be replaces regardless of the currently installed
      *                          version of the AMP.  Generally used during development of the AMP.
      * @param backupWAR         indicates whether we should backup the war we are modifying or not
      */
@@ -205,35 +206,7 @@
         {  
             outputMessage("Installing AMP '" + ampFileLocation + "' into WAR '" + warFileLocation + "'");
            
-            if (preview == false)
-            {
-                // Make sure the module and backup directory exisits in the WAR file
-                File moduleDir = new File(warFileLocation + MODULE_DIR, DETECTOR_AMP_AND_WAR);
-                if (moduleDir.exists() == false)
-                {
-                    moduleDir.mkdir();
-                }
-                File backUpDir = new File(warFileLocation + BACKUP_DIR, DETECTOR_AMP_AND_WAR);
-                if (backUpDir.exists() == false)
-                {
-                    backUpDir.mkdir();
-                }
-               
-                // Make a backup of the war we are going to modify
-                if (backupWAR == true)
-                {
-                    java.io.File warFile = new java.io.File(warFileLocation);
-                    if (warFile.exists() == false)
-                    {
-                        throw new ModuleManagementToolException("The war file '" + warFileLocation + "' does not exist.");
-                    }
-                    String backupLocation = warFileLocation + "-" + System.currentTimeMillis() + ".bak";
-                    java.io.File backup = new java.io.File(backupLocation);
-                    copyFile(warFile, backup);
-                         
-                    outputMessage("WAR has been backed up to '" + backupLocation + "'");
-                }
-            }
+            backupCurrentWar(warFileLocation, preview, backupWAR);
            
             // Get the details of the installing module
             String propertiesLocation = ampFileLocation + "/module.properties";
@@ -268,21 +241,7 @@
             ModuleDetails installedModuleDetails = ModuleDetailsHelper.createModuleDetailsFromWarAndId(warFileLocation, installingId);
             if (installedModuleDetails == null)
             {
-                // It might be there as one of the aliases
-                List<String> installingAliases = installingModuleDetails.getAliases();
-                for (String installingAlias : installingAliases)
-                {
-                    ModuleDetails installedAliasModuleDetails = ModuleDetailsHelper.createModuleDetailsFromWarAndId(warFileLocation, installingAlias);
-                    if (installedAliasModuleDetails == null)
-                    {
-                        // There is nothing by that alias
-                        continue;
-                    }
-                    // We found an alias and will treat it as the same module
-                    installedModuleDetails = installedAliasModuleDetails;
-                    outputMessage("Module '" + installingAlias + "' is installed and is an alias of '" + installingId + "'");
-                    break;
-                }
+                installedModuleDetails = findModuleAlias(warFileLocation, installingModuleDetails, installingId);
             }
            
             // Now clean up the old instance
@@ -413,6 +372,58 @@
             throw new ModuleManagementToolException("An IO error was encountered during deployment of the AEP into the WAR", exception);
         }      
     }
+
+   private void backupCurrentWar(String warFileLocation, boolean preview,
+         boolean backupWAR) throws IOException {
+      if (preview == false)
+      {
+          // Make sure the module and backup directory exists in the WAR file
+          File moduleDir = new File(warFileLocation + MODULE_DIR, DETECTOR_AMP_AND_WAR);
+          if (moduleDir.exists() == false)
+          {
+              moduleDir.mkdir();
+          }
+          File backUpDir = new File(warFileLocation + BACKUP_DIR, DETECTOR_AMP_AND_WAR);
+          if (backUpDir.exists() == false)
+          {
+              backUpDir.mkdir();
+          }
+         
+          // Make a backup of the war we are going to modify
+          if (backupWAR == true)
+          {
+              java.io.File warFile = new java.io.File(warFileLocation);
+              if (warFile.exists() == false)
+              {
+                  throw new ModuleManagementToolException("The war file '" + warFileLocation + "' does not exist.");
+              }
+              String backupLocation = warFileLocation + "-" + System.currentTimeMillis() + ".bak";
+              java.io.File backup = new java.io.File(backupLocation);
+              copyFile(warFile, backup);
+                   
+              outputMessage("WAR has been backed up to '" + backupLocation + "'");
+          }
+      }
+   }
+
+   private ModuleDetails findModuleAlias(String warFileLocation,
+         ModuleDetails installingModuleDetails, String installingId) {
+      // It might be there as one of the aliases
+      List<String> installingAliases = installingModuleDetails.getAliases();
+      for (String installingAlias : installingAliases)
+      {
+          ModuleDetails installedAliasModuleDetails = ModuleDetailsHelper.createModuleDetailsFromWarAndId(warFileLocation, installingAlias);
+          if (installedAliasModuleDetails == null)
+          {
+              // There is nothing by that alias
+              continue;
+          }
+          // We found an alias and will treat it as the same module
+          outputMessage("Module '" + installingAlias + "' is installed and is an alias of '" + installingId + "'");
+          return installedAliasModuleDetails;
+      }
+      return null;
+   }
    
     /**
      * @return Returns the custom file mapping properties or null if they weren't overwritten
@@ -623,11 +634,39 @@
     }
    
     /**
-     * @throws  UnsupportedOperationException
+     * Uninstalls the module from the war file.  Does NOT do dependency checks.
      */
-    public void uninstallModule(String moduleId, String warLocation)
+    public void uninstallModule(String moduleId, String warFileLocation, boolean preview)
     {
-        throw new UnsupportedOperationException("Uninstall module is not currently supported");
+       try {
+       
+        outputMessage("Uninstalling module '" +  moduleId + "' from WAR '" + warFileLocation + "'");
+        backupCurrentWar(warFileLocation, preview, true);
+
+       // Try to find an installed module by the ID
+        ModuleDetails installedModuleDetails = ModuleDetailsHelper.createModuleDetailsFromWarAndId(warFileLocation, moduleId);
+        //outputMessage(installedModuleDetails.getTitle());
+
+        // Now clean up the old instance
+        if (installedModuleDetails != null)
+        {
+            String installedId = installedModuleDetails.getId();
+            VersionNumber installedVersion = installedModuleDetails.getVersion();
+           
+            outputMessage("Clearing out files relating to version '" + installedVersion + "' of module '" + installedId + "' in war '" + warFileLocation + "'" );
+            outputMessage("WARNING:  No dependencies checks are currently done during the uninstall");
+
+            cleanWAR(warFileLocation, installedId, preview);
+        } else {
+            outputMessage("ERROR: Module '" + moduleId + "' was not found in the war.");
+        }
+       
+       } catch (IOException exception)
+        {
+            throw new ModuleManagementToolException("An IO error was encountered during deployment of the AEP into the WAR", exception);
+        }      
+
+
     }
    
     /**
@@ -795,6 +834,23 @@
             String warFileLocation = args[1];
             manager.listModules(warFileLocation);               
         }
+        else if (OP_UNINSTALL.equals(operation) == true && (args.length == 3 || args.length ==4)) {
+            manager.setVerbose(true);
+           String moduleId = args[1];
+            String warLocation = args[2];
+           
+           boolean preview = false;
+            manager.setVerbose(true);
+
+           if (args.length==4) {
+               if (OPTION_PREVIEW.equals(args[3]) == true)
+               {
+                   preview = true;
+                   manager.outputMessage("PREVIEW mode enabled");
+               }
+           }
+           manager.uninstallModule(moduleId, warLocation, preview);
+       }
         else
         {
             outputUsage();
@@ -810,7 +866,7 @@
     }
    
     /**
-     * Code borrowed directly from the Springframework FileCopyUtils.
+     * Code borrowed directly from the Spring Framework FileCopyUtils.
      */
     private static void copyFile(java.io.File in, java.io.File out) throws IOException
     {
@@ -857,6 +913,10 @@
         System.out.println("   -preview   : previews installation of AMP without modifying WAR file");
         System.out.println("   -nobackup  : indicates that no backup should be made of the WAR\n");
         System.out.println("———————————————————–\n");
+        System.out.println("uninstall: Uninstalls the module a AMP file(s) from an Alfresco WAR file.");
+        System.out.println("usage: uninstall <moduleName> <WARFileLocation> [options]  \n");
+        System.out.println("   -preview   : previews uninstallation of AMP without modifying WAR file");
+        System.out.println("———————————————————–\n");
         System.out.println("list:  Lists all the modules currently installed in an Alfresco WAR file.");
         System.out.println("usage: list <WARFileLocation>\n");
         System.out.println("———————————————————–\n");

cgonzalez
Champ on-the-rise
Champ on-the-rise
But if i do that when i start alfresco i receive the following WARNING:


WARN  [org.alfresco.repo.module.ModuleServiceImpl] A previously-installed module 'myModule (version 0.0)is not present in your distribution.

zomurn
Champ in-the-making
Champ in-the-making
Same message.
Can't we still uninstall an AMP ? (I change the name of the module and the old "named" module still appears in the startup logs).

cerberos
Champ in-the-making
Champ in-the-making
Hi all,
same message here trying to uninstall a module. I restore an old backup, but the log warns about some missing module. Is possible to avoid this annoying message?

Thanks

cerberos
Champ in-the-making
Champ in-the-making
Hi, i discovered that Alfresco creates nodes in the repository about installed modules. In example i found using the query browser this node:

Primary Path:   /{http://www.alfresco.org/model/system/1.0}system-registry/{http://www.alfresco.org/system/modules/1.0...
with 4 children, corrisponding to my old 4 modules, now uninstalled.
So, how can i try to delete this nodes? Cant'use the UI, because it's not possible to browse the "system store". Probably using the REST API, but don't know how to send quickly a DELETE request via http.

Someone can help me?

Thank you

manish
Champ in-the-making
Champ in-the-making
OK. I was looking for this, but seems that it's not yet implemented.

vjalilov
Champ in-the-making
Champ in-the-making
To downgrade a module:
After you install an "older" version of the module into alfresco.war, when you start alfresco it will throw an error saying downgrading modules is not supported and not start.  Smiley Sad

To "fix" this problem, connect to your database (mine was a MySQL DB) and run these SQL commands(at your own risk, after you have backed up your DB  Smiley Very Happy)
1. This is so you know what the qname_id means in the latter tables:

mysql> SELECT * FROM alf_qname WHERE alf_qname.id IN (34, 59, 62, 101, 102 );
+—–+———+——-+——————+
| id  | version | ns_id | local_name       |
+—–+———+——-+——————+
|  34 |       1 |     3 | name             |
|  59 |       1 |     5 | container        |
|  62 |       1 |     5 | store_root       |
| 101 |       1 |     8 | currentVersion   |
| 102 |       1 |     8 | installedVersion |
+—–+———+——-+——————+
5 rows in set (0.00 sec)

2. Dig deeper into the 101 and 102 qname_ids:

mysql> SELECT node_id, qname_id, locale_id, string_value FROM alf_node_properties WHERE qname_id IN (101, 102) ORDER BY node_id;
+———+———-+———–+————–+
| node_id | qname_id | locale_id | string_value |
+———+———-+———–+————–+
| 2345995 |      101 |         1 | 2.1.13       |
| 2345995 |      102 |         1 | 2.1.13       |
| 3216313 |      101 |         1 | 2.4.0        |
| 3216313 |      102 |         1 | 2.4.0        |
| 3216314 |      101 |         1 | 2.4.0        |
| 3216314 |      102 |         1 | 2.4.0        |
| 3216315 |      101 |         1 | 2.4.0        |
| 3216315 |      102 |         1 | 2.4.0        |
+———+———-+———–+————–+
8 rows in set (0.00 sec)
I want to change 2.4.0 version of my module, so the first 2 lines are irrelevant. I have 3 node_ids of interest (3216313, 3216314, 3216315). Yours will/should be different.


3. See what modules they are:

mysql> SELECT node_id, qname_id, locale_id, string_value FROM alf_node_properties WHERE node_id IN (3216313, 3216314, 3216315) ;
+———+———-+———–+——————-+
| node_id | qname_id | locale_id | string_value      |
+———+———-+———–+——————-+
| 3216313 |       34 |         1 | content-********* |
| 3216313 |      101 |         1 | 2.4.0             |
| 3216313 |      102 |         1 | 2.4.0             |
| 3216314 |       34 |         1 | ******-content    |
| 3216314 |      101 |         1 | 2.4.0             |
| 3216314 |      102 |         1 | 2.4.0             |
| 3216315 |       34 |         1 | ******-alfresco   |
| 3216315 |      101 |         1 | 2.4.0             |
| 3216315 |      102 |         1 | 2.4.0             |
+———+———-+———–+——————-+
9 rows in set (0.00 sec)
So, I have 3 modules installed. ******-alfresco is the one I want to change/downgrade to version 2.1.1


4. update the DB. You should by now have Alfresco down, and your database backed up!

mysql> UPDATE alf_node_properties SET string_value = '2.1.1' WHERE node_id = 3216315 AND qname_id IN (101, 102);
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2  Changed: 2  Warnings: 0

5. Verify the glory of our achievement 😎 :

mysql> SELECT node_id, qname_id, locale_id, string_value FROM alf_node_properties WHERE node_id = 3216315 ;
+———+———-+———–+—————–+
| node_id | qname_id | locale_id | string_value    |
+———+———-+———–+—————–+
| 3216315 |       34 |         1 | ******-alfresco |
| 3216315 |      101 |         1 | 2.1.1           |
| 3216315 |      102 |         1 | 2.1.1           |
+———+———-+———–+—————–+
3 rows in set (0.00 sec)

mpeters
Champ in-the-making
Champ in-the-making
This made my day. Thanks!!!

This worked great for me with the exception of the 'currentVersion' and 'installedVersion' id.  Instead of 101 and 102, my vals were 222 and 223.  After that, everything worked great.

I got the different IDs by running:


select local_name, id from alf_qname where  local_name in ('currentVersion', 'installedVersion')


FWIW, I am running 4.2.f CE against a Postgres database.

Thanks for sharing this solution!!