Skip to content

Commit 5d1ede4

Browse files
authored
[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 classpath via `<dependency>spark-interpreter</dependency>`. 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` type. Whichever the classloader picks first wins; post-merge the shaded variant wins, so `dependencyResolver.getRepos()` returns shaded `RemoteRepository` instances which fail to cast to the unshaded type expected by `InterpreterSettingManager`. 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 <jongyoul@gmail.com>
1 parent dffe85f commit 5d1ede4

3 files changed

Lines changed: 61 additions & 5 deletions

File tree

zeppelin-integration/pom.xml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,29 @@
185185
<id>enforce-dependency-convergence</id>
186186
<phase>none</phase>
187187
</execution>
188+
<execution>
189+
<id>enforce-no-interpreter-shaded-leak</id>
190+
<goals>
191+
<goal>enforce</goal>
192+
</goals>
193+
<configuration>
194+
<rules>
195+
<bannedDependencies>
196+
<excludes>
197+
<exclude>org.apache.zeppelin:zeppelin-interpreter-shaded</exclude>
198+
</excludes>
199+
<searchTransitive>true</searchTransitive>
200+
<message>
201+
zeppelin-interpreter-shaded must NOT appear on the zeppelin-integration test classpath.
202+
MiniZeppelinServer instantiates ZeppelinServer in-process; mixing shaded and unshaded
203+
org.eclipse.aether.* in the same JVM causes ClassCastException in
204+
InterpreterSettingManager. See ZEPPELIN-6416.
205+
</message>
206+
</bannedDependencies>
207+
</rules>
208+
<fail>true</fail>
209+
</configuration>
210+
</execution>
188211
</executions>
189212
</plugin>
190213
</plugins>

zeppelin-jupyter-interpreter/pom.xml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,13 @@
8484
<artifactId>commons-codec</artifactId>
8585
</dependency>
8686

87-
<dependency>
88-
<groupId>${project.groupId}</groupId>
89-
<artifactId>zeppelin-interpreter-shaded</artifactId>
90-
<version>${project.version}</version>
91-
</dependency>
87+
<!--
88+
zeppelin-interpreter-shaded is inherited from zeppelin-interpreter-parent with <scope>provided</scope>.
89+
Do NOT re-declare it here without that scope (ZEPPELIN-6416): doing so silently downgrades it to
90+
the default compile scope and leaks the shaded jar into transitive consumers (e.g. spark-interpreter,
91+
and onward into zeppelin-integration's test classpath), which causes ClassCastException between
92+
shaded and unshaded org.eclipse.aether.repository.RemoteRepository inside InterpreterSettingManager.
93+
-->
9294

9395
<dependency>
9496
<groupId>${project.groupId}</groupId>

zeppelin-server/pom.xml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,37 @@
593593
<groupId>org.apache.maven.plugins</groupId>
594594
<artifactId>maven-dependency-plugin</artifactId>
595595
</plugin>
596+
597+
<plugin>
598+
<groupId>org.apache.maven.plugins</groupId>
599+
<artifactId>maven-enforcer-plugin</artifactId>
600+
<executions>
601+
<execution>
602+
<id>enforce-no-interpreter-shaded-leak</id>
603+
<goals>
604+
<goal>enforce</goal>
605+
</goals>
606+
<configuration>
607+
<rules>
608+
<bannedDependencies>
609+
<excludes>
610+
<exclude>org.apache.zeppelin:zeppelin-interpreter-shaded</exclude>
611+
</excludes>
612+
<searchTransitive>true</searchTransitive>
613+
<message>
614+
zeppelin-interpreter-shaded must NOT appear on the zeppelin-server classpath.
615+
The shaded jar is meant for interpreter JVMs only (loaded from
616+
${ZEPPELIN_HOME}/interpreter/zeppelin-interpreter-shaded-*.jar). Mixing the shaded
617+
and unshaded org.eclipse.aether.* on the server classpath causes ClassCastException
618+
in InterpreterSettingManager. See ZEPPELIN-6416.
619+
</message>
620+
</bannedDependencies>
621+
</rules>
622+
<fail>true</fail>
623+
</configuration>
624+
</execution>
625+
</executions>
626+
</plugin>
596627
</plugins>
597628
</build>
598629

0 commit comments

Comments
 (0)