Hi

I've added the stack trace printing (to be converted into LOG statements)
but I start thinking JAXBElementProvider is not at fault here - because it
does not deal with serializing individual fields, it creates a context for
the given JAXB bean and then delegates to Marshaller.

I'll try to add a test shortly, just a bit overwhelmed at the moment...

thanks, Sergey

On Mon, Mar 14, 2011 at 3:44 PM, KARR, DAVID (ATTSI) <[email protected]> wrote:

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


-- 
Sergey Beryozkin

Application Integration Division of Talend <http://www.talend.com>
http://sberyozkin.blogspot.com

Reply via email to