Repository: cucumber/cucumber-jvm

Issue #2469: class *ClassWithSteps* does not have a public zero-argument constructor
Created: 2022-01-20T13:25:49Z
Describe the bug
After upgrading from 7.0.0 to any version from 7.1.0 to 7.2.3, the following error occurs when trying to run Cucumber through io.cucumber.core.cli.Main. It's basically the same problem mentioned in #2431 , but now with a reproducible example.
io.cucumber.core.exception.CucumberException: class *ClassWithSteps* does not have a public zero-argument constructor.

To use dependency injection add an other ObjectFactory implementation such as:
 * cucumber-picocontainer
 * cucumber-spring
 * cucumber-jakarta-cdi
 * ...etc

To Reproduce
Steps to reproduce the behavior:

Clone this project: https://github.com/ralphavalon/cucumber-issue
Build it ( docker run -it --rm -v "$(pwd)":/usr/src/mymaven -w /usr/src/mymaven maven:3-adoptopenjdk-15 mvn clean package )
Run it ( docker run -v "$PWD":/home -w /home openjdk:15-jdk java -jar target/demo-0.0.1-SNAPSHOT-fat-testjar.jar )

Expected behavior
The expected behavior is to run the tests with no error, as it happens when you change cucumber version to 7.0.0 in the reproducible example.
Context & Motivation
While upgrading libraries to the latest to stay up-to-date, faced this issue and stopped this upgrade.
Environment
On the reproducible example:
Cucumber version: 7.2.2
Java 15
Maven 3.6.1
Used modules: cucumber-java, cucumber-core, cucumber-junit, cucumber-picocontainer
Additional context
On the reproducible example it's generated a jar through the assembly plugin that should run the cucumber command.
Let me know if you need any more information.

Duplicate issue #2746: CucumberException: class does not have a public zero-argument constructor
Created: 2023-05-03T11:49:42Z
👓 What did you see?
@Demo
Scenario Outline: Saying hello to the Server with JDK HttpClient # Hello.feature:38
  Given Server is alive                                          # nl.altindag.client.stepdefs.HelloStepDefs.serverIsAlive()
      io.cucumber.core.exception.CucumberException: class nl.altindag.client.stepdefs.HelloStepDefs does not have a public zero-argument constructor.

To use dependency injection add an other ObjectFactory implementation such as:
 * cucumber-picocontainer
 * cucumber-spring
 * cucumber-jakarta-cdi
 * ...etc

	at io.cucumber.core.backend.DefaultObjectFactory.cacheNewInstance(DefaultObjectFactory.java:57)
	at io.cucumber.core.backend.DefaultObjectFactory.getInstance(DefaultObjectFactory.java:45)
	at io.cucumber.java.AbstractGlueDefinition.invokeMethod(AbstractGlueDefinition.java:47)
	at io.cucumber.java.JavaStepDefinition.execute(JavaStepDefinition.java:29)
	at io.cucumber.core.runner.CoreStepDefinition.execute(CoreStepDefinition.java:66)
	at io.cucumber.core.runner.PickleStepDefinitionMatch.runStep(PickleStepDefinitionMatch.java:63)
	at io.cucumber.core.runner.ExecutionMode$1.execute(ExecutionMode.java:10)
	at io.cucumber.core.runner.TestStep.executeStep(TestStep.java:86)
	at io.cucumber.core.runner.TestStep.run(TestStep.java:57)
	at io.cucumber.core.runner.PickleStepTestStep.run(PickleStepTestStep.java:51)
	at io.cucumber.core.runner.TestCase.run(TestCase.java:95)
	at io.cucumber.core.runner.Runner.runPickle(Runner.java:75)
	at io.cucumber.core.runtime.Runtime.lambda$executePickle$6(Runtime.java:128)
	at io.cucumber.core.runtime.CucumberExecutionContext.lambda$runTestCase$3(CucumberExecutionContext.java:151)
	at io.cucumber.core.runtime.RethrowingThrowableCollector.executeAndThrow(RethrowingThrowableCollector.java:23)
	at io.cucumber.core.runtime.CucumberExecutionContext.runTestCase(CucumberExecutionContext.java:151)
	at io.cucumber.core.runtime.Runtime.lambda$executePickle$7(Runtime.java:128)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at io.cucumber.core.runtime.Runtime$SameThreadExecutorService.execute(Runtime.java:249)
	at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:123)
	at io.cucumber.core.runtime.Runtime.lambda$runFeatures$3(Runtime.java:110)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.SliceOps$1$1.accept(SliceOps.java:200)
	at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1602)
	at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
	at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
	at io.cucumber.core.runtime.Runtime.runFeatures(Runtime.java:111)
	at io.cucumber.core.runtime.Runtime.lambda$run$0(Runtime.java:82)
	at io.cucumber.core.runtime.Runtime.execute(Runtime.java:94)
	at io.cucumber.core.runtime.Runtime.run(Runtime.java:80)
	at io.cucumber.core.cli.Main.run(Main.java:87)
	at io.cucumber.core.cli.Main.main(Main.java:30)
	at nl.altindag.client.ClientRunner.main(ClientRunner.java:34)
