> -----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.
