You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@commons.apache.org by Scott Heaberlin <he...@gmail.com> on 2005/03/18 00:58:44 UTC

[JXPATH] StackOverflowError with xpath to Map object

Hello JXPath users -

Preface:  I am using JXPath release 1.2
My object graph is as follows:
Vector
index[1]: Hashtable, 3 entries, all String keyed. For 2 of the entries
the value is another String; for  one key the value is another
Hashtable with its own String keyed values.
index[2]: Vector, not relevant for this message.

It somewhat looks as follows (I hope this looks ok in your email client)

Vector
    [1] Hashtable
           KeyOne="SomeStringOne"
           KeyTwo="SomeStringTwo"
           KeyThree=Hashtable
                    KeyA="StringA"
                    KeyB="StringB"
                    KeyC="StringC" ... etc
    [2] Array
        [1]
        [2]
        [3]...etc


When I do a getValue() using the following xpaths:

.[1]/KeyOne
.[1]KeyTwo

I have no problems - this works as expected.

When I do a getValue() using 

.[1]/KeyThree/KeyA

I also have no problem - the result is "StringA"

When I do getValue() using ".[1]/KeyThree" I get a StackOverflowError.  

java.lang.StackOverflowError
        at org.apache.commons.jxpath.ri.model.beans.CollectionPointer.getValuePointer(CollectionPointer.java:98)
        at org.apache.commons.jxpath.ri.model.beans.CollectionPointer.testNode(CollectionPointer.java:202)
        at org.apache.commons.jxpath.ri.model.beans.CollectionPointer.testNode(CollectionPointer.java:202)
...

I see dozens of lines following in the stack trace all at
CollectionPointer.testNode(). Lots.


It appears that when my xpath evaluates to a specific element in the
"KeyThree" hashtable, there is no problem.  Trying to reference the
actual "KeyThree" object itself always causes the problem.

Ultimately I'm trying to perform an xpath function "size()" to receive
the size of the inner Hashtable keyed in the outer hashtable by
"KeyThree".  I've tried different xpaths:
.[1]/KeyThree/*
.[1]/KeyThree//
.[1]/KeyThree/

I've also tried writing my own static method and using xpath
"com.mypkg.MyClass.mapSize(.[1]/KeyThree)"  but I get the same result.
 During this approach I tried having the argument to my mapSize()
method be a Node, NodeSet, a Map, and finally ExpressionContext... but
in the debugger I never EVER make it to my method... the
StackOverflowError occurs before any breakpoints in my method.

Am I missing something?  Is there anyway I can either A) get a direct
reference to a non-empty hashtable in an object graph via xpath, or B)
write an xpath query that will cause JXPath to return me the size of
said hashtable?  I am unable to do either.

Thanks in advance for any help,

-- 


-Scott


Scott Heaberlin

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-user-help@jakarta.apache.org


Re: [JXPATH] StackOverflowError with xpath to Map object

Posted by Scott Heaberlin <he...@gmail.com>.
Dmitri - 

I patched a local copy of jxpath (CVS head) with your fix and my tests
and operations now all succeed.

Would you like me to file a bug report for this or will you?


Thanks again for all your help!

-Scott Heaberlin

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-user-help@jakarta.apache.org


Re: [JXPATH] StackOverflowError with xpath to Map object

Posted by Dmitri Plotnikov <dm...@apache.org>.
Scott,

After I added that additional vector to the vector, I was able to reproduce 
the problem you reported.

I fixed the issue by implementing the method CollectionPointer.testNode as 
follows:

    public boolean testNode(NodeTest test) {
        if (index == WHOLE_COLLECTION) {
            if (test == null) {
                return true;
            }
            else if (test instanceof NodeNameTest) {
                return false;
            }
            else if (test instanceof NodeTypeTest) {
                if (((NodeTypeTest) test).getNodeType() == 
Compiler.NODE_TYPE_NODE) {
                    return true;
                }
            }
            return false;
        }
        return getValuePointer().testNode(test);
    }

Now this test case seems to work correctly:

    /**
     * Scott Heaberlin's test - collection of collections
     */
    public void testCollectionPointer() {
        List list = new ArrayList();
        Map map = new HashMap();
        map.put("KeyOne", "SomeStringOne");
        map.put("KeyTwo", "SomeStringTwo");

        Map map2 = new HashMap();
        map2.put("KeyA", "StringA");
        map2.put("KeyB", "StringB");

        map.put("KeyThree", map2);
        list.add(map);

        List list2 = new ArrayList();
        list2.add("foo");
        list2.add(map);
        list2.add(map);
        list.add(list2);

        context = JXPathContext.newContext(list);

        assertEquals("SomeStringOne", context.getValue(".[1]/KeyOne"));
        assertEquals("StringA", context.getValue(".[1]/KeyThree/KeyA"));
        assertEquals(new Integer(3), 
context.getValue("size(.[1]/KeyThree)"));
        assertEquals(new Double(6.0), 
context.getValue("count(.[1]/KeyThree/*)"));
        assertEquals(new Double(3.0), 
context.getValue("count(.[1]/KeyThree/KeyA)"));
    }

