@Inject With @Provides Cannot Find Matching Constructor

1,861 views
Skip to first unread message

michael....@farecompare.com

unread,
Jul 26, 2013, 3:10:50 PM7/26/13
to google...@googlegroups.com
Hi, 

I'm still pretty new to Guice and I feel like I'm missing something very basic. I have an annotated object Foo that I need constructed with an injected dependency Bar. The Bar object requires some construction on my part that is usually handled with a Builder or Factory because of the parameters needed for it's contractor. My simple hypothetical example might look like the following: 

public class Foo {
   private Bar bar;

   @Inject
   public Foo( Bar bar ) { this.bar = bar; }
}

public class Bar {

   public Bar( int x, int y, int z ) {
      // Bar is initialized via the parameters passed to this constructor. No default constructor provided. Normally a builder knows how to construct Bar, but I want Guice to do it.
   }
}

Now here is my Module: 

public class FooModule implements Module
{
   public void configure(final Binder binder)
   {
      binder.bind(Foo.class);
   }
      
   @Provides
   public Bar provideBar() {
      return new Bar( 1, 2, 3 );
   }   
}

The problem is that when I start up my app, I get the following error: 

SEVERE: Exception sending context initialized event to listener instance of class org.jboss.resteasy.plugins.guice.GuiceResteasyBootstrapServletContextListener

java.lang.RuntimeException: Unable to find a public constructor for class Foo

at org.jboss.resteasy.plugins.server.resourcefactory.POJOResourceFactory.registered(POJOResourceFactory.java:35)

at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:120)

at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:106)

at org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:83)

at org.jboss.resteasy.core.ResourceMethodRegistry.addPerRequestResource(ResourceMethodRegistry.java:72)


It appears to me that it is trying to locate a default no-args constructor and is ignoring the constructor in Foo that takes a Bar as a parameter. And finally, it doesn't appear to now how to map that to the @Provides defined in the module that builds the object when requested. 


Am I missing something? Could this simply be a problem in the Resteasy Guice implementation? Or is it just something basic about Guice that I'm not understanding? All the examples I've downloaded and scanned seem to always use very simple objects with default constructors. I know there's a way to do this. I've tried adding @Named("Bar") to my @Provides method and the corresponding @Inject method parameter. Still does not work.


Any help would be greatly appreciated.


Thanks,


Michael

Sam Berlin

unread,
Jul 26, 2013, 3:27:05 PM7/26/13
to google...@googlegroups.com
The stack trace doesn't appear to have anything to do with Guice.  I'm not really familiar with resteasy -- are you certain it's actually using Guice?  It looks to me like it's just doing its own thing and failing.


--
You received this message because you are subscribed to the Google Groups "google-guice" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-guice...@googlegroups.com.
To post to this group, send email to google...@googlegroups.com.
Visit this group at http://groups.google.com/group/google-guice.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

michael....@farecompare.com

unread,
Jul 26, 2013, 3:37:17 PM7/26/13
to google...@googlegroups.com
Well that's a good point. I assumed I was doing something wrong on the Guice Module side because I couldn't find any examples doing what I'm trying to do there. And it seems like magic how Guice understands that it has to call the @Provides method to get back an object of type Bar. I guess I'm wondering if I need to tell it somehow ... am I missing something? Should the code above work? 

One thing I wondered ... do I need to add this line to the configure() method: 

... binder.bind(Bar.class);

Again, how does it know that to construct Foo it will need a Bar, and to construct a Bar it needs to call FooModule.provideBar()? This is the source of my confusion and why I think I'm doing something wrong here.

michael....@farecompare.com

unread,
Jul 26, 2013, 3:57:20 PM7/26/13
to google...@googlegroups.com
Ok Sam, looks like you were right. I got it to work. Problem was in my web.xml for my Resteasy app. In case anyone makes the same mistake, here is what I had to change: 

    <context-param>

        <param-name>resteasy.scan</param-name>

        <param-value>false</param-value>   

    </context-param>

    <!-- NEEDED TO REMOVE THE RESTEASY RESOURCE LIST 

    <context-param>

        <param-name>resteasy.resources</param-name>

        <param-value>Foo</param-value>   

    </context-param>

    -->

    <context-param>

        <param-name>resteasy.guice.modules</param-name>

        <param-value>FooModule</param-value>

    </context-param>


Having both the guice.modules and rest easy.resources defined was redundant and caused the problem. 

Michael

On Friday, July 26, 2013 2:27:05 PM UTC-5, Sam Berlin wrote:

Sam Berlin

unread,
Jul 26, 2013, 4:02:34 PM7/26/13
to google...@googlegroups.com
There's absolutely nothing in your stack trace that indicates Guice is involved anywhere.  If Guice were involved, this should work.  Guice looks at @Provides methods and basically creates binding statements that bind the return type to a "provider" that calls your method.

 sam


Reply all
Reply to author
Forward
Message has been deleted
0 new messages