Discussions

News: Jakarta JXPath 1.1 Released

  1. Jakarta JXPath 1.1 Released (6 messages)

    JXPath is a Jakarta module that applies XPath expressions to graphs of objects of all kinds: JavaBeans, Maps, Servlet contexts, DOM etc, including mixtures thereof.

    JXPath Home

    JXPath User Guide

    JXPath 1.1 Download

    The 1.1 release introduces:

    - Full support for JDOM. Just like with DOM, if a JDOM node is the root node of a JXPathContext, the implementation strictly follows the XPath 1.0 standard. A JDOM node can also be a part of a mixed model, i.e. the value of a property, variable, container, collection element etc.

    - Pointer has an additional method: getNode(), which returns the raw value without converting it to a primitive value. This makes a difference when you are working with DOM/JDOM and want to obtain the Node itself, not the textual value of the Node.

    - Support for DynaBeans (see Jakarta Commons BeanUtils).

    - Refactored XML parsing by container to allow for alternate parsers. All you do now is specify which model you want the container to use - DOM (default) or JDOM. From that point the processing is transparent. See org.apache.commons.jxpath.xml.DocumentContainer.

    - The format-number XSLT function is now supported. In order to provide full conformance with the standard, we also needed to introduce the format customization mechanism known in XSLT as <xsl:decimal-format> (see W3Schools tutorial ). The new methods of JXPathContext: setDecimalFormatSymbols() and getDecimalFormatSymbols() fulfill that requirement.

    - The attribute:: axis is now supported models other than DOM/JDOM. For beans and maps it is interpreted the same way as the "child::" axis.

    - In JXPath 1.0 you could only register DynamicPropertyHandlers for concrete classes, now you can also register them for interfaces.

    - The implementation of setValue() has changed for DOM/JDOM nodes. In JXPath 1.0 it would replace text in the element, but leave sub-elements alone. The new implementation is more consistent: it drops all subelements first. Also, if you pass a Node as the new value, it will insert the Node in the tree.

    - If you need to evaluate multiple paths relative to a certain node in the object graph, you can now create a relative JXPathContext. Obtain the pointer for the location that is supposed to define the relative context and then a relative context by calling context.getRelativeContext(pointer) .

    - The JUnit tests for JXPath have been completely redisigned and significantly enhanced.

    Threaded Messages (6)

  2. I looked at the example they provided (see below) and all I can say is *wow*. It's really an innovative way of looking at Java coding, and it's definitely a powerful concept and undoubtably leads to shorter code, but I'm a bit concerned about how maintainable it is.

    The example below is moderately easy to read, but I can easily see it yielding some very complicated APL-like expressions, especially after it's been maintained a while. SQL faces similar issues, but SQL has views and other constructs to help simplify things, and SQL has a well-defined abstract engine with well defined behaviours with (often) fairly clear error messages when things go wrong. Since JXPath deals with real-world JavaBeans, Maps, Servlets, DOM, etc, which may fail or act in unexpected ways, I'm wondering how well it works when something unexpected happens and how easy it is to troubleshoot when things go wrong.

    For instance, if somehow a DatagramPacket got added to the vendor.getLocations() collection, the long form of the code would fail on the line:
        Location location = (Location)it.next();
    and the exception will say that DatagramPacket cannot be cast to Location. This bug is easy to diagnose and, with a good debugger or cross-referencer, moderately easy to track down.

    In the JXPath short form example, JXPath would detect that DatagramPacket had a "getAddress()" method and then fail when it determined that the resulting InetAddress did not contain a "getZipCode()" method and would (I imagine) give a far more cryptic error about "getZipCode()" not being found.

    What are the current plans to handle this issue?

    ---------------------------------------------
    ---------------------------------------------
    Consider this example:
          
    Address address = (Address)JXPathContext.newContext(vendor).
             getValue("locations[address/zipCode='90210']/address");

        
    This XPath expression is equvalent to the following Java code:
          
    Address address = null;
    Collection locations = vendor.getLocations();
    Iterator it = locations.iterator();
    while (it.hasNext()){
        Location location = (Location)it.next();
        String zipCode = location.getAddress().getZipCode();
        if (zipCode.equals("90210")){
          address = location.getAddress();
          break;
        }
    }
  3. Especially if the constructs are very likely to have a severe performance impact. I assume that this is almost a certainity, when something needs to rely on run time interpretation and/or introspection/reflection. I assume this does (haven't looked at it really, or is it a precompiler - with problems in its own right of course)...The other things is readibility of code. I agree that such technologies are quite likely to create complicated expressions and constructs that are hard to understand. However compared to a tool like AspectJ the amount of potential confusion for code maintainers is still quite mild in this case :-).
  4. I wouldn't be so quick to assume that use of reflection guarantees a severe performance impact. There are a number of technologies out there now that use reflection profusely, and with optimizations available in jdks 1.3 and 1.4, reflection doesn't cause anywhere near the performance hit it used to. Take a look at the Hibernate project (hibernate.sourceforge.net); the author takes head on the view that reflection means poor performance. In his, as well as mine, it does not. I have a web application that makes extensive use of reflection for everything from data access (via Hiberate) to rules evaluation and security. The struts framework that it uses also makes extensive use of reflection. I do not believe that it operates any slower than similar systems that do not rely on reflection, and the flexibility and configurability that the reflection-dependent features grant it make me very happy with using reflection.
  5. JXPath is a great![ Go to top ]

    Using JXPath I was able to create a rally flexible XML Configuration Framework in a very short period of time. Combine JXPath and Jelly and you can do some really handy XML work.

    TLK.
  6. object methods[ Go to top ]

    JXPath is indeed cool. Expression languages combined with a Jelly (or Ant) approach make for a neat high level XML glue to bind together Java Beans or XML data elegantly which can be very useful for configuration, building, workflow definitions, creating rich user interfaces or creating XML test scripts etc.

    The only downside of JXPath is that AFAIK it doesn't cleanly support bean method invocations. So using something else like Jexl or beanshell or Jython with Jelly allows you to do much more expressive things when working with beans.

    e.g. you can do things like this in Jelly with Jexl

    <j:useBean var="tool" class="com.acme.MyBean" name="James"/>
    <j:set var="answer" value="${tool.doSomething(1234, 'abc', something)}"/>
  7. object methods[ Go to top ]

    James, thank you for your kind words.

    Just a quick correction: you can in fact call methods in JXPath. The syntax is this:

       doSomething(tool, 1234, 'abc', something)

    The target of the method is passed as the first argument. This treatment of methods as "automatic" extension functions is done the same way in Xalan.