4

Following up on this SO thread, my question is whether I'm doing something fundamentally wrong here:

Using GlassFish 4.1, I'm trying to write a MessageBodyReader that has a constructor like this:

package com.acme;

import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.Providers;
import javax.ws.rs.Consumes;

@Provider
@Consumes( "application/xml" )
public class MyMessageBodyReader implements MessageBodyReader<Object> {
   public MyMessageBodyReader(@Context Providers ps) {
      // try to do something with ps here
      // e.g. pass to a superclass constructor,
      // as required by the solution in the other thread
   }

   [...] // implemented interface methods
}

But whatever I do wrt surrounding configuration, I always get a sequence of these exceptions:

2016-06-07T17:19:28.484+0200|WARN: The following warnings have been detected: WARNING: Unknown HK2 failure detected:
MultiException stack 1 of 1
org.jboss.weld.exceptions.CreationException: WELD-001530: Cannot produce an instance of class com.acme.MyMessageBodyReader.
    at org.jboss.weld.injection.producer.NonProducibleInjectionTarget.produce(NonProducibleInjectionTarget.java:55)
    at org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider$CdiFactory$2.getInstance(CdiComponentProvider.java:242)
    at org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider$CdiFactory.provide(CdiComponentProvider.java:189)
    [...]

followed by

WARNING: Unknown HK2 failure detected:
MultiException stack 1 of 2
org.jboss.weld.exceptions.CreationException: WELD-001530: Cannot produce an instance of class com.acme.MyMessageBodyReader.
    at org.jboss.weld.injection.producer.NonProducibleInjectionTarget.produce(NonProducibleInjectionTarget.java:55)
    at org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider$CdiFactory$2.getInstance(CdiComponentProvider.java:242)
    at org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider$CdiFactory.provide(CdiComponentProvider.java:189)
    [...]
MultiException stack 2 of 2
java.lang.IllegalStateException: Unable to perform operation: create on org.glassfish.jersey.message.internal.MessageBodyFactory
    at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:389)
    at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:461)
    at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:114)
    [...]

I've found several examples of injecting Providers into a constructor, not the least in the subclasses of XmlRootElementJaxbProvider that ship with GlassFish 4.1 - after all, I want to reuse their class hierarchy anyway, as it's done in the linked thread.

Thanks in advance for any advice.

Hein Blöd
  • 1,553
  • 1
  • 18
  • 25
  • Is this still using the modified MessageBodyFactory you described in your other thread? If you've hacked up core classes in Jersey and rebuilt it, and you're getting errors that indicate that class cannot be provisioned - those two things are probably related. Plus your code now has zero portability... – BadZen Jun 07 '16 at 15:51
  • Note, I'm not the author in the other thread. I haven't modified the MessageBodyFactory (yet) as the OP did as I wanted to see first if I could get a customized MessageBodyReader/Writer up and running at all. – Hein Blöd Jun 07 '16 at 15:55

1 Answers1

2

I can't explain the root cause of the exception, but I ran into the same issue and at the time didn't feel like delving any more into the Jersey source than I already had.

I ended up lazily loading my custom MessageBodyReader/Writers so I could inject Providers into the wrapper. It's not pretty but it works.

Something along the lines of:

@Provider
@Consumes( "application/xml" )
public class MyLazyMessageBodyReader implements MessageBodyReader<Object> {
  @Context
  private Providers ps;

  private MessageBodyReader<Object> reader;

  @Override
  public final Object readFrom(
          Class<Object> type,
          Type type1,
          Annotation[] antns,
          MediaType mt,
          MultivaluedMap<String, String> mm,
          InputStream in)
          throws IOException, WebApplicationException
  {
    return this.getLazyReader().readFrom(type, type1, antns, mt, mm, in);
  }

  private MessageBodyReader<Object> getLazyReader() {
    if (this.reader == null) {
      this.reader = new MyMessageBodyReader(this.ps);
    }
    return this.reader;
  }
}

public class MyMessageBodyReader implements MessageBodyReader<Object> {
   public MyMessageBodyReader(Providers ps) {
      // try to do something with ps here
      // e.g. pass to a superclass constructor,
      // as required by the solution in the other thread
   }

   [...] // implemented interface methods
}
David Kleszyk
  • 642
  • 3
  • 10