Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » MOXy: Binding working and not working with 'same' XmlPath
MOXy: Binding working and not working with 'same' XmlPath [message #1076230] Wed, 31 July 2013 01:33 Go to next message
Tim Braun is currently offline Tim Braun
Messages: 8
Registered: July 2013
Junior Member
As you can see from the bindings below, I would not expect a different behavior from the following to bindings. Using xml-path="a/b/@text" to bind a XML attribute to a String or xml-path="a/b" to a java-type that then binds @text to a String. However, in the latter case there is no binding at all. Full example below.

Input:
    <?xml version="1.0" encoding="UTF-8"?>
    <foo:root xmlns:foo="http://www.domain.org/foo" 
          xmlns="http://www.domain.org/foo"
          xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <a xsi:type="foo:someType">
          <b text="some text" />
      </a>
    </foo:root>


Bindings:
    <?xml version="1.0"?>
    <xml-bindings
       xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
       package-name="test">

    <xml-schema element-form-default="QUALIFIED" namespace="http://www.domain.org/foo">
        <xml-ns prefix="foo" namespace-uri="http://www.domain.org/foo" />
    </xml-schema>
    
     <java-types>        
        <java-type name="Root">
	    <xml-root-element name="root"/>
	    <java-attributes>
		<xml-element java-attribute="contentRoot" xml-path="." type="test.ContentRoot" />
            </java-attributes>
        </java-type>
        
       	<java-type name="ContentRoot">
            <java-attributes>
                <xml-element java-attribute="text" xml-path="a/b/@text" />
		<xml-element java-attribute="contents" xml-path="a/b" type="test.Content" container-type="java.util.List" />
            </java-attributes>
        </java-type>
        
        <java-type name="Content">
     	    <java-attributes>
		<xml-element java-attribute="text" xml-path="@text" />
            </java-attributes>
        </java-type>
    </java-types>
    
    </xml-bindings>


Classes in package test:
    public class Root {
	 private List<ContentRoot> contentRoots = new LinkedList<ContentRoot>();
	 public List<ContentRoot> getContentRoots() {
		return contentRoots;
	 } 
	 public void setContentRoots(List<ContentRoot> contentRoots) {
		this.contentRoots = contentRoots;
	 }
	 public void setContentRoot(ContentRoot contentRoot) {
		this.contentRoots.add(contentRoot);
	 }
    }

    public class ContentRoot {
	 private List<Content> contents;
	 private String text;
	 public List<Content> getContents() {
		return contents;
	 }
	 public void setContents(List<Content> contents) {
	 	this.contents = contents;
	 }
	 public String getText() {
		return text;
	 }
	 public void setText(String text) {
		this.text = text;
	 }	
    }

    public class Content  {
	 private String text;
	 public String getText() {
		return text;
	 }
	 public void setText(String text) {
		this.text = text;
	 }
    }


Running Code:
	Map<String, Object> jaxbContextProperties = new HashMap<String, Object>(1);
	jaxbContextProperties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "bindings.xml");
	JAXBContext jaxbContext = JAXBContextFactory.createContext(new Class[] {Root.class}, jaxbContextProperties);
	Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
	Root root = (Root)unmarshaller.unmarshal(new File("input.xml"));
	System.out.println(root.getContentRoots().get(0).getText());	
	System.out.println(root.getContentRoots().get(0).getContents().get(0).getText());


The result is, that text is set in ContentRoot but not in Content (I get a NullPointerException from the last System.out.println()). Can someone tell me why?

[Updated on: Wed, 31 July 2013 01:35]

Report message to a moderator

