Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 10 additions & 19 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,30 +55,24 @@ Apache Zeppelin is a web-based notebook for interactive data analytics. It provi

## Build Gotchas

### Shaded JAR Rebuild Chain
### Interpreter Runtime JAR

The most common build mistake: modifying `zeppelin-interpreter` without rebuilding `zeppelin-interpreter-shaded`. The shaded JAR is an uber JAR that all interpreter processes use. If it's stale, you get `ClassNotFoundException` or `NoSuchMethodError` at runtime.
Packaging `zeppelin-interpreter` produces both the normal Maven artifact and the relocated runtime JAR that every interpreter process uses:

```bash
# After changing zeppelin-interpreter, ALWAYS rebuild in order:
./mvnw clean package -pl zeppelin-interpreter -DskipTests
./mvnw clean package -pl zeppelin-interpreter-shaded -DskipTests
# Then rebuild affected interpreter modules

# Shorthand:
./mvnw clean package -pl zeppelin-interpreter,zeppelin-interpreter-shaded -DskipTests
./mvnw clean package -pl zeppelin-interpreter --am -DskipTests
```

The shaded JAR is also copied to `interpreter/` directory by maven-antrun-plugin after packaging. If this directory has a stale JAR, interpreter processes will load old code.
The normal `zeppelin-interpreter-${version}.jar` remains under `zeppelin-interpreter/target` and is installed or deployed as the module artifact. The build stages the runtime-only `zeppelin-interpreter-shaded-${version}.jar` under `target/`, publishes the complete file to `interpreter/`, and then deletes older versions so interpreter launchers never see multiple matching JARs.

### Module Build Order

Maven modules are ordered in the root `pom.xml`. Key sequence:
```
zeppelin-interpreter → zeppelin-interpreter-shaded → zeppelin-server
zeppelin-interpreter → interpreter modules / zeppelin-server
```

All interpreter modules build after `zeppelin-interpreter-shaded`. A second shading chain exists for Jupyter:
A separate shading chain exists for Jupyter:
```
zeppelin-jupyter-interpreter → zeppelin-jupyter-interpreter-shaded → python
```
Expand All @@ -88,17 +82,17 @@ zeppelin-jupyter-interpreter → zeppelin-jupyter-interpreter-shaded → python
### Dependency Flow

```
zeppelin-interpreter Base API: Interpreter, InterpreterContext, Thrift services
zeppelin-interpreter-shaded Uber JAR (maven-shade-plugin, relocated packages)
zeppelin-interpreter Base API + normal Maven JAR + relocated runtime JAR
interpreter modules Spark, Flink, Python, JDBC, etc.

zeppelin-server Core engine + Jetty 11, REST/WebSocket APIs, HK2 DI, entry point
```

### Core Modules

#### `zeppelin-interpreter/`
The base framework that all interpreters depend on. Defines the interpreter API and the Thrift communication protocol. This module is shaded into an uber JAR (`zeppelin-interpreter-shaded`) and placed on each interpreter process's classpath.
The base framework that all interpreters depend on. Defines the interpreter API and the Thrift communication protocol. Its package phase also builds a relocated runtime JAR under `interpreter/`; that internal file is placed on each interpreter process's classpath but is not installed or deployed as a Maven artifact.

