Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

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

Open Beginner friendly
#3,429 2 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
77/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
docker, java, spring-boot
Domain
backend, devops

Research direction

Start with hawkbit-dmf/hawkbit-dmf-server/pom.xml and compare its servlet API dependency with the 1.0.4 version. Build the DMF server with mvn -pl hawkbit-dmf/hawkbit-dmf-server -am package, then run the packaged jar with the H2 profile. Done when the service starts without the jakarta.servlet NoClassDefFoundError.

Written by the indexing model from the issue text.

Description

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.

Dominant language
Java
Stars
601
Forks
228
Avg merge
15h 58m
Merged PRs (30d)
62

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from eclipse-hawkbit/hawkbit

All issues in eclipse-hawkbit/hawkbit

Similar issues

More Java issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.