Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] How to create "conditional ITDs"?

Hi Matthew,
I've done that to introduce @Id and @Version if not provided on JPA classes. You need to use the -XhasMember compiler option, and then I wrote it this way :

public aspect InstallIdByDefault {

	/**
	 * Marker interface for beans receiving the default id.
	 *
	 * @author Simone Gianni <simoneg@xxxxxxxxxx>
	 */
	public static interface WithDefaultId {
		
	}
	
	declare parents : ((@Entity *) && !(@NoId *) && !hasmethod(@(Id||EmbeddedId) public * get*()) && !hasfield(@(Id||EmbeddedId) * *)) implements WithDefaultId;
	
	/**
	 * The default provided id field.
	 */
	private long WithDefaultId.id;
	
	/**
	 * Getter for the default id.
	 * @return The entity id.
	 */
	@Id
	@GeneratedValue
	public long WithDefaultId.getId() {
		return id;
	}
	
	/**
	 * Setter for the default id.
	 * @param newId The entity id.
	 */
	void WithDefaultId.setId(long newId) {
		id = newId;
	}
	
}

You can find the complete aspects (also for @Version) here : http://svn.apache.org/repos/asf/labs/magma/trunk/database-jpa/src/main/java/org/apache/magma/database/openjpa/

Simone



Matthew Adams wrote:
Hi all,

I was wondering how it might be possible to achieve what I'm calling a
conditional inter-type declaration.

Here's a simple auditing example.  For a JPA entity, I want to
introduce a @PrePersist method if and only if the target class doesn't
have one because it's an error to have multiple @PrePersist methods on
an entity.  If it already has a @PrePersist method, I want to execute
advice after the target instance's @PrePersist method is invoked by
the JPA implementation.  Same for @PreUpdate.

The example below will work for Person, but not for Document --
Document will end up with two @PrePersist methods.  How can I refactor
this to work for both?

========
@Entity
public class Document {
  // ...
  @PrePersist
  private void prePersist() { /* ... */ }
}
========
@Entity
public class Person {
  // ...
}
========
// works only for an @Entity that DOES NOT define a @PrePersist or a
@PreUpdate method
public aspect AuditingItd {
	private interface Auditable {
	}

	declare parents:  (@javax.persistence.Entity *) implements Auditable;

	@Column(name = "updated")
	private Date Auditable.updated;

	@PrePersist
	private void Auditable.auditablePrePersist() {
		updated = new Date();
	}

	@PreUpdate
	private void Auditable.auditablePreUpdate() {
		updated = new Date();
	}
}
=========

-matthew



--
Simone Gianni            CEO Semeru s.r.l.           Apache Committer
http://www.simonegianni.it/



Back to the top