Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » HELP! What are the possible types of value an @XmlPath can have?
HELP! What are the possible types of value an @XmlPath can have? [message #1714796] Mon, 16 November 2015 17:59 Go to next message
J F is currently offline J FFriend
Messages: 256
Registered: July 2009
Senior Member
I wish to represent the following schema using MOXy

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <xsd:complexType name="container5">
      <xsd:sequence>
         <xsd:element name="A" type="xsd:string"/>
         <xsd:sequence minOccurs="0">
	         <xsd:element name="innerMarker" type="xsd:string" />
	         <xsd:element name="O" type="xsd:string"/>
	         <xsd:element name="P" type="xsd:string"/>
         </xsd:sequence>
         <xsd:element name="postInnerMarker" type="xsd:string"/>
         <xsd:element name="O" type="xsd:string"/>
         <xsd:element name="P" type="xsd:string"/>
         <xsd:element name="Z" type="xsd:string"/>
      </xsd:sequence>
   </xsd:complexType>
   <xsd:element name="Container" type="container5"/>
</xsd:schema>


Because the inner sequence is optional I represent it using the following.
I have to come up with some form of XPath which says that the 'O' in the Container5OptionalInner should only be set if the innerMarker element has been found.
I duck out of specifying the Container5 'O' element as being after its predecessor as I wanted to test that last() seemed to work when marshalling an object with no Container5OptionalInner.

package uk.co.his.test;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlAccessorType(XmlAccessType.NONE)
@XmlType(propOrder={"a", "optionalInner", "postInnerMarker", "o", "p", "z"})
@XmlRootElement(name = "Container")
public class Container5 {
	@XmlElement(name="A", required=true)
	public String a;
	
	@XmlPath(".")
	@XmlElement(required=false)
	public Container5OptionalInner optionalInner;
	

	@XmlElement(required=true, name="postInnerMarker")
	public String postInnerMarker;

	
	@XmlPath("O[last()]/text()")
	@XmlElement(required=true)
	public String o;

	@XmlPath("P[last()]/text()")
	@XmlElement(required=true)
	public String p;
	
	@XmlElement(name="Z", required=true)
	public String z;

	@Override
	public String toString() {
		return "Container5 [a=" + a + ", optionalInner=" + optionalInner + ", o=" + o + ", p=" + p + ", z=" + z + "]";
	}
}

@XmlAccessorType(XmlAccessType.NONE)
@XmlType(propOrder= {"innerMarker", "o", "p"})
public class Container5OptionalInner {
	
	@XmlElement(name="innerMarker", required=true)
	public String innerMarker;
	
	@XmlPath("O[preceding-sibling::innerMarker]/text()")
	@XmlElement(name="O", required=true)
	public String o;

	@XmlPath("P[preceding-sibling::innerMarker]/text()")
	@XmlElement(name="P", required=true)
	public String p;

	@Override
	public String toString() {
		return "Container5InnerChoice [marker=" + innerMarker + ", o=" + o + ", p=" + p + "]";
	}
}


If I run the following test

@Test
	public void test2() throws JAXBException
	{
		System.setProperty("javax.xml.bind.context.factory", "org.eclipse.persistence.jaxb.JAXBContextFactory");
		final File etXml = new File("target/Container5.xml");
		Container5 et = new Container5();
		et.a = "A";
		et.optionalInner = new Container5OptionalInner();
		et.optionalInner.innerMarker = "optionalInner";
		et.optionalInner.o = "O";
		et.optionalInner.p = "P";
		et.postInnerMarker = "postInnerMarker";
		et.o = "O2";
		et.p = "P2";
		et.z = "Z";
		
		JAXBContext jbc =  JAXBContext.newInstance(Container5.class);
		System.out.println("jaxbContext is=" +jbc.getClass().getName());
		Marshaller m = jbc.createMarshaller();
		m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
		m.marshal(et, etXml);
		
		Unmarshaller u = jbc.createUnmarshaller();
		Container5 et2 = (Container5) u.unmarshal(etXml);
		m.marshal(et, System.out);
		m.marshal(et2, System.out);
		
		System.out.println(et);
		System.out.println(et2);
	}



I get the following NPE, which seems to be down to the fact that the parsing of the @XmlPath does not set the localname.
For example the function public void setXPath(String xpathString) in org.eclipse.persistence.internal.oxm.XPathFragment simply returns when I finds an axis in the XPath predicate;

 // handle case:  ancestor::*/jaxb:class/@name
            if (xpath.indexOf("::") != -1) {
                setShouldExecuteSelectNodes(true);
                return;
            }

where as in simpler cases such as @XmlPath("O[last()]/text()") it always calls setupNamespaceInformation as thus sets the localName whose null value seems to be the cause of the NPE.


The NPE:

javax.xml.bind.MarshalException
 - with linked exception:
[javax.xml.bind.MarshalException
 - with linked exception:
[java.lang.NullPointerException]]
	at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:522)
	at uk.co.his.test.genpi.jaxbgen.Tests4.test2(Tests4.java:76)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: javax.xml.bind.MarshalException
 - with linked exception:
