I was trying to get something like this:
<entries>
<entry key="c">d</entry>
<entry key="a">b</entry>
</entries>
What I get with the workaround is this:
<entries>
<entry>
<key xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">c</key>
<value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xsi:type="xs:string">d</value>
</entry>
<entry>
<key xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">a</key>
<value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xsi:type="xs:string">b</value>
</entry>
</entries>
I imagine there should be a straightforward way to get those namespaces
on the root element, instead of repeated here, but I haven't looked at
that yet.
From: Sergey Beryozkin [mailto:[email protected]]
Sent: Monday, March 14, 2011 2:36 PM
To: [email protected]
Cc: KARR, DAVID (ATTSI)
Subject: Re: Getting NPE without stack trace while rendering, with no
Spring context
Great, can you post please the original structure expected and the
structure produced after the workaround ?
Just would like to see if the transformation feature [1] can be applied
or not...I'm still planning to investigate, at least to make sure the
stack trace is available...
Cheers, Sergey
[1] http://cxf.apache.org/docs/transformationfeature.html
On Mon, Mar 14, 2011 at 6:32 PM, KARR, DAVID (ATTSI) <[email protected]>
wrote:
> -----Original Message-----
> From: KARR, DAVID (ATTSI)
> Sent: Monday, March 14, 2011 8:45 AM
> To: [email protected]
> Subject: RE: Getting NPE without stack trace while rendering, with no
> Spring context
>
> > -----Original Message-----
> > From: Sergey Beryozkin [mailto:[email protected]]
> > Sent: Monday, March 14, 2011 5:29 AM
> > To: [email protected]
> > Subject: Re: Getting NPE without stack trace while rendering, with
no
> > Spring context
> >
> > > Can you please try and register a custom JAXBElementProvider with
> the
> > > JAXRSServerFactoryBean ? This provider will only extend
> > writeTo/ReadFrom and
> > > will have a try/catch block around super.writeFrom and readFrom ?
> > > I'll check the JAXBElementProvider, I think it has few catches for
> > > different types of exceptions including the Exception class - and
> in
> > this
> > > case it should indeed print a stacktrace...Letting users to
> configure
> > the
> > > default WebApplicationExceptionMapper for it to print the
> stacktraces
> > is
> > > another option...
> > >
> > >
> > I updated the code accordingly, but in meantime the easiest option
to
> > catch
> > the origin of the exception is to actually register a custom
> > WebAplicationExceptionMapper, i.e,
> > ExceptionMapper<WebApplicationException>
> > implementation (as a provider on the JAXRSServerFactoryBean) and
then
> > just
> > print the stack trace
>
> I'll implement this.
>
> In the meantime, I set a breakpoint on NPE in my debugger, so I at
> least
> know where this is happening, but I don't know why yet.
>
> This is mostly an excerpt from the post I sent to the jaxb-users list.
>
> I found that it was throwing the NPE at line 165 in class
> "com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor<BeanT>".
>
> That line is in this function (decompiled from class):
>
> /* */ public static <T> TransducedAccessor<T>
get(JAXBContextImpl
> context, RuntimeNonElementRef ref)
> /* */ {
> /* 153 */ Transducer xducer =
> RuntimeModelBuilder.createTransducer(ref);
> /* 154 */ RuntimePropertyInfo prop = ref.getSource();
> /* */
> /* 156 */ if (prop.isCollection()) {
> /* 157 */ return new ListTransducedAccessorImpl(xducer,
> prop.getAccessor(),
> Lister.create(Navigator.REFLECTION.erasure(prop.getRawType()),
> prop.id(), prop.getAdapter()));
> /* */ }
> /* */
> /* 162 */ if (prop.id() == ID.IDREF) {
> /* 163 */ return new
> IDREFTransducedAccessorImpl(prop.getAccessor());
> /* */ }
> /* 165 */ if ((xducer.isDefault()) && (!(context.fastBoot))) {
> /* 166 */ TransducedAccessor xa =
> OptimizedTransducedAccessorFactory.get(prop);
> /* 167 */ if (xa != null) return xa;
> /* */ }
> /* */
> /* 170 */ if (xducer.useNamespace()) {
> /* 171 */ return new
> CompositeContextDependentTransducedAccessorImpl(context, xducer,
> prop.getAccessor());
> /* */ }
> /* 173 */ return new CompositeTransducedAccessorImpl(context,
> xducer, prop.getAccessor());
> /* */ }
>
> The NPE happens because "xducer" is null.
>
> I googled this class, method, and line number, and I found one person
> on
> StackOverflow who got an NPE on the same line, but his situation seems
> to be slightly different.
>
> So, I figure I must have made a mistake in setting up the XmlAdapter.
>
> The following is where I declared the field I'm annotating:
>
> @XmlElement(name = "myMap")
> @XmlJavaTypeAdapter(HashMapStringStringAdapter.class)
> private HashMap<String, String> myMap;
>
> Here's the adapter class:
>
> public class HashMapStringStringAdapter extends
> XmlAdapter<HashMapType<String,String>,HashMap<String,String>> {
>
> @Override
> public HashMap<String, String> unmarshal(HashMapType<String,
> String>
> value) throws Exception {
> HashMap<String, String> result = new HashMap<String,
> String>();
> for (HashMapEntryType<String, String> hashMapEntry :
> value.getEntries())
> result.put(hashMapEntry.key, hashMapEntry.value);
> return result;
> }
>
> @Override
> public HashMapType<String, String> marshal(HashMap<String, String>
> value) throws Exception {
> HashMapType<String, String> result = new HashMapType<String,
> String>();
> for (Map.Entry<String, String> entry : value.entrySet())
> result.put(entry.getKey(), entry.getValue());
> return result;
> }
> }
>
> Here's the HashMapType:
>
> public class HashMapType<K,V> {
> private List<HashMapEntryType<K,V>> entries = new
> ArrayList<HashMapEntryType<K,V>>();
> public List<HashMapEntryType<K,V>> getEntries() { return entries;
}
> public void setEntries(List<HashMapEntryType<K,V>> entries) {
> this.entries = entries; }
> public void put(K key, V value) {
> getEntries().add(new HashMapEntryType<K,V>(key, value));
> }
> }
>
> And the HashMapEntryType:
>
> public class HashMapEntryType<K,V> {
> @XmlAttribute
> public K key;
> @XmlValue
> public V value;
> public HashMapEntryType() {}
> public HashMapEntryType(K key, V value) {
> this.key = key;
> this.value = value;
> }
> }
>
> Anyone have any idea what I might be doing wrong?
I've found a workaround for this. I changed the two annotations in
HashMapEntryType to both be @XmlElement. It's not the structure I
wanted, but I also need it to work. Changing only one of them to
@XmlElement doesn't fix the problem.
--
Sergey Beryozkin
Application Integration Division of Talend <http://www.talend.com>
http://sberyozkin.blogspot.com