Compare commits

..

No commits in common. "main" and "MEapp-development" have entirely different histories.

25 changed files with 2269 additions and 8018 deletions

View file

@ -1,8 +0,0 @@
/.gradle/
/.idea/
/.pybuilder/
/build/
/doc/
.gitignore
gradlew.bat

3
.gitignore vendored
View file

@ -1,5 +1,4 @@
build/ build/
.gradle/ .gradle/
.idea/ .idea/
frontend/generated/ frontend/generated/
__pycache__/

View file

@ -1,70 +0,0 @@
stages:
# - test
# - buildjar
- buildimage
# - publish
variables:
CACHE_FALLBACK_KEY: fallback-key
.img: &img
image: openjdk:22-jdk-slim
cache:
- key: ${CI_COMMIT_REF_SLUG}
fallback_keys:
- cache-$CI_DEFAULT_BRANCH
- cache-default
- paths:
- /var/cache/apt
- .gradle/wrapper
- .gradle/caches
before_script:
- echo "___________________START_before_script________________________"
- echo ${CI_COMMIT_REF_SLUG}
- apt-get update && apt-get -qqy upgrade
#test:
# <<: *img
# stage: test
# script:
# - ./gradlew test
#buildjar:
# <<: *img
# stage: buildjar
# cache:
# - key: ${CI_COMMIT_REF_SLUG}
# script:
# - ./gradlew clean build -Pvaadin.productionMode
# artifacts:
# name: "ModeratorElection"
# paths:
# - build/libs/
# expire_in: 1 week
buildimage:
stage: buildimage
image: docker:latest
services:
- docker:dind
cache:
- key: ${CI_COMMIT_REF_SLUG}
# dependencies:
# - buildjar
before_script:
- echo "---------- BEFORE -------------"
# - echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY --username $CI_REGISTRY_USER --password-stdin
- docker login -u $DOCKERHUB_USER -p $DOCKERHUB_PASSWORD
script:
- export DOCKER_BUILDKIT=1
- docker build --tag=$DOCKERHUB_USER/moderator-election-vaadin_fullstack:latest --target=ci-image-stage --build-arg BUILDKIT_INLINE_CACHE=1 .
- docker push $DOCKERHUB_USER/moderator-election-vaadin_fullstack
# stage: image
# script:
#publish:
# stage: publish
#- export IMAGE_DOCKERHUB_USER=$DOCKERHUB_USER
#- export IMAGE_DOCKERHUB_PASSWORD=$DOCKERHUB_PASSWORD

View file

@ -1,41 +0,0 @@
#buildJar-stage
FROM openjdk:22-jdk-slim as build-jar-stage
RUN \
--mount=type=cache,target=/var/cache/apt \
apt-get update && apt-get -qqy upgrade
ADD ./ /usr/local/src/ModeratorElection
WORKDIR /usr/local/src/ModeratorElection/
RUN ./gradlew build -Pvaadin.productionMode
# Run jar stage
FROM build-jar-stage AS run-jar-stage
EXPOSE 8080
WORKDIR /usr/local/src/ModeratorElection/build/libs/
RUN chmod 0740 ./ModeratorElection.jar
ENTRYPOINT ["java", "-jar", "./ModeratorElection.jar"]
FROM build-jar-stage AS ci-image-stage
RUN chmod 0740 ./build/libs/ModeratorElection.jar
ENTRYPOINT ["java", "-jar", "./build/libs/ModeratorElection.jar"]
#build-native-stage
FROM ubuntu:latest as build-native-stage
ADD image/resources /tmp
RUN \
--mount=type=cache,target=/var/cache/apt \
/tmp/install.sh
ENV LANG=en_US.UTF-8 \
JAVA_HOME=/usr/lib/jvm/graalvm/bin
# Run native binary stage
FROM build-native-stage AS run-native-stage
EXPOSE 8080
#CMD ["mkdir /usr/local/src/ModeratorElection"]
WORKDIR /usr/local/src/ModeratorElection/build/native/nativeCompile/
##copy native binary
#COPY --from=buildNative-stage /usr/local/src/ModeratorElection/build/native/nativeCompile/ .
RUN chmod 0740 ./ModeratorElection
ENTRYPOINT ["./ModeratorElection"]

View file

@ -1,48 +0,0 @@
# meapp-fullstack: ModeratorElection
## Purpose
**ModeratorElection** provides a fullstack java app development as **graalvm binary** containing:
* Java app to elect a team member from a comma separated list delivered by environment variable
* Backend Spring Boot embeded Tomcat<sup>®</sup> Server
* Frontend Vaadin Framework
* Dockerfile to generate multi stage image,
first stage compilation to graalvm binary, second stage as run stage - graalvm binary execution
## Try out
Development phase is completed, we will deploy production soon - reachable at
https://meapp-fullstack.jitsi.prod.meissa.de
## Setup
* in **IDE development**, run
`./gradlew clean vaadinPrepareFrontend`
* build **jar file**
`./gradlew clean build -Pvaadin.productionMode`
-> output jar to build/libs/
* compile **native-image graalvm binary**
(1) use graalvm agent to announce project dependencies
```shell
MEMBERNAMES=er,sie,es java -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image -jar build/libs/ModeratorElection-0.0.1-SNAPSHOT.jar
```
(2)
`./gradlew nativeCompile -Dvaadin.productionMode=true`
-> output binary and necessary libs to build/native/nativeCompile/
* **py builder/build.py** usage recommendation:
`pyb <task>` to either create docker image, publish docker image, run test or dry run.
py builder is using **meissa PyPi package ddadevops** for smart deployment.
## Get help
`./gradlew tasks`
## Development & mirrors
Development completed at:
https://repo.prod.meissa.de/meissa/ModeratorElection
Mirror:
https://gitlab.com/domaindrivenarchitecture/ModeratorElection (CI)
## License
Copyright © 2024 meissa GmbH
Licensed under the [Apache License, Version 2.0](LICENSE)

View file

