deploying-java-sdk-bundles

Par astronomer · agents

Compile et déploie les bundles du SDK Java Airflow afin que les workers puissent les exécuter. À utiliser lorsque l'utilisateur souhaite packager un bundle de tâches JVM dans un JAR, pose des questions sur le plugin Gradle `org.apache.airflow.sdk`, `./gradlew bundle`, la configuration Maven shade/BOM, les JARs fat vs thin, les artefacts d'intégration de logging (JPL, SLF4J, Log4j 2, JUL), les builds preview/snapshot, ou le déploiement du JAR sur un worker Airflow (Docker, Kubernetes ou Astro). Pour le code des tâches, voir authoring-java-sdk-tasks ; pour les paramètres du coordinateur Airflow, voir configuring-airflow-language-sdks.

npx skills add https://github.com/astronomer/agents --skill deploying-java-sdk-bundles

Déployer les bundles Java SDK

Un déploiement Java SDK dispose d'un seul artifact : un bundle — vos classes de tâches compilées plus le SDK, empaquetés en JAR (ou en JAR fin accompagné de JARs de dépendances). Vous le construisez avec Gradle ou Maven, puis le placez dans un répertoire que le JavaCoordinator analyse (jars_root) sur chaque worker. Cette compétence est indépendante de la plateforme ; elle montre la construction une fois, puis deux chemins de déploiement : open-source et Astro.

Expérimental. Le Java SDK est en aperçu. Les versions d'artifacts ci-dessous sont indiquées comme ${version} ; tant que le SDK est en pré-version, vous devrez peut-être construire les artifacts dans votre dépôt Maven local vous-même (voir la section des versions d'aperçu).

Ordre des opérations : construire le bundle (cette compétence) → le placer où jars_root pointe → configurer le coordinateur (configuring-airflow-language-sdks). Le code de tâche lui-même est dans authoring-java-sdk-tasks.


Construire avec Gradle (recommandé)

Appliquez le plugin Gradle du SDK et déclarez les dépendances dans build.gradle :

plugins {
    id("org.apache.airflow.sdk") version "${version}"
}

repositories {
    mavenCentral()
}

dependencies {
    annotationProcessor("org.apache.airflow:airflow-sdk-processor:${version}")  // annotation API only
    implementation("org.apache.airflow:airflow-sdk:${version}")
    // Optional logging integration, e.g.:
    // implementation("org.apache.airflow:airflow-sdk-jpl:${version}")
}

airflowBundle {
    mainClass = "com.example.Main"   // your BundleBuilder entry point
    // fatJar = false                // opt out of the single-JAR build (see below)
}

Construisez-le :

./gradlew bundle

Le répertoire build/bundle/ contient alors tous les JARs requis. Notes :

  • La ligne annotationProcessor est nécessaire uniquement si vous utilisez l'API basée sur les annotations. L'API basée sur les interfaces n'en a pas besoin.
  • Par défaut, le plugin produit un fat JAR (via le plugin Shadow) — un fichier autonome, ce qui évite les conflits de dépendances entre projets. Définissez fatJar = false dans airflowBundle pour des JARs fins ; vous devez alors déployer aussi chaque JAR de dépendance.
  • Le plugin Gradle valide que mainClass existe au moment de la construction (verifyBundleMainClass).

Construire avec Maven

Importez le BOM pour que les versions des artifacts et la version du schéma du supervisor soient gérées en un seul endroit :

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.apache.airflow</groupId>
      <artifactId>airflow-sdk-bom</artifactId>
      <version>${version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>org.apache.airflow</groupId>
    <artifactId>airflow-sdk</artifactId>   <!-- version from the BOM -->
  </dependency>
</dependencies>

Connectez le processeur d'annotations via maven-compiler-plugin (API annotation uniquement) pour qu'il reste hors du classpath runtime. Ensuite, choisissez une option de packaging :

  • Fat JAR (recommandé) : utilisez maven-shade-plugin. Dans son ManifestResourceTransformer, définissez <mainClass> sur votre BundleBuilder et ajoutez l'entrée manifest Airflow-Supervisor-Schema-Version résolue à partir de la propriété BOM ${airflow.supervisor.schema.version} (ne la codez pas en dur). mvn package écrit le JAR dans target/.
  • Thin JAR : utilisez maven-jar-plugin pour définir Main-Class et maven-dependency-plugin (copy-dependencies) pour collecter les JARs runtime dans target/bundle/. Ici, Airflow-Supervisor-Schema-Version n'est pas nécessaire — Airflow le lit depuis le JAR airflow-sdk sur le classpath.

Contrairement à Gradle, Maven ne valide pas mainClass au moment de la construction ; une valeur incorrecte échoue seulement à l'exécution.


Intégration de la journalisation

Pour que les enregistrements de log des tâches atteignent le magasin de logs d'Airflow (et la vue de log des tâches dans l'UI), le bundle doit inclure exactement un artifact de logging SDK par façade de logging que vous utilisez. Les versions sont gérées par airflow-sdk-bom ; les utilisateurs Maven appliquent les mêmes IDs d'artifact.

