Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] How to advise setters in JPA entities using AOP?

I have tried to answer that under http://stackoverflow.com/a/24839202/1082681 if anyone is interested.

Bottom line: set() pointcuts are not enough here, you need to do manual bookkeeping for which collections/maps are assigned to which object members of interest. I think my solution is rather ugly, but it was fun to develop. Hopefully someone else can come up with something better.
-- 
Alexander Kriegisch
http://scrum-master.de


Eric B schrieb am 16.07.2014 18:51:

> I've posted this question on StackOverflow (http://stackoverflow.com/q/24786391/827480 <http://stackoverflow.com/q/24786391/827480> ), but am sending it here as well as not everyone monitors StackOverflow.
> 
> 
>  have the need to log any changes to fields in an entity - whether it is a String change, or addition/deletion to a collection/map.
> 
> Given a JPA entity with a bunch of primitive fields, it is fairly trivial to write an pointcut that will intercept any set(..) methods on the fields.
> 
> However, where I am stuck is how to write the pointcut to handle Collections/Sets/Embedded/etc.
> 
> Given the following entity:
> 
> 
> @Entity
> public class Provider implements Serializable {
> 
>     @Id
>     @GeneratedValue(strategy = GenerationType.AUTO)
>     @Column(name = "id")
>     private Long id;
> 
> 
>     private String name;
> 
>     @Column(name="type", nullable=false)
>     @Enumerated(EnumType.STRING)
>     private ProviderType providerType;
> 
> 
>     @ManyToMany
>     private List<Contact> contacts;
> 
>     @Embedded
>     private Validity validity;
> 
>    // setters and getters omitted for brevity
> 
> }
> 
> 
> where Contact is a simple entity with a bunch of primitive fields and Validity is a non-entity object with some primitive fields.
> 
> The following pointcut will intercept all set() methods in the class:
> 
> 
> pointcut fieldSetter() : set(!static !final !transient * *.Provider) && args(val) && target(o);
> 
> 
> to which I can write a before/after/around advice.
> 
> 
> before( Object val, Object o) : fieldSetter{
>   String fieldName = thisJoinPointStaticPart.getSignature().getName();
>   System.out.println( "Object being changed: " + o.toString() );
>   System.out.println( "New Value for: " + fieldname + " is: " + v.toString() );
> }
> 
> 
> But how do I handle that case for an Embedded object or a Collection? For an Embedded object, if I just put my advice around the setter method in the object, how do I know which is the parent object that is actually being modified/persisted?
> 
> And in the case of collections/sets/maps/etc, how do I advise against the add/remove methods? What I need to end up doing is advising the getCollection().add() methods as well as the getCollection.remove() methods. But I can't seem to figure out a good way.
> 
> 
> Thanks,
> 
> Eric
> 
>


Back to the top