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:
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.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 ); } } }
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


Reply With Quote
