Return-Path: Delivered-To: apmail-jakarta-commons-dev-archive@www.apache.org Received: (qmail 42506 invoked from network); 28 Nov 2005 02:29:07 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 28 Nov 2005 02:29:07 -0000 Received: (qmail 86035 invoked by uid 500); 28 Nov 2005 02:29:05 -0000 Delivered-To: apmail-jakarta-commons-dev-archive@jakarta.apache.org Received: (qmail 86009 invoked by uid 500); 28 Nov 2005 02:29:05 -0000 Mailing-List: contact commons-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Help: List-Post: List-Id: "Jakarta Commons Developers List" Reply-To: "Jakarta Commons Developers List" Delivered-To: mailing list commons-dev@jakarta.apache.org Received: (qmail 85998 invoked by uid 99); 28 Nov 2005 02:29:04 -0000 X-ASF-Spam-Status: No, hits=0.6 required=10.0 tests=NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [192.87.106.226] (HELO ajax.apache.org) (192.87.106.226) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 27 Nov 2005 18:29:04 -0800 Received: by ajax.apache.org (Postfix, from userid 99) id 33326C9; Mon, 28 Nov 2005 03:28:42 +0100 (CET) From: bugzilla@apache.org To: commons-dev@jakarta.apache.org Subject: DO NOT REPLY [Bug 37657] New: - JXPath 1.1 code using custom functions failing when run in 1.2 onwards X-Bugzilla-Reason: AssignedTo Message-Id: <20051128022842.33326C9@ajax.apache.org> Date: Mon, 28 Nov 2005 03:28:42 +0100 (CET) X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG� RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT . ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND� INSERTED IN THE BUG DATABASE. http://issues.apache.org/bugzilla/show_bug.cgi?id=37657 Summary: JXPath 1.1 code using custom functions failing when run in 1.2 onwards Product: Commons Version: 1.2 Final Platform: PC OS/Version: other Status: NEW Severity: regression Priority: P2 Component: JXPath AssignedTo: commons-dev@jakarta.apache.org ReportedBy: paul.parisi@iag.com.au We have recently attempted to upgrade from a 1.1 release of jxpath to 1.2 and found a great deal of our jxpath code fails to run correctly. We isolated the problem to relating to the use of Custom Extension Functions and have included sample junit test case snippets that should demonstrate the issue clearly. The background on what we are trying to do with jxpath is as follows (included so its clear on what we are trying to use jxpath to achieve): Within our project, we make extensive use of Custom Extension Functions in JXPath. We also use JXPath variables significantly, in combination with these functions, that often take a JXPath variable as an argument(s) to the function. We now rely heavily on the use of the ExpressionContext interface as the first argument to many of our functions. The reason for this is that we need a convienient way to obtain access to �original� object references within the context invoked by the function (as you would expect). However, we have also begun using a very useful combination of features, which the API supports in version 1.1, where the first argument always defines the ExpressionContext interface (which isn�t really part of the method signature � from a caller perspective), and a 2nd argument as �Object� type. Within body of the function, we then cast the object of the 2nd argument as a NodeSet (or define the NodeSet type within the method signature � either appears to work), which provides us with access to the pointers for the object. As previously mentioned, a jxpath variable is passed from the caller of the function (received via the 2nd argument in the method signature), which is automatically resolved, by jxpath, to the object itself. The benefit of casting the object to NodeSet (interface) enables us to retrieve the first pointer in the NodeSet list. The first pointer concerns us, as it refers to the String value passed to the argument of the function which we need access to. The object reference itself is of little concern in this case, as once we have access to the variable name sent to the function, we can access the object via the ExpressionContext. This all works fine in jxpath 1.1, however, in version 1.2 this functionality is now broken, since our objects are no longer being cast to NodeSet (previously achieved via the internal implementation of jxpath NodeSet using a SimpleNodeSet � as per inspecting jxpath 1.1 source code). Note on the use of ExpressionContext: For those methods that declare the ExpressionContext interface (which must be the first argument, if used), as part of the argument list, the method signature from the caller perspective, excludes it from the argument list, as it is implied by jxpath. In other words, there will be one less argument from the caller when the interface is used. In the case where this interface was the only argument, which is common, then the caller would be invoking a zero-argument method. This is behaviour we expect. Here is a simplified example of one of our functions using the techniques discussed:- public static void deleteSomeObject(ExpressionContext expContext, Object obj) { // create a local jxpath context to retrieve values for jxpath variables JXPathContext localContext = expContext.getJXPathContext(); // Nodeset of the object passed to method NodeSet nodeset = (NodeSet)obj; // Retrieve variable name passed to function String declaredVariable = nodeset.getPointers().get(0).toString(); Object objectToDelete = null; // If this method was passed the $obj1 var to delete, then retrieve 'Object Type 1' via $obj1 variable if (declaredVariable.equals("$obj1")) { objectToDelete = (ObjectType1)localContext.getValue("$obj1"); } // If this method was passed the $obj2 var to delete, then retrieve 'Object Type 2' via $obj2 variable if (declaredVariable.equals("$obj2")) { objectToDelete = (ObjectType2)localContext.getValue("$obj2"); } collectionOfSomeObjects.delete(objectToDelete); } Which would be used (called) in the following way:- � // add to collection ObjectType1 objectType1 = new ObjectType1(); ObjectType2 objectType2 = new ObjectType2(); CollectionOfSomeObjects.add(objectType1); CollectionOfSomeObjects.add(objectType2); // add collection to jxpath context JXPathContext context = JXPathContext.newContext(collectionOfSomeObjects); // define jxpath variables context.getVariables().declareVariable("obj1", objectType1); context.getVariables().declareVariable("obj2", objectType2); // call jxpath Custom Extension Function String method2Invoke; method2Invoke = �ftn:deleteSomeObject($obj1)� context.getValue(method2Invoke); // � invoke function & return value (for non-void methods) method2Invoke = �ftn:deleteSomeObject($obj2)� context.getValue(method2Invoke); // � invoke function & return value (for non-void methods) In addition to the above example, I have prepared a suite of JUnit tests (& functions) that work against JXPath version 1.1, but fail against version 1.2. These code snippets can simply be dropped into the appropriate classes and executed. Also, I would like to note that the JXPath user guide is a little unclear with respect to the use of NodeSet�s. After looking at many of the existing JUnit tests for JXPath, many un-documented features became evident & existing features became a little obscure, such as �Collections as NodeSets�. The code examples provided should give you our perspective on it�s use. CODE SNIPPETS BELOW TO INSERT INTO EXISTING JXPATH TEST SUITE: Below you will find two sections:- (1) JUnit Tests to test Extension Functions (2) Additional Extension Functions for these new tests --------------------------------------------------------------------------------------------------------- 3 JUnit Tests to add to 'ExtensionFunctionTest.java" (in package org.apache.commons.jxpath.ri.compiler) : /** * To test the use of NodeSet to retrieve String value passed to argument of method */ public void testMyTestNodeSetOnly() { context.getVariables().declareVariable("obj1", new String("$12345.00")); assertXPathValue( context, "test:myTestNodeSetOnly($obj1)", "$obj1"); } /** * To test the use of ContextExpression & NodeSet Combined */ public void testMyTestContextExpressionAndNodeSetCombined() { HashMap map = new HashMap(); map.put("1",new String("Item 1")); map.put("2",new String("Item 2")); map.put("3",new String("Item 3")); context.getVariables().declareVariable("obj2", map); assertXPathValue( context, "test:myTestContextExpressionAndNodeSetCombined($obj2)", "$obj2"); } /** * To test the use of ContextExpression & NodeSet Combined with additional arguments */ public void testMyTestContextExpressionAndNodeSetCombinedExtraArgs() { HashMap map = new HashMap(); map.put("1",new String("Item 1")); map.put("2",new String("Item 2")); map.put("3",new String("Item 3")); HashMap map2 = new HashMap(); map2.put("another collection",map); map2.put("a bean",new TestBean()); TestBean testBean = new TestBean(); Map beanMap = testBean.getMap(); context.getVariables().declareVariable("obj1", beanMap); context.getVariables().declareVariable("obj2", map2); context.getVariables().declareVariable("obj3", testBean); context.getVariables().declareVariable("obj4", new Integer(10)); assertXPathValue( context, "test:myTestContextExpressionAndNodeSetCombinedExtraArgs($obj1, $obj2, $obj3, $obj4)", "$obj1"); } --------------------------------------------------------------------------------------------------------- 3 Additional Functions to add to 'TestFunctions.java' (in package org.apache.commons.jxpath.ri.compiler) : public static String myTestNodeSetOnly(NodeSet obj) { // Nodeset of the object passed to method NodeSet nodeset = (NodeSet)obj; // Retrieve variable name passed to function String declaredVariable = ""; declaredVariable = nodeset.getPointers().get(0).toString(); // for (int i=0; i < nodeset.getPointers().size();i++ ) { // declaredVariable = nodeset.getPointers().get(i).toString(); // System.out.println(" declaredVariable Name = "+declaredVariable+" value ="+nodeset.getNodes().get(i)); // // } // System.out.println(" declaredVariable Name = "+declaredVariable); return declaredVariable; } public static String myTestContextExpressionAndNodeSetCombined(ExpressionContext expContext, Object obj) { // create a local jxpath context to retrieve values for jxpath variables JXPathContext localContext = expContext.getJXPathContext(); // Nodeset of the object passed to method NodeSet nodeset = (NodeSet)obj; // Retrieve variable name passed to function String declaredVariable = nodeset.getPointers().get(0).toString(); // System.out.println(" declaredVariable Name = "+declaredVariable); HashMap object = (HashMap)localContext.getValue(declaredVariable); // System.out.println(" declaredVariable reference to object via context = "+object); return declaredVariable; } public static String myTestContextExpressionAndNodeSetCombinedExtraArgs(ExpressionContext expContext, Object obj1, Object obj2, Object obj3, Object obj4 ) { // create a local jxpath context to retrieve values for jxpath variables JXPathContext localContext = expContext.getJXPathContext(); // Nodesets of the object(s) passed to method NodeSet nodeset1 = (NodeSet)obj1; NodeSet nodeset2 = (NodeSet)obj2; NodeSet nodeset3 = (NodeSet)obj3; NodeSet nodeset4 = (NodeSet)obj4; // Retrieve variable name passed to function String declaredVariable = nodeset1.getPointers().get(0).toString(); // System.out.println(" declaredVariable 1 Name = "+declaredVariable); HashMap object = (HashMap)localContext.getValue(declaredVariable); // System.out.println(" declaredVariable reference to object via context = "+object); return declaredVariable; } -- Configure bugmail: http://issues.apache.org/bugzilla/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are the assignee for the bug, or are watching the assignee. --------------------------------------------------------------------- To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org For additional commands, e-mail: commons-dev-help@jakarta.apache.org