Caused by: java.lang.NoSuchMethodException: nl.altindag.client.stepdefs.HelloStepDefs.<init>()
	at java.base/java.lang.Class.getConstructor0(Class.java:3585)
	at java.base/java.lang.Class.getConstructor(Class.java:2271)
	at io.cucumber.core.backend.DefaultObjectFactory.cacheNewInstance(DefaultObjectFactory.java:52)
	... 38 more

  When I say hello with "JDK HttpClient"                         # nl.altindag.client.stepdefs.HelloStepDefs.iSayHelloWithClient(java.lang.String)
  Then I expect to receive status code 200                       # nl.altindag.client.stepdefs.HelloStepDefs.iExpectToReceiveStatusCodeStatusCode(int)
  And I expect to receive "Hello" message                        # nl.altindag.client.stepdefs.HelloStepDefs.iExpectToReceiveBody(java.lang.String)
  And I display the time it took to get the message              # nl.altindag.client.stepdefs.HelloStepDefs.iDisplayTheTimeItTookToGetTheMessage()

Failed scenarios:
classpath:Hello.feature:38 # Saying hello to the Server with JDK HttpClient

1 Scenarios (1 failed)
5 Steps (1 failed, 4 skipped)
0m0.474s


io.cucumber.core.exception.CucumberException: class nl.altindag.client.stepdefs.HelloStepDefs does not have a public zero-argument constructor.

To use dependency injection add an other ObjectFactory implementation such as:
 * cucumber-picocontainer
 * cucumber-spring
 * cucumber-jakarta-cdi
 * ...etc

	at io.cucumber.core.backend.DefaultObjectFactory.cacheNewInstance(DefaultObjectFactory.java:57)
	at io.cucumber.core.backend.DefaultObjectFactory.getInstance(DefaultObjectFactory.java:45)
	at io.cucumber.java.AbstractGlueDefinition.invokeMethod(AbstractGlueDefinition.java:47)
	at io.cucumber.java.JavaStepDefinition.execute(JavaStepDefinition.java:29)
	at io.cucumber.core.runner.CoreStepDefinition.execute(CoreStepDefinition.java:66)
	at io.cucumber.core.runner.PickleStepDefinitionMatch.runStep(PickleStepDefinitionMatch.java:63)
	at io.cucumber.core.runner.ExecutionMode$1.execute(ExecutionMode.java:10)
	at io.cucumber.core.runner.TestStep.executeStep(TestStep.java:86)
	at io.cucumber.core.runner.TestStep.run(TestStep.java:57)
	at io.cucumber.core.runner.PickleStepTestStep.run(PickleStepTestStep.java:51)
	at io.cucumber.core.runner.TestCase.run(TestCase.java:95)
	at io.cucumber.core.runner.Runner.runPickle(Runner.java:75)
	at io.cucumber.core.runtime.Runtime.lambda$executePickle$6(Runtime.java:128)
	at io.cucumber.core.runtime.CucumberExecutionContext.lambda$runTestCase$3(CucumberExecutionContext.java:151)
	at io.cucumber.core.runtime.RethrowingThrowableCollector.executeAndThrow(RethrowingThrowableCollector.java:23)
	at io.cucumber.core.runtime.CucumberExecutionContext.runTestCase(CucumberExecutionContext.java:151)
	at io.cucumber.core.runtime.Runtime.lambda$executePickle$7(Runtime.java:128)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at io.cucumber.core.runtime.Runtime$SameThreadExecutorService.execute(Runtime.java:249)
	at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:123)
	at io.cucumber.core.runtime.Runtime.lambda$runFeatures$3(Runtime.java:110)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.SliceOps$1$1.accept(SliceOps.java:200)
	at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1602)
	at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
	at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
	at io.cucumber.core.runtime.Runtime.runFeatures(Runtime.java:111)
	at io.cucumber.core.runtime.Runtime.lambda$run$0(Runtime.java:82)
	at io.cucumber.core.runtime.Runtime.execute(Runtime.java:94)
	at io.cucumber.core.runtime.Runtime.run(Runtime.java:80)
	at io.cucumber.core.cli.Main.run(Main.java:87)
	at io.cucumber.core.cli.Main.main(Main.java:30)
	at nl.altindag.client.ClientRunner.main(ClientRunner.java:34)
Caused by: java.lang.NoSuchMethodException: nl.altindag.client.stepdefs.HelloStepDefs.<init>()
	at java.base/java.lang.Class.getConstructor0(Class.java:3585)
	at java.base/java.lang.Class.getConstructor(Class.java:2271)
	at io.cucumber.core.backend.DefaultObjectFactory.cacheNewInstance(DefaultObjectFactory.java:52)
	... 38 more


✅ What did you expect to see?
I would have expected my executable fat jar to be executed sucessfully without any exception.

📦 Which tool/library version are you using?

Java 11
Maven 3.8.3
Cucumber 7.2.3
maven-shade-plugin 3.2.4
Spring 2.6.6
Junit/Jupiter 5.8.2

🔬 How could we reproduce it?
The issue is present within the following project: https://github.com/Hakky54/mutual-tls-ssl
Run the following steps:

run command git clone https://github.com/Hakky54/mutual-tls-ssl.git
run command cd mutual-tls-ssl
run command mvn clean verify
run command java -jar server/target/server.jar
run command java -jar client/target/client.jar

Closing comment (2023-05-03T11:59:18Z): It should work fine provided you've correctly created your fat jar. I suspect you're not correctly merging META-INF/services. You should configure the maven shade plugin to use the ServicesResourceTransformer.
Duplicate of #2469.