I've written a web service using Jersey and Spring. I am using Spring AOP to perform entity validation for some service methods. Everything seems to work fine, except for every few hours or so, a java.util.ConcurrentModificationException is thrown from the Spring AOP code. I can't consistently reproduce the issue yet. More precisely, the exception is caused by code in the AspectJ libraries used by Spring AOP. I am using Spring AOP version 3.1.2.RELEASE and version 1.6.8 of the AspectJ libraries. I am not sure if there is an error in my code, or if there is a bug in Spring AOP, or the AspectJ libraries.

I am using the @AspectJ style declaration for my aspect. Here is the code for it:

Code:
@Aspect
@Component
public class SpringAOPValidationAspect implements ValidationAspect
{
    private Validator validator;

    @Autowired
    public void setValidator(Validator validator) {
        this.validator = validator;
    }

    @Pointcut("execution(* com.sensus.da.service.DomainEntityService.*(*)) && args(entity)")
    private void updateServiceMethod(Object entity) {}

    @Pointcut("execution(* com.sensus.da.data.core.IGenericRepository.save(*)) && args(entity)")
    private void createRepositoryMethod(Object entity) {}

    @Pointcut("execution(* com.sensus.da.ui.infrastructure.EntityAssembler.fromDto(*)) && args(dto)")
    private void fromDtoMethod(Object dto) {}

    @Pointcut("execution(* com.sensus.da.service.RemoteUpdateService.*(..)) && args(entity,..)")
    private void publishJobServiceMethod(Object entity) {}

    @Pointcut(value = "updateServiceMethod(entity) || createRepositoryMethod(entity) || fromDtoMethod(entity) || " +
            "publishJobServiceMethod(entity)", argNames = "entity")
    private void saveEntityMethod(Object entity) {}

    @Pointcut("execution(* com.sensus.da.data.core.IGenericRepository.delete(*)) && args(domainEntity)")
    private void deleteEntityMethod(IDomainEntity<?> domainEntity) {}

    @Before(value = "saveEntityMethod(entity)", argNames = "entity")
    public void validateSave(Object entity)
    {
        validate(entity);
    }

    @Before(value = "deleteEntityMethod(domainEntity)", argNames = "domainEntity")
    public void validateDelete(IDomainEntity<?> domainEntity)
    {
        validate(domainEntity, DeleteChecks.class);
    }

    public <T> void validate(T entity, Class<?>... groups)
    {
        final Set<ConstraintViolation<T>> constraintViolations = validator.validate(entity, groups );
        if ( constraintViolations.size() > 0 )
        {
            Set<ConstraintViolation<?>> propagatedViolations =
                    new HashSet<ConstraintViolation<?>>( constraintViolations.size() );
            Set<String> classNames = new HashSet<String>();
            for ( ConstraintViolation<?> violation : constraintViolations )
            {
                propagatedViolations.add( violation );
                classNames.add( violation.getLeafBean().getClass().getName() );
            }
            StringBuilder builder = new StringBuilder();
            builder.append( "Validation failed for classes " );
            builder.append( classNames );
            builder.append( " during " );
            // builder.append( operation.getName() );
            builder.append( " time for groups " );
            //builder.append( toString( groups ) );
            builder.append( "\nList of constraint violations:[\n" );
            for (ConstraintViolation<?> violation : constraintViolations) {
                builder.append( "\t" ).append( violation.toString() ).append("\n");
            }
            builder.append( "]" );

            throw new ConstraintViolationException(
                    builder.toString(), propagatedViolations
            );
        }
    }
}
The service and repository classes are fairly standard, so I don't think I need to show them here. I am using hibernate in the data access layer.

I will post the exception and stack trace information in a follow up post to this, as it puts me over the character limit. I am fairly new to Spring AOP, so I may be missing something, even though I've read through all the documentation. Thanks in advance for your help.

Brendan