Re: MOXy: Binding working and not working with 'same' XmlPath [message #1076516 is a reply to message #1076230] Wed, 31 July 2013 14:08 Go to previous message
Blaise Doughan is currently offline Blaise Doughan
Messages: 163
Registered: July 2009
Senior Member

There are a few items that are tripping you up:

ISSUE #1 - ContentRoot Contains Invalid Mappings

EclipseLink JAXB (MOXy) does not allow the following combination of mappings. With the second xml-element you are telling MOXy to map the contents properties to the repeating element b that occur within the element a. With the first xml-element you are trying to map the text attribute of one of the potentially many b elements to the String property text.

<java-type name="ContentRoot">
    <java-attributes>
        <xml-element java-attribute="text" xml-path="a/b/@text" />
        <xml-element java-attribute="contents" xml-path="a/b" type="test.Content" container-type="java.util.List" />
    </java-attributes>
</java-type>


The correct place to map the text attribute is on the Content class which you already had. Instead of using the xml-element mapping with the xml-path pointing at the attribute (which would work), I would recomment using the xml-attribute mapping and specifying a name.

<java-type name="Content">
    <java-attributes>
        <xml-attribute java-attribute="text"/>
    </java-attributes>
</java-type>


ISSUE #2 - xml-path Is Not Properly Namespace Qualified

Since in bindings.xml you have associated the foo prefix with the http://www.domain.org/foo namespace URI.

<xml-schema element-form-default="QUALIFIED" namespace="http://www.domain.org/foo">
    <xml-ns prefix="foo" namespace-uri="http://www.domain.org/foo" />
</xml-schema>


When you specify the xml-path you need to include the prefix in order to get the correct namespace qualification.

<java-type name="ContentRoot">
    <java-attributes>
        <xml-element java-attribute="contents" xml-path="foo:a/foo:b"/>
    </java-attributes>
</java-type>


For More Information

http://blog.bdoughan.com/2010/09/xpath-based-mapping-geocode-example.html

Alternatively you could have mapped it with an xml-element-wrapper as follows:

<java-type name="ContentRoot">
    <java-attributes>
        <xml-element java-attribute="contents" name="b">
            <xml-element-wrapper name="a"/>
        </xml-element>
    </java-attributes>
</java-type>


ISSUE #3 - xml-path="." Can Not Be Used on a Collection Property

Currently MOXy requires that each item in a collection correspond to its own element. This means that at this time you can not specify the self XPath . for collection properties.
Full Example

Your demo code didn't seem to fully match your domain model. Here is a complete example that pulls everything together:

Root
package test;

public class Root {

    private ContentRoot contentRoot;

    public ContentRoot getContentRoot() {
        return contentRoot;
    }

    public void setContentRoot(ContentRoot contentRoot) {
        this.contentRoot = contentRoot;
    }

}

ContentRoot
package test;

import java.util.List;

public class ContentRoot {

    private List<Content> contents;

    public List<Content> getContents() {
        return contents;
    }

    public void setContents(List<Content> contents) {
        this.contents = contents;
    }

}

Content
package test;

public class Content {

    private String text;

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

}

bindings.xml
<?xml version="1.0"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="test"
    xml-accessor-type="FIELD">

    <xml-schema element-form-default="QUALIFIED" namespace="http://www.domain.org/foo">
        <xml-ns prefix="foo" namespace-uri="http://www.domain.org/foo" />
    </xml-schema>

    <java-types>
        <java-type name="Root">
            <xml-root-element/>
            <java-attributes>
                <xml-element java-attribute="contentRoot" xml-path="."/>
            </java-attributes>
        </java-type>

        <java-type name="ContentRoot">
            <java-attributes>
                <xml-element java-attribute="contents" xml-path="foo:a/foo:b"/>
            </java-attributes>
        </java-type>

        <java-type name="Content">
            <java-attributes>
                <xml-attribute java-attribute="text"/>
            </java-attributes>
        </java-type>
    </java-types>

</xml-bindings>

Demo
package test;

import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.JAXBContextProperties;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> jaxbContextProperties = new HashMap<String, Object>(1);
        jaxbContextProperties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "test/bindings.xml");
        JAXBContext jaxbContext = JAXBContextFactory.createContext(new Class[] {Root.class}, jaxbContextProperties);

        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        Root root = (Root)unmarshaller.unmarshal(new File("src/test/input.xml"));
        System.out.println(root.getContentRoot().getContents().get(0).getText());

        Marshaller marshaller = jaxbContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

Previous Topic:AdditionalCriteria in ServerSession
Next Topic:EclipseLink MOXy exception due to package structure
Goto Forum:
  


Current Time: Mon Oct 20 21:16:07 GMT 2014

Powered by FUDForum. Page generated in 0.01910 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software