Glue Path Configuration in Cucumber JVM
What Is Glue Path Configuration?
Glue Path Configuration is the process of telling Cucumber where to find the Java classes that implement the steps written in feature files. A feature file may contain readable Gherkin lines such as Given the user opens the application, but Cucumber cannot execute that sentence until it finds a matching Java method. The glue path is the configuration that tells Cucumber where those Java methods and related Cucumber support classes are located.
Glue is not limited to step definitions. It can include hooks such as @Before and @After, custom parameter types, data table type mappings, doc string type mappings, and other Cucumber-specific support classes. In simple terms, the glue path points Cucumber to the automation code needed to execute business-readable scenarios.
Without the correct glue path, Cucumber can still read feature files. It can parse Feature, Scenario, Given, When, and Then lines. But when execution starts, it will fail to match steps and usually reports undefined step errors. This is why glue configuration is one of the first things to check when a new Cucumber framework is not running correctly.
Why Is Glue Needed?
Consider a login feature file. The scenario says the user opens the application, enters valid credentials, and sees the dashboard. These are readable business steps. Cucumber needs Java code behind each step. The sentence Given the user opens the application may map to a method annotated with @Given("the user opens the application"). The glue path tells Cucumber which package should be scanned to find that method.
@Given("the user opens the application")
public void openApplication() {
driver.get(config.getBaseUrl());
}
The feature file and the Java method are connected only when Cucumber discovers the method through glue scanning. If the method exists in the project but the package is not included in the glue path, Cucumber behaves as if the method does not exist. This can confuse beginners because the code appears correct, but it is invisible to Cucumber execution.
Execution Flow
The glue discovery flow begins with the runner class. The runner reads the Cucumber configuration, locates feature files, reads the glue path, scans the configured Java packages, identifies step definitions and hooks, matches feature steps, and then executes the Java methods.
Runner Class
-> Read Glue Path
-> Locate Step Definition Classes
-> Locate Hooks and Types
-> Match Feature Steps
-> Execute Java Methods
This flow explains many common problems. If feature files are discovered but every step is undefined, the feature path is probably correct but the glue path is wrong. If steps execute but hooks do not run, the step definition package may be included but the hooks package may be missing. If custom parameter types are not recognized, the package containing those parameter type definitions may not be included.
What Does Glue Include?
Glue usually includes several types of Cucumber code. Step definitions map Gherkin steps to Java methods. Hooks run setup and teardown logic before or after scenarios. Custom parameter types convert text into richer values. Data table types convert table rows into objects. Doc string types convert multiline text into structured data. All these pieces must be discoverable through glue configuration.
glue
stepdefinitions
hooks
common
parameter types
data table types
doc string types
Page objects, API clients, utilities, and service classes are often used by step definitions, but they are not always Cucumber glue themselves. They do not need to be in glue unless they contain Cucumber annotations. Keeping this distinction clear helps prevent bloated glue packages and keeps the framework easier to reason about.
Configuring Glue in JUnit 4 and TestNG
In JUnit 4 and TestNG based projects, glue is commonly configured inside @CucumberOptions. The value should be a Java package name, not a file system path.
@CucumberOptions(
features = "src/test/resources/features",
glue = "stepdefinitions"
)
public class TestRunner {
}
This configuration tells Cucumber to search the stepdefinitions Java package. If hooks are stored in a separate package, that package must also be included unless a common parent package already covers it.
@CucumberOptions(
features = "src/test/resources/features",
glue = {"stepdefinitions", "hooks", "common"}
)
This is common in enterprise frameworks where step definitions, hooks, and shared Cucumber components are separated for maintainability.
Configuring Glue in JUnit 5
Modern Cucumber projects using JUnit Platform configure glue through Cucumber configuration parameters. The exact location may be a suite class, junit-platform.properties, Maven configuration, or Gradle configuration.
@ConfigurationParameter(
key = GLUE_PROPERTY_NAME,
value = "stepdefinitions"
)
The concept is the same as JUnit 4 or TestNG. Cucumber still needs a package name to scan. The difference is only the configuration mechanism. New JUnit 5 projects often prefer platform configuration, while many existing automation frameworks still use @CucumberOptions.
Package Name vs Folder Path
A critical rule is that glue uses Java package names, not file system paths. If a Java file is stored at src/test/java/com/project/steps/LoginSteps.java and the class declares package com.project.steps;, then the glue should be com.project.steps. It should not be src/test/java/com/project/steps.
| Wrong | Correct |
|---|---|
glue = "src/test/java/stepdefinitions" | glue = "stepdefinitions" |
glue = "src/test/java/com/project/steps" | glue = "com.project.steps" |
This distinction is a frequent interview question and a common framework setup mistake. Java package names are logical namespaces. File system paths are physical locations. Cucumber expects package names for glue.
Recursive Package Search
When a parent package is configured as glue, Cucumber can discover classes in subpackages. If the project has com.project.steps.login, com.project.steps.payment, and com.project.steps.customer, configuring com.project.steps can cover all those child packages.
This makes parent package configuration useful in large frameworks. Instead of listing every child package, teams can point to a stable parent package. However, the parent should not be too broad. Configuring the root of the entire test codebase may work, but it can also scan unrelated classes and hide poor organization. A good parent package includes Cucumber-specific code without swallowing everything in the framework.
Glue for Hooks and Custom Types
Hooks are discovered through glue just like step definitions. If hooks are stored in a package named hooks and the runner includes only stepdefinitions, the hooks will not execute. This can cause missing browser setup, missing cleanup, missing screenshot capture, or missing scenario context initialization.
Custom parameter types, data table types, and doc string types follow the same rule. If a class contains @ParameterType, @DataTableType, or @DocStringType, it must be inside a configured glue package. Otherwise Cucumber cannot use the mapping during step execution.
Glue Path vs Feature Path
Feature path and glue path solve different problems. Feature path tells Cucumber where to find Gherkin files. Glue path tells Cucumber where to find Java implementation code. Both are required for successful execution.
| Configuration | Contains | Purpose |
|---|---|---|
| Feature path | .feature files | Discovers scenarios |
| Glue path | Java packages | Discovers step code and hooks |
If the feature path is wrong, scenarios are not found. If the glue path is wrong, scenarios are found but steps are undefined or hooks are skipped. Debugging becomes easier when these responsibilities are separated clearly.
Common Mistakes
The first common mistake is using a folder path instead of a package name. The second is configuring only the step definition package and forgetting hooks or common Cucumber component packages. The third is placing custom parameter types outside the glue path. The fourth is using a package name that does not match the actual package declaration in the Java class.
Another mistake is putting too much inside glue packages. Utility classes without Cucumber annotations do not need to be glue. Page objects should usually be called by step definitions, not treated as step definitions themselves. Keeping glue focused improves framework clarity.
Best Practices
Use Java package names in glue configuration. Keep step definitions, hooks, and Cucumber-specific shared components in organized packages. Use a common parent package when it simplifies configuration without scanning unrelated code. Keep glue code under src/test/java. Separate business workflow and UI interaction logic into page objects, services, clients, and utilities rather than overloading step definitions.
For enterprise frameworks, a clean package structure might use com.company.automation.stepdefinitions, com.company.automation.hooks, and com.company.automation.common. The runner may point to com.company.automation if that parent covers all Cucumber-specific packages. This makes future additions easier because new step packages under the parent are discovered automatically.
Real-Time Enterprise Example
In a real Selenium and API automation framework, glue configuration usually sits beside other runner settings. The framework may have feature files under src/test/resources/features, step definitions under com.company.automation.stepdefinitions, hooks under com.company.automation.hooks, and shared Cucumber converters under com.company.automation.common. Page objects, API clients, database helpers, and utility classes may live under other packages, but they are called by step definitions rather than directly discovered as glue.
com.company.automation
runners
stepdefinitions
login
payment
customer
hooks
common
pages
services
utilities
A runner can use glue = "com.company.automation" when the team wants Cucumber to discover all Cucumber-specific packages under the common parent. This is simple and maintainable. Another team may prefer glue = {"com.company.automation.stepdefinitions", "com.company.automation.hooks", "com.company.automation.common"} to be more explicit. Both approaches can work. The better choice depends on package discipline and project size.
The most important design rule is that step definitions should stay thin. They should connect Gherkin steps to the automation layer, not contain long Selenium scripts or business algorithms. Glue configuration finds the step definitions, but clean framework design decides what those step definitions do after they are found.
Troubleshooting Glue Problems
When a Cucumber run fails with undefined steps, first verify the step text and annotation pattern. If the text is correct, verify the Java package declaration at the top of the step definition class. Then compare that package to the runner's glue configuration. Many problems are caused by a mismatch between the package declared in Java and the package listed in the runner.
If hooks do not execute, check whether the hook class package is inside the glue path. If custom parameter types do not work, check whether the class containing @ParameterType is discoverable. If data table transformations are ignored, check whether the class containing @DataTableType is included. Glue problems are not limited to ordinary step definitions.
A useful debugging strategy is to temporarily create one tiny feature file and one tiny step definition in the expected glue package. If Cucumber finds that simple step, the runner configuration is basically correct. Then move outward to hook packages, common packages, and module-specific step packages. Debugging glue in layers is faster than changing many paths at once.
How Glue Design Affects Maintainability
Glue path configuration seems like a small runner setting, but it affects long-term maintainability. If glue packages are messy, duplicate steps become common. If every module has its own unrelated package style, new team members struggle to know where to add step definitions. If glue points to a very broad root package, unrelated classes may be scanned and the project structure becomes less intentional.
A mature project has a predictable naming convention. Login steps go under login-related step packages. Payment steps go under payment-related packages. Shared step phrases are carefully reviewed before being added. Hooks are centralized or clearly separated by purpose. Parameter and data table transformations are placed in common Cucumber support packages. With this structure, the glue path becomes stable and rarely needs changes.
Interview-Ready Summary
Glue Path Configuration tells Cucumber where to locate step definitions, hooks, parameter types, data table types, doc string types, and other Cucumber-specific Java classes. In JUnit 4 and TestNG projects, glue is configured using the glue attribute of @CucumberOptions. In JUnit 5 projects, glue is configured through JUnit Platform configuration such as GLUE_PROPERTY_NAME.
The most important rule is that glue values are Java package names, not directory paths. Correct feature path and correct glue path are both required. The golden rule is simple: feature path finds scenarios, glue path finds the automation code that executes those scenarios.