This is an automated email from the ASF dual-hosted git repository.
jongyoul pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zeppelin.git
The following commit(s) were added to refs/heads/master by this push:
new 5d1ede4dad [ZEPPELIN-6416] Fix zeppelin-interpreter-shaded leak via
zeppelin-jupyter-interpreter scope
5d1ede4dad is described below
commit 5d1ede4dad1224edac8eaa44f71a53bb5865cd84
Author: Jongyoul Lee <[email protected]>
AuthorDate: Thu May 14 09:55:36 2026 +0900
[ZEPPELIN-6416] Fix zeppelin-interpreter-shaded leak via
zeppelin-jupyter-interpreter scope
### What is this PR for?
Fixes a regression that breaks all Selenium integration tests in
`zeppelin-integration` (`InterpreterIT`, `AuthenticationIT`, `ZeppelinIT`,
`InterpreterModeActionsIT`, `SparkParagraphIT`, `PersonalizeActionsIT`,
`ParagraphActionsIT`) on master since the [ZEPPELIN-6355] zengine→server merge.
They abort during `MiniZeppelinServer` startup with:
```
java.lang.ClassCastException: class
shaded.org.apache.zeppelin.org.eclipse.aether.repository.RemoteRepository
cannot be cast to class org.eclipse.aether.repository.RemoteRepository
(... in unnamed module of loader 'app')
at
org.apache.zeppelin.interpreter.InterpreterSettingManager.<init>(InterpreterSettingManager.java:186)
```
#### Scope of impact
* **CI**: `frontend.yml` selenium IT job has been red on every master push
since 2026-05-05, blocking PR merges.
* **Runtime**: *no production impact*. The Zeppelin distribution does not
ship `zeppelin-interpreter-shaded.jar` on the server JVM classpath; the two-JVM
isolation introduced by [ZEPPELIN-3689] still holds for deployed installations.
The leak is confined to `zeppelin-integration`'s test classpath.
#### Root cause
`zeppelin-jupyter-interpreter/pom.xml` re-declared its dependency on
`zeppelin-interpreter-shaded` *without scope*, silently overriding the parent's
`<scope>provided</scope>` and downgrading it to compile. That made the shaded
jar transitive to anyone depending on `zeppelin-jupyter-interpreter` — in
particular `spark-interpreter` (because `IPySparkInterpreter` extends
`IPythonInterpreter` which extends `JupyterKernelInterpreter`), and onward into
`zeppelin-integration`'s test classpat [...]
Both unshaded `zeppelin-interpreter.jar` and
`zeppelin-interpreter-shaded.jar` end up in the same test JVM. Because the
shade plugin keeps `org.apache.zeppelin.dep.*` class names un-relocated (per
`<exclude>org/apache/zeppelin/**</exclude>`) but rewrites their internal
`org.eclipse.aether.*` references to
`shaded.org.apache.zeppelin.org.eclipse.aether.*`, both jars contain
identically-named `Booter` / `Repository` / `DependencyResolver` classes that
disagree on the `RemoteRepository` [...]
The scope-omission has been latent since 2019-12 ([ZEPPELIN-4497]). The
[ZEPPELIN-6355] merge changed the dependency-resolution order in
`zeppelin-integration`'s test classpath and exposed it.
### What type of PR is it?
Bug Fix
### Todos
* [x] Drop the redundant `zeppelin-interpreter-shaded` redeclaration in
`zeppelin-jupyter-interpreter/pom.xml` so the parent's `provided` applies
* [x] Add `maven-enforcer-plugin` `bannedDependencies` rule on
`zeppelin-server` and `zeppelin-integration` to catch any future leak
* [x] Verify `mvn dependency:tree` is clean for `zeppelin-server` and
`zeppelin-integration`
* [x] Verify the enforcer rule fails as expected when the leak is
reintroduced (negative test)
* [ ] Verify `frontend.yml` selenium IT goes green on this PR
### What is the Jira issue?
* https://issues.apache.org/jira/browse/ZEPPELIN-6416 — this PR
* https://issues.apache.org/jira/browse/ZEPPELIN-6417 — follow-up: extract
`zeppelin-jupyter-kernel-client` library so interpreter modules never depend on
the `%jupyter` magic interpreter artifact directly (structural decoupling)
### How should this be tested?
```bash
# 1. Verify dep tree is clean (no zeppelin-interpreter-shaded)
./mvnw -pl zeppelin-server dependency:tree -Pintegration
-Pspark-scala-2.12 -Pspark-3.5 | grep zeppelin-interpreter-shaded
./mvnw -pl zeppelin-integration dependency:tree -Pintegration
-Pspark-scala-2.12 -Pspark-3.5 | grep zeppelin-interpreter-shaded
# both should produce no matches
# 2. Verify enforcer rule passes
./mvnw validate -pl zeppelin-server,zeppelin-integration -Pintegration
-Pspark-scala-2.12 -Pspark-3.5
# 3. Negative test: reintroduce the leak (revert the jupyter-interpreter
pom hunk) and run #2;
# enforcer should fail with a BannedDependencies error pointing to
ZEPPELIN-6416.
# 4. Full CI: rely on this PR's frontend.yml run.
```
### Screenshots (if appropriate)
N/A
### Questions
* Does the license files need to update? **No** — pom-only change.
* Is there breaking changes for older versions? **No**.
* Does this needs documentation? **No**.
Closes #5246 from jongyoul/ZEPPELIN-6416-jupyter-shaded-leak-fix.
Signed-off-by: Jongyoul Lee <[email protected]>
---
zeppelin-integration/pom.xml | 23 +++++++++++++++++++++++
zeppelin-jupyter-interpreter/pom.xml | 12 +++++++-----
zeppelin-server/pom.xml | 31 +++++++++++++++++++++++++++++++
3 files changed, 61 insertions(+), 5 deletions(-)
diff --git a/zeppelin-integration/pom.xml b/zeppelin-integration/pom.xml
index 5bdd890b83..fe665f2d01 100644
--- a/zeppelin-integration/pom.xml
+++ b/zeppelin-integration/pom.xml
@@ -185,6 +185,29 @@
<id>enforce-dependency-convergence</id>
<phase>none</phase>
</execution>
+ <execution>
+ <id>enforce-no-interpreter-shaded-leak</id>
+ <goals>
+ <goal>enforce</goal>
+ </goals>
+ <configuration>
+ <rules>
+ <bannedDependencies>
+ <excludes>
+
<exclude>org.apache.zeppelin:zeppelin-interpreter-shaded</exclude>
+ </excludes>
+ <searchTransitive>true</searchTransitive>
+ <message>
+ zeppelin-interpreter-shaded must NOT appear on the
zeppelin-integration test classpath.
+ MiniZeppelinServer instantiates ZeppelinServer in-process;
mixing shaded and unshaded
+ org.eclipse.aether.* in the same JVM causes
ClassCastException in
+ InterpreterSettingManager. See ZEPPELIN-6416.
+ </message>
+ </bannedDependencies>
+ </rules>
+ <fail>true</fail>
+ </configuration>
+ </execution>
</executions>
</plugin>
</plugins>
diff --git a/zeppelin-jupyter-interpreter/pom.xml
b/zeppelin-jupyter-interpreter/pom.xml
index adeda333b5..4651e0f473 100644
--- a/zeppelin-jupyter-interpreter/pom.xml
+++ b/zeppelin-jupyter-interpreter/pom.xml
@@ -84,11 +84,13 @@
<artifactId>commons-codec</artifactId>
</dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>zeppelin-interpreter-shaded</artifactId>
- <version>${project.version}</version>
- </dependency>
+ <!--
+ zeppelin-interpreter-shaded is inherited from
zeppelin-interpreter-parent with <scope>provided</scope>.
+ Do NOT re-declare it here without that scope (ZEPPELIN-6416): doing so
silently downgrades it to
+ the default compile scope and leaks the shaded jar into transitive
consumers (e.g. spark-interpreter,
+ and onward into zeppelin-integration's test classpath), which causes
ClassCastException between
+ shaded and unshaded org.eclipse.aether.repository.RemoteRepository
inside InterpreterSettingManager.
+ -->
<dependency>
<groupId>${project.groupId}</groupId>
diff --git a/zeppelin-server/pom.xml b/zeppelin-server/pom.xml
index 6844c96428..6c6b9a0b26 100644
--- a/zeppelin-server/pom.xml
+++ b/zeppelin-server/pom.xml
@@ -593,6 +593,37 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
</plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-enforcer-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>enforce-no-interpreter-shaded-leak</id>
+ <goals>
+ <goal>enforce</goal>
+ </goals>
+ <configuration>
+ <rules>
+ <bannedDependencies>
+ <excludes>
+
<exclude>org.apache.zeppelin:zeppelin-interpreter-shaded</exclude>
+ </excludes>
+ <searchTransitive>true</searchTransitive>
+ <message>
+ zeppelin-interpreter-shaded must NOT appear on the
zeppelin-server classpath.
+ The shaded jar is meant for interpreter JVMs only (loaded
from
+
${ZEPPELIN_HOME}/interpreter/zeppelin-interpreter-shaded-*.jar). Mixing the
shaded
+ and unshaded org.eclipse.aether.* on the server classpath
causes ClassCastException
+ in InterpreterSettingManager. See ZEPPELIN-6416.
+ </message>
+ </bannedDependencies>
+ </rules>
+ <fail>true</fail>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>