Please let me know if this fixes the problem for you.

Thank you very much for your feedback.

Regards,

- Dmitri


----- Original Message ----- 
From: "Scott Heaberlin" <he...@gmail.com>
To: "Jakarta Commons Users List" <co...@jakarta.apache.org>
Sent: Friday, March 18, 2005 10:19 AM
Subject: Re: [JXPATH] StackOverflowError with xpath to Map object


> That structure at first seemed like what I was using (or at least the
> relevant part of the root structure from my JXPathContext).
>
> I ran your test locally and it succeeded.  I ran my test case again
> and it failed, in the same VM with the same classpath.
>
> The only difference in your test and mine is that my test has a second
> element in the outermost List - a list within a list.  Though the
> xpath query that is failing does not reference (or at least, should
> not) that part of the structure I nearly blew it off... but look what
> happens with your very own test case when I add another vector (like
> my own scenario):
>
> public void testCollectionPointer() {
>   List list = new ArrayList();
>
>   Map map = new HashMap();
>   map.put("KeyOne", "SomeStringOne");
>   map.put("KeyTwo", "SomeStringTwo");
>
>   Map map2 = new HashMap();
>   map2.put("KeyA", "StringA");
>   map2.put("KeyB", "StringB");
>
>   map.put("KeyThree", map2);
>
>   list.add(map);
>
>   list.add(new Vector(22));  // <-- NOTE: this is the only difference
>
>   context = JXPathContext.newContext(list);
>
>   System.out.println(context.getValue(".[1]/KeyOne"));
>   System.out.println(context.getValue(".[1]/KeyThree/KeyA"));
>   System.out.println(context.getValue(".[1]/KeyThree"));
>   System.out.println(context.getValue("count(.[1]/KeyThree/*)"));
> }
>
> When running this, I get:
>
> ------------- Standard Output ---------------
> SomeStringOne
> StringA
> {KeyB=StringB, KeyA=StringA}
> ------------- ---------------- ---------------
> Testcase: testCollectionPointer1(test.JXPathTest): Caused an ERROR
> null
> java.lang.StackOverflowError
>
>
> Note: there is no possibility of a circular reference, as that inner
> Vector is size 22 but has all null elements.
>
> Do you get the same result?
>
> Also - I tried the following xpath (calls Map::size) and I get the
> exact same result:
>
> context.getValue("size(.[1]/KeyThree/*)")
>
> Does this happen for you as well?  I had a co-worker verify the
> results in a different development environment (I'm running in
> JDK1.4.2_06, he was using an earlier JDK1.4 release).  We both get a
> stack overflow in the two scenarios (size() and count() )
>
>
> I appreciate the help!
>
> -Scott Heaberlin
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-user-help@jakarta.apache.org
>
>
>
> 



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-user-help@jakarta.apache.org


Re: [JXPATH] StackOverflowError with xpath to Map object

Posted by Scott Heaberlin <he...@gmail.com>.
That structure at first seemed like what I was using (or at least the
relevant part of the root structure from my JXPathContext).

I ran your test locally and it succeeded.  I ran my test case again
and it failed, in the same VM with the same classpath.

The only difference in your test and mine is that my test has a second
element in the outermost List - a list within a list.  Though the
xpath query that is failing does not reference (or at least, should
not) that part of the structure I nearly blew it off... but look what
happens with your very own test case when I add another vector (like
my own scenario):

public void testCollectionPointer() {
   List list = new ArrayList();

   Map map = new HashMap();
   map.put("KeyOne", "SomeStringOne");
   map.put("KeyTwo", "SomeStringTwo");

   Map map2 = new HashMap();
   map2.put("KeyA", "StringA");
   map2.put("KeyB", "StringB");

   map.put("KeyThree", map2);

   list.add(map);

   list.add(new Vector(22));  // <-- NOTE: this is the only difference

   context = JXPathContext.newContext(list);

   System.out.println(context.getValue(".[1]/KeyOne"));
   System.out.println(context.getValue(".[1]/KeyThree/KeyA"));
   System.out.println(context.getValue(".[1]/KeyThree"));
   System.out.println(context.getValue("count(.[1]/KeyThree/*)"));
}

When running this, I get:

------------- Standard Output ---------------
SomeStringOne
StringA
{KeyB=StringB, KeyA=StringA}
------------- ---------------- ---------------
Testcase: testCollectionPointer1(test.JXPathTest):	Caused an ERROR
null
java.lang.StackOverflowError


Note: there is no possibility of a circular reference, as that inner
Vector is size 22 but has all null elements.

