cancel
Showing results for 
Search instead for 
Did you mean: 

User id in act_hi_attachment is always null

sistemasmunicip
Champ in-the-making
Champ in-the-making
Hello,
using Java api to add attachments to a Task, the field user_id_ in the act_hi_attachment is never set.
As for the Attachment java class, it doesn't have an user_id attribute either.
I was hoping to control the users that can read/delete an attachment usin the user id.
I tried with Authorization.authenticatedUser and IdentityLink but the field is alwas null.
I'm using PostgreSQL and Activiti 5.14
Is it possible to save - retrieve user id from act_hi_attachment?

Thanks in advance
Esteban
14 REPLIES 14

frederikherema1
Star Contributor
Star Contributor
If you're adding attachments using the API, make sure the logic that calls the API is managing the "current user" the engine uses.
This is done by setting a (internally thread-local) value using org.activiti.engine.impl.identity.Authentication:



try {
  Authentication.setAuthenticatedUserId("kermit");

  // Your code here
} finally {
  Authentication.setAuthenticatedUserId(null); 
}

You can perhaps add it to a shared base-class of your application (or a servlet-filter) to have this done transparently.

sistemasmunicip
Champ in-the-making
Champ in-the-making
Frederik, thanks for the answer.
I had tried with Authentication.setAuthenticatedUserId but the result is the same. (in the first post I wrote the class wrong - Authorization.authenticatedUser) Here, the code for a test that attachs a file but without user id
<code>
                // ActProcessEngine is a custom class that returns default process engine if exists, or creates a new one
  ProcessEngine processEngine = ActProcessEngine.getProcessEngine();
  Authentication.setAuthenticatedUserId("my.user");
 
  File f = new File("/home/Descargas/5577.pdf");
 
  TaskService ts = processEngine.getTaskService();
   
  try {
   ts.createAttachment("application/pdf", "42592", "42221", "pruebaUsuario.pdf", "prueba con authenticated user", new FileInputStream(f));
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  }

  Authentication.setAuthenticatedUserId(null);
  processEngine.close();
</code>

thanks again. Greetings
Esteban

balsarori
Champ on-the-rise
Champ on-the-rise
AttachmentEntity doesn't have a userId property and USER_ID_ of ACT_HI_ATTACHMENT is not mapped in Attachment.xml to any property.

frederikherema1
Star Contributor
Star Contributor
Good point balsarori. The user who creates the attachment is stored in a "comment":


public void createAttachmentComment(String taskId, String processInstanceId, String attachmentName, boolean create) {
    if (isHistoryEnabled()) {
      String userId = Authentication.getAuthenticatedUserId();
      CommentEntity comment = new CommentEntity();
      comment.setUserId(userId);
      comment.setType(CommentEntity.TYPE_EVENT);
      comment.setTime(ClockUtil.getCurrentTime());
      comment.setTaskId(taskId);
      comment.setProcessInstanceId(processInstanceId);
      if(create) {
        comment.setAction(Event.ACTION_ADD_ATTACHMENT);
      } else {
        comment.setAction(Event.ACTION_DELETE_ATTACHMENT);
      }
      comment.setMessage(attachmentName);
      getSession(CommentEntityManager.class).insert(comment);
    }
  }

sistemasmunicip
Champ in-the-making
Champ in-the-making
I know the AttachmentEntity doesn't have a user_id_ property, but I was thinking I could query directly to the table in the worst case. I will try the comment and let you know.
Thanks for your answers.
Esteban

sistemasmunicip
Champ in-the-making
Champ in-the-making
Hello. here's an update:
I got it working by querying the TaskService via getProcessInstanceComments(processInstanceId) - once the task is completed the attachment is related to the process instance - and then matching with the taskId (will see what to do when a task has more than one attachment)

Maybe I'm approaching it the wrong way, but here's the scenario:
I have a user task that has a listener for the onComplete event. That listener generates a pdf and attachs it to the task. This task is a part of an administrative process and I want  only the user that generated the attachment to be able to delete it, or someone with admin permission only (it is not saved as a file but as a byte stream on the act_ge_bytearray table).
So, when I saw the user_id_ field on the attachment table I thought - problem solved.

As balsarori pointed out,  AttachmentEntity doesn't have a user_id_ property, but there's still the field on the table. The comment table obviously has no attachment_id field - that would be wrong, but saves "AddAttachment" as action_ , and the file name as message_ . I'm curious as to why I can't retrieve any of the 2 fields through the Comment class (no getAction() or getMessage() methods ) - I can use getFullMessage() but it's null.

In my opinion, it would be much easier to save the user_id to the act_hi_attachment table, but then again, is my approach wrong?

Thanks
Esteban

frederikherema1
Star Contributor
Star Contributor
Esteban,

Comments and Attachments are a bit of "entities on the side", not 100% critical to the BPMN behaviour (as opposed to tasks, identity-links, executions, …). So the comments and attachments are added to facilitate working around tasks.

However, when I see your requirements, I think a better solution would be to use a process-variable for this and make your services smart enough to allow users to modify/delete that specific variable.

sistemasmunicip
Champ in-the-making
Champ in-the-making
Frederik:
I understand your point, will try to work out the solution.
Any chance, in future versions, of user_id_ being inserted in act_hi_attachment?
Thanks
Esteban

balsarori
Champ on-the-rise
Champ on-the-rise
@Frederik

I also had a similar requirement. I solved it by adding a userId property to AttachmentEntity (getUserId method to Attachment interface) and mapped it to Attachment.xml.

If you are interested I can create a pull request for this.