Problem solved
After change the XmlElementRef annotation to @XmlElementRef(name = "Option", type = Option.class, required = false) and add @XmlRootElement(name = "Option") to Option.class
Update:
I have added two classes(Options and Option) as laune's recommend and modified the GuiMOProperties class as below
@XmlAccessorType(XmlAccessType.FIELD)
public class GuiMOProperties
{
@XmlElement(name="Grouping")
private boolean grouping;
@XmlElement(name="Type")
private String type;
@XmlElement(name="Regex")
private String regex;
@XmlElement(name="DisplayName")
private String displayName;
@XmlElement(name="Options")
private Options options;
@XmlElement(name="Mask")
private String mask;
@XmlElement(name="DefaultValue")
private String defaultValue;
}
But got some exception when I have to new an instance of JAXBContext as below:
JAXBContext jaxbContext = JAXBContext.newInstance(GuiMOProperties.class);
java.lang.IllegalArgumentException: can't parse argument number: ''{0}''
at java.text.MessageFormat.makeFormat(MessageFormat.java:1429)
at java.text.MessageFormat.applyPattern(MessageFormat.java:479)
at java.text.MessageFormat.<init>(MessageFormat.java:362)
at java.text.MessageFormat.format(MessageFormat.java:840)
at com.sun.xml.internal.bind.v2.model.impl.Messages.format(Messages.java:117)
at com.sun.xml.internal.bind.v2.model.impl.ReferencePropertyInfoImpl.calcTypes(ReferencePropertyInfoImpl.java:171)
at com.sun.xml.internal.bind.v2.model.impl.ReferencePropertyInfoImpl.link(ReferencePropertyInfoImpl.java:372)
at com.sun.xml.internal.bind.v2.model.impl.ClassInfoImpl.link(ClassInfoImpl.java:1257)
at com.sun.xml.internal.bind.v2.model.impl.RuntimeClassInfoImpl.link(RuntimeClassInfoImpl.java:182)
at com.sun.xml.internal.bind.v2.model.impl.ModelBuilder.link(ModelBuilder.java:439)
at com.sun.xml.internal.bind.v2.model.impl.RuntimeModelBuilder.link(RuntimeModelBuilder.java:118)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:443)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:277)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:124)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1123)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:147)
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 javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:247)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:234)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:462)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:641)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
at devicemanage.utility.Tree2xml.omElementToGuiMOPropertiesList(Tree2xml.java:332)
at devicemanage.service.appdeploy.DeviceMgtServiceImpl.getMOProperties(DeviceMgtServiceImpl.java:250)
at devicemanage.service.appdeploy.DeviceMgtServiceImpl.access$0(DeviceMgtServiceImpl.java:238)
at devicemanage.service.appdeploy.DeviceMgtServiceImpl$1.load(DeviceMgtServiceImpl.java:233)
at devicemanage.service.appdeploy.DeviceMgtServiceImpl$1.load(DeviceMgtServiceImpl.java:1)
at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3527)
at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2319)
at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2282)
at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2197)
at com.google.common.cache.LocalCache.get(LocalCache.java:3937)
at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3941)
at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4824)
at devicemanage.service.appdeploy.DeviceMgtServiceImpl.findMOPropertiesByDeviceType(DeviceMgtServiceImpl.java:208)
at devicemanage.service.appdeploy.DeviceMgtServiceImpl$$FastClassBySpringCGLIB$$1a89f063.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:266)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
at devicemanage.service.appdeploy.DeviceMgtServiceImpl$$EnhancerBySpringCGLIB$$97274215.findMOPropertiesByDeviceType(<generated>)
at TestDeviceMgtService.testFindMOPropertiesByDeviceType(TestDeviceMgtService.java:38)
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.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:72)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:81)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:216)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:82)
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.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:60)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:67)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:162)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
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: java.lang.NumberFormatException: For input string: "''{0}''"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:569)
at java.lang.Integer.parseInt(Integer.java:615)
at java.text.MessageFormat.makeFormat(MessageFormat.java:1427)
... 78 more
I have a class defined as below for JAXB parsing:
@XmlAccessorType(XmlAccessType.FIELD)
public class GuiMOProperties
{
@XmlElement(name="Grouping")
private boolean grouping;
@XmlElement(name="Type")
private String type;
@XmlElement(name="Regex")
private String regex;
@XmlElement(name="DisplayName")
private String displayName;
@XmlElement(name="Options")
@XmlJavaTypeAdapter(OptionsAdapter.class)
private GuiMOOption options;
@XmlElement(name="Mask")
private String mask;
@XmlElement(name="DefaultValue")
private String defaultValue;
}
And the xml string I have to parsed as below:
<VolumeUpKey>
<Type/>
<Regex/>
<DisplayName/>
<Options>testOptions</Options>
<Mask/>
<DefaultValue/>
</VolumeUpKey>
<SSID>
<Type/>
<Regex/>
<DisplayName/>
<Options>
<Option name="1" value="1"></Option>
<Option name="2" value="2"></Option>
<Option name="3" value="3"></Option>
<Option name="4" value="4"></Option>
</Options>
<Mask/>
<DefaultValue/>
</SSID>
In the unmarshal method of my OptionsAdapter.class, the first one Options element works fine, there has a string "testOptions" input. However, the second one Options element didn't. The input paramater will be come \n\t\t\t\t, but not a string <Option name="1" value="1"></Option><Option name="2" value="2"></Option><Option name="3" value="3"></Option><Option name="4" value="4"></Option>
.
The OptionsAdapter.class as below
public class OptionsAdapter extends XmlAdapter<String, GuiMOOption>
{
@Override
public GuiMOOption unmarshal(String v) throws Exception
{
try
{
System.out.println("unmarshal string : " + v);
} catch (Exception e)
{
// TODO: handle exception
}
return null;
}
@Override
public String marshal(GuiMOOption v) throws Exception
{
// TODO Auto-generated method stub
return null;
}
}
Any help is appreciated.
Mixed content isn't quite straightforward, although JAXB can handle it without an adapter.
You can define the type of the options field as Options (instead of GuiMOOption):
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Options", propOrder = { "content" }) public class Options { @XmlElementRef(name = "field", type = JAXBElement.class, required = false) @XmlMixed protected List content; public List getContent() { if (content == null) { content = new ArrayList(); } return this.content; } }
The List will contain elements of type JAXBElement<Option>
and String, where Option is a class
@XmlAccessorType(XmlAccessType.FIELD) public class Option { @XmlAttribute protected String name; @XmlAttribute protected String value; //... }
You have to iterate the List to learn whether you have the first or the second XML form. In the first case there'll be just one String. In the second case, there may be white space strings among the wrapped Option objects.