Key classes:
- `Interpreter` (abstract) / `AbstractInterpreter` — base class every interpreter extends
Expand Down Expand Up @@ -137,9 +131,6 @@ Engine / runtime (`org.apache.zeppelin.notebook`, `interpreter`, `scheduler`, `s
- `RecoveryStorage` — persists interpreter process info for server-restart recovery
- `ConfigStorage` — persists interpreter settings to JSON

#### `zeppelin-interpreter-shaded/`
Uses maven-shade-plugin to package `zeppelin-interpreter` + dependencies into an uber JAR with relocated packages (e.g., `org.apache.thrift` → `org.apache.zeppelin.shaded.org.apache.thrift`). This JAR is placed on each interpreter process's classpath.

#### `zeppelin-client/`
REST/WebSocket client library for programmatic access to Zeppelin.

Expand Down
2 changes: 0 additions & 2 deletions bin/interpreter.sh
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,6 @@ if [[ -d "${ZEPPELIN_HOME}/zeppelin-server/target/test-classes" ]]; then
addJarInDirForIntp "${ZEPPELIN_HOME}/zeppelin-server/target/test-classes"
fi

addJarInDirForIntp "${ZEPPELIN_HOME}/zeppelin-interpreter-shaded/target"

HOSTNAME=$(hostname)
ZEPPELIN_SERVER=org.apache.zeppelin.interpreter.remote.RemoteInterpreterServer

Expand Down
4 changes: 4 additions & 0 deletions docs/setup/operation/upgrading.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ So, copying `notebook` and `conf` directory should be enough.

## Migration Guide

### Upgrading from Zeppelin 0.12 to 0.13

- The `org.apache.zeppelin:zeppelin-interpreter-shaded` Maven artifact is no longer published. Custom interpreters should depend on `org.apache.zeppelin:zeppelin-interpreter` with `provided` scope instead. The Zeppelin distribution continues to provide the internal shaded runtime JAR to interpreter processes; custom interpreters should not depend on classes packaged only in that internal runtime JAR. Custom interpreters that use Commons Configuration, Commons BeanUtils, JSR 305, the Maven Plugin API, or Sisu Plexus must now declare those libraries directly instead of relying on transitive dependencies from `zeppelin-interpreter`.

### Upgrading from Zeppelin 0.9, 0.10 to 0.11
- From 0.11, The type of `Pegdown` for parsing markdown was deprecated ([ZEPPELIN-5529](https://issues.apache.org/jira/browse/ZEPPELIN-2619)). It will use `Flexmark` instead.

Expand Down
4 changes: 2 additions & 2 deletions jdbc/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ WORKDIR /zeppelin

RUN chmod +x ./mvnw

RUN ./mvnw clean package -am -pl zeppelin-interpreter-shaded,zeppelin-interpreter,jdbc -DskipTests
RUN ./mvnw clean package -am -pl zeppelin-interpreter,jdbc -DskipTests


FROM openjdk:11
Expand All @@ -32,7 +32,7 @@ COPY --from=builder /zeppelin/bin /zeppelin/bin/
COPY --from=builder /zeppelin/conf /zeppelin/conf

COPY --from=builder /zeppelin/interpreter/jdbc /zeppelin/interpreter/jdbc
COPY --from=builder /zeppelin/zeppelin-interpreter-shaded/target /zeppelin/zeppelin-interpreter-shaded/target
COPY --from=builder /zeppelin/interpreter/zeppelin-interpreter-shaded-*.jar /zeppelin/interpreter/

WORKDIR /zeppelin

Expand Down
8 changes: 7 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
<module>build-tools</module>
<module>zeppelin-interpreter-parent</module>
<module>zeppelin-interpreter</module>
<module>zeppelin-interpreter-shaded</module>
<module>zeppelin-jupyter-interpreter</module>
<module>zeppelin-jupyter-interpreter-shaded</module>
<module>groovy</module>
Expand Down Expand Up @@ -137,6 +136,7 @@
<dropwizard.version>4.2.29</dropwizard.version>
<micrometer.version>1.14.2</micrometer.version>
<findbugs.jsr305.version>3.0.2</findbugs.jsr305.version>
<jsr250.api.version>1.0</jsr250.api.version>

<hadoop.version>3.3.6</hadoop.version>
<hadoop.deps.scope>provided</hadoop.deps.scope>
Expand Down Expand Up @@ -362,6 +362,12 @@
<version>${findbugs.jsr305.version}</version>
</dependency>

<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>${jsr250.api.version}</version>
</dependency>

<!-- Apache Shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
Expand Down
11 changes: 2 additions & 9 deletions python/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,8 @@
</plugin>

<!--
shade for python interpreter is different from other interpreter, it depends on zeppelin-interpreter instead of
zeppelin-interpreter-shaded. Because spark interpreter depends on python interpreter and spark's py4j conflict with python interpreter's py4j.
python interpreter would generate 2 versions of jars, one is shaded jar which is used for running python interpreter, another is normal jar
which is used by spark interpreter as dependency.
Python produces two JARs because Spark depends on the normal Python interpreter JAR while the
standalone Python interpreter needs a shaded JAR to isolate its Py4J dependency.
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand All @@ -156,11 +154,6 @@
<resource>reference.conf</resource>
</transformer>
</transformers>
<artifactSet>
<excludes>
<exclude>org.apache.zeppelin:zeppelin-interpreter-shaded</exclude>
</excludes>
</artifactSet>
<outputFile>${project.build.directory}/../../interpreter/python/${interpreter.jar.name}-${project.version}.jar</outputFile>
</configuration>
<executions>
Expand Down
4 changes: 2 additions & 2 deletions shell/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ WORKDIR /zeppelin

RUN chmod +x ./mvnw

RUN ./mvnw package -am -pl zeppelin-interpreter-shaded,zeppelin-interpreter,shell -DskipTests
RUN ./mvnw package -am -pl zeppelin-interpreter,shell -DskipTests


FROM openjdk:11
Expand All @@ -32,7 +32,7 @@ COPY --from=builder /zeppelin/bin /zeppelin/bin/
COPY --from=builder /zeppelin/conf /zeppelin/conf

COPY --from=builder /zeppelin/interpreter/sh /zeppelin/interpreter/sh
COPY --from=builder /zeppelin/zeppelin-interpreter-shaded/target /zeppelin/zeppelin-interpreter-shaded/target
COPY --from=builder /zeppelin/interpreter/zeppelin-interpreter-shaded-*.jar /zeppelin/interpreter/

WORKDIR /zeppelin

Expand Down
1 change: 0 additions & 1 deletion spark/interpreter/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,6 @@
<exclude>org.scala-lang:scala-reflect</exclude>
<exclude>commons-lang:commons-lang</exclude>
<exclude>org.apache.commons:commons-compress</exclude>
<exclude>org.apache.zeppelin:zeppelin-interpreter-shaded</exclude>
</excludes>
</artifactSet>

Expand Down
5 changes: 3 additions & 2 deletions zeppelin-integration/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,9 @@
</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
The legacy zeppelin-interpreter-shaded Maven artifact 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>
Expand Down
13 changes: 0 additions & 13 deletions zeppelin-interpreter-parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,6 @@
<name>Zeppelin: Interpreter Parent</name>

<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>zeppelin-interpreter-shaded</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-interpreter</artifactId>
Expand Down Expand Up @@ -117,7 +110,6 @@
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
<exclude>org.apache.zeppelin:zeppelin-interpreter-shaded</exclude>
</excludes>
</filter>
</filters>
Expand All @@ -127,11 +119,6 @@
<resource>reference.conf</resource>
</transformer>
</transformers>
<artifactSet>
<excludes>
<exclude>org.apache.zeppelin:zeppelin-interpreter-shaded</exclude>
</excludes>
</artifactSet>
<outputFile>${project.basedir}/../interpreter/${interpreter.name}/${project.artifactId}-${project.version}.jar</outputFile>
</configuration>
<executions>
Expand Down
Loading
Loading