Hello,
Just a post concerning the immutable document : Documentum doesn’t allow the modification of an immutable document:
DQL> SELECT r_object_id, status, r_immutable_flag FROM my_huo_type WHERE ref_document = 'JavaLu_test_immutable'; r_object_id status r_immutable_flag ================ ====== ====== 090xxxxxxxxxxxx8 1 1 (1 rows affected)
If, we try to change the status attribute of this document, we will obtain the following error:
DQL> UPDATE my_huo_type OBJECTS set status=6 where r_object_id ='090xxxxxxxxxxxx8'; [DM_QUERY_F_UP_SAVE]fatal: "UPDATE: An error has occurred during a save operation." [DM_SYSOBJECT_E_CANT_SAVE_IMMUTABLE]error: "Cannot save MY_DOC_OBJ_NAME_1 since it is immutable."
However, even on an immutable document, some attributes/actions could be done: change of ACL, content moving, modification done via SQL instructions like last modification date,…etc.
When the above error occurs, the simple « workarround solution » is:
1. set the r_immutable_flag attribute to FALSE,
2. do the modifications on the document,
3. finally set again the r_immutable_flag attribute to its previous TRUE value.
Here, the steps of this « workarround solution »:
1. Check the value of r_immutable_flag attributwe of the document :
DQL> SELECT r_immutable_flag from my_huo_type where r_object_id ='090xxxxxxxxxxxx8'; r_immutable_flag 1
2. IF r_immutable_flag=TRUE OR r_immutable_flag=1 THEN,
Solution 1 : via DQL
- Update the flag r_immutable_flag=FALSE via DQL
DQL> EXECUTE exec_sql WITH query= 'update dm_sysobject_s set r_immutable_flag=0 where r_object_id= ''090xxxxxxxxxxxx8'''; OR DQL> EXECUTE exec_sql WITH query= 'update dm_sysobject_s set r_immutable_flag=''F'' where r_object_id= ''090xxxxxxxxxxxx8''';
- Update the target « status » attribute via DQL
DQL> UPDATE my_huo_type OBJECTS set status=6 where r_object_id ='090xxxxxxxxxxxx8';
- Update the flag r_immutable_flag=TRUE (previous value) via DQL
DQL> EXECUTE exec_sql WITH query= 'update dm_sysobject_s set r_immutable_flag=1 where r_object_id= ''090xxxxxxxxxxxx8'''; OR DQL> EXECUTE exec_sql WITH query= 'update dm_sysobject_s set r_immutable_flag=''T'' where r_object_id= ''090xxxxxxxxxxxx8''';
Solution 2 : via API
- Update the flag r_immutable_flag=FALSE via API
APi>set,c,090xxxxxxxxxxxx8,r_immutable_flag 0 ... OK
- Update the target « status » attribute via API
API>set,c,090xxxxxxxxxxxx8,status 6 ... OK
- Update the flag r_immutable_flag=TRUE (previous value) via API
API>set,c,090xxxxxxxxxxxx8,r_immutable_flag 1 ... OK
- Save the document via API
API>save,c,090xxxxxxxxxxxx8 ... OK
Solution 3 : Change the behaviour of docbase in order to ignore value of the r_immutable_flag flag when the ‘status’ attribute of the type ‘my_huo_type’ is modified.
select r_object_id, type_name, label_text, nls_key, i_ignore_immutable, ignore_immutable from dmi_dd_attr_info where type_name = 'my_huo_type' and attr_name IN ('status','status_free_to_change'); r_object_id = 6axxxxxxxxxxxxxxa0 type_name = my_huo_type label_text = status nls_key = en i_ignore_immutable = 0 ignore_immutable = 0 r_object_id = 6ayyyyyyyyyyyyyy87 type_name = my_huo_type label_text = status_free_to_change nls_key = en i_ignore_immutable = 0 ignore_immutable = 1
The value of the dmi_dd_attr_info.ignore_immutable determines if the attribute is free for changes even if the object is immutable. In either case i_ignore_immutable doesn’t make any difference. In the above example the status_free_to_change attribute is free for changes.
update dmi_dd_attr_info object set ignore_immutable = T where type_name = 'my_huo_type' and attr_name = 'status';
3. ELSE (IF r_immutable_flag=FALSE OR r_immutable_flag=0 THEN),
- See the logs,
- Check if the target version of document is lock :
# Get the all versions DQL>SELECT mytype.r_version_label, mytype.r_lock_owner, mytype.r_object_id, mytype.status, mytype.acl_domain, mytype.acl_name FROM my_huo_type (ALL) mytype WHERE mytype.ref_doc = 'JavaLu_test_immutable' order by r_creation_date desc, r_version_label desc ENABLE (ROW_BASED); ... # unlock the version API>unlock,c,090xxxxxxxxxxc1 ...etc
In practice via DFC / Java code:
EXAMPLE 1 : Simple example
for (String documentId : documentIds) { try { LOGGER.info(documentId + " : update content (" + countCurrent + "/" + countTotal + ")... "); IDfDocument document = (IDfDocument) session.getObject(new DfId(documentId)); boolean isImmutable = document.isImmutable(); if (isImmutable) { document.setBoolean("r_immutable_flag", false); document.save(); } document.setSubject(SUBJECT_ANONYMIZED); document.setContentType("pdf"); document.setFile(docFolder + File.separator + canal + "-encrypted.pdf"); document.save(); if (isImmutable) { document.setBoolean("r_immutable_flag", true); document.save(); } LOGGER.info(documentId + " : [OK]"); } catch(Exception e) { LOGGER.error(documentId + " : [KO: error to update content]", e); } countCurrent++; }
EXAMPLE 2 : Complete example with transaction and rollback on last modifier, last modification date and immutable flag
private void setPreviousValuesOfLastModifAttributesBySQL(IDfSession session, String currObjectId, IDfTime previousModifyDateTime, String previousModifier) throws Throwable{ StringBuilder sql = new StringBuilder(); sql.append("UPDATE ").append(session.getDocbaseOwnerName()).append(".DM_SYSOBJECT_S"); sql.append(" SET "); sql.append(" R_MODIFIER = '").append(previousModifier).append("',"); DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); sql.append(" R_MODIFY_DATE = to_date('").append(dateFormat.format(previousModifyDateTime.getDate())).append("', 'DD-MM-YYYY HH24:MI:SS')"); sql.append(" WHERE R_OBJECT_ID = '").append(currObjectId).append("'"); IDfApplyExecSQL dfApplyExecSQL = (IDfApplyExecSQL) DfAdminCommand.getCommand(DfAdminCommand.APPLY_EXEC_SQL); dfApplyExecSQL.setQuery(sql.toString()); IDfCollection coll = dfApplyExecSQL.execute(session); try { if (coll.next()) { IDfValue dfValue = coll.getValueAt(0); if (!dfValue.asBoolean()) { throw new RuntimeException(""); } } else { throw new RuntimeException(""); } } finally { if(coll!=null){ coll.close(); } } }
…..
private void setValuesToImmutableAttributeBySQL(IDfSession session, String currObjectId, boolean bValue) throws Throwable{ StringBuilder sql = new StringBuilder(); sql.append("UPDATE ").append(session.getDocbaseOwnerName()).append(".DM_SYSOBJECT_S"); sql.append(" SET "); sql.append(" R_IMMUTABLE_FLAG = '").append(bValue?"1":"0").append("' "); sql.append(" WHERE R_OBJECT_ID = '").append(currObjectId).append("'"); IDfApplyExecSQL dfApplyExecSQL = (IDfApplyExecSQL) DfAdminCommand.getCommand(DfAdminCommand.APPLY_EXEC_SQL); dfApplyExecSQL.setQuery(sql.toString()); IDfCollection coll = dfApplyExecSQL.execute(session); try { if (coll.next()) { IDfValue dfValue = coll.getValueAt(0); if (!dfValue.asBoolean()) { throw new RuntimeException(""); } } else { throw new RuntimeException(""); } } finally { if(coll!=null){ coll.close(); } } }
…..
IDfSession session = ...; IDfCollection documents = ...; while (documents.next()) { String currObjectId = null; boolean previousImmutableFlag = false; boolean isTransactionalSession = false; boolean noErrorWithCurrentDocument = false; try { if (!session.isTransactionActive()) { session.beginTrans(); isTransactionalSession = true; } currObjectId = documents.getString("r_object_id"); // Get and store the value of r_modify_date AND r_modifier BEFORE the changes IDfTime previousModifyDateTime = documents.getTime("r_modify_date"); String previousModifier = documents.getString("r_modifier"); String aContentType = documents.getString("a_content_type"); // excel12book previousImmutableFlag = documents.getBoolean("r_immutable_flag"); //Mise à jour du flag « r_immutable_flag=FALSE » via SQL if(previousImmutableFlag){ setValuesToImmutableAttributeBySQL(session, currObjectId, false); } // #### Appying changements //.... // Setting of the previous value for r_modify_date AND r_modifier because the attachment of aspect needs a SAVE action on document. // So, Content server overrides r_modifer and r_modify_date informations. setPreviousValuesOfLastModifAttributesBySQL(session, currObjectId, previousModifyDateTime, previousModifier); noErrorWithCurrentDocument = true; } catch(Throwable th) { Throwable rootCause = ExceptionUtils.getRootCause(th); if(rootCause!=null){ rootCause.printStackTrace(pw); }else{ th.printStackTrace(pw); } throw th; }finally{ //Mise à jour du flag « r_immutable_flag=TRUE » via SQL if(previousImmutableFlag){ setValuesToImmutableAttributeBySQL(session, currObjectId, true); } if (isTransactionalSession) { if (noErrorWithCurrentDocument) { session.commitTrans(); } else { session.abortTrans(); } } } }// end-while
That’s all!!!!
Huseyin OZVEREN