Do you get the same result?

Also - I tried the following xpath (calls Map::size) and I get the
exact same result:

context.getValue("size(.[1]/KeyThree/*)")

Does this happen for you as well?  I had a co-worker verify the
results in a different development environment (I'm running in
JDK1.4.2_06, he was using an earlier JDK1.4 release).  We both get a
stack overflow in the two scenarios (size() and count() )


I appreciate the help!

-Scott Heaberlin

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-user-help@jakarta.apache.org


Re: [JXPATH] StackOverflowError with xpath to Map object

Posted by Dmitri Plotnikov <dm...@apache.org>.
Scott,

I was trying to follow your description and here's what I got:


public void testCollectionPointer() {
    List list = new ArrayList();

    Map map = new HashMap();
    map.put("KeyOne", "SomeStringOne");
    map.put("KeyTwo", "SomeStringTwo");

    Map map2 = new HashMap();
    map2.put("KeyA", "StringA");
    map2.put("KeyB", "StringB");

    map.put("KeyThree", map2);

    list.add(map);

    context = JXPathContext.newContext(list);

    System.out.println(context.getValue(".[1]/KeyOne"));
    System.out.println(context.getValue(".[1]/KeyThree/KeyA"));
    System.out.println(context.getValue(".[1]/KeyThree"));
    System.out.println(context.getValue("count(.[1]/KeyThree/*)"));
}

This printed:
   SomeStringOne
   StringA
   {KeyB=StringB, KeyA=StringA}
   2.0

What's the difference between what you do and what I do?

Regards,

- Dmitri

----- Original Message ----- 
From: "Scott Heaberlin" <he...@gmail.com>
To: "Jakarta Commons Users List" <co...@jakarta.apache.org>
Sent: Thursday, March 17, 2005 6:58 PM
Subject: [JXPATH] StackOverflowError with xpath to Map object


> Hello JXPath users -
>
> Preface:  I am using JXPath release 1.2
> My object graph is as follows:
> Vector
> index[1]: Hashtable, 3 entries, all String keyed. For 2 of the entries
> the value is another String; for  one key the value is another
> Hashtable with its own String keyed values.
> index[2]: Vector, not relevant for this message.
>
> It somewhat looks as follows (I hope this looks ok in your email client)
>
> Vector
>    [1] Hashtable
>           KeyOne="SomeStringOne"
>           KeyTwo="SomeStringTwo"
>           KeyThree=Hashtable
>                    KeyA="StringA"
>                    KeyB="StringB"
>                    KeyC="StringC" ... etc
>    [2] Array
>        [1]
>        [2]
>        [3]...etc
>
>
> When I do a getValue() using the following xpaths:
>
> .[1]/KeyOne
> .[1]KeyTwo
>
> I have no problems - this works as expected.
>
> When I do a getValue() using
>
> .[1]/KeyThree/KeyA
>
> I also have no problem - the result is "StringA"
>
> When I do getValue() using ".[1]/KeyThree" I get a StackOverflowError.
>
> java.lang.StackOverflowError
>        at 
> org.apache.commons.jxpath.ri.model.beans.CollectionPointer.getValuePointer(CollectionPointer.java:98)
>        at 
> org.apache.commons.jxpath.ri.model.beans.CollectionPointer.testNode(CollectionPointer.java:202)
>        at 
> org.apache.commons.jxpath.ri.model.beans.CollectionPointer.testNode(CollectionPointer.java:202)
> ...
>
> I see dozens of lines following in the stack trace all at
> CollectionPointer.testNode(). Lots.
>
>
> It appears that when my xpath evaluates to a specific element in the
> "KeyThree" hashtable, there is no problem.  Trying to reference the
> actual "KeyThree" object itself always causes the problem.
>
> Ultimately I'm trying to perform an xpath function "size()" to receive
> the size of the inner Hashtable keyed in the outer hashtable by
> "KeyThree".  I've tried different xpaths:
> .[1]/KeyThree/*
> .[1]/KeyThree//
> .[1]/KeyThree/
>
> I've also tried writing my own static method and using xpath
> "com.mypkg.MyClass.mapSize(.[1]/KeyThree)"  but I get the same result.
> During this approach I tried having the argument to my mapSize()
> method be a Node, NodeSet, a Map, and finally ExpressionContext... but
> in the debugger I never EVER make it to my method... the
> StackOverflowError occurs before any breakpoints in my method.
>
> Am I missing something?  Is there anyway I can either A) get a direct
> reference to a non-empty hashtable in an object graph via xpath, or B)
> write an xpath query that will cause JXPath to return me the size of
> said hashtable?  I am unable to do either.
>
> Thanks in advance for any help,
>
> -- 
>
>
> -Scott
>
>
> Scott Heaberlin
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-user-help@jakarta.apache.org
>
>
>
> 



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-user-help@jakarta.apache.org