-1

Class "Quotation" and class "Item" are related with class "QuotationJoinItem". and they are all annotated with "@Audited" so that manage log of changing of entity. but when I try to get revisions of "Quotation" by specific id. Quotation and QuotationJoinItem are call each other infinite. Could you introduce any solution?

Quotation.kt

@Entity(name = "quotation")
@Audited
data class Quotation (
    //... some other fields ...

        @OneToMany(mappedBy = "quotation", cascade = [CascadeType.PERSIST])
        @AuditMappedBy(mappedBy ="quotation")
        var items: MutableList<QuotationJoinItem>? = null

): BaseEntity(), Serializable

QuotationJoinItem.kt

@Entity("quotation_join_item")
@Audited
data class QuotationJoinItem (
    // ... some other fields

        @ManyToOne
        @JsonBackReference
        @JoinColumn(name="quotation_id")
        var quotation: Quotation,

        @ManyToOne
        @JoinColumn(name="item_id")
        @Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)
        var item: Item,

):BaseEntity(), Serializable

Item.kt

@Entity(name="item")
data class Item(
    //... It has no reference about Quotation or QuotationJoinItem table.
): BaseEntity(), Serializable

through property [quotation_AUD] [quotation_join_item_AUD] table generated.

application.properties

# other configuration

spring.jpa.hibernate.ddl-auto=update

and insert logic operated well. and each *_AUD table has own log(history).

but, problem occurred when i'm trying to retrieve log data as below process.

QuotationRepository.kt

@Repository
interface QuotationRepository: JpaRepository<Quotation, Int>, QuotationRepositoryCustom, RevisionRepository<Quotation, Int, Int>{
    //some other funtion
}

QuotationService.kt

@Service
class QuotationService (
    // some other arguments of constructor

    private val quotationRepository: QuotationRepository 
){

}
    // some other function

    @Transactional
    fun findRevision(id: Int): Revisions<Int, Quotation> {
        return quotationRepository.findRevisions(id) //!!problem occured here.
    }

that process generated error like this.


org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.StackOverflowError
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1054)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:853)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.StackOverflowError
    at com.factorysunny.mrtmes.model.CodeCategory.hashCode(CodeCategory.kt)
    at com.factorysunny.mrtmes.model.Code.hashCode(Code.kt)
    at com.factorysunny.mrtmes.model.Employee.hashCode(Employee.kt)
    at com.factorysunny.mrtmes.model.User.hashCode(User.kt)
    at com.factorysunny.mrtmes.model.Quotation.hashCode(Quotation.kt)
    at com.factorysunny.mrtmes.model.QuotationJoinItem.hashCode(QuotationJoinItem.kt)
    at java.util.AbstractList.hashCode(AbstractList.java:541)
    at org.hibernate.envers.internal.entities.mapper.relation.lazy.proxy.CollectionProxy.hashCode(CollectionProxy.java:131)
    at com.factorysunny.mrtmes.model.Quotation.hashCode(Quotation.kt)
    at com.factorysunny.mrtmes.model.QuotationJoinItem.hashCode(QuotationJoinItem.kt)
    at java.util.AbstractList.hashCode(AbstractList.java:541)
    at org.hibernate.envers.internal.entities.mapper.relation.lazy.proxy.CollectionProxy.hashCode(CollectionProxy.java:131)
    at com.factorysunny.mrtmes.model.Quotation.hashCode(Quotation.kt)
    at com.factorysunny.mrtmes.model.QuotationJoinItem.hashCode(QuotationJoinItem.kt)
    at java.util.AbstractList.hashCode(AbstractList.java:541)
    at org.hibernate.envers.internal.entities.mapper.relation.lazy.proxy.CollectionProxy.hashCode(CollectionProxy.java:131)
    at com.factorysunny.mrtmes.model.Quotation.hashCode(Quotation.kt)
    at com.factorysunny.mrtmes.model.QuotationJoinItem.hashCode(QuotationJoinItem.kt)
    at java.util.AbstractList.hashCode(AbstractList.java:541)
    at org.hibernate.envers.internal.entities.mapper.relation.lazy.proxy.CollectionProxy.hashCode(CollectionProxy.java:131)
    at com.factorysunny.mrtmes.model.Quotation.hashCode(Quotation.kt)
    at com.factorysunny.mrtmes.model.QuotationJoinItem.hashCode(QuotationJoinItem.kt)
    at java.util.AbstractList.hashCode(AbstractList.java:541)
    at org.hibernate.envers.internal.entities.mapper.relation.lazy.proxy.CollectionProxy.hashCode(CollectionProxy.java:131)
    at com.factorysunny.mrtmes.model.Quotation.hashCode(Quotation.kt)
    at com.factorysunny.mrtmes.model.QuotationJoinItem.hashCode(QuotationJoinItem.kt)
    at java.util.AbstractList.hashCode(AbstractList.java:541)
    at org.hibernate.envers.internal.entities.mapper.relation.lazy.proxy.CollectionProxy.hashCode(CollectionProxy.java:131)
    at com.factorysunny.mrtmes.model.Quotation.hashCode(Quotation.kt)
    at com.factorysunny.mrtmes.model.QuotationJoinItem.hashCode(QuotationJoinItem.kt)
//... and above three sentences shows on and on. infinite loop.

Thanks for check this question. Though it is poor english, Thanks a lot for caring it.

coldMater
  • 31
  • 4
  • Can you paste the whole mapping? `@OneToMany(mappedBy="quotation")` is not refleced in child – Andronicus Nov 29 '19 at 06:26
  • @Andronicus I'm sorry. I made a mistake. I updated source code of question. Could you check it again? Is their any more information needed? – coldMater Nov 29 '19 at 07:37

1 Answers1

0

It's been solved!

I used "data class" as entity. That was the problem.

It overrides hashCode() method automatically.

Hash code of "Quotation" class references "QuotationJoinItem". And then, Hash code of "QuotationJoinItem" class references "Quotation". This way, They referenced cyclic each other.

There was two solutions.

Solution 1. I Just deleted "data" keyword from the "data class" of the entity.

Solution 2. I Moved @OneToMany variable(in this question, "items") to field instead of constructor.

Please reference my coworker's question. Thanks.

coldMater
  • 31
  • 4
  • hi, i got the same problem but in my entity, i use "Public Class EntityName" when i remove Public word, the other class can't access my Entity Class, what should i do? – Ke Vin Jun 21 '20 at 09:45
  • 1
    Thanks for visiting and remaining your comment to this question. It seems you already got answer from another Question [hibernate-envers-how-to-get-the-log-history-properly](https://stackoverflow.com/questions/62495740/hibernate-envers-how-to-get-the-log-history-properly). So I linked your QUESTION LINK here. To whom suffering with same problem. Thanks for helping get enhanced principle. – coldMater Jul 07 '20 at 15:42