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
