Skip to content

BeanPersistController will not be invoked if an M2M relation is updated #3652

@rPraml

Description

@rPraml

Hello Rob,

we use the BeanPersistController on various places to intercept save/update events on bean.
Now, we noticed, when a M2M (and only a M2M) will be modified, the bean itself does not get dirty and no PersistController will be invoked.

Some context

To give you some context, we need to implement "row level security" for some entities in our DB.
For example, if you imagine an issue tracking system, not everyone should be able to see every issue.
This all depends on several factors:

  • which group the ticket belongs to (issueGroup - M2O - the issueGroup defines the access members)
  • was the ticket assigned to a specific person (assignee - M2O - the issue itself defines assignee as access member)
  • other partipiciants - an additional M2M relation may define more access members

To keep things fast, we build a cache using a PersistController. It collects all access members (that are normally a handfull) and stores them in a compressed form, so that we can then use an efficient SQL query like
select * from issue i where exists (select 1 from issue_permission_cache c where c.issue_id = i and c.user_id = :current_user)

This all works as we want it to, as long as no M2M relations are involved (and the procedure how we build the cache should not be the topic of discussion here)

We have code in our permission controller like this:

public void addUpdate(final BeanPersistRequest<?> request) {
     Set<String> changedProps = request.database().beanState(request.bean()).changedProps()
     if (changedProps .contains("issueGroup")) {
           // the issue was moved to an other issue group, so
           // we need to recalculate the cache accordingly
     }
     if (changedProps .changedProps().contains("assignee")) {
           // new assignee added -> make sure, the assignee can access the issue
     }
     if (changedProps.changedProps().contains("partipiciants")) {
           // partipiciants - a M2M was changed -> update the cache
     }
}

Problem
As mentioned above, the permissionController will not be invoked, when only a M2M like partipiciants will be updated.
The reason for this, that the issue bean does not get technically dirty, as no modification occurs.
Sample code:

issue.getPartipiciants().add(user)
DB.markDirty(issue); // workaround
DB.save(issue); // will call persistAdapter.addUpdate, only when bean gets dirty

Workaround
Ensure, that the bean will get dirty, when only a M2M will be modified. (This will also solve an other problem, as we want that LastModified will be updated on the issue)

Question
Is there a reliable callback mechanism in ebean, that tracks M2M changes or is this "markDirty" the only workaround I currently have?

Thanks.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions