class BuggyTagLib {def applicationData = { attrs ->...out << "<div class='u'>${campaign.betaTesters.size()}</div>"...}}
class Campaign {
static hasMany = [ betaTesters: CampaignUser ]
int betaTestersCount
static mapping = {
betaTestersCount formula: '(select count(*) from campaign_betatesters b where b.campaign_id = id)'
}
}
class Campaign {
static hasMany = [ betaTesters: CampaignUser ]
int getBetaTestersCount() {
betaTesters == null ? 0 : withSession {
it.createFilter(betaTesters, 'select count(*)').uniqueResult()
}
}
}
class BootStrap {
def init = { injectMappedCollectionCountMethod() }
private void injectMappedCollectionCountMethod() {
def classesWithCollections = grailsApplication.domainClasses.findAll { it.hasProperty('hasMany') }.collect { it.clazz }
classesWithCollections.each {
it.hasMany.each { colName, colClass ->
String countMethodName = 'get' + colClass.subString(0,1).toUppercase() + colClass.subString(1) + 'Count'
it.metaClass."$countMethodName" << { ->
withSession { session ->
delegate."$colName" == null ? 0 :
session.createFilter(delegate."$colName", 'select count(*)').uniqueResult()
}
}
}
}

DON'T REPEAT YOUR FAILURES
¿Puedo mejorar el proceso de desarrollo para que este error no vuelva a producirse?
Puede tratarse de cualquier restricción (por simple que sea) incorporada al diseño de un proceso para evitar errores o detectarlos lo antes posible.



"AOP was invented to be a move away from explicit metaprogramming to a direct semantics for some of the kinds of problems metaprogramming could be used for. It helps to raise abstraction level."import org.codehaus.groovy.runtime.callsite.Callsite;import org.hibernate.collection.PersistentCollection;public aspect GormCollectionSize extends AbstractPokaYoke {public pointcut violation():sizeOnPersistentCollection(Object, Callsite);public sizeOnPersistentCollection(Object receiver, Callsite callsite):GroovyPointCuts.groovyCall(receiver, callsite) &&if ((receiver instanceof PersistentCollection) &&("size".equals(callsite.getName())));}
public aspect GroovyPointCuts {public pointcut groovyCall(Object receiver, CallSite callsite):call(public Object CallSite.call*(..)) &&target(callsite) &&args(receiver);}
public abstract aspect AbstractPokaYoke implements PokaYoke {public abstract pointcut violation();public abstract String getDescription();before(): violation() {warn(thisJoinPoint);}...}
Be careful when calling an annotated method within a service when the annotation settings are different.
Because you're underneath the proxy it's a direct method call, and any checks that the proxy would have done will be bypassed.
@Trasactionalvoid someMethod() {anotherMethod()}@Transactional(propagation=Propagation.REQUIRES_NEW)void anotherMethod() {...}
public aspect ServiceTransactionalServiceBypassed extends AbstractPokaYoke {public pointcut violation():proxyBypassed(Object, Transactional, Object, Transactional);public pointcut proxyByPassed(Object caller, Transactional callerAnnotation,Object callee, Transactional calleeAnnotation):cflowbelow(annotatedPublicServiceMethod(caller, callerAnnotation)) &&annotatedPublicServiceMethod(callee, calleeAnnotation) &&if ((caller.getClass() == callee.getClass()) &&(!callerAnnotation.equals(calleeAnnotation)) &&(!isCalledThroughProxy()));...}
public boolean isCalledThroughProxy() {StackTraceElement[] elements = Thread.currentThread().getStackTrace();StackTraceElement callerElement = elements[3];return ClassUtils.isCglibProxyClassName(callerElement.getClassName());}
public pointcut annotatedPublicServiceMethod(Object receiver, Transactional ann):GrailsPointCuts.publicServiceMethod() && this(receiver) && @annotation(ann);
public aspect GrailsPointCuts {public pointcut inService(): within(..*Service);public pointcut publicServiceMethod():inService() && execution(public * *.*(..));...}
public aspect GormLayeringViolation extends AbstractPokaYoke {public pointcut violation():GrailsPointCuts.isDomain() &&GormPointCuts.gormMethod() &&!cflowbelow(GrailsPointCuts.isService());}
public pointcut gormMethod():saveMethod() || ...;public pointcut saveMethod():execution(public Object save()) ||execution(public Object save(java.util.Map)) ||execution(public Object save(boolean));
public pointcut isDomain():@within(grails.persistence.Entity);