diff --git a/.github/workflows/maven.yaml b/.github/workflows/maven.yaml index 322717d..9547f66 100644 --- a/.github/workflows/maven.yaml +++ b/.github/workflows/maven.yaml @@ -32,7 +32,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@v4 with: - java-version: '21' + java-version: '25' distribution: corretto cache: maven diff --git a/Dockerfile b/Dockerfile index 3d3d668..f9b1a7e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,24 +2,24 @@ # Run: docker run --name moresleep-container -p 5000:5000 moresleep-app:latest # Check localhost:5000 and you should get a homepage # Stage 1: Build the application -FROM maven:3.9.11-eclipse-temurin-21 AS build +FROM maven:3.9.12-eclipse-temurin-25 AS build WORKDIR /app COPY pom.xml . COPY src ./src RUN mvn clean package -Dmaven.test.skip=true # Stage 2: Create the final runtime image -FROM eclipse-temurin:21-jre-jammy AS final +FROM eclipse-temurin:25-jre-jammy AS final -# Install SOPS -RUN curl -L -o /usr/local/bin/sops https://github.com/getsops/sops/releases/download/v3.10.2/sops-v3.10.2.linux.amd64 && \ - chmod +x /usr/local/bin/sops - - # Install unzip and curl -RUN apt-get update && \ +# Install unzip and curl +RUN apt-get update -y && \ apt-get install -y curl unzip && \ rm -rf /var/lib/apt/lists/* +# Install SOPS +RUN curl -L -o /usr/local/bin/sops https://github.com/getsops/sops/releases/download/v3.11.0/sops-v3.11.0.linux.amd64 && \ + chmod +x /usr/local/bin/sops + # Install AWS CLI v2 RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "/tmp/awscliv2.zip" && \ unzip /tmp/awscliv2.zip -d /tmp && \ @@ -27,11 +27,11 @@ RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "/tmp/aws rm -rf /tmp/aws /tmp/awscliv2.zip WORKDIR /app -COPY --from=build /app/target/cake-redux-0.3-SNAPSHOT-jar-with-dependencies.jar app.jar +COPY --from=build /app/target/cake-redux-jar-with-dependencies.jar app.jar COPY ./config/.enc.prod.env /app/.enc.env # Remove AWS profile from SOPS config to use container's AWS credentials RUN sed -i 's/sops_kms__list_0__map_aws_profile=javabin/sops_kms__list_0__map_aws_profile=/' /app/.enc.env EXPOSE 8081 -ENTRYPOINT ["sops", "exec-env", ".enc.env", "java -jar app.jar"] \ No newline at end of file +ENTRYPOINT ["sops", "exec-env", ".enc.env", "java -jar app.jar"] diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..730b727 --- /dev/null +++ b/compose.yml @@ -0,0 +1,54 @@ +name: cake-lie + +services: + db: + image: postgres:17.6-alpine + restart: unless-stopped + command: | + postgres + -c max_connections=200 + -c shared_buffers=2GB + -c wal_level=minimal + -c fsync=off + -c synchronous_commit=off + -c full_page_writes=off + -c work_mem=16MB + -c max_wal_senders=0 + -c wal_level=minimal + -c wal_writer_delay=5s + -c wal_buffers=32MB + -c maintenance_work_mem=128MB + -c max_wal_size=3GB + -c shared_preload_libraries=pg_stat_statements,auto_explain + -c auto_explain.log_min_duration=50ms + -c auto_explain.log_analyze=true + -c auto_explain.log_buffers=true + -c auto_explain.log_timing=true + volumes: + - pg-data:/var/lib/postgresql/data + environment: + POSTGRES_USER: localdevuser + POSTGRES_PASSWORD: localdevuser + POSTGRES_DB: moresleeplocal + TZ: Europe/Oslo + healthcheck: + test: [ "CMD" , "/usr/local/bin/pg_isready", "-d", "moresleeplocal", "-U", "localdevuser", "-t", "3" ] + retries: 3 + timeout: 1m + start_period: 15s + + moresleep: + image: ghcr.io/javabin/moresleep:edge + ports: + - "8082:8082" + env_file: + - path: ./.env.moresleep + required: false + environment: + DBHOST: db + depends_on: + db: + condition: service_healthy + +volumes: + pg-data: {} diff --git a/mise.toml b/mise.toml new file mode 100644 index 0000000..be33bd2 --- /dev/null +++ b/mise.toml @@ -0,0 +1,29 @@ +[tools] +java = "25" +maven = "latest" + +[tasks.infrastructure] +run = [ + """ + if ! netstat -an | grep -q '[.:]5432\\b'; then + echo "Starter Infrastrutur..." + docker compose up --wait + else + echo "Infrastruturen kjører allerede" + fi + """, + "" +] + +[tasks.infrastructure-destroy] +run = [ + "docker compose down -v" +] + +[tasks.start] +depends = ["infrastructure"] +env = { SLEEPINGPILL_BASE_LOCATION = "http://localhost:8082", NO_AUTH_MODE = "true", SERVER_PORT = "5000", CAKE_LOCATION = "localhost" } +run = [ + "mvn clean package", + "java -jar -Xmx512m -Djava.net.preferIPv4Stack=true -Dfile.encoding=UTF-8 target/cake-redux-jar-with-dependencies.jar env-only" +] diff --git a/pom.xml b/pom.xml index a22e986..5510762 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 no.javazone cake-redux @@ -10,9 +11,23 @@ UTF-8 UTF-8 - 1.8.0 + 2.3.0 true + + + + commons-codec + commons-codec + 1.19.0 + + + commons-logging + commons-logging + 1.3.5 + + + @@ -23,30 +38,41 @@ junit junit - 4.11 + 4.13.2 test + + jakarta.servlet + jakarta.servlet-api + 6.0.0 + provided + org.eclipse.jetty jetty-server - 9.4.16.v20190411 + 12.1.5 - org.eclipse.jetty - jetty-plus - 9.4.16.v20190411 + org.eclipse.jetty.ee10 + jetty-ee10-servlet + 12.1.5 + + + org.eclipse.jetty.ee10 + jetty-ee10-webapp + 12.1.5 org.assertj assertj-core - 1.7.0 + 3.11.1 test org.mockito - mockito-all - 1.9.5 + mockito-core + 5.19.0 test @@ -54,20 +80,20 @@ org.jsonbuddy jsonbuddy - 0.8.0 + 0.18.1 com.sendgrid sendgrid-java - 4.1.0 + 4.10.3 org.logevents logevents - 0.1.38 + 0.5.9 org.jetbrains.kotlin @@ -77,6 +103,7 @@ + ${project.artifactId} kotlin-maven-plugin @@ -85,7 +112,9 @@ compile - compile + + compile + ${project.basedir}/src/main/kotlin @@ -95,7 +124,9 @@ test-compile - test-compile + + test-compile + ${project.basedir}/src/test/kotlin @@ -110,10 +141,9 @@ maven-compiler-plugin - 11 - 11 + 25 - 3.10.1 + 3.14.1 @@ -128,12 +158,16 @@ java-compile compile - compile + + compile + java-test-compile test-compile - testCompile + + testCompile + @@ -145,7 +179,9 @@ copy-dependencies package - copy-dependencies + + copy-dependencies + diff --git a/src/main/java/no/javazone/cake/redux/DataServlet.java b/src/main/java/no/javazone/cake/redux/DataServlet.java index 18f6146..5ef1392 100644 --- a/src/main/java/no/javazone/cake/redux/DataServlet.java +++ b/src/main/java/no/javazone/cake/redux/DataServlet.java @@ -13,10 +13,10 @@ import org.jsonbuddy.parse.JsonParser; import org.jsonbuddy.pojo.PojoMapper; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; diff --git a/src/main/java/no/javazone/cake/redux/EntranceServlet.java b/src/main/java/no/javazone/cake/redux/EntranceServlet.java index 17aad38..f0f0060 100644 --- a/src/main/java/no/javazone/cake/redux/EntranceServlet.java +++ b/src/main/java/no/javazone/cake/redux/EntranceServlet.java @@ -4,10 +4,10 @@ import org.jsonbuddy.JsonObject; import org.jsonbuddy.parse.JsonParser; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; diff --git a/src/main/java/no/javazone/cake/redux/OpenDataServlet.java b/src/main/java/no/javazone/cake/redux/OpenDataServlet.java index 10f287e..f526ce2 100644 --- a/src/main/java/no/javazone/cake/redux/OpenDataServlet.java +++ b/src/main/java/no/javazone/cake/redux/OpenDataServlet.java @@ -10,10 +10,10 @@ import org.jsonbuddy.JsonObject; import org.jsonbuddy.parse.JsonParser; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; diff --git a/src/main/java/no/javazone/cake/redux/SecurityFilter.java b/src/main/java/no/javazone/cake/redux/SecurityFilter.java index 730bd10..3df383a 100644 --- a/src/main/java/no/javazone/cake/redux/SecurityFilter.java +++ b/src/main/java/no/javazone/cake/redux/SecurityFilter.java @@ -1,7 +1,7 @@ package no.javazone.cake.redux; -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; import java.io.IOException; public class SecurityFilter implements Filter { diff --git a/src/main/java/no/javazone/cake/redux/SigninServlet.java b/src/main/java/no/javazone/cake/redux/SigninServlet.java index 095cc90..f95cc1e 100644 --- a/src/main/java/no/javazone/cake/redux/SigninServlet.java +++ b/src/main/java/no/javazone/cake/redux/SigninServlet.java @@ -1,9 +1,9 @@ package no.javazone.cake.redux; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; public class SigninServlet extends HttpServlet { diff --git a/src/main/java/no/javazone/cake/redux/SlackServlet.java b/src/main/java/no/javazone/cake/redux/SlackServlet.java index 9a52c9b..5f45f32 100644 --- a/src/main/java/no/javazone/cake/redux/SlackServlet.java +++ b/src/main/java/no/javazone/cake/redux/SlackServlet.java @@ -3,10 +3,10 @@ import org.jsonbuddy.JsonObject; import org.jsonbuddy.parse.JsonParser; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; diff --git a/src/main/java/no/javazone/cake/redux/WebServer.java b/src/main/java/no/javazone/cake/redux/WebServer.java index 5949003..744fefc 100644 --- a/src/main/java/no/javazone/cake/redux/WebServer.java +++ b/src/main/java/no/javazone/cake/redux/WebServer.java @@ -3,17 +3,17 @@ import no.javazone.cake.redux.videoadmin.VideoAdminFilter; import no.javazone.cake.redux.videoadmin.VideoAdminServlet; import no.javazone.cake.redux.whyda.WhydaServlet; +import org.eclipse.jetty.ee10.servlet.FilterHolder; +import org.eclipse.jetty.ee10.servlet.ServletHolder; +import org.eclipse.jetty.ee10.webapp.WebAppContext; import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.servlet.FilterHolder; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.webapp.WebAppContext; +import org.eclipse.jetty.util.resource.ResourceFactory; import java.io.File; import java.util.Arrays; import java.util.EnumSet; -import static javax.servlet.DispatcherType.REQUEST; +import static jakarta.servlet.DispatcherType.REQUEST; public class WebServer { @@ -49,25 +49,25 @@ private WebAppContext createHandler() { if (isDevEnviroment()) { // Development ie running in ide - webAppContext.setResourceBase("src/main/resources/webapp"); + webAppContext.setBaseResource(ResourceFactory.root().newResource("src/main/resources/webapp")); } else { // Prod ie running from jar - webAppContext.setBaseResource(Resource.newClassPathResource("webapp", true, false)); + webAppContext.setBaseResource(ResourceFactory.root().newClassLoaderResource("webapp", false)); } - webAppContext.addServlet(new ServletHolder(new DataServlet()),"/secured/data/*"); - webAppContext.addServlet(new ServletHolder(new OpenDataServlet()),"/data/*"); + webAppContext.addServlet(new ServletHolder(new DataServlet()), "/secured/data/*"); + webAppContext.addServlet(new ServletHolder(new OpenDataServlet()), "/data/*"); webAppContext.addServlet(new ServletHolder(new SigninServlet()), "/signin/"); webAppContext.addServlet(new ServletHolder(new EntranceServlet()), "/entrance"); - webAppContext.addServlet(new ServletHolder(new WhydaServlet()),"/whydalogin"); - webAppContext.addServlet(new ServletHolder(new SlackServlet()),"/slack/signin"); + webAppContext.addServlet(new ServletHolder(new WhydaServlet()), "/whydalogin"); + webAppContext.addServlet(new ServletHolder(new SlackServlet()), "/slack/signin"); webAppContext.addFilter(new FilterHolder(new SecurityFilter()), "/secured/*", EnumSet.of(REQUEST)); webAppContext.addFilter(new FilterHolder(new VideoAdminFilter()), "/videoadmin/*", EnumSet.of(REQUEST)); - webAppContext.addServlet(new ServletHolder(new VideoAdminServlet()),"/videoadmin/api/*"); + webAppContext.addServlet(new ServletHolder(new VideoAdminServlet()), "/videoadmin/api/*"); return webAppContext; diff --git a/src/main/java/no/javazone/cake/redux/mail/SendGridSender.java b/src/main/java/no/javazone/cake/redux/mail/SendGridSender.java index ae436f2..d6ac0e6 100644 --- a/src/main/java/no/javazone/cake/redux/mail/SendGridSender.java +++ b/src/main/java/no/javazone/cake/redux/mail/SendGridSender.java @@ -1,6 +1,13 @@ package no.javazone.cake.redux.mail; -import com.sendgrid.*; +import com.sendgrid.Method; +import com.sendgrid.Request; +import com.sendgrid.Response; +import com.sendgrid.SendGrid; +import com.sendgrid.helpers.mail.Mail; +import com.sendgrid.helpers.mail.objects.Content; +import com.sendgrid.helpers.mail.objects.Email; +import com.sendgrid.helpers.mail.objects.Personalization; import no.javazone.cake.redux.Configuration; import java.io.IOException; @@ -18,7 +25,7 @@ public boolean send() { SendGrid sg = new SendGrid(Optional.ofNullable(Configuration.sendGridKey()).orElseThrow(() -> new RuntimeException("Send grid key not set"))); Request request = new Request(); try { - Email from = new Email(mailToSend.from,mailToSend.fromName); + Email from = new Email(mailToSend.from, mailToSend.fromName); Content content = new Content("text/html", mailToSend.content); Mail mail = new Mail(); @@ -35,7 +42,8 @@ public boolean send() { request.setEndpoint("mail/send"); request.setBody(mail.build()); Response response = sg.api(request); - return true; + int statusCode = response.getStatusCode(); + return statusCode >= 200 && statusCode < 300; } catch (IOException ex) { throw new RuntimeException(ex); } diff --git a/src/main/java/no/javazone/cake/redux/videoadmin/VideoAdminFilter.java b/src/main/java/no/javazone/cake/redux/videoadmin/VideoAdminFilter.java index e27dd1c..056315e 100644 --- a/src/main/java/no/javazone/cake/redux/videoadmin/VideoAdminFilter.java +++ b/src/main/java/no/javazone/cake/redux/videoadmin/VideoAdminFilter.java @@ -2,10 +2,10 @@ import no.javazone.cake.redux.Configuration; -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Base64; diff --git a/src/main/java/no/javazone/cake/redux/videoadmin/VideoAdminServlet.java b/src/main/java/no/javazone/cake/redux/videoadmin/VideoAdminServlet.java index 1377c77..fbeebd0 100644 --- a/src/main/java/no/javazone/cake/redux/videoadmin/VideoAdminServlet.java +++ b/src/main/java/no/javazone/cake/redux/videoadmin/VideoAdminServlet.java @@ -5,12 +5,12 @@ import org.jsonbuddy.JsonObject; import org.jsonbuddy.parse.JsonParser; -import javax.servlet.Servlet; -import javax.servlet.ServletException; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.Servlet; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.util.Optional; diff --git a/src/main/java/no/javazone/cake/redux/whyda/WhydaServlet.java b/src/main/java/no/javazone/cake/redux/whyda/WhydaServlet.java index 1694d5b..f9afbe1 100644 --- a/src/main/java/no/javazone/cake/redux/whyda/WhydaServlet.java +++ b/src/main/java/no/javazone/cake/redux/whyda/WhydaServlet.java @@ -3,10 +3,10 @@ import no.javazone.cake.redux.Configuration; import no.javazone.cake.redux.EntranceServlet; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.*; import java.net.URL; import java.net.URLConnection; diff --git a/src/main/kotlin/no/javazone/cake/redux/PkomFeedbackCompute.kt b/src/main/kotlin/no/javazone/cake/redux/PkomFeedbackCompute.kt index 6db5a6f..ce91e9f 100644 --- a/src/main/kotlin/no/javazone/cake/redux/PkomFeedbackCompute.kt +++ b/src/main/kotlin/no/javazone/cake/redux/PkomFeedbackCompute.kt @@ -26,7 +26,7 @@ object PkomFeedbackCompute { } val allRatings:List = allRatingsJson.map { Rating.fromText(it.requiredString("info")) } - val sum = allRatings.sumBy { it.ratingValue } + val sum = allRatings.sumOf { it.ratingValue } val count = allRatings.size val mean:Int = sum / count diff --git a/src/test/java/no/javazone/cake/redux/DataServletWriteTest.java b/src/test/java/no/javazone/cake/redux/DataServletWriteTest.java index 2335988..bfe822d 100644 --- a/src/test/java/no/javazone/cake/redux/DataServletWriteTest.java +++ b/src/test/java/no/javazone/cake/redux/DataServletWriteTest.java @@ -5,11 +5,11 @@ import org.junit.Before; import org.junit.Test; -import javax.servlet.ReadListener; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; import java.io.*; import java.util.Arrays;