[JVM] PicoContainer UnsatisfiableDependenciesException Problem

1,952 views
Skip to first unread message

Bill Wright

unread,
Feb 24, 2016, 5:02:54 PM2/24/16
to Cukes
Hi all,

I'm having a frustrating problem with my Cucumber-JVM BDD. I use this technique in a number of different projects and it works fine in all of them but one. I've been trying to find the difference between them without any luck and I'm hoping for some help debugging it. My situation is slightly involved. I pull steps from a common library (pulled in via a gradle dependency) and from the current project. My common step defs class looks like this:

public GenericServiceStepDefs(ServiceClient theClient) {
}


I'm using picocontainer for dependency injection and my dependencies are:


dependencies {
testCompile 'org.codehaus.groovy:groovy-all:2.3.6'
testCompile 'info.cukes:cucumber-java:1.2.4'
testCompile 'info.cukes:cucumber-junit:1.2.4'
testCompile 'info.cukes:cucumber-picocontainer:1.2.4'
)

The ServiceClient class is abstract:


abstract class DlxServiceClient {

...
}


The current project is required to implement a concrete subclass. Like I said, I've done this successfully in three other projects. Here's my subclass:


package com.company.audience.audiencedefinition

public class AudienceDefinitionClientService extends ServiceClient {
}


I run this either via gradle or inside of IntelliJ and get the same error, which is this:


org.picocontainer.injectors.AbstractInjector$UnsatisfiableDependenciesException: com.company.audience.common.stepdefs.GenericServiceStepDefs has unsatisfied dependency 'class com.company.audience.common.ServiceClient' for constructor 'public com. company.audience.common.stepdefs.GenericServiceStepDefs(com. company.audience.common.ServiceClient,)' from org.picocontainer.DefaultPicoContainer@7dd712e8:9<|

at org.picocontainer.injectors.ConstructorInjector.getGreediestSatisfiableConstructor(ConstructorInjector.java:191)

at org.picocontainer.injectors.ConstructorInjector.getGreediestSatisfiableConstructor(ConstructorInjector.java:110)

at org.picocontainer.injectors.ConstructorInjector.access$100(ConstructorInjector.java:51)

at org.picocontainer.injectors.ConstructorInjector$1.run(ConstructorInjector.java:331)

at org.picocontainer.injectors.AbstractInjector$ThreadLocalCyclicDependencyGuard.observe(AbstractInjector.java:270)

at org.picocontainer.injectors.ConstructorInjector.getComponentInstance(ConstructorInjector.java:364)

at org.picocontainer.behaviors.AbstractBehavior.getComponentInstance(AbstractBehavior.java:64)

at org.picocontainer.behaviors.Stored.getComponentInstance(Stored.java:91)

at org.picocontainer.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:699)

at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:647)

at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:678)

at cucumber.runtime.java.picocontainer.PicoFactory.getInstance(PicoFactory.java:37)

at cucumber.runtime.java.JavaStepDefinition.execute(JavaStepDefinition.java:38)

at cucumber.runtime.StepDefinitionMatch.runStep(StepDefinitionMatch.java:37)

....


So, it can't find the concrete subclass, right? Or doesn't think it is a valid concrete ServiceClient class. 


My gradle runner has the same configuration as my JUnit runner class. The Gradle runner looks like this:


logger.info("running Cuke tests")
        println
"The classpath used contains this test.output: ${sourceSets.test.output}, which is of type ${sourceSets.test.output.class.name}"
       
println "These are on the classpath from integrationTest:"
       
sourceSets.integrationTest.runtimeClasspath. each {
            println it
        }
        (
new File('build/integration-results')).mkdirs()
        javaexec {
            main =
"cucumber.api.cli.Main"
           
classpath = sourceSets.integrationTest.runtimeClasspath
            args = [

                   
// This is where cucumber will look for step definition classes - you can have as many paths as you like
                   
'--glue',   'com. company.audience.common.stepdefs',
                   
'--glue',   'com. company.audience.audiencedefinition',

                    // Here we can specify either a path to a directory contain .feature files or a specific feature file
                    // or even a specific scenario within a file.
                   
'src/integration/resources',
            ]
        }
    }


The code above prints out the classpath that is passed to the JVM and the first couple of paths are:

...//build/classes/main


and the class file is there:


bill.w.wright:$ ls -ltr .../build/classes/main/com/company/audience/audiencedefinition/

total 8

-rw-r--r--  1 bill.w.wright  staff  3025 Feb 24 12:57 AudienceDefinitionClientService.class



After failing to find a difference between my projects, I tried to debug the Cucumber-JVM code. I'm using version 1.2.4, which uses Picocontainer 2.1.5 without any luck. If I can find where in the code that Picocontainer searches the classpath (or something) for the required classes for the step-definition class constructor. I've been trying to debug in the classes of the stack dump above with no success. I'm hoping that someone knowledgable about Picocontainer code can point me in the right direction to figure this out. 


Thanks for any help or pointers.


Bill

Tim Walker

unread,
Feb 24, 2016, 5:23:23 PM2/24/16
to cu...@googlegroups.com

Do you have a default constructor in your class?

> Thanks for any help or pointers.
>
>
> Bill
>

> --
> Posting rules: http://cukes.info/posting-rules.html
> ---
> You received this message because you are subscribed to the Google Groups "Cukes" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to cukes+un...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

aslak hellesoy

unread,
Feb 24, 2016, 5:51:15 PM2/24/16
to Cucumber Users
On Wed, Feb 24, 2016 at 10:02 PM, Bill Wright <billwr...@gmail.com> wrote:
Hi all,

I'm having a frustrating problem with my Cucumber-JVM BDD.

--

Bill Wright

unread,
Feb 24, 2016, 6:13:06 PM2/24/16
to Cukes
Thanks, Aslak. That's a great link. I really appreciate the quick response here.

Fifteen minutes after posting I figured it out. I had thought that PicoContainer somehow searched the classpath to find a concrete subclass to satisfy the Cucumber request to make a given Step-def class. After reading more on the PicoContainer.com site I realized that Picocontainer doesn't do that. It just manages whatever classes you tell it to manage. Cucumber was only telling it to manage Step-def classes and PicoContainer will manage any direct constructor-argument classes. The problem was that I had no Step-def classes that explicitly took the concrete subclass in its constructor. Hence, PicoContainer couldn't find it. It doesn't go about searching the entire classpath. I know that now. The solution was, and would be when I finished fleshing out all my steps, would be to have at least one Step-def class explicitly take the concrete class in the constructor. I spent a day learning that... Next time I'll reach out for help after half a day. :-)

And I'll study Aslak's blog link and maybe use that approach as well.

Thanks,
Bill

SIVVA K

unread,
Jul 30, 2016, 10:23:05 AM7/30/16
to Cukes
Hi Bill,

i am also currently encountering the same issue. can you please explain in detail with an example about the fix ?
already wasted a day on this :( the quicker the better.
Thanks in advance
Sivva
Reply all
Reply to author
Forward
0 new messages