Feature/docker dbinit (#2371)

* Standalone tool for initializing of hawkBit Database

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>

* Add docker build for dbinit

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>

---------

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2025-04-24 16:40:55 +03:00
committed by GitHub
parent 323738bda9
commit d2a41d1bff
29 changed files with 574 additions and 11 deletions

1
.gitignore vendored
View File

@@ -1,5 +1,4 @@
# Directories # # Directories #
build
bin bin
tmp tmp
.settings .settings

View File

@@ -14,17 +14,17 @@ $ docker run -d -p 8080:8080 hawkbit/hawkbit-update-server:latest
Start the hawkBit Update Server together with an MySQL and RabbitMQ instance as containers (Requires Docker Compose to be installed) Start the hawkBit Update Server together with an MySQL and RabbitMQ instance as containers (Requires Docker Compose to be installed)
```bash ```bash
$ docker compose -f docker-compose-monolith-mysql.yml up $ docker compose -f mysql/docker-compose-monolith-mysql.yml up
``` ```
You could, also start it in different flavours, with UI or in microservices mode. You could, also start it in different flavours, with UI or in microservices mode.
Note: Whit the upper command CTRL+C shuts down all services. Add '-d' at the end to start all into detached mode: Note: Whit the upper command CTRL+C shuts down all services. Add '-d' at the end to start all into detached mode:
```bash ```bash
$ docker compose -f docker-compose-monolith-mysql.yml up -d $ docker compose -f mysql/docker-compose-monolith-mysql.yml up -d
``` ```
Then stop all services with: Then stop all services with:
```bash ```bash
$ docker compose -f docker-compose-monolith-mysql.yml down $ docker compose -f mysql/docker-compose-monolith-mysql.yml down
``` ```
# Access # Access

View File

@@ -23,7 +23,8 @@ RUN set -x &&\
mkdir -p ${BUILD_DIR} &&\ mkdir -p ${BUILD_DIR} &&\
cd ${BUILD_DIR} &&\ cd ${BUILD_DIR} &&\
java -Djarmode=tools -jar /${APP}.jar extract --layers --launcher --destination . &&\ java -Djarmode=tools -jar /${APP}.jar extract --layers --launcher --destination . &&\
rm /${APP}.jar rm /${APP}.jar &&\
rm /${APP}.jar.asc
FROM eclipse-temurin:${JAVA_VERSION}-jre-alpine FROM eclipse-temurin:${JAVA_VERSION}-jre-alpine

View File

@@ -0,0 +1,45 @@
# set Java
ARG JAVA_VERSION=21.0.6_7
FROM eclipse-temurin:${JAVA_VERSION}-jre-alpine as build
ARG HAWKBIT_APP=hawkbit-repository-jpa-init
ARG HAWKBIT_VERSION=pass_as_buils_arg
ENV APP=${HAWKBIT_APP}
ENV VERSION=${HAWKBIT_VERSION}
COPY KEY .
RUN set -x &&\
apk add --no-cache --virtual build-dependencies gnupg unzip libressl wget &&\
gpg --import KEY &&\
wget -O ${APP}-${VERSION}.jar --no-verbose https://repo1.maven.org/maven2/org/eclipse/hawkbit/${APP}/${VERSION}/${APP}-${VERSION}.jar &&\
wget -O ${APP}-${VERSION}.asc --no-verbose https://repo1.maven.org/maven2/org/eclipse/hawkbit/${APP}/${VERSION}/${APP}-${VERSION}.jar.asc &&\
gpg --batch --verify ${APP}-${VERSION}.jar.asc ${APP}-${VERSION}.jar &&\
rm /${APP}-${VERSION}.jar.asc /KEY &&\
apk del build-dependencies
FROM eclipse-temurin:${JAVA_VERSION}-jre-alpine
RUN addgroup -S hawkbit_group && adduser -D hawkbit -G hawkbit_group
USER hawkbit
ENV BUILD_DIR=/opt/hawkbit_build
COPY --from=build /${APP}-${VERSION}.jar ./
ARG X_MS=256m
ENV X_MS=${X_MS}
ARG X_MX=256m
ENV X_MX=${X_MX}
ARG XX_MAX_METASPACE_SIZE=1150m
ENV XX_MAX_METASPACE_SIZE=${XX_MAX_METASPACE_SIZE}
ARG XX_METASPACE_SIZE=115m
ENV XX_METASPACE_SIZE=${XX_METASPACE_SIZE}
ARG XSS=150K
ENV XSS=${XSS}
ARG GC=G1
ENV GC=${GC}
ARG AND_THEN="exit 0"
ENV AND_THEN=${AND_THEN}
ENTRYPOINT ["sh", "-c", "java -classpath /${APP}-${VERSION}.jar ${JAVA_OPTS} -Xms${X_MS} -Xmx${X_MX} -XX:MaxMetaspaceSize=${XX_MAX_METASPACE_SIZE} -XX:MetaspaceSize=${XX_METASPACE_SIZE} -Xss${XSS} -XX:+Use${GC}GC -XX:+UseStringDeduplication -XX:+UseCompressedOops -XX:+HeapDumpOnOutOfMemoryError org.eclipse.hawkbit.repository.jpa.init.HawkbitFlywayDbInit ${@} && ${AND_THEN}"]

View File

@@ -0,0 +1,32 @@
# set Java
ARG JAVA_VERSION=21.0.6_7
FROM eclipse-temurin:${JAVA_VERSION}-jre-alpine as build
ARG HAWKBIT_APP=hawkbit-repository-jpa-init
ARG HAWKBIT_VERSION=0-SNAPSHOT
ENV APP=${HAWKBIT_APP}
ENV VERSION=${HAWKBIT_VERSION}
RUN addgroup -S hawkbit_group && adduser -D hawkbit -G hawkbit_group
RUN mkdir -p /artifactrepo && chown -R hawkbit /artifactrepo
USER hawkbit
COPY org/eclipse/hawkbit/${APP}/${VERSION}/${APP}-${VERSION}.jar /${APP}-${VERSION}.jar
ARG X_MS=256m
ENV X_MS=${X_MS}
ARG X_MX=256m
ENV X_MX=${X_MX}
ARG XX_MAX_METASPACE_SIZE=1150m
ENV XX_MAX_METASPACE_SIZE=${XX_MAX_METASPACE_SIZE}
ARG XX_METASPACE_SIZE=115m
ENV XX_METASPACE_SIZE=${XX_METASPACE_SIZE}
ARG XSS=150K
ENV XSS=${XSS}
ARG GC=G1
ENV GC=${GC}
ARG AND_THEN="exit 0"
ENV AND_THEN=${AND_THEN}
ENTRYPOINT ["sh", "-c", "java -classpath /${APP}-${VERSION}.jar ${JAVA_OPTS} -Xms${X_MS} -Xmx${X_MX} -XX:MaxMetaspaceSize=${XX_MAX_METASPACE_SIZE} -XX:MetaspaceSize=${XX_METASPACE_SIZE} -Xss${XSS} -XX:+Use${GC}GC -XX:+UseStringDeduplication -XX:+UseCompressedOops -XX:+HeapDumpOnOutOfMemoryError org.eclipse.hawkbit.repository.jpa.init.HawkbitFlywayDbInit ${@} && ${AND_THEN}"]

View File

@@ -38,10 +38,14 @@ echo "hawkBit version : ${VERSION}"
echo "maven repository : ${MVN_REPO}" echo "maven repository : ${MVN_REPO}"
echo "docker tag : ${TAG}" echo "docker tag : ${TAG}"
DOCKER_FILE="Dockerfile_dev"
echo "docker file : ${DOCKER_FILE}"
function build() { function build() {
if [ "$1" == "hawkbit-repository-jpa-init" ]; then
DOCKER_FILE="Dockerfile_dbinit_dev"
else
DOCKER_FILE="Dockerfile_dev"
fi
echo "docker file : ${DOCKER_FILE}"
docker build -t hawkbit/$1:${TAG} --build-arg HAWKBIT_APP=$1 --build-arg HAWKBIT_VERSION=${VERSION} -f ${DOCKER_FILE} "${MVN_REPO}" docker build -t hawkbit/$1:${TAG} --build-arg HAWKBIT_APP=$1 --build-arg HAWKBIT_VERSION=${VERSION} -f ${DOCKER_FILE} "${MVN_REPO}"
} }
@@ -54,6 +58,8 @@ if [ -z "$1" ]; then
build "hawkbit-simple-ui" build "hawkbit-simple-ui"
# monolith # monolith
build "hawkbit-update-server" build "hawkbit-update-server"
# db init
build "hawkbit-repository-jpa-init"
else else
echo "Build $1" echo "Build $1"
build $1 build $1

View File

@@ -33,7 +33,7 @@ services:
# RabbitMQ service # RabbitMQ service
# --------------------- # ---------------------
rabbitmq: rabbitmq:
image: "rabbitmq:3-management-alpine" image: "rabbitmq:4-management-alpine"
hostname: "rabbitmq" hostname: "rabbitmq"
environment: environment:
RABBITMQ_DEFAULT_VHOST: "/" RABBITMQ_DEFAULT_VHOST: "/"

View File

@@ -0,0 +1,106 @@
#
# Copyright (c) 2018 Bosch Software Innovations GmbH and others
#
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
#
# SPDX-License-Identifier: EPL-2.0
#
version: '3.7'
include:
- docker-compose-deps-mysql.yml
services:
# ---------------------
# HawkBit DB Init
# ---------------------
hawkbit-db-init:
image: "hawkbit/hawkbit-repository-jpa-init:latest"
environment:
- 'HAWKBIT_DB_MODE=migrate'
- 'SPRING_DATASOURCE_URL=jdbc:mariadb://mysql:3306/hawkbit'
- 'SPRING_DATASOURCE_USERNAME=root'
- 'AND_THEN=sleep infinity'
restart: always
healthcheck:
test: ["CMD", "pgrep", "sleep"]
start_period: 30s
interval: 10s
retries: 5
timeout: 60s
depends_on:
mysql:
condition: service_healthy
labels:
NAME: "hawkbit-db-init"
# ---------------------
# HawkBit DDI
# ---------------------
hawkbit-ddi:
image: "hawkbit/hawkbit-ddi-server:latest"
environment:
- 'PROFILES=mysql'
- 'SPRING_DATASOURCE_URL=jdbc:mariadb://mysql:3306/hawkbit'
- 'SPRING_DATASOURCE_USERNAME=root'
- 'SPRING_RABBITMQ_HOST=rabbitmq'
- 'SPRING_RABBITMQ_USERNAME=guest'
- 'SPRING_RABBITMQ_PASSWORD=guest'
restart: always
ports:
- "8081:8081"
depends_on:
hawkbit-db-init:
condition: service_healthy
labels:
NAME: "hawkbit-ddi"
# ---------------------
# HawkBit DMF
# ---------------------
hawkbit-dmf:
image: "hawkbit/hawkbit-dmf-server:latest"
environment:
- 'PROFILES=mysql'
- 'SPRING_DATASOURCE_URL=jdbc:mariadb://mysql:3306/hawkbit'
- 'SPRING_DATASOURCE_USERNAME=root'
- 'SPRING_RABBITMQ_HOST=rabbitmq'
- 'SPRING_RABBITMQ_USERNAME=guest'
- 'SPRING_RABBITMQ_PASSWORD=guest'
restart: always
depends_on:
hawkbit-db-init:
condition: service_healthy
labels:
NAME: "hawkbit-dmf"
# ---------------------
# HawkBit MGMT
# ---------------------
hawkbit-mgmt:
image: "hawkbit/hawkbit-mgmt-server:latest"
environment:
- 'PROFILES=mysql'
- 'SPRING_FLYWAY_ENABLED=false'
- 'SPRING_DATASOURCE_URL=jdbc:mariadb://mysql:3306/hawkbit'
- 'SPRING_DATASOURCE_USERNAME=root'
- 'SPRING_RABBITMQ_HOST=rabbitmq'
- 'SPRING_RABBITMQ_USERNAME=guest'
- 'SPRING_RABBITMQ_PASSWORD=guest'
volumes:
- artifactrepo:/artifactrepo
restart: always
ports:
- "8080:8080"
depends_on:
hawkbit-db-init:
condition: service_healthy
labels:
NAME: "hawkbit-mgmt"
volumes:
artifactrepo:
driver: local

View File

@@ -0,0 +1,32 @@
#
# Copyright (c) 2018 Bosch Software Innovations GmbH and others
#
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
#
# SPDX-License-Identifier: EPL-2.0
#
version: '3.7'
include:
- docker-compose-micro-services-dbinit-mysql.yml
services:
# ---------------------
# HawkBit Simple UI
# ---------------------
hawkbit-simple-ui:
image: "hawkbit/hawkbit-simple-ui:latest"
environment:
- 'SPRING_APPLICATION_JSON={"hawkbit.server.mgmtUrl": "http://hawkbit-mgmt:8080"}'
restart: always
ports:
- 8088:8088
labels:
NAME: "hawkbit-simple-ui"
volumes:
artifactrepo:
driver: local

View File

@@ -0,0 +1,66 @@
#
# Copyright (c) 2018 Bosch Software Innovations GmbH and others
#
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
#
# SPDX-License-Identifier: EPL-2.0
#
version: '3'
include:
- docker-compose-deps-mysql.yml
services:
# ---------------------
# HawkBit DB Init
# ---------------------
hawkbit-db-init:
image: "hawkbit/hawkbit-repository-jpa-init:latest"
environment:
- 'HAWKBIT_DB_MODE=migrate'
- 'SPRING_DATASOURCE_URL=jdbc:mariadb://mysql:3306/hawkbit'
- 'SPRING_DATASOURCE_USERNAME=root'
- 'AND_THEN=sleep infinity'
restart: always
healthcheck:
test: ["CMD", "pgrep", "sleep"]
start_period: 30s
interval: 10s
retries: 5
timeout: 60s
depends_on:
mysql:
condition: service_healthy
labels:
NAME: "hawkbit-db-init"
# ---------------------
# HawkBit service
# ---------------------
hawkbit:
image: "hawkbit/hawkbit-update-server:latest"
environment:
- 'PROFILES=mysql'
- 'SPRING_FLYWAY_ENABLED=false'
- 'SPRING_DATASOURCE_URL=jdbc:mariadb://mysql:3306/hawkbit'
- 'SPRING_DATASOURCE_USERNAME=root'
- 'SPRING_RABBITMQ_HOST=rabbitmq'
- 'SPRING_RABBITMQ_USERNAME=guest'
- 'SPRING_RABBITMQ_PASSWORD=guest'
volumes:
- artifactrepo:/artifactrepo
restart: always
ports:
- "8080:8080"
depends_on:
hawkbit-db-init:
condition: service_healthy
labels:
NAME: "hawkbit"
volumes:
artifactrepo:
driver: local

View File

@@ -0,0 +1,32 @@
#
# Copyright (c) 2018 Bosch Software Innovations GmbH and others
#
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
#
# SPDX-License-Identifier: EPL-2.0
#
version: '3'
include:
- docker-compose-monolith-dbinit-mysql.yml
services:
# ---------------------
# HawkBit Simple UI service
# ---------------------
hawkbit-simple-ui:
image: "hawkbit/hawkbit-simple-ui:latest"
environment:
- 'SPRING_APPLICATION_JSON={"hawkbit.server.mgmtUrl": "http://hawkbit:8080"}'
restart: always
ports:
- 8088:8088
labels:
NAME: "hawkbit-simple-ui"
volumes:
artifactrepo:
driver: local

View File

@@ -33,7 +33,7 @@ services:
# RabbitMQ service # RabbitMQ service
# --------------------- # ---------------------
rabbitmq: rabbitmq:
image: "rabbitmq:3-management-alpine" image: "rabbitmq:4-management-alpine"
hostname: "rabbitmq" hostname: "rabbitmq"
environment: environment:
RABBITMQ_DEFAULT_VHOST: "/" RABBITMQ_DEFAULT_VHOST: "/"

View File

@@ -0,0 +1,110 @@
#
# Copyright (c) 2018 Bosch Software Innovations GmbH and others
#
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
#
# SPDX-License-Identifier: EPL-2.0
#
version: '3.7'
include:
- docker-compose-deps-postgres.yml
services:
# ---------------------
# HawkBit DB Init
# ---------------------
hawkbit-db-init:
image: "hawkbit/hawkbit-repository-jpa-init:latest"
environment:
- 'HAWKBIT_DB_MODE=migrate'
- 'SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/hawkbit'
- 'SPRING_DATASOURCE_USERNAME=postgres'
- 'SPRING_DATASOURCE_PASSWORD=admin'
- 'AND_THEN=sleep infinity'
restart: always
healthcheck:
test: ["CMD", "pgrep", "sleep"]
start_period: 30s
interval: 10s
retries: 5
timeout: 60s
depends_on:
postgress:
condition: service_healthy
labels:
NAME: "hawkbit-db-init"
# ---------------------
# HawkBit DDI
# ---------------------
hawkbit-ddi:
image: "hawkbit/hawkbit-ddi-server:latest"
environment:
- 'PROFILES=postgresql'
- 'SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/hawkbit'
- 'SPRING_DATASOURCE_USERNAME=postgres'
- 'SPRING_DATASOURCE_PASSWORD=admin'
- 'SPRING_RABBITMQ_HOST=rabbitmq'
- 'SPRING_RABBITMQ_USERNAME=guest'
- 'SPRING_RABBITMQ_PASSWORD=guest'
restart: always
ports:
- "8081:8081"
depends_on:
hawkbit-db-init:
condition: service_healthy
labels:
NAME: "hawkbit-ddi"
# ---------------------
# HawkBit DMF
# ---------------------
hawkbit-dmf:
image: "hawkbit/hawkbit-dmf-server:latest"
environment:
- 'PROFILES=postgresql'
- 'SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/hawkbit'
- 'SPRING_DATASOURCE_USERNAME=postgres'
- 'SPRING_DATASOURCE_PASSWORD=admin'
- 'SPRING_RABBITMQ_HOST=rabbitmq'
- 'SPRING_RABBITMQ_USERNAME=guest'
- 'SPRING_RABBITMQ_PASSWORD=guest'
restart: always
depends_on:
hawkbit-db-init:
condition: service_healthy
labels:
NAME: "hawkbit-dmf"
# ---------------------
# HawkBit MGMT
# ---------------------
hawkbit-mgmt:
image: "hawkbit/hawkbit-mgmt-server:latest"
environment:
- 'PROFILES=postgresql'
- 'SPRING_FLYWAY_ENABLED=false'
- 'SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/hawkbit'
- 'SPRING_DATASOURCE_USERNAME=postgres'
- 'SPRING_DATASOURCE_PASSWORD=admin'
- 'SPRING_RABBITMQ_HOST=rabbitmq'
- 'SPRING_RABBITMQ_USERNAME=guest'
- 'SPRING_RABBITMQ_PASSWORD=guest'
volumes:
- artifactrepo:/artifactrepo
restart: always
ports:
- "8080:8080"
depends_on:
hawkbit-db-init:
condition: service_healthy
labels:
NAME: "hawkbit-mgmt"
volumes:
artifactrepo:
driver: local

View File

@@ -0,0 +1,32 @@
#
# Copyright (c) 2018 Bosch Software Innovations GmbH and others
#
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
#
# SPDX-License-Identifier: EPL-2.0
#
version: '3.7'
include:
- docker-compose-micro-services-dbinit-postgres.yml
services:
# ---------------------
# HawkBit Simple UI
# ---------------------
hawkbit-simple-ui:
image: "hawkbit/hawkbit-simple-ui:latest"
environment:
- 'SPRING_APPLICATION_JSON={"hawkbit.server.mgmtUrl": "http://hawkbit-mgmt:8080"}'
restart: always
ports:
- 8088:8088
labels:
NAME: "hawkbit-simple-ui"
volumes:
artifactrepo:
driver: local

View File

@@ -0,0 +1,68 @@
#
# Copyright (c) 2018 Bosch Software Innovations GmbH and others
#
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
#
# SPDX-License-Identifier: EPL-2.0
#
version: '3'
include:
- docker-compose-deps-postgres.yml
services:
# ---------------------
# HawkBit DB Init
# ---------------------
hawkbit-db-init:
image: "hawkbit/hawkbit-repository-jpa-init:latest"
environment:
- 'HAWKBIT_DB_MODE=migrate'
- 'SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/hawkbit'
- 'SPRING_DATASOURCE_USERNAME=postgres'
- 'SPRING_DATASOURCE_PASSWORD=admin'
- 'AND_THEN=sleep infinity'
restart: always
healthcheck:
test: ["CMD", "pgrep", "sleep"]
start_period: 30s
interval: 10s
retries: 5
timeout: 60s
depends_on:
postgress:
condition: service_healthy
labels:
NAME: "hawkbit-db-init"
# ---------------------
# HawkBit service
# ---------------------
hawkbit:
image: "hawkbit/hawkbit-update-server:latest"
environment:
- 'PROFILES=postgresql'
- 'SPRING_FLYWAY_ENABLED=false'
- 'SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/hawkbit'
- 'SPRING_DATASOURCE_USERNAME=postgres'
- 'SPRING_DATASOURCE_PASSWORD=admin'
- 'SPRING_RABBITMQ_HOST=rabbitmq'
- 'SPRING_RABBITMQ_USERNAME=guest'
- 'SPRING_RABBITMQ_PASSWORD=guest'
volumes:
- artifactrepo:/artifactrepo
restart: always
ports:
- "8080:8080"
depends_on:
hawkbit-db-init:
condition: service_healthy
labels:
NAME: "hawkbit"
volumes:
artifactrepo:
driver: local

View File

@@ -0,0 +1,32 @@
#
# Copyright (c) 2018 Bosch Software Innovations GmbH and others
#
# This program and the accompanying materials are made
# available under the terms of the Eclipse Public License 2.0
# which is available at https://www.eclipse.org/legal/epl-2.0/
#
# SPDX-License-Identifier: EPL-2.0
#
version: '3'
include:
- docker-compose-monolith-dbinit-postgres.yml
services:
# ---------------------
# HawkBit Simple UI service
# ---------------------
hawkbit-simple-ui:
image: "hawkbit/hawkbit-simple-ui:latest"
environment:
- 'SPRING_APPLICATION_JSON={"hawkbit.server.mgmtUrl": "http://hawkbit:8080"}'
restart: always
ports:
- 8088:8088
labels:
NAME: "hawkbit-simple-ui"
volumes:
artifactrepo:
driver: local

View File

@@ -118,7 +118,8 @@
</manifest> </manifest>
</archive> </archive>
<descriptors> <descriptors>
<descriptor>src/assembly/exec.xml</descriptor> <!-- override default descriptor in order to merge services -->
<descriptor>src/assembly/jar-with-dependencies.xml</descriptor>
</descriptors> </descriptors>
<appendAssemblyId>false</appendAssemblyId> <appendAssemblyId>false</appendAssemblyId>
</configuration> </configuration>

View File

@@ -19,6 +19,7 @@
<includeBaseDirectory>false</includeBaseDirectory> <includeBaseDirectory>false</includeBaseDirectory>
<containerDescriptorHandlers> <containerDescriptorHandlers>
<containerDescriptorHandler> <containerDescriptorHandler>
<!-- merge services for flyway -->
<handlerName>metaInf-services</handlerName> <handlerName>metaInf-services</handlerName>
</containerDescriptorHandler> </containerDescriptorHandler>
</containerDescriptorHandlers> </containerDescriptorHandlers>