Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

hawkbit-dmf-server 1.1.0 does not start: NoClassDefFoundError jakarta/servlet/ServletResponse

Aperta Adatta ai principianti
#3,429 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
77/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
docker, java, spring-boot
Ambito
backend, devops

Direzione di ricerca

Inizia da hawkbit-dmf/hawkbit-dmf-server/pom.xml e confronta la sua dipendenza dalla Servlet API con la versione 1.0.4. Compila il server DMF con mvn -pl hawkbit-dmf/hawkbit-dmf-server -am package, quindi esegui il JAR generato con il profilo H2. Il lavoro è completato quando il servizio si avvia senza il NoClassDefFoundError di jakarta.servlet.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Summary

hawkbit/hawkbit-dmf-server:1.1.0 does not start. The Spring context fails while it creates the authenticationSuccessHandler bean of SecurityAutoConfiguration, with java.lang.NoClassDefFoundError: jakarta/servlet/ServletResponse, and the process exits with code 1. 1.0.4 starts with the same setup.

It happens with the image defaults (H2, no broker) and with docker/mysql/docker-compose-micro-services-mysql.yml of the 1.1.0 tag, where the hawkbit-dmf container restarts in a loop. A build of the current master (bf5812735) fails in the same way.

Steps to reproduce

  1. docker run --rm hawkbit/hawkbit-dmf-server:1.1.0
  2. The container exits after a few seconds with code 1. No database, broker or configuration is needed for this; the image defaults to PROFILES=h2.

The script below runs 1.0.4 as control and then 1.1.0, and it shows whether jakarta.servlet-api is in BOOT-INF/lib. It needs only docker and removes its container on exit.

repro.sh
#!/usr/bin/env bash
# hawkbit-dmf-server 1.1.0 does not start: NoClassDefFoundError for
# jakarta/servlet/ServletResponse.
#
# Usage: repro.sh [image ...]
#   default images: hawkbit/hawkbit-dmf-server:1.0.4 (control) and :1.1.0
#
# Each image runs with its defaults (PROFILES=h2, no database, no broker,
# no configuration). The script waits up to 90 s for "Started DmfStart" or
# for the container to exit, prints the result, the first error lines and
# whether jakarta.servlet-api is in BOOT-INF/lib. Needs docker only; the
# containers are removed on exit.
set -euo pipefail

IMAGES=("$@")
[ ${#IMAGES[@]} -gt 0 ] || IMAGES=(hawkbit/hawkbit-dmf-server:1.0.4 hawkbit/hawkbit-dmf-server:1.1.0)
NAME=dmf-repro

cleanup() { docker rm -f "$NAME" >/dev/null 2>&1 || true; }
trap cleanup EXIT

for image in "${IMAGES[@]}"; do
  cleanup
  docker pull -q "$image" >/dev/null
  echo "== $image ($(docker image inspect -f '{{.Id}}' "$image" | cut -c8-19))"
  docker run -d --name "$NAME" "$image" >/dev/null
  result="no result after 90 s"
  for _ in $(seq 90); do
    if docker logs "$NAME" 2>&1 | grep -q 'Started DmfStart'; then
      result="started: $(docker logs "$NAME" 2>&1 | grep -o 'Started DmfStart in [0-9.]* seconds')"
      break
    fi
    if [ "$(docker inspect -f '{{.State.Status}}' "$NAME")" = exited ]; then
      result="exited with code $(docker inspect -f '{{.State.ExitCode}}' "$NAME")"
      break
    fi
    sleep 1
  done
  echo "result: $result"
  docker logs "$NAME" 2>&1 | grep -E '^(Caused by|org\.springframework\.beans\.factory\.BeanCreationException)' |
    awk 'length > 240 { s = substr($0, 1, 240); sub(/ [^ ]*$/, "", s); $0 = s " …" } 1' | head -4
  echo "servlet API in BOOT-INF/lib: $(docker run --rm --entrypoint sh "$image" -c \
    'ls /app/BOOT-INF/lib | grep -i "^jakarta.servlet-api" || echo none')"
  echo
done

./repro.sh uses 1.0.4 and 1.1.0; other images can be passed as arguments.

Measured

2026-10-21, Docker Engine 29.9.1. The images run Java 21.0.11 (Temurin); the master build ran on maven:3.9-eclipse-temurin-21. The transcripts are in the comment.

Run Result jakarta.servlet-api in BOOT-INF/lib
hawkbit-dmf-server:1.0.4 (sha256:353c2cb0ce2f) Started DmfStart in 6.129 seconds jakarta.servlet-api-6.0.0.jar
hawkbit-dmf-server:1.1.0 (sha256:66e18cb15068) exit 1, NoClassDefFoundError: jakarta/servlet/ServletResponse none
master bf5812735, mvn -pl hawkbit-dmf/hawkbit-dmf-server -am package, then java -Dspring.profiles.active=h2 -jar exit 1, same error none
the same master build with the dependency from "Possible direction" Started DmfStart in 5.41 seconds jakarta.servlet-api-6.1.0.jar
docker/mysql/docker-compose-micro-services-mysql.yml of the 1.1.0 tag (images pinned to 1.1.0, host ports removed) hawkbit-dmf restarted 9 times in 2 minutes with the same error; mgmt and ddi run not checked

Where

SecurityAutoConfiguration (hawkbit-autoconfigure) creates three beans from Spring Security's servlet classes: authenticationSuccessHandler() returns a SimpleUrlAuthenticationSuccessHandler, logoutHandler() a SecurityContextLogoutHandler and logoutSuccessHandler() a SimpleUrlLogoutSuccessHandler. These classes come from spring-security-web (declared in hawkbit-dmf-amqp) and refer to jakarta.servlet types. The DMF server runs with spring.main.web-application-type=none, but the auto-configuration is applied anyway and creates the beans.

Up to 1.0.4, hawkbit-dmf/hawkbit-dmf-server/pom.xml declared jakarta.servlet:jakarta.servlet-api in compile scope. Commit 1be473b22 ("[#2845] Bump Spring boot to 4.x (#2941)") removed this declaration. The same commit also removed the provided declaration in hawkbit-autoconfigure and the test one in hawkbit-core, but these never reached the DMF jar, so the declaration in the DMF server was the one that counted. Since then nothing brings the servlet API onto the classpath of this module: the 1.0.4 image has jakarta.servlet-api-6.0.0.jar, the 1.1.0 image has none.

Possible direction

  • Restore the dependency in hawkbit-dmf/hawkbit-dmf-server/pom.xml, as it was in 1.0.4. With this change the master build starts (see the table):

    <dependency>
        <groupId>jakarta.servlet</groupId>
        <artifactId>jakarta.servlet-api</artifactId>
    </dependency>
    
  • Or create the servlet-bound beans only in a servlet web application, for example with @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) on the three methods, so a non-web service does not need the servlet API at all. We did not test this variant.

References

Thanks for having a look.

Lingua principale
Java
Stelle
601
Fork
228
Merge medio
18h 20m
PR unite (30g)
58

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di eclipse-hawkbit/hawkbit

Tutte le issue di eclipse-hawkbit/hawkbit

Issue simili

Altre issue su Java

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.