0

I encountered a stackoverflow error when I implement audit using AuditorAware. The code successfully gets the login username. However, @CreatedBy and @ModifiedBy should be the primary key of the user record and not the login username. I tried two versions of the code but both of them results to stackoverflow.

Version 1: Autowiring UserService

public class SpringSecurityAuditorAware implements AuditorAware<String> {

@Autowired
UserService userService;

@Override
public Optional<String> getCurrentAuditor() {

    Authentication auth = SecurityContextHolder.getContext().getAuthentication();

    if (auth == null || !auth.isAuthenticated()) return null;

    String loginName = auth.getPrincipal().toString();  
    UserDto user = userService.getUser(loginName);
    return Optional.of(user.getUserPk());
}}

Version 2: Using application context to get the bean

public class SpringSecurityAuditorAware implements AuditorAware<String> {

@Override
public Optional<String> getCurrentAuditor() {

    Authentication auth = SecurityContextHolder.getContext().getAuthentication();

    if (auth == null || !auth.isAuthenticated()) return null;

    String loginName = auth.getPrincipal().toString(); 
    UserService userService = (UserService)SpringApplicationContext.getBean("userServiceImpl");     
    UserDto user = userService.getUser(loginName);
    return Optional.of(user.getUserPk());
}

}

Here is the UserService code:

@Service
public class UserServiceImpl implements UserService {

@Autowired
UserRepository userRepository;

@Override
public UserDto getUser(String loginId) {
    UserEntity userEntity = userRepository.findByUserLoginId(loginId);
    
    if (userEntity == null) throw new UsernameNotFoundException(loginId);
    
    ModelMapper modelMapper = new ModelMapper();        
    UserDto returnValue = modelMapper.map(userEntity, UserDto.class);
    return returnValue;
}}

I included the screenshots of the debug for reference. Debug at Line: UserDto user = userService.getUser(loginName); Debug at Line: UserEntity userEntity = userRepository.findByUserLoginId(loginId); Basically, the code moves between these two lines, causing the infinite loop. Also, the error occurs when saving one-to-many or many-to-many entities (i.e., master-detail). There is no error when saving one-to-one bi-directional entities and a single entity.

Below is the error log:

java.lang.StackOverflowError: null
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152) ~[spring-tx-5.3.12.jar:5.3.12]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.12.jar:5.3.12]
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:145) ~[spring-data-jpa-2.5.6.jar:2.5.6]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.12.jar:5.3.12]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-5.3.12.jar:5.3.12]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.12.jar:5.3.12]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.12.jar:5.3.12]
at jdk.proxy2/jdk.proxy2.$Proxy116.findByUserLoginId(Unknown Source) ~[na:na]
at ph.com.absi.iibsv5.ws.service.impl.UserServiceImpl.getUser(UserServiceImpl.java:73) ~[classes/:na]
at ph.com.absi.iibsv5.ws.SpringSecurityAuditorAware.getCurrentAuditor(SpringSecurityAuditorAware.java:28) ~[classes/:na]
at jdk.internal.reflect.GeneratedMethodAccessor82.invoke(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.12.jar:5.3.12]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-5.3.12.jar:5.3.12]
at jdk.proxy2/jdk.proxy2.$Proxy127.getCurrentAuditor(Unknown Source) ~[na:na]
at java.base/java.util.Optional.map(Optional.java:260) ~[na:na]
at org.springframework.data.auditing.AuditingHandler.getAuditor(AuditingHandler.java:109) ~[spring-data-commons-2.5.6.jar:2.5.6]
at org.springframework.data.auditing.AuditingHandler.markModified(AuditingHandler.java:104) ~[spring-data-commons-2.5.6.jar:2.5.6]
at org.springframework.data.jpa.domain.support.AuditingEntityListener.touchForUpdate(AuditingEntityListener.java:112) ~[spring-data-jpa-2.5.6.jar:2.5.6]
at jdk.internal.reflect.GeneratedMethodAccessor83.invoke(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.hibernate.jpa.event.internal.ListenerCallback.performCallback(ListenerCallback.java:35) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.jpa.event.internal.CallbackRegistryImpl.callback(CallbackRegistryImpl.java:95) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.jpa.event.internal.CallbackRegistryImpl.preUpdate(CallbackRegistryImpl.java:69) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.event.internal.DefaultFlushEntityEventListener.invokeInterceptor(DefaultFlushEntityEventListener.java:369) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.event.internal.DefaultFlushEntityEventListener.handleInterception(DefaultFlushEntityEventListener.java:351) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.event.internal.DefaultFlushEntityEventListener.scheduleUpdate(DefaultFlushEntityEventListener.java:302) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:171) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:99) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:229) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:93) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]
at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:50) ~[hibernate-core-5.4.32.Final.jar:5.4.32.Final]

I hope you can help me with this error. Thank you for your time.

A Aragon
  • 1
  • 2

0 Answers0