spring-soy-view icon indicating copy to clipboard operation
spring-soy-view copied to clipboard

Infinite Loop in DefaultToSoyDataConverter when model contains BindingResult

Open solidjb opened this issue 9 years ago • 2 comments

Spring can add a BindingResult object into the model for objects in the model that are not primitive or collections. Unfortunately if this happens, DefaultToSoyDataConverter blows the stack. When DefaultToSoyDataConverter creates a pojo map from the BindingResult objects, it adds an entry with the key 'model', and a value of the entire model which essentially starts the whole recursive stack over again. It eventually works its way through the model until it gets to the BindingResult again, infinite loop...

Here is a simple test case that reproduces this error. (I put it into pl.matisoft.soy.data.DefaultToSoyDataConverterTest)


    @Test
    public void testNestedObjectInfiniteLoopBug() throws Exception {
        ModelAndView mav = new ModelAndView("test-view");
        PojoTest nestedReference = new PojoTest();

        mav.addObject("top-level", nestedReference);
        mav.addObject("binding", new DirectFieldBindingResult(nestedReference, "nested"));

        Object results = objectToSoyDataConverter.toSoyCompatibleMap(mav);
    }

Running the above test produced the following results :


Tests run: 15, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.141 sec (ReflectiveOperationException.java:89)
    at java.lang.reflect.InvocationTargetException.(InvocationTargetException.java:72)
    at sun.reflect.GeneratedMethodAccessor11.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at pl.matisoft.soy.data.DefaultToSoyDataConverter.pojoToMap(DefaultToSoyDataConverter.java:145)
    at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:126)
    at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:102)
    at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:129)
    at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:102)
    at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:129)
    at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:102)
    at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:129)
    at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:102)
    at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:129)
    at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:102)
...
    at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:129)
    at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:102)
    at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:129)
    at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:102)


Results :

Tests in error: 
   » StackOverflow

Tests run: 131, Failures: 0, Errors: 1, Skipped: 0

I am not sure about the best way to deal with this. We could add explicit code to deal with BindingResults, but I am not sure that is the best solution...

solidjb avatar May 19 '15 14:05 solidjb

I am aware of this, this is why I have this https://github.com/matiwinnetou/spring-soy-view/blob/master/spring-soy-view/src/main/java/pl/matisoft/soy/data/adjust/ModelAdjuster.java, this basically allows to filter out the model passed to DefaultToSoyDataConverter class.

matiwinnetou avatar May 28 '15 19:05 matiwinnetou

How do I fix that? It worked with POJOs, but since I'm using Spring Data JPA, it stackoverflows:

2016-08-09 04:39:23.388 [qtp1327127443-25] [DEBUG] o.s.w.s.DispatcherServlet - Could not complete request org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.StackOverflowError at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:986) ~[spring-webmvc-4.3.1.RELEASE.jar:4.3.1.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) ~[spring-webmvc-4.3.1.RELEASE.jar:4.3.1.RELEASE] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.1.RELEASE.jar:4.3.1.RELEASE] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) [spring-webmvc-4.3.1.RELEASE.jar:4.3.1.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:687) [javax.servlet-api-3.1.0.jar:3.1.0] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.1.RELEASE.jar:4.3.1.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [javax.servlet-api-3.1.0.jar:3.1.0] at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:751) [jetty-servlet-9.2.1.v20140609.jar:9.2.1.v20140609] at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:566) [jetty-servlet-9.2.1.v20140609.jar:9.2.1.v20140609] at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) [jetty-server-9.2.1.v20140609.jar:9.2.1.v20140609] at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:578) [jetty-security-9.2.1.v20140609.jar:9.2.1.v20140609] at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:221) [jetty-server-9.2.1.v20140609.jar:9.2.1.v20140609] at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1111) [jetty-server-9.2.1.v20140609.jar:9.2.1.v20140609] at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:498) [jetty-servlet-9.2.1.v20140609.jar:9.2.1.v20140609] at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:183) [jetty-server-9.2.1.v20140609.jar:9.2.1.v20140609] at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1045) [jetty-server-9.2.1.v20140609.jar:9.2.1.v20140609] at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) [jetty-server-9.2.1.v20140609.jar:9.2.1.v20140609] at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:199) [jetty-server-9.2.1.v20140609.jar:9.2.1.v20140609] at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:109) [jetty-server-9.2.1.v20140609.jar:9.2.1.v20140609] at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:98) [jetty-server-9.2.1.v20140609.jar:9.2.1.v20140609] at org.eclipse.jetty.server.Server.handle(Server.java:461) [jetty-server-9.2.1.v20140609.jar:9.2.1.v20140609] at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:284) [jetty-server-9.2.1.v20140609.jar:9.2.1.v20140609] at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:244) [jetty-server-9.2.1.v20140609.jar:9.2.1.v20140609] at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:534) [jetty-io-9.2.1.v20140609.jar:9.2.1.v20140609] at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:607) [jetty-util-9.2.1.v20140609.jar:9.2.1.v20140609] at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:536) [jetty-util-9.2.1.v20140609.jar:9.2.1.v20140609] at java.lang.Thread.run(Thread.java:745) [na:1.8.0_25] Caused by: java.lang.StackOverflowError: null at java.beans.WeakIdentityMap.get(WeakIdentityMap.java:56) ~[na:1.8.0_25] at java.beans.ThreadGroupContext.getContext(ThreadGroupContext.java:57) ~[na:1.8.0_25] at java.beans.Introspector.getBeanInfo(Introspector.java:167) ~[na:1.8.0_25] at pl.matisoft.soy.data.DefaultToSoyDataConverter.pojoToMap(DefaultToSoyDataConverter.java:135) ~[spring-soy-view-1.25.4.jar:na] at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:122) ~[spring-soy-view-1.25.4.jar:na] at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:106) ~[spring-soy-view-1.25.4.jar:na] at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:125) ~[spring-soy-view-1.25.4.jar:na] at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:125) ~[spring-soy-view-1.25.4.jar:na] at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:106) ~[spring-soy-view-1.25.4.jar:na] at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:125) ~[spring-soy-view-1.25.4.jar:na] at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:125) ~[spring-soy-view-1.25.4.jar:na] at pl.matisoft.soy.data.DefaultToSoyDataConverter.toSoyCompatibleObjects(DefaultToSoyDataConverter.java:106) ~[spring-soy-view-1.25.4.jar:na]

lilalinux avatar Aug 09 '16 10:08 lilalinux