cancel
Showing results for 
Search instead for 
Did you mean: 

How to get the proper exception message to the CMIS client

signjoy
Confirmed Champ
Confirmed Champ

Hi,

We have a policy that moves the document according to the metadata called state id. So if the state id is 123456. It will move the document to 123 -> 456 -> 123456 -> c.pdf

As and when document comes into  Alfresco through JAVA CMIS call, we check using NodeService whether the document is exists or not at the destination location. (123 -> 456 -> 123456 ->) . If it exists then we trow DuplicateChildNodeNameException like below.

message = "Duplicate child name not allowed c.pdf";
throw new DuplicateChildNodeNameException(docRef, ContentModel.ASSOC_CONTAINS, docName, new Exception(message));

The problem is even though we set the proper message in the exception, we are not getting the same message on the CMIS side. Instead we get below message...

Exception : 05280006 Failed to execute transaction-level behaviour public abstract void org.alfresco.repo.node.NodeServicePolicies$OnUpdateNodePolicy.onUpdateNode(org.alfresco.service.cmr.repository.NodeRef) in transaction 6f796a47-cdde-4930-b83a-c12fcf9de17d

Without policy code if I upload a document x.pdf into folder A and again I try to reupload a same document when x.pdf to folder A, it gives me proper exception on the CMIS side saying duplicate content or content already exists.  

How can I show the same message that Alfresco policy throws to the CMIS client?

Thank you in advance

1 ACCEPTED ANSWER

afaust
Legendary Innovator
Legendary Innovator

You will only get called 20 times for 20 properties if some code in Alfresco is extremely inefficient and calling NodeService.setProperty for each property instead of calling NodeService.addProperties once for all properties. Unfortunately, it looks like the Alfresco CMIS implementation is that inefficient (I just checked the source).

But still, you should check in the code of your policy if the change is actually interesting for you, and such a check can be implement quite efficiently with two gets on the before/after maps and a single call to EqualsHelper.nullSafeEquals to check for a change/no-change.

Alfresco will always recommend using TRANSACTION_COMMIT because they have to deal with a lot of unqualified 3rd-party / customer developers that do not know how to properly / efficiently implement an EVERY_EVENT policy. I just see too many problems with TRANSACTION_COMMIT in almost every customer project where a non-professional (i.e. someone with little Alfresco development experience) is working on behaviour code, because the people know even less about properly using that frequency than they regarding to EVERY_EVENT.

View answer in original post

6 REPLIES 6

afaust
Legendary Innovator
Legendary Innovator

You will never get the proper exception message from a transaction-level policy (bound using NotificationFrequency.TRANSACTION_COMMIT) to any client - CMIS or otherwise. All exceptions from such policies are wrapped and only via a stacktrace (not available to clients) could you get at the real cause.

This is one of the many reasons I typically recommend to NOT use transaction-level policies at all, and none of the policies I write are ever transaction-level. I do use custom transaction listeners combined with regular EVERY_EVENT policies on occasion to aggregate multiple events into a single processing step at the end of a transaction, but at least if a listener throws an exception, it is not wrapped excessively on the way up the call-chain.

signjoy
Confirmed Champ
Confirmed Champ

Axel Faust‌ 

If I keep policy for EVERY_EVENT then it will be called multiple times for a single file. I need to keep checking the metadata whether they are updated or not that I want to manipulate. So if I have 20 metadata then the code will run 20 times.. is that a good practice ?

But yes I have tested with EVERY_EVENT and it shows the actual exception thrown by the policy...

Thank you

afaust
Legendary Innovator
Legendary Innovator

You will only get called 20 times for 20 properties if some code in Alfresco is extremely inefficient and calling NodeService.setProperty for each property instead of calling NodeService.addProperties once for all properties. Unfortunately, it looks like the Alfresco CMIS implementation is that inefficient (I just checked the source).

But still, you should check in the code of your policy if the change is actually interesting for you, and such a check can be implement quite efficiently with two gets on the before/after maps and a single call to EqualsHelper.nullSafeEquals to check for a change/no-change.

Alfresco will always recommend using TRANSACTION_COMMIT because they have to deal with a lot of unqualified 3rd-party / customer developers that do not know how to properly / efficiently implement an EVERY_EVENT policy. I just see too many problems with TRANSACTION_COMMIT in almost every customer project where a non-professional (i.e. someone with little Alfresco development experience) is working on behaviour code, because the people know even less about properly using that frequency than they regarding to EVERY_EVENT.

signjoy
Confirmed Champ
Confirmed Champ

Thanks Axel Faust‌ for your time and information...

As we have lot of properties and CMIS calls I would rather stick to TRANSACTION_COMMIT option. But I understand why I was not able to catch the actual error message from the policy.

douglascrp
World-Class Innovator
World-Class Innovator

Interesting approach, and I didn't know that class.

By

I do use custom transaction listeners combined with regular EVERY_EVENT policies on occasion to aggregate multiple events into a single processing step at the end of a transaction

Do you mean something like this? Alfresco – Implementing delete behavior | Programming and So 

Do you have any sample code you can share using the approach you described?

Thank you.

Hi,

All you need to do is set the NotificationFrequency to EVERY_EVENT in the initialization method of your policy.

public class CustomDocPolicy implements NodeServicePolicies.OnCreateNodePolicy,
        NodeServicePolicies.OnUpdateNodePolicy,
        NodeServicePolicies.BeforeDeleteNodePolicy {

public void initialise() {
this.policyComponent.bindClassBehaviour(QName.createQName(NamespaceService.ALFRESCO_URI, "onCreateNode"),
CustomConstants.TYPE_BASE_DOC, new JavaBehaviour(this, "onCreateNode", Behaviour.NotificationFrequency.EVERY_EVENT));
}



}