Choisir une façade. Pour un nouveau projet, préférez JPL (System.Logger) — elle est intégrée au JDK, donc vos tâches n'ont besoin d'aucune API de logging supplémentaire. Choisissez une autre façade uniquement quand les bibliothèques que vous intégrez enregistrent déjà via celle-ci, pour que leurs enregistrements atteignent aussi Airflow. Ordre de préférence : JPL > SLF4J = Log4j 2 > JUL ; traitez JUL comme une intégration héritée uniquement, pas un choix pour du nouveau code.

Façade Artifact Configuration au-delà de la dépendance
System.Logger (JPL) airflow-sdk-jpl Aucune — le fournisseur est découvert via ServiceLoader.
SLF4J 2.x airflow-sdk-slf4j Aucune — la liaison est découverte automatiquement (récupère slf4j-api pour vous).
Log4j 2 airflow-sdk-log4j2 log4j-core sur le classpath runtime + AirflowAppender déclaré dans log4j2.xml (ci-dessous).
java.util.logging (JUL) airflow-sdk-jul Appelez AirflowJulHandler.setup() dans main() (ci-dessous), ou utilisez un fichier logging.properties (voir configuring-airflow-language-sdks).

Log4j 2log4j-core héberge le chargeur de plugins qui découvre l'appender (log4j-api arrive de manière transitive) :

implementation("org.apache.airflow:airflow-sdk-log4j2:${version}")
runtimeOnly("org.apache.logging.log4j:log4j-core:${log4jVersion}")
<Configuration>
  <Appenders>
    <AirflowAppender name="Airflow"/>
  </Appenders>
  <Loggers>
    <Root level="info">
      <AppenderRef ref="Airflow"/>
    </Root>
  </Loggers>
</Configuration>

JUL — appelez AirflowJulHandler.setup() avant que toute tâche s'exécute. Il efface les gestionnaires existants du logger racine (le ConsoleHandler par défaut écrit sur stderr, qu'Airflow capturerait sinon comme task.stderr au niveau ERROR, dupliquant chaque enregistrement) :

public static void main(String[] args) {
    AirflowJulHandler.setup();
    Server.create(args).serve(new MyBundle().build());
}

Ne doublez pas les fournisseurs. Une deuxième implémentation System.LoggerFinder aux côtés de airflow-sdk-jpl, ou une deuxième liaison SLF4J (logback-classic, slf4j-simple) aux côtés de airflow-sdk-slf4j, rend la sélection du fournisseur imprévisible.


Versions d'aperçu (avant une version stable)

Ignorez cette section si vous dépendez d'une version stable. Une fois que vous épinglez une version publiée (par exemple 1.0.0) publiée sur Maven Central, le dépôt mavenCentral() dans les snippets de construction ci-dessus suffit.

Tant que le SDK est en pré-version, le chemin documenté est de construire les artifacts et le plugin Gradle à partir du dépôt Airflow dans votre dépôt Maven local :

# in apache/airflow's java-sdk/ directory
./gradlew publishToMavenLocal -PskipSigning=true

Puis ajoutez mavenLocal() dans votre projet, dans à la fois pluginManagement (dans settings.gradle) et dans les repositories du projet (dans build.gradle) — c'est ainsi que le propre projet d'exemple du SDK le résout.

Une fois que les artifacts -SNAPSHOT sont publiés sur le Nexus snapshot d'Apache, ce dépôt peut remplacer la construction locale (les deux mêmes endroits) :