[java.lang.NullPointerException]
	at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:500)
	at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:515)
	... 24 more
Caused by: java.lang.NullPointerException
	at org.eclipse.persistence.oxm.record.OutputStreamRecord.outputStreamWrite(OutputStreamRecord.java:581)
	at org.eclipse.persistence.oxm.record.OutputStreamRecord.outputStreamWrite(OutputStreamRecord.java:568)
	at org.eclipse.persistence.oxm.record.FormattedOutputStreamRecord.openStartElement(FormattedOutputStreamRecord.java:120)
	at org.eclipse.persistence.oxm.record.MarshalRecord.openStartGroupingElements(MarshalRecord.java:482)
	at org.eclipse.persistence.internal.oxm.XMLDirectMappingNodeValue.marshalSingleValue(XMLDirectMappingNodeValue.java:86)
	at org.eclipse.persistence.internal.oxm.XMLDirectMappingNodeValue.marshal(XMLDirectMappingNodeValue.java:65)
	at org.eclipse.persistence.internal.oxm.NodeValue.marshal(NodeValue.java:102)
	at org.eclipse.persistence.internal.oxm.record.ObjectMarshalContext.marshal(ObjectMarshalContext.java:59)
	at org.eclipse.persistence.internal.oxm.XPathNode.marshal(XPathNode.java:448)
	at org.eclipse.persistence.internal.oxm.XPathNode.marshal(XPathNode.java:423)
	at org.eclipse.persistence.internal.oxm.XPathObjectBuilder.buildRow(XPathObjectBuilder.java:243)
	at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:118)
	at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:1)
	at org.eclipse.persistence.internal.oxm.XMLCompositeObjectMappingNodeValue.marshalSingleValue(XMLCompositeObjectMappingNodeValue.java:260)
	at org.eclipse.persistence.internal.oxm.XMLCompositeObjectMappingNodeValue.marshal(XMLCompositeObjectMappingNodeValue.java:151)
	at org.eclipse.persistence.internal.oxm.NodeValue.marshal(NodeValue.java:102)
	at org.eclipse.persistence.internal.oxm.record.ObjectMarshalContext.marshal(ObjectMarshalContext.java:59)
	at org.eclipse.persistence.internal.oxm.XPathNode.marshal(XPathNode.java:448)
	at org.eclipse.persistence.internal.oxm.XPathObjectBuilder.buildRow(XPathObjectBuilder.java:243)
	at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:118)
	at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:1)
	at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:767)
	at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshalStreamOrWriter(XMLMarshaller.java:1143)
	at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:934)
	at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:878)
	at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:496)
	... 25 more


Moreover the value is ignored in parsing the instance document;

<?xml version="1.0" encoding="UTF-8"?>
<Container>
   <A>A</A>
   <choiceMarker>choiceMarker</choiceMarker>
   <O>O</O>
   <P>P</P>
   <postChoiceMarker>postChoiceMarker</postChoiceMarker>
   <O>O2</O>
   <P>P2</P>
   <Z>Z</Z>
</Container>


Will cause Container5 to print out;

Container5 [a=A, optionalInner=Container5InnerChoice [marker=null, o=null, p=null], o=O2, p=P2, z=Z]



So it seems that MOXy does a restricted st of XPath ( which might seem logical if one considered the cases when it was using a SAX type streaming parse to unpack an Object ).

I wish to ask
0) Can my example be done ins some other way which MOXy will accept - am I just missing something?
1) Are the set of XPaths which MOXy can bind to resticted to those in the examples O[1], ".", is there any definition (beyond the source, which I am still getting to know) of what it does accept?
2) Is the set of valid @XmlPath values depedendent on the intermediate representation of the XML (Full XPath on DOM, restricted on streaming, a bit like the XSLT2 streaming restrictions)?

[Updated on: Mon, 16 November 2015 18:07]

Report message to a moderator

Re: HELP! What are the possible types of value an @XmlPath can have? [message #1714857 is a reply to message #1714796] Tue, 17 November 2015 10:30 Go to previous message
J F is currently offline J FFriend
Messages: 256
Registered: July 2009
Senior Member
The best I could find were the answers on Stack Overflow which I should have looked at first.
See the bottom of my question there
Previous Topic:javax.validation.ConstraintViolationException not found
Next Topic:Direct self-reference leading to cycle error despite having JsonManagedReference and JsonBackReferen
Goto Forum:
  


Current Time: Wed Mar 03 09:21:27 GMT 2021

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

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

Back to the top