I have made a simple crud program.
I have used Spring audit
Everything works fine to the moment:
When I post a new "Inventory" there is no problem, but when I try to update it, I got this error
I 've got long not seen StackOverFlowError
the thing is that when I add a new object to my db, it finds user by login in repository,
with the class:
public User findUserByLogin(String login){
return userRepository.findByLogin(login);
}
public User getThisUser(){
return findUserByLogin(request.getUserPrincipal().getName());
}
Repository:
@Query("select u from User u where lower(u.login) = lower(?1) ")
User findByLogin(String login);
when I update object that already exists, it throws null, and trying to find something it stucks.
Did I forget about something?
I don't add the DTO's , I think that the class has no matter here. (I think :) )
@Entity
@EntityListeners({AuditingEntityListener.class})
public class Inventory extends BaseEntity{
@Embedded
private EntityDescription entityDescription;
private BigDecimal price;
public EntityDescription getEntityDescription() {
return entityDescription;
}
public void setEntityDescription(EntityDescription entityDescription) {
this.entityDescription = entityDescription;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
}
Base Entity:
@MappedSuperclass
public class BaseEntity extends AbstractAuditable<User, Long> {
@Version
private Long version;
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
@Override
public String toString() {
return "BaseEntity{" +
"version=" + version +
'}';
}
}
@Service
public class UserService {
private final HttpServletRequest request;
private final UserRepository userRepository;
private final UserRoleRepository userRoleRepository;
public UserService(HttpServletRequest request,
UserRepository userRepository,
UserRoleRepository userRoleRepository) {
this.request = request;
this.userRepository = userRepository;
this.userRoleRepository = userRoleRepository;
}
public List<User> findAll(){
return userRepository.findAll();
}
public User findUserByLogin(String login){
return userRepository.findByLogin(login);
}
public User getThisUser(){
return findUserByLogin(request.getUserPrincipal().getName());
}
}
@GetMapping("/inventory")
public List<InventoryDTO> allInventory(){
return inventoryService.findAll();
}
@PostMapping("/inventory")
public InventoryDTO addInventory(@RequestBody InventoryDTO inventoryDTO){
return inventoryService.add(inventoryDTO);
}
@GetMapping("/inventory/{id}")
public InventoryDTO getInventoryById(@PathVariable Long id){
return inventoryService.findById(id);
}
@DeleteMapping("/inventory/{id}")
public List<InventoryDTO> deleteItem(@PathVariable Long id){
inventoryService.remove(id);
return inventoryService.findAll();
}
@PostMapping("/inventory/{id}")
public InventoryDTO updateInventory(@PathVariable Long id, @RequestBody InventoryDTO inventoryDTO){
return inventoryService.update(id, inventoryDTO);
}
}
And the error:
java.lang.StackOverflowError: null
at java.base/java.net.URL.<init>(URL.java:605) ~[na:na]
at java.base/java.net.URL.<init>(URL.java:553) ~[na:na]
at java.base/jdk.internal.loader.URLClassPath$FileLoader.getResource(URLClassPath.java:1222) ~[na:na]
at java.base/jdk.internal.loader.URLClassPath.getResource(URLClassPath.java:317) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:718) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:644) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602) ~[na:na]
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) ~[na:na]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
at java.base/java.lang.ClassLoader.defineClass1(Native Method) ~[na:na]
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016) ~[na:na]
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:151) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:823) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:721) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:644) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602) ~[na:na]
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) ~[na:na]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1533) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]
at org.hibernate.query.internal.AbstractProducedQuery.getSingleResult(AbstractProducedQuery.java:1581) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]
at org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:196) ~[spring-data-jpa-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:88) ~[spring-data-jpa-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:154) ~[spring-data-jpa-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:142) ~[spring-data-jpa-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor$QueryMethodInvoker.invoke(QueryExecutorMethodInterceptor.java:195) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:152) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:130) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367) ~[spring-tx-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) ~[spring-tx-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:149) ~[spring-data-jpa-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at com.sun.proxy.$Proxy102.findByLogin(Unknown Source) ~[na:na]
at com.teamcompetencymatrix.www.service.UserService.findUserByLogin(UserService.java:31) ~[classes/:na]
at com.teamcompetencymatrix.www.service.UserService.getThisUser(UserService.java:35) ~[classes/:na]
at com.teamcompetencymatrix.www.config.AuditorAwareImpl.getCurrentAuditor(AuditorAwareImpl.java:24) ~[classes/:na]
at org.springframework.data.auditing.AuditingHandler.lambda$touchAuditor$6(AuditingHandler.java:193) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at java.base/java.util.Optional.map(Optional.java:258) ~[na:na]
at org.springframework.data.auditing.AuditingHandler.touchAuditor(AuditingHandler.java:191) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at org.springframework.data.auditing.AuditingHandler.lambda$touch$0(AuditingHandler.java:165) ~[spring-data-commons-2.3.4.RELEASE.jar:2.3.4.RELEASE]
at java.base/java.util.Optional.map(Optional.java:258) ~[na:na]
The solution was in UserRepository
I have added a @Transactional
annotation
The problem was with finding an auditor. It was a problem with transactions, so making a new one solved the problem.
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Query("select u from User u where lower(u.login) = lower(?1) ")
User findAuditorByLogin(String login);
This is a working solution, but maybe there are better.