@ -6,14 +6,12 @@ buildscript {
} }
} }
plugins { plugins {
id 'org.springframework.boot' version '3.3.1' id 'org.springframework.boot' version '3.1.5'
id 'io.spring.dependency-management' version '1.1.6' id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id 'java' id 'java'
id 'com.vaadin' version '24.4.4' id 'com.vaadin'
id 'org.graalvm.buildtools.native' version '0.10.2' id 'org.graalvm.buildtools.native' version '0.10.2'
} }
group = 'com.ModeratorElection'
//version = '0.0.1-SNAPSHOT'
repositories { repositories {
mavenCentral() mavenCentral()
@ -22,10 +20,6 @@ repositories {
maven { setUrl("https://maven.vaadin.com/vaadin-addons") } maven { setUrl("https://maven.vaadin.com/vaadin-addons") }
} }
ext {
set('vaadinVersion', '24.4.4')
}
configurations { configurations {
developmentOnly developmentOnly
runtimeClasspath { runtimeClasspath {
@ -34,13 +28,11 @@ configurations {
} }
dependencies { dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web' implementation('com.vaadin:vaadin-spring-boot-starter')
implementation 'com.vaadin:vaadin-spring-boot-starter'
developmentOnly 'org.springframework.boot:spring-boot-devtools' developmentOnly 'org.springframework.boot:spring-boot-devtools'
testImplementation('org.springframework.boot:spring-boot-starter-test') { testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
} }
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
} }
dependencyManagement { dependencyManagement {
@ -49,28 +41,22 @@ dependencyManagement {
} }
} }
tasks.named('test') { test{
useJUnitPlatform() useJUnitPlatform()
jvmArgs "-Xshare:off"
} }
java { java {
toolchain { toolchain {
languageVersion = JavaLanguageVersion.of(22) languageVersion = JavaLanguageVersion.of(17)
} }
} }
graalvmNative { graalvmNative {
binaries { binaries {
main { main {
mainClass = 'com.ModeratorElection.MEApplication'
buildArgs.add("-march=native")
buildArgs.add("-R:MaxHeapSize=6442450944")
fallback = false
imageName.set('ModeratorElection') imageName.set('ModeratorElection')
//javaLauncher @JavaExec :: Configures the java executable to be used to run the tests.
javaLauncher.set(javaToolchains.launcherFor { javaLauncher.set(javaToolchains.launcherFor {
languageVersion.set(JavaLanguageVersion.of(22)) languageVersion.set(JavaLanguageVersion.of(17))
//vendor.set(JvmVendorSpec.GRAAL_VM) //vendor.set(JvmVendorSpec.GRAAL_VM)
}) })
} }
@ -79,17 +65,3 @@ graalvmNative {
toolchainDetection = false toolchainDetection = false
} }
/*tasks.withType(JavaCompile) {
options.compilerArgs += ['-Xlint:deprecation']
//,'-Xlint:unchecked'
}*/
/*
task runApp(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'package.Main'
// arguments to pass to the application
args 'membernames'
}*/

View file

@ -1,5 +1,4 @@
from os import environ from os import environ
from subprocess import run
from datetime import datetime from datetime import datetime
from pybuilder.core import task, init from pybuilder.core import task, init
from ddadevops import * from ddadevops import *
@ -7,7 +6,7 @@ from ddadevops import *
name = 'moderator-election' name = 'moderator-election'
MODULE = '' MODULE = ''
PROJECT_ROOT_PATH = '../..' PROJECT_ROOT_PATH = '../..'
version = "0.0.1-dev" version = "1.0.0-dev"
@init @init
def initialize(project): def initialize(project):
@ -17,7 +16,7 @@ def initialize(project):
input = { input = {
"name": name, "name": name,
"module": "vaadin_fullstack", "module": "notused",
"stage": "notused", "stage": "notused",
"project_root_path": PROJECT_ROOT_PATH, "project_root_path": PROJECT_ROOT_PATH,
"build_types": ["IMAGE"], "build_types": ["IMAGE"],
@ -46,7 +45,7 @@ def drun(project):
@task @task
def test(project): def test(project):
build = get_devops_build(project) build = get_devops_build(project)
run("./gradlew test", shell=True, check=True) build.test()
@task @task

View file

@ -10,82 +10,22 @@ java -jar build/libs/ModeratorElection.jar -> localhost:6333 "White Label..."-Er
..in ide dev: ./gradlew clean vaadinPrepareFrontend ..in ide dev: ./gradlew clean vaadinPrepareFrontend
``` ```
```
-x processTestAot - exclude, skip tests
https://docs.spring.io/spring-boot/gradle-plugin/aot.html
Processing Tests
The AOT engine can be applied to JUnit 5 tests that use Springs Test Context Framework.
Suitable tests are processed by the 'processTestAot' task to generate
'ApplicationContextInitializer' code. As with application AOT processing, the 'BeanFactory'
is fully prepared at build-time. As with 'processAot', the 'processTestAot' task is 'JavaExec'
subclass and can be configured as needed to influence this processing.
The 'nativeTest' task of the GraalVM Native Image plugin is automatically configured to
use the output of the 'processAot' and 'processTestAot' tasks.
```
``` ```
For production: For production:
* install.sh * install.sh
git clone --single-branch --branch main https://repo.prod.meissa.de/meissa/ModeratorElection.git /usr/local/src/ModeratorElection git clone --single-branch --branch MEapp-development https://repo.prod.meissa.de/meissa/ModeratorElection.git /usr/local/src/ModeratorElection
=> --branch main
``` ```
``` ```
build graalvm binary build graalvm binary
1. First build jar locally, and get META-INF with ./gradlew nativeCompile failed, need for some improvements!
./gradlew clean build -Pvaadin.productionMode -x processTestAot
MEMBERNAMES=er,sie,es java -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image -jar build/libs/ModeratorElection-0.0.1-SNAPSHOT.jar
curl -X GET localhost:8080
2. graalvm native-image compilation
./gradlew nativeCompile -Dvaadin.productionMode=true //-H:ConfigurationFileDirectories=/path/to/config-dir/ notwendig falls nicht in src/main/resources/META-INF/native-image/
```
```
Dockerizing -> image/Dockerfile
install buildx-plugin by binary to use build-native-stage only with DOCKER_BUILDKIT:
- https://github.com/docker/buildx/releases/download/v0.15.1/buildx-v0.15.1.linux-amd64
- sha256sum buildx-v0.15.1.linux-amd64
- move to file: mv buildx-v0.15.1.linux-amd64 $HOME/.docker/cli-plugins/docker-buildx
- chmod x $HOME/.docker/cli-plugins/docker-buildx
further:
It could be either build jar file or graalvm binary
(1)build-jar-stage
docker build --tag=meapp-jar --target=build-jar-stage .
(2)ENTRYPOINT as run-jar-stage
docker build --tag=run-meapp-jar --target=run-jar-stage
(3)build-native-stage
DOCKER_BUILDKIT=1 docker build --tag=meapp-native --target= build-native-stage .
(4)ENTRYPOINT as run-native-stage
DOCKER_BUILDKIT=1 docker build --tag=meapp-run-native --target=run-native-stage .
Test images:
docker run -e MEMBERNAMES=er,sie,es -p 8080:8080 run-jar-stage:latest
docker run -e MEMBERNAMES=er,sie,es -p 8080:8080 run-native-stage:latest
Buildkit caching:
export DOCKER_BUILDKIT=1
--build-arg BUILDKIT_INLINE_CACHE=1
(1)docker build --tag=meapp-jar --target=build-jar-stage --build-arg BUILDKIT_INLINE_CACHE=1 .
(2)docker build --tag=moderator-election-vaadin_fullstack --target=run-jar-stage --build-arg BUILDKIT_INLINE_CACHE=1 .
(3)docker build --tag=meapp-native --target=build-native-stage --build-arg BUILDKIT_INLINE_CACHE=1 .
(4)docker build --tag=meapp-run-native --target=run-native-stage --build-arg BUILDKIT_INLINE_CACHE=1 .
```
```
gu available
https://docs.oracle.com/en/graalvm/enterprise/21/docs/reference-manual/graalvm-updater/#component-installation
``` ```
``` ```
vaadin 24.3.3, after npm audit fix during image build: after npm audit fix during image build
npm warn deprecated workbox-google-analytics@7.0.0: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained npm warn deprecated workbox-google-analytics@7.0.0: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained
npm warn deprecated sourcemap-codec@1.4.8: Please use @jridgewell/sourcemap-codec instead npm warn deprecated sourcemap-codec@1.4.8: Please use @jridgewell/sourcemap-codec instead
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
@ -93,14 +33,4 @@ npm warn deprecated rollup-plugin-terser@7.0.2: This package has been deprecated
npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
``` ```
```
Refresh, Singleton Issue
https://github.com/vaadin/flow/issues/9376
https://mvysny.github.io/cant-move-node/
https://vaadin.com/forum/t/unregistered-node-was-not-found-based-on-its-id-the-tree-is-most-likely-co/161068
https://vaadin.com/docs/v14/flow/integrations/spring/tutorial-spring-scopes
=> @PreserveOnRefresh annotation in MainView.java does the trick
```
```
ddadevops anpassung, dass src code ins docker image übergeben werden kann - ohne git clone
```

View file

@ -3,7 +3,7 @@
This file is auto-generated by Vaadin. This file is auto-generated by Vaadin.
--> -->
<html> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />

View file

@ -1 +1 @@
vaadinVersion=24.4.4 vaadinVersion=24.3.13

6
image/Dockerfile Normal file
View file

@ -0,0 +1,6 @@
#Build Stage
FROM node:22.3.0-bookworm-slim
ADD resources /tmp
RUN /tmp/install.sh

View file

@ -0,0 +1 @@
Silke,Hans,Dieter,Anne

View file

@ -4,13 +4,13 @@ set -exo pipefail
function main() function main()
{ {
#upgradeSystem upgradeSystem
apt-get update && apt-get -qqy upgrade #openjdk-17-jdk-headless, no need, we are installing graalvm
apt-get -qqy install curl git build-essential libz-dev zlib1g-dev apt-get -qqy install git curl unzip
mkdir /usr/local/src/ModeratorElection
#change to main branch for production #change to main branch for production
#change to MEapp-development branch for development git clone --single-branch --branch MEapp-development https://repo.prod.meissa.de/meissa/ModeratorElection.git /usr/local/src/ModeratorElection
git clone --single-branch --branch main https://repo.prod.meissa.de/meissa/ModeratorElection.git /usr/local/src/ModeratorElection cp /tmp/MEMBERNAMES /usr/local/src/ModeratorElection
#download gradle #download gradle
#gradle_version="8.4" #gradle_version="8.4"
@ -18,60 +18,59 @@ function main()
#curl -SsLo /tmp/gradle-${gradle_version}-bin.zip.sha256 https://services.gradle.org/distributions/gradle-${gradle_version}-bin.zip.sha256 #curl -SsLo /tmp/gradle-${gradle_version}-bin.zip.sha256 https://services.gradle.org/distributions/gradle-${gradle_version}-bin.zip.sha256
#download graalvm #download graalvm
#graalvm-community-jdk, v22.0.1 2024-04-16 #oracle graalvm-jdk, v17.0.11, 2024-06-14
graalvm_jdk_version="22.0.1" graalvm_JDK_version="17"
curl -SsLo /tmp/graalvm-community-jdk-${graalvm_jdk_version}_linux-x64_bin.tar.gz https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-22.0.1/graalvm-community-jdk-22.0.1_linux-x64_bin.tar.gz curl -SsLo /tmp/graalvm-jdk-${graalvm_JDK_version}_linux-x64_bin.tar.gz https://download.oracle.com/graalvm/${graalvm_JDK_version}/latest/graalvm-jdk-${graalvm_JDK_version}_linux-x64_bin.tar.gz
curl -SsLo /tmp/graalvm-community-jdk-${graalvm_jdk_version}_linux-x64_bin.tar.gz.sha256 https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-${graalvm_jdk_version}/graalvm-community-jdk-${graalvm_jdk_version}_linux-x64_bin.tar.gz.sha256 curl -SsLo /tmp/graalvm-jdk-${graalvm_JDK_version}_linux-x64_bin.tar.gz.sha256 https://download.oracle.com/graalvm/${graalvm_JDK_version}/latest/graalvm-jdk-${graalvm_JDK_version}_linux-x64_bin.tar.gz.sha256
#checksum graalvm #graalvm-community-jdk, v17.0.8, 2023-07-25
#graalvm_jdk_version="17.0.8"
#curl -SsLo /tmp/graalvm-community-jdk.tar.gz https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-${graalvm_jdk_version}/graalvm-community-jdk-${graalvm_jdk_version}_linux-x64_bin.tar.gz
#curl -SsLo /tmp/graalvm-checksum https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-${graalvm_jdk_version}/graalvm-community-jdk-${graalvm_jdk_version}_linux-x64_bin.tar.gz.sha256
#checksum gradle, graalvm
checksum checksum
#install graalvm #install gradle
graalvm_inst #mkdir /opt/gradle
#unzip -qqd /opt/gradle /tmp/gradle-${gradle_version}-bin.zip
#export PATH=$PATH:/opt/gradle/gradle-${gradle_version}/bin
#nativeCompile #install graalvm -- ToDo: need to be checked, graalvm after installing available as default-jvm?
buildproc tar -C /usr/lib/jvm/ -xzf graalvm-jdk-${graalvm_JDK_version}_linux-x64_bin.tar.gz
dirname_graalvm=$(ls /usr/lib/jvm/|grep -e graa)
ln -s /usr/lib/jvm/$dirname_graalvm /usr/lib/jvm/graalvm
ln -s /usr/lib/jvm/graalvm/bin/gu /usr/local/bin
update-alternatives --install /usr/bin/java java /usr/lib/jvm/graalvm/bin/java 2
#ToDo install by graalvm, put graalvm binary here
#install -m 0700 /tmp/entrypoint-start-and-wait.sh /
#install -m 0700 /tmp/init.sh /usr/local/bin/
#install -m 0700 /tmp/backup.sh /usr/local/bin/
#install -m 0700 /tmp/restore.sh /usr/local/bin/
#install -m 0700 /tmp/restic-snapshots.sh /usr/local/bin/
#cleanupDocker #cleanupDocker
rm -f /root/.ssh/authorized_keys } #> /dev/null
rm -f /root/.ssh/authorized_keys2
apt-get clean
apt-get -qqy autoremove --purge
apt-get -qqy autoclean
rm -rf /var/lib/apt/lists/
rm -rf /tmp/*
find /var/cache -type f -exec rm -rf {} \;
find /var/log/ -name '*.log' -exec rm -f {} \;
} > /dev/null
function checksum() { function checksum() {
#gradle
#echo " /tmp/gradle-${gradle_version}-bin.zip"|tee -a /tmp/gradle-${gradle_version}-bin.zip.sha256
#sha256sum -c --status /tmp/gradle-${gradle_version}-bin.zip.sha256
#graalvm #graalvm
echo " /tmp/graalvm-community-jdk-${graalvm_jdk_version}_linux-x64_bin.tar.gz"|tee -a /tmp/graalvm-community-jdk-${graalvm_jdk_version}_linux-x64_bin.tar.gz.sha256 echo " /tmp/graalvm-jdk-${graalvm_JDK_version}_linux-x64_bin.tar.gz"|tee -a /tmp/graalvm-jdk-${graalvm_JDK_version}_linux-x64_bin.tar.gz.sha256
sha256sum -c --status /tmp/graalvm-community-jdk-${graalvm_jdk_version}_linux-x64_bin.tar.gz.sha256 sha256sum -c --status graalvm-jdk-${graalvm_JDK_version}_linux-x64_bin.tar.gz.sha256
} }
function graalvm_inst(){ source /tmp/install_functions_debian.sh
mkdir /usr/lib/jvm/
tar -C /usr/lib/jvm/ -xzf /tmp/graalvm-community-jdk-${graalvm_jdk_version}_linux-x64_bin.tar.gz
dirname_graalvm=$(ls /usr/lib/jvm/|grep -e graa)
mkdir /usr/lib/jvm/graalvm/
ln -s /usr/lib/jvm/$dirname_graalvm/bin/ /usr/lib/jvm/graalvm/
update-alternatives --install /usr/bin/java java /usr/lib/jvm/graalvm/bin/java 0
echo "export PATH=$PATH:/usr/lib/jvm/graalvm/bin"| tee -a ~/.bashrc
}
function buildproc() {
cd /usr/local/src/ModeratorElection/
#build graalvm binary
./gradlew nativeCompile -Dvaadin.productionMode=true -x processTestAot
}
#source /tmp/install_functions_debian.sh
DEBIAN_FRONTEND=noninteractive DEBCONF_NOWARNINGS=yes main DEBIAN_FRONTEND=noninteractive DEBCONF_NOWARNINGS=yes main
#cd /usr/local/src/ModeratorElection
#npm install -g npm@latest
#npm audit fix
#npm ci --omit=dev
#./gradlew build

3698
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -4,102 +4,248 @@
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@polymer/polymer": "3.5.1", "@polymer/polymer": "3.5.1",
"@vaadin/bundles": "24.4.0", "@vaadin/a11y-base": "24.3.13",
"@vaadin/accordion": "24.3.13",
"@vaadin/app-layout": "24.3.13",
"@vaadin/avatar": "24.3.13",
"@vaadin/avatar-group": "24.3.13",
"@vaadin/bundles": "24.3.13",
"@vaadin/button": "24.3.13",
"@vaadin/checkbox": "24.3.13",
"@vaadin/checkbox-group": "24.3.13",
"@vaadin/combo-box": "24.3.13",
"@vaadin/common-frontend": "0.0.19", "@vaadin/common-frontend": "0.0.19",
"@vaadin/polymer-legacy-adapter": "24.4.0", "@vaadin/component-base": "24.3.13",
"@vaadin/react-components": "24.4.0", "@vaadin/confirm-dialog": "24.3.13",
"@vaadin/context-menu": "24.3.13",
"@vaadin/custom-field": "24.3.13",
"@vaadin/date-picker": "24.3.13",
"@vaadin/date-time-picker": "24.3.13",
"@vaadin/details": "24.3.13",
"@vaadin/dialog": "24.3.13",
"@vaadin/email-field": "24.3.13",
"@vaadin/field-base": "24.3.13",
"@vaadin/field-highlighter": "24.3.13",
"@vaadin/form-layout": "24.3.13",
"@vaadin/grid": "24.3.13",
"@vaadin/horizontal-layout": "24.3.13",
"@vaadin/icon": "24.3.13",
"@vaadin/icons": "24.3.13",
"@vaadin/input-container": "24.3.13",
"@vaadin/integer-field": "24.3.13",
"@vaadin/item": "24.3.13",
"@vaadin/list-box": "24.3.13",
"@vaadin/lit-renderer": "24.3.13",
"@vaadin/login": "24.3.13",
"@vaadin/menu-bar": "24.3.13",
"@vaadin/message-input": "24.3.13",
"@vaadin/message-list": "24.3.13",
"@vaadin/multi-select-combo-box": "24.3.13",
"@vaadin/notification": "24.3.13",
"@vaadin/number-field": "24.3.13",
"@vaadin/overlay": "24.3.13",
"@vaadin/password-field": "24.3.13",
"@vaadin/polymer-legacy-adapter": "24.3.13",
"@vaadin/progress-bar": "24.3.13",
"@vaadin/radio-group": "24.3.13",
"@vaadin/router": "1.7.5", "@vaadin/router": "1.7.5",
"@vaadin/scroller": "24.3.13",
"@vaadin/select": "24.3.13",
"@vaadin/side-nav": "24.3.13",
"@vaadin/split-layout": "24.3.13",
"@vaadin/tabs": "24.3.13",
"@vaadin/tabsheet": "24.3.13",
"@vaadin/text-area": "24.3.13",
"@vaadin/text-field": "24.3.13",
"@vaadin/time-picker": "24.3.13",
"@vaadin/tooltip": "24.3.13",
"@vaadin/upload": "24.3.13",
"@vaadin/vaadin-development-mode-detector": "2.0.7", "@vaadin/vaadin-development-mode-detector": "2.0.7",
"@vaadin/vaadin-lumo-styles": "24.4.0", "@vaadin/vaadin-lumo-styles": "24.3.13",
"@vaadin/vaadin-material-styles": "24.4.0", "@vaadin/vaadin-material-styles": "24.3.13",
"@vaadin/vaadin-themable-mixin": "24.4.0", "@vaadin/vaadin-themable-mixin": "24.3.13",
"@vaadin/vaadin-usage-statistics": "2.1.2", "@vaadin/vaadin-usage-statistics": "2.1.2",
"@vaadin/vertical-layout": "24.3.13",
"@vaadin/virtual-list": "24.3.13",
"construct-style-sheets-polyfill": "3.1.0", "construct-style-sheets-polyfill": "3.1.0",
"date-fns": "2.29.3", "date-fns": "2.29.3",
"lit": "3.1.4", "lit": "3.1.2"
"react": "18.3.1",
"react-dom": "18.3.1",
"react-router-dom": "6.23.1"
}, },
"devDependencies": { "devDependencies": {
"@babel/preset-react": "7.24.7", "@rollup/plugin-replace": "5.0.5",
"@rollup/plugin-replace": "5.0.7",
"@rollup/pluginutils": "5.1.0", "@rollup/pluginutils": "5.1.0",
"@types/react": "18.3.3", "@vitejs/plugin-react": "4.2.1",
"@types/react-dom": "18.3.0", "@vitejs/plugin-react-swc": "3.5.0",
"@vitejs/plugin-react": "4.3.1", "async": "3.2.4",
"async": "3.2.5", "glob": "10.3.3",
"glob": "10.4.1",
"rollup-plugin-brotli": "3.1.0", "rollup-plugin-brotli": "3.1.0",
"rollup-plugin-visualizer": "5.12.0", "rollup-plugin-visualizer": "5.12.0",
"strip-css-comments": "5.0.0", "strip-css-comments": "5.0.0",
"transform-ast": "2.4.4", "transform-ast": "2.4.4",
"typescript": "5.4.5", "typescript": "5.3.3",
"vite": "5.3.1", "vite": "5.1.7",
"vite-plugin-checker": "0.6.4", "vite-plugin-checker": "0.6.4",
"workbox-build": "7.1.1", "workbox-build": "7.0.0",
"workbox-core": "7.1.0", "workbox-core": "7.0.0",
"workbox-precaching": "7.1.0" "workbox-precaching": "7.0.0"
}, },
"vaadin": { "vaadin": {
"dependencies": { "dependencies": {
"@polymer/polymer": "3.5.1", "@polymer/polymer": "3.5.1",
"@vaadin/bundles": "24.4.0", "@vaadin/a11y-base": "24.3.13",
"@vaadin/accordion": "24.3.13",
"@vaadin/app-layout": "24.3.13",
"@vaadin/avatar": "24.3.13",
"@vaadin/avatar-group": "24.3.13",
"@vaadin/bundles": "24.3.13",
"@vaadin/button": "24.3.13",
"@vaadin/checkbox": "24.3.13",
"@vaadin/checkbox-group": "24.3.13",
"@vaadin/combo-box": "24.3.13",
"@vaadin/common-frontend": "0.0.19", "@vaadin/common-frontend": "0.0.19",
"@vaadin/polymer-legacy-adapter": "24.4.0", "@vaadin/component-base": "24.3.13",
"@vaadin/react-components": "24.4.0", "@vaadin/confirm-dialog": "24.3.13",
"@vaadin/context-menu": "24.3.13",
"@vaadin/custom-field": "24.3.13",
"@vaadin/date-picker": "24.3.13",
"@vaadin/date-time-picker": "24.3.13",
"@vaadin/details": "24.3.13",
"@vaadin/dialog": "24.3.13",
"@vaadin/email-field": "24.3.13",
"@vaadin/field-base": "24.3.13",
"@vaadin/field-highlighter": "24.3.13",
"@vaadin/form-layout": "24.3.13",
"@vaadin/grid": "24.3.13",
"@vaadin/horizontal-layout": "24.3.13",
"@vaadin/icon": "24.3.13",
"@vaadin/icons": "24.3.13",
"@vaadin/input-container": "24.3.13",
"@vaadin/integer-field": "24.3.13",
"@vaadin/item": "24.3.13",
"@vaadin/list-box": "24.3.13",
"@vaadin/lit-renderer": "24.3.13",
"@vaadin/login": "24.3.13",
"@vaadin/menu-bar": "24.3.13",
"@vaadin/message-input": "24.3.13",
"@vaadin/message-list": "24.3.13",
"@vaadin/multi-select-combo-box": "24.3.13",
"@vaadin/notification": "24.3.13",
"@vaadin/number-field": "24.3.13",
"@vaadin/overlay": "24.3.13",
"@vaadin/password-field": "24.3.13",
"@vaadin/polymer-legacy-adapter": "24.3.13",
"@vaadin/progress-bar": "24.3.13",
"@vaadin/radio-group": "24.3.13",
"@vaadin/router": "1.7.5", "@vaadin/router": "1.7.5",
"@vaadin/scroller": "24.3.13",
"@vaadin/select": "24.3.13",
"@vaadin/side-nav": "24.3.13",
"@vaadin/split-layout": "24.3.13",
"@vaadin/tabs": "24.3.13",
"@vaadin/tabsheet": "24.3.13",
"@vaadin/text-area": "24.3.13",
"@vaadin/text-field": "24.3.13",
"@vaadin/time-picker": "24.3.13",
"@vaadin/tooltip": "24.3.13",
"@vaadin/upload": "24.3.13",
"@vaadin/vaadin-development-mode-detector": "2.0.7", "@vaadin/vaadin-development-mode-detector": "2.0.7",
"@vaadin/vaadin-lumo-styles": "24.4.0", "@vaadin/vaadin-lumo-styles": "24.3.13",
"@vaadin/vaadin-material-styles": "24.4.0", "@vaadin/vaadin-material-styles": "24.3.13",
"@vaadin/vaadin-themable-mixin": "24.4.0", "@vaadin/vaadin-themable-mixin": "24.3.13",
"@vaadin/vaadin-usage-statistics": "2.1.2", "@vaadin/vaadin-usage-statistics": "2.1.2",
"@vaadin/vertical-layout": "24.3.13",
"@vaadin/virtual-list": "24.3.13",
"construct-style-sheets-polyfill": "3.1.0", "construct-style-sheets-polyfill": "3.1.0",
"date-fns": "2.29.3", "date-fns": "2.29.3",
"lit": "3.1.4", "lit": "3.1.2"
"react": "18.3.1",
"react-dom": "18.3.1",
"react-router-dom": "6.23.1"
}, },
"devDependencies": { "devDependencies": {
"@babel/preset-react": "7.24.7", "@rollup/plugin-replace": "5.0.5",
"@rollup/plugin-replace": "5.0.7",
"@rollup/pluginutils": "5.1.0", "@rollup/pluginutils": "5.1.0",
"@types/react": "18.3.3", "@vitejs/plugin-react": "4.2.1",
"@types/react-dom": "18.3.0", "@vitejs/plugin-react-swc": "3.5.0",
"@vitejs/plugin-react": "4.3.1", "async": "3.2.4",
"async": "3.2.5", "glob": "10.3.3",
"glob": "10.4.1",
"rollup-plugin-brotli": "3.1.0", "rollup-plugin-brotli": "3.1.0",
"rollup-plugin-visualizer": "5.12.0", "rollup-plugin-visualizer": "5.12.0",
"strip-css-comments": "5.0.0", "strip-css-comments": "5.0.0",
"transform-ast": "2.4.4", "transform-ast": "2.4.4",
"typescript": "5.4.5", "typescript": "5.3.3",
"vite": "5.3.1", "vite": "5.1.7",
"vite-plugin-checker": "0.6.4", "vite-plugin-checker": "0.6.4",
"workbox-build": "7.1.1", "workbox-build": "7.0.0",
"workbox-core": "7.1.0", "workbox-core": "7.0.0",
"workbox-precaching": "7.1.0" "workbox-precaching": "7.0.0"
}, },
"hash": "a138b9347a25dacd61eb23a186fb55a3bff3993609bd58738beb6651e7993e01" "hash": "1b578191af08a883e68dfca9e08ad525b69d9824e0ec3e82a2689cdcf77b5ffe"
}, },
"overrides": { "overrides": {
"@vaadin/bundles": "$@vaadin/bundles", "@vaadin/bundles": "$@vaadin/bundles",
"@vaadin/a11y-base": "$@vaadin/a11y-base",
"@vaadin/accordion": "$@vaadin/accordion",
"@vaadin/app-layout": "$@vaadin/app-layout",
"@vaadin/avatar": "$@vaadin/avatar",
"@vaadin/avatar-group": "$@vaadin/avatar-group",
"@vaadin/button": "$@vaadin/button",
"@vaadin/checkbox": "$@vaadin/checkbox",
"@vaadin/checkbox-group": "$@vaadin/checkbox-group",
"@vaadin/combo-box": "$@vaadin/combo-box",
"@vaadin/component-base": "$@vaadin/component-base",
"@vaadin/confirm-dialog": "$@vaadin/confirm-dialog",
"@vaadin/context-menu": "$@vaadin/context-menu",
"@vaadin/custom-field": "$@vaadin/custom-field",
"@vaadin/date-picker": "$@vaadin/date-picker",
"@vaadin/date-time-picker": "$@vaadin/date-time-picker",
"@vaadin/details": "$@vaadin/details",
"@vaadin/dialog": "$@vaadin/dialog",
"@vaadin/email-field": "$@vaadin/email-field",
"@vaadin/field-base": "$@vaadin/field-base",
"@vaadin/field-highlighter": "$@vaadin/field-highlighter",
"@vaadin/form-layout": "$@vaadin/form-layout",
"@vaadin/grid": "$@vaadin/grid",
"@vaadin/horizontal-layout": "$@vaadin/horizontal-layout",
"@vaadin/icon": "$@vaadin/icon",
"@vaadin/icons": "$@vaadin/icons",
"@vaadin/input-container": "$@vaadin/input-container",
"@vaadin/integer-field": "$@vaadin/integer-field",
"@vaadin/item": "$@vaadin/item",
"@vaadin/list-box": "$@vaadin/list-box",
"@vaadin/lit-renderer": "$@vaadin/lit-renderer",
"@vaadin/login": "$@vaadin/login",
"@vaadin/menu-bar": "$@vaadin/menu-bar",
"@vaadin/message-input": "$@vaadin/message-input",
"@vaadin/message-list": "$@vaadin/message-list",
"@vaadin/multi-select-combo-box": "$@vaadin/multi-select-combo-box",
"@vaadin/notification": "$@vaadin/notification",
"@vaadin/number-field": "$@vaadin/number-field",
"@vaadin/overlay": "$@vaadin/overlay",
"@vaadin/password-field": "$@vaadin/password-field",
"@vaadin/polymer-legacy-adapter": "$@vaadin/polymer-legacy-adapter", "@vaadin/polymer-legacy-adapter": "$@vaadin/polymer-legacy-adapter",
"@vaadin/progress-bar": "$@vaadin/progress-bar",
"@vaadin/radio-group": "$@vaadin/radio-group",
"@vaadin/scroller": "$@vaadin/scroller",
"@vaadin/select": "$@vaadin/select",
"@vaadin/side-nav": "$@vaadin/side-nav",
"@vaadin/split-layout": "$@vaadin/split-layout",
"@vaadin/tabs": "$@vaadin/tabs",
"@vaadin/tabsheet": "$@vaadin/tabsheet",
"@vaadin/text-area": "$@vaadin/text-area",
"@vaadin/text-field": "$@vaadin/text-field",
"@vaadin/time-picker": "$@vaadin/time-picker",
"@vaadin/tooltip": "$@vaadin/tooltip",
"@vaadin/upload": "$@vaadin/upload",
"@vaadin/vaadin-development-mode-detector": "$@vaadin/vaadin-development-mode-detector", "@vaadin/vaadin-development-mode-detector": "$@vaadin/vaadin-development-mode-detector",
"@vaadin/vaadin-lumo-styles": "$@vaadin/vaadin-lumo-styles", "@vaadin/vaadin-lumo-styles": "$@vaadin/vaadin-lumo-styles",
"@vaadin/vaadin-material-styles": "$@vaadin/vaadin-material-styles", "@vaadin/vaadin-material-styles": "$@vaadin/vaadin-material-styles",
"@vaadin/router": "$@vaadin/router", "@vaadin/router": "$@vaadin/router",
"@vaadin/vaadin-usage-statistics": "$@vaadin/vaadin-usage-statistics", "@vaadin/vaadin-usage-statistics": "$@vaadin/vaadin-usage-statistics",
"@vaadin/vertical-layout": "$@vaadin/vertical-layout",
"@vaadin/virtual-list": "$@vaadin/virtual-list",
"@vaadin/common-frontend": "$@vaadin/common-frontend", "@vaadin/common-frontend": "$@vaadin/common-frontend",
"construct-style-sheets-polyfill": "$construct-style-sheets-polyfill", "construct-style-sheets-polyfill": "$construct-style-sheets-polyfill",
"lit": "$lit", "lit": "$lit",
"@polymer/polymer": "$@polymer/polymer", "@polymer/polymer": "$@polymer/polymer",
"@vaadin/vaadin-themable-mixin": "$@vaadin/vaadin-themable-mixin", "@vaadin/vaadin-themable-mixin": "$@vaadin/vaadin-themable-mixin",
"date-fns": "$date-fns", "date-fns": "$date-fns"
"@vaadin/react-components": "$@vaadin/react-components",
"react-dom": "$react-dom",
"react-router-dom": "$react-router-dom",
"react": "$react"
} }
} }

View file

@ -14,7 +14,6 @@ import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route; import com.vaadin.flow.router.Route;
import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.spring.annotation.RouteScope;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -24,7 +23,6 @@ import java.util.List;
@Route("") @Route("")
@PageTitle("Moderatorenwahl") @PageTitle("Moderatorenwahl")
@RouteScope
@Configuration @Configuration
public class MainView extends VerticalLayout { public class MainView extends VerticalLayout {
@ -40,9 +38,8 @@ public class MainView extends VerticalLayout {
Button electNow = new Button("Elect!", buttonClickEvent -> { Button electNow = new Button("Elect!", buttonClickEvent -> {
try { try {
ArrayList<String> checkboxSelectedMembers = new ArrayList<>(checkboxGroup.getSelectedItems()); ArrayList checkboxSelectedMembers = new ArrayList(checkboxGroup.getSelectedItems());
new Notification(); Notification moderatorNotification = new Notification()
Notification moderatorNotification = Notification
.show("Nächster Moderator: " + electMember(checkboxSelectedMembers)); .show("Nächster Moderator: " + electMember(checkboxSelectedMembers));
moderatorNotification.setPosition(Notification.Position.BOTTOM_CENTER); moderatorNotification.setPosition(Notification.Position.BOTTOM_CENTER);
} catch(Exception exceptionEvent) { } catch(Exception exceptionEvent) {

View file

@ -1,49 +0,0 @@
[
{
"name":"java.awt.GraphicsEnvironment",
"methods":[{"name":"isHeadless","parameterTypes":[] }]
},
{
"name":"java.awt.image.BufferedImage",
"fields":[{"name":"colorModel"}, {"name":"imageType"}, {"name":"raster"}],
"methods":[{"name":"getRGB","parameterTypes":["int","int","int","int","int[]","int","int"] }, {"name":"setRGB","parameterTypes":["int","int","int","int","int[]","int","int"] }]
},
{
"name":"java.awt.image.ColorModel",
"fields":[{"name":"colorSpace"}, {"name":"colorSpaceType"}, {"name":"isAlphaPremultiplied"}, {"name":"is_sRGB"}, {"name":"nBits"}, {"name":"numComponents"}, {"name":"supportsAlpha"}, {"name":"transparency"}],
"methods":[{"name":"getRGBdefault","parameterTypes":[] }]
},
{
"name":"java.awt.image.Raster",
"fields":[{"name":"dataBuffer"}, {"name":"height"}, {"name":"minX"}, {"name":"minY"}, {"name":"numBands"}, {"name":"numDataElements"}, {"name":"sampleModel"}, {"name":"sampleModelTranslateX"}, {"name":"sampleModelTranslateY"}, {"name":"width"}]
},
{
"name":"java.awt.image.SampleModel",
"fields":[{"name":"height"}, {"name":"width"}],
"methods":[{"name":"getPixels","parameterTypes":["int","int","int","int","int[]","java.awt.image.DataBuffer"] }, {"name":"setPixels","parameterTypes":["int","int","int","int","int[]","java.awt.image.DataBuffer"] }]
},
{
"name":"java.awt.image.SinglePixelPackedSampleModel",
"fields":[{"name":"bitMasks"}, {"name":"bitOffsets"}, {"name":"bitSizes"}, {"name":"maxBitSize"}]
},
{
"name":"java.lang.Boolean",
"methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }]
},
{
"name":"java.lang.System",
"methods":[{"name":"load","parameterTypes":["java.lang.String"] }]
},
{
"name":"sun.awt.image.ByteComponentRaster",
"fields":[{"name":"data"}, {"name":"dataOffsets"}, {"name":"pixelStride"}, {"name":"scanlineStride"}, {"name":"type"}]
},
{
"name":"sun.java2d.Disposer",
"methods":[{"name":"addRecord","parameterTypes":["java.lang.Object","long","long"] }]
},
{
"name":"sun.management.VMManagementImpl",
"fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}]
}
]

View file

@ -1,8 +0,0 @@
[
{
"type":"agent-extracted",
"classes":[
]
}
]

View file

@ -1,26 +0,0 @@
[
{
"interfaces":["java.lang.reflect.ParameterizedType","org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy","java.io.Serializable"]
},
{
"interfaces":["java.lang.reflect.TypeVariable","org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy","java.io.Serializable"]
},
{
"interfaces":["java.lang.reflect.WildcardType","org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy","java.io.Serializable"]
},
{
"interfaces":["org.atmosphere.cpr.AtmosphereHandler"]
},
{
"interfaces":["org.atmosphere.cpr.Broadcaster"]
},
{
"interfaces":["org.springframework.boot.context.properties.ConfigurationProperties"]
},
{
"interfaces":["org.springframework.web.bind.annotation.PathVariable"]
},
{
"interfaces":["org.springframework.web.bind.annotation.RequestMapping"]
}
]

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,8 +0,0 @@
{
"types":[
],
"lambdaCapturingTypes":[
],
"proxies":[
]
}

View file

@ -1,8 +1,4 @@
spring.application.name=ModeratorElection server.port=${PORT:6333}
spring.main.banner-mode=off
server.port=${PORT:8080}
logging.level.org.atmosphere = warn logging.level.org.atmosphere = warn
spring.mustache.check-template-location = false spring.mustache.check-template-location = false
@ -10,6 +6,6 @@ spring.mustache.check-template-location = false
vaadin.launch-browser=true vaadin.launch-browser=true
# To improve the performance during development. # To improve the performance during development.
# For more information https://vaadin.com/docs/latest/integrations/spring/configuration#special-configuration-parameters # For more information https://vaadin.com/docs/latest/integrations/spring/configuration#special-configuration-parameters
vaadin.allowed-packages = com.vaadin,org.vaadin,dev.hilla,com.ModeratorElection.MEApplication vaadin.allowed-packages = com.vaadin,org.vaadin,dev.hilla,com.example.application
spring.jpa.defer-datasource-initialization = true spring.jpa.defer-datasource-initialization = true
membernames=${MEMBERNAMES} membernames=${MEMBERNAMES:Micha,Ansgar,Clemens,Mattis,Erik,Mirco}

View file

@ -0,0 +1,13 @@
package com.ModeratorElection;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DemoApplicationTests {
@Test
void contextLoads() {
}
}

View file

@ -5,13 +5,12 @@ import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(classes = MainView.class) //@SpringBootTest
public class MainViewTest { public class MainViewTest {
@Test @Test
void mainViewConstructor() { void mainViewConstructor() {
MainView sut = new MainView("Harry,Sven,Ida"); MainView sut = new MainView("Harry,Sven,Ida");
CheckboxGroup cgroupTest = (CheckboxGroup) sut.getChildren().filter(child -> child instanceof CheckboxGroup).findAny().orElse(null); CheckboxGroup cgroupTest = (CheckboxGroup) sut.getChildren().filter(child -> child instanceof CheckboxGroup).findAny().orElse(null);
assert cgroupTest != null;
int cgroupTestSelectedItemsSize = cgroupTest.getSelectedItems().size(); int cgroupTestSelectedItemsSize = cgroupTest.getSelectedItems().size();
Assertions.assertEquals(3,cgroupTestSelectedItemsSize); Assertions.assertEquals(3,cgroupTestSelectedItemsSize);
} }