JavaScriptUtils infinite loop

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

JavaScriptUtils infinite loop

Constantin G
When trying to use javascript inlining with a map that has another map embedded, org.thymeleaf.util.JavaScriptUtils gets into an infinite loop:

at org.thymeleaf.util.JavaScriptUtils.printMap(JavaScriptUtils.java:315)
        at org.thymeleaf.util.JavaScriptUtils.printObject(JavaScriptUtils.java:343)
        at org.thymeleaf.util.JavaScriptUtils.print(JavaScriptUtils.java:168)
        at org.thymeleaf.util.JavaScriptUtils.printKeyValue(JavaScriptUtils.java:324)
        at org.thymeleaf.util.JavaScriptUtils.printMap(JavaScriptUtils.java:315)
        at org.thymeleaf.util.JavaScriptUtils.printObject(JavaScriptUtils.java:343)
        at org.thymeleaf.util.JavaScriptUtils.print(JavaScriptUtils.java:168)
        at org.thymeleaf.util.JavaScriptUtils.printArray(JavaScriptUtils.java:205)
        at org.thymeleaf.util.JavaScriptUtils.print(JavaScriptUtils.java:157)
        at org.thymeleaf.util.JavaScriptUtils.printKeyValue(JavaScriptUtils.java:324)
        at org.thymeleaf.util.JavaScriptUtils.printMap(JavaScriptUtils.java:315)
        at org.thymeleaf.util.JavaScriptUtils.printObject(JavaScriptUtils.java:343)
Reply | Threaded
Open this post in threaded view
|

Re: JavaScriptUtils infinite loop

danielfernandez
Administrator
Hi,

I'm not able to reproduce your problem. There's nothing I can see in the code of JavaScriptUtils that could cause such infinite loop, and I've even tested javascript inlining for a Map<Map<String,String>,Map<String,String>> object, and it is printed OK...

Could it be that you have a reference loop in your Map? this could happen for example if an object in your map --be it key or value-- has a reference to the containing Map itself in any of its attributes, something like:

Map<String, MyObject> map = Map<String, MyObject>();

MyObject obj = new MyObject();
obj.setMyMap(map);

map.put("aKey", obj);

This would create an infinite loop when printing "map" because, when writing the "obj" object from one of its values, thymeleaf would find a property called "myMap" which value would be the initial map itself...

If your map does not have a structure similar to this, and you see no way in which such a reference loop could happen, could you give me more data about the kind of structure you are trying to inline?

Thanks,
Daniel.

Reply | Threaded
Open this post in threaded view
|

Re: JavaScriptUtils infinite loop

Constantin G
It's actually an enum value inside a map. Here is s simple test to reproduce:

import org.thymeleaf.util.JavaScriptUtils;
import java.util.HashMap;

public class Test {

    private static enum Choice {
        yes, no;
    }
    public static void main(String[] args) {

        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("key", Choice.yes);
        JavaScriptUtils.print(map);
    }
}
Reply | Threaded
Open this post in threaded view
|

Re: JavaScriptUtils infinite loop

FingolfinTEK
Actually, I too have encountered this problem, I used a list of Java beans which had an enum as one of it's properties, so it seems the problem is not limited to Maps.
Fingolfin like a shooting light
beneath a cloud, a stab of white,
sprang then aside, and Ringil drew
like ice that gleameth cold and blue,
his sword devised of elvish skill
to pierce the flesh with deadly chill.
Reply | Threaded
Open this post in threaded view
|

Re: JavaScriptUtils infinite loop

danielfernandez
Administrator
In fact, the problem is enums, not maps. Enums are not handled in any special way when inlined, and they are handled instead as normal Objects. The problem is they have a "declaringClass" property which exploration ends up creating the infinite loop.

I'll create a patch for this ASAP. Enums will be inlined in a similar way to general objects, so that the simplest enum will look like:

{ value: 'SOMETHING' }

If an enum has more than one property, then these will appear as usual object properties:

{ value: 'SOMETHING', someOtherValue: 'ANYTHING' }

If everything goes well, I'll upload a snapshot with this fix tomorrow.

Regards,
Daniel.
Reply | Threaded
Open this post in threaded view
|

Re: JavaScriptUtils infinite loop

danielfernandez
Administrator
A new snapshot version for 1.1.2 (1.1.2-SNAPSHOT) has been uploaded including a patch for this. See http://www.thymeleaf.org/faq.html#use-snapshot for learning how to use it.

I finally chose to represent enums in the following way:

  * Enums will be represented as javascript objects (like "{ 'a': 3}").
  * These objects will at least have two properties, called '$type' and '$name'. These properties will contain, respectively, the class name (without package) and name of the enum constant being inlined.
  * These JS objects will have a property for each additional property they might have in the Java side.

For example, the "Choice.yes" example before mentioned would render as:

    { '$type': 'Choice', '$name':'yes' }

If Choice had an additional attribute called "message", and the Choice.yes constant would have been created as:

Choice.yes("My choice is yes!")

...then it would render as:

    { '$type' : 'Choice', '$name' : 'yes', 'message' : 'My choice is yes!' }

I hope this fits your needs.

Regards,
Daniel.

Reply | Threaded
Open this post in threaded view
|

Re: JavaScriptUtils infinite loop

Constantin G
Thanks for the quick fix.