Wednesday, June 20, 2012

Is it possible to delete users? - RTC 4.0

By definition, users can not be deleted, only users can be archived. That tells us the online help of RTC 4.0 (Managing Users) :

Archiving and restoring users

It seems that users are not physically deleted from the repository because they can leave the database inconsistent as they may have associated objects such as WI, plans, reports, streams, etc.

But what about a procedure that creates/load users with their users id wrong?
Diving for the Java API I found that there is a public interface com.ibm.team.repository.client.IContributorManager with the following method:
 
void deleteContributor (IContributorHandle contributorHandle,
                        org.eclipse.core.runtime.IProgressMonitor monitor)
                        throws TeamRepositoryException

Interesting is not it?

Carefully, I develop a process to delete repository users.
Environment:
- Windows 2003 Server sp2
- IBM WebSphere Application Server 7.0 fp 19
- IBM DB2 9.5
- IBM Rational Team Concert 4.0 

The process is performed on the repository JTS.

Apparently, users have been deleted from the repository, but when looking at the trace file (ccm.log), I have the following error:
WARN ility.contributor.internal.ContributorSynchronizer  - CRJAZ1765E An error occurred while synchronizing user data with the Jazz Team Server.
com.ibm.team.repository.common.ItemNotFoundException: CRJAZ0215I The following record was not found in the database: com.ibm.team.repository.common.model.impl.ContributorRecordHandleImpl@ecc0ecc (stateId: [UUID _cmTyJLYsEeGak91zCxBafg], itemId: [UUID _cmKBJ7YsEeGak91zCxBafg], origin: <unset>, immutable: <unset>) .........

Does the process have deleted users correctly? This is what I feared, that the database can be inconsistent.
The funny thing is that only affects users who have associated objects such as WI, plans, reports, streams, etc.

I made ​​a Java program that searches the tables and fields with the value of this UUID. The result, there are records with this value in the following tables:
- REPOSITORY.DELETED_ITEMS
- COMPATIBILITYPACK.URI_MAPPING

I make the following query on the database:
SELECT * FROM REPOSITORY."DELETED_ITEMS" WHERE ITEM_UUID = '_cmKBJ7YsEeGak91zCxBafg';
SELECT * FROM COMPATIBILITYPACK.."URI_MAPPING" WHERE ITEM_ITEM_ID = '_cmKBJ7YsEeGak91zCxBafg';

 
The tables do not have anything related then I delete the record of the database:
DELETE FROM REPOSITORY."DELETED_ITEMS" WHERE ITEM_UUID = '_cmKBJ7YsEeGak91zCxBafg';
DELETE FROM COMPATIBILITYPACK."URI_MAPPING" WHERE ITEM_ITEM_ID = '_cmKBJ7YsEeGak91zCxBafg';
 

I delete the trace file and restart the JTS and CCM servers checking that no errors appears.

Conclusions: 
- In this version of RTC, it seems that this method should not be used for user management

Recommendations:
- Run the users batch mechanism in test environments

Java program (Using DB2 database):

package  jif.develop.db;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

 
/** 
 * @author Jorge Iglesias
 */
public class FindDB2ItemID {
        public static void main(String[] args) {
                // RTC 4.0 vmware
                String server = "xxx.xxx.xxx.xx"; //
                String alias = "CCM";
                int portNumber = 50000;
                String userId = "xxxx";
                String password = "xxxx";

                try {
                        String url = "jdbc:db2://" + server + ":" + portNumber + "/" + alias;
                        Class.forName("com.ibm.db2.

jcc.DB2Driver").newInstance();
                        Properties props = new Properties();
                        props.setProperty("user", userId);
                        props.setProperty("password", password);

                        // In Partitioned Database environment, set this to the node number
                        // to which you wish to connect (leave as "0" in non-Partitioned
                        // Database environment)
                        props.setProperty("
CONNECTNODE", "0");
                        Connection conn = DriverManager.getConnection(
url, props);
                        // enable transactions
                        conn.setAutoCommit(false);

                        DatabaseMetaData metadata=conn.getMetaData();
            System.out.println(metadata.
getDriverName());
            System.out.println("Driver version: "
+metadata.getDriverVersion());

            System.out.println("Database product name: "
+metadata.
getDatabaseProductName());
            System.out.println("Database product version: "
+metadata.
getDatabaseProductVersion());
            System.out.println("Database version: "
+metadata.
getDatabaseMajorVersion());
            System.out.println("." +metadata.
getDatabaseMinorVersion());
            String[] names = {"TABLE"};
            ResultSet schemas = metadata.getSchemas();
                        List<String> schemaNames = new ArrayList<String>();
            while (schemas.next()) {
                String tableName = schemas.getString("TABLE_
SCHEM");
                schemaNames.add(tableName);
            }

            for (String stringSchema : schemaNames) {
                ResultSet tables = metadata.getTables(null,
stringSchema,
null, names);

                        List<String> tablesNames = new ArrayList<String>();

                while (tables.next()) {
                    String tableName = tables.getString("TABLE_NAME")
;
                                tablesNames.add(tableName);
                }

                for (String stringTable : tablesNames) {
                        System.out.println("*** SCHEMA : " + stringSchema + "
***");
                        System.out.println("*** TABLE : " + stringTable + "
***");
                        Statement statement = conn.createStatement();
                                ResultSet resultset = statement.executeQuery("SELECT * FROM "
+ stringSchema + ".\""+stringTable+"\"");

                                ResultSetMetaData metadataTable =
resultset.getMetaData();
                                int noOfColumns = metadataTable.getColumnCount()
;
                                //Ids examples:
                                //   comp = "_6tXCELYoEeGak91zCxBafg";
                                //   comp = "_c8qcprYsEeGak91zCxBafg";
                                //   comp = "_cmKBJ7YsEeGak91zCxBafg";
                                String comp = "Unassigned";

                                while (resultset.next()) {
                                        for (int i = 1; i <= noOfColumns; i++) {
                                                String rsValue = resultset.getString(i);
                                                if (rsValue != null) {
                                                        if (comp.compareToIgnoreCase(
rsValue) == 0) {
                                                                System.err.println("FOUND ON SCHEMA: " + stringSchema);
                                                                System.err.println("FOUND ON TABLE: " + stringTable);
                                                        }
                                                }
                                        }
                                }
                        }
                        }

            // makes all changes made since the previous commit/rollback
permanent
                // and releases any database locks currrently held by the
Connection.
                conn.commit();

                // immediately disconnects from database and releases JDBC
resources
                conn.close();

                } catch (Exception e) {
                        // TODO Bloque catch generado automáticamente
                        e.printStackTrace();
                }
        }
}

No comments:

Post a Comment