maven {
    name = "apacheSnapshots"
    url = "https://repository.apache.org/content/repositories/snapshots/"
    mavenContent { snapshotsOnly() }
}

Les snapshots bougent ; forcez une actualisation avec ./gradlew bundle --refresh-dependencies. (Pour Maven, ajoutez le même dépôt à <repositories> et <pluginRepositories>.)


Placer le bundle où le coordinateur analyse

Le coordinateur analyse jars_root récursivement et construit le classpath automatiquement, vous copiez donc tout le répertoire de sortie :

cp build/bundle/* /opt/airflow/jars/    # /opt/airflow/jars == jars_root

Le worker a aussi besoin d'un JRE 17+. Connecter le coordinateur à ce répertoire est couvert dans configuring-airflow-language-sdks.


Chemins de déploiement

Les outils Astronomer ne sont pas requis — le SDK s'exécute sur n'importe quel Airflow avec le Task SDK. Choisissez le chemin qui correspond à la configuration de l'utilisateur.

Open-source (Docker / Kubernetes)

Intégrez le JRE et le bundle dans votre image Airflow, ou montez-les :

FROM apache/airflow:3          # pin a specific 3.x in production
USER root
RUN apt-get update \
    && apt-get install -y --no-install-recommends default-jre-headless \
    && apt-get clean && rm -rf /var/lib/apt/lists/*
RUN mkdir -p /opt/airflow/jars
COPY build/bundle/ /opt/airflow/jars/
USER airflow

Sur Kubernetes (charte Helm), intégrez le JAR dans une image personnalisée comme ci-dessus, ou montez-le via un volume partagé ; définissez la config [sdk] via des variables d'environnement sur le worker/scheduler. Voir deploying-airflow pour le workflow plus large de Docker Compose et Helm.

Astro (une option, non requis)

Si l'utilisateur est sur l'Astro CLI d'Astronomer, la même idée s'applique à un projet Astro :

  1. Construisez le bundle, puis préparez-le dans le projet : mkdir -p include/jars && cp ../java-bundle/build/bundle/*.jar include/jars/.

  2. Modifiez le Dockerfile du projet pour installer un JRE et copier les JARs dans le répertoire du coordinateur :

    FROM quay.io/astronomer/astro-runtime:<version>
    USER root
    RUN apt-get update \
        && apt-get install -y --no-install-recommends default-jre-headless \
        && apt-get clean && rm -rf /var/lib/apt/lists/*
    RUN mkdir -p /opt/airflow/jars
    COPY include/jars/ /opt/airflow/jars/
    USER airflow
  3. Mettez la config du coordinateur dans le .env du projet (chargé automatiquement) — voir configuring-airflow-language-sdks pour les valeurs AIRFLOW__SDK__*.

  4. astro dev start (ou astro dev restart après des changements) construit l'image et démarre Airflow localement ; déployez avec astro deploy comme d'habitude.

N'épinglez pas les versions d'Astro Runtime / Airflow de mémoire — lisez le Dockerfile généré ou consultez la documentation actuelle. Tant que le SDK et Airflow 3.3 sont en aperçu, une image Astro Runtime bêta/dev peut être requise.


Checklist de déploiement

  • Bundle construit (./gradlew bundle ou mvn package) et mainClass pointe sur votre BundleBuilder.
  • annotationProcessor présent si et seulement si vous utilisez l'API annotation.
  • JAR(s) copiés dans le répertoire jars_root du worker ; avec les JARs fins, les JARs de dépendance aussi.
  • JRE 17+ disponible sur le worker.
  • Coordinateur + queue_to_coordinator configurés (configuring-airflow-language-sdks).
  • Si plusieurs JARs exécutables existent sous jars_root, définissez main_class explicitement.

Compétences connexes

  • authoring-java-sdk-tasks : Écrivez le code de tâche Java et les stubs Python correspondants.
  • configuring-airflow-language-sdks : Enregistrez le coordinateur et acheminez la queue.
  • deploying-airflow : Déploiement Airflow général (Astro, Docker Compose, Kubernetes).
  • setting-up-astro-project : Initialisez et configurez un projet Astro.

Skills similaires