diff --git a/Dockerfile b/Dockerfile index 74fbcfb..d19c01a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,24 +1,28 @@ -FROM maven:3.9-eclipse-temurin-21 AS build - +FROM maven:3.9-eclipse-temurin-17 AS build WORKDIR /app -COPY . . -# Compilar la aplicación sin ejecutar tests -RUN mvn package -DskipTests +# Copy project dependencies +COPY pom.xml . +COPY src ./src -FROM registry.access.redhat.com/ubi8/openjdk-21-runtime:latest +# Build the project +RUN mvn clean package -DskipTests +FROM eclipse-temurin:17-jre-alpine WORKDIR /app -COPY --from=build /app/target/quarkus-app /app/ -# Puerto que expondrá la aplicación +# Create uploads directory +RUN mkdir -p /app/uploads + +# Copy built jar +COPY --from=build /app/target/*.jar app.jar + +# Copy initial images +COPY uploads /app/uploads + +# Setting environment variables +ENV SPRING_PROFILES_ACTIVE=prod + EXPOSE 8080 -# Variables de entorno para configuración de DB y perfil -ENV QUARKUS_PROFILE="prod" \ - QUARKUS_DATASOURCE_USERNAME=${DB_USERNAME} \ - QUARKUS_DATASOURCE_PASSWORD=${DB_PASSWORD} \ - QUARKUS_DATASOURCE_JDBC_URL=jdbc:postgresql://${POSTGRESSHOST}:${POSTGRESSPORT}/${POSTGRESSDATABASE} - -# Comando para iniciar la aplicación -CMD ["java", "-Dquarkus.profile=${QUARKUS_PROFILE}", "-jar", "quarkus-run.jar"] \ No newline at end of file +ENTRYPOINT ["java", "-jar", "app.jar"] \ No newline at end of file diff --git a/README.md b/README.md index 79cd792..5d0913b 100644 --- a/README.md +++ b/README.md @@ -1,93 +1,65 @@ -# gym-backend +# Gym Backend (Spring Boot) -This project uses Quarkus, the Supersonic Subatomic Java Framework. +A Spring Boot backend application for a gym management system. This application provides RESTful APIs for managing users, gym classes and bookings. -If you want to learn more about Quarkus, please visit its website: . +## Requirements -## Running the application in dev mode +- Java 17 or higher +- Maven 3.8+ +- PostgreSQL -You can run your application in dev mode that enables live coding using: +## Getting Started -```shell script -./mvnw quarkus:dev +### Running Locally + +1. Clone the repository +2. Configure PostgreSQL database (default credentials in application.properties) +3. Run the application: + +```bash +mvn spring-boot:run ``` -> **_NOTE:_** Quarkus now ships with a Dev UI, which is available in dev mode only at . +The application will start at http://localhost:8080 -## Packaging and running the application +### Using Docker -The application can be packaged using: +1. Build the Docker image: -```shell script -./mvnw package +```bash +docker build -t gym-backend . ``` -It produces the `quarkus-run.jar` file in the `target/quarkus-app/` directory. -Be aware that it’s not an _über-jar_ as the dependencies are copied into the `target/quarkus-app/lib/` directory. +2. Run the container: -The application is now runnable using `java -jar target/quarkus-app/quarkus-run.jar`. - -If you want to build an _über-jar_, execute the following command: - -```shell script -./mvnw package -Dquarkus.package.jar.type=uber-jar +```bash +docker run -p 8080:8080 gym-backend ``` -The application, packaged as an _über-jar_, is now runnable using `java -jar target/*-runner.jar`. +## API Endpoints -## Creating a native executable +### Users -You can create a native executable using: +- `GET /api/users`: Get all users +- `GET /api/users/{id}`: Get user by ID +- `POST /api/users`: Create new user +- `PUT /api/users/{id}`: Update user -```shell script -./mvnw package -Dnative -``` +### Gym Classes -Or, if you don't have GraalVM installed, you can run the native executable build in a container using: +- `GET /api/classes`: Get all classes +- `GET /api/classes/{id}`: Get class by ID +- `POST /api/classes`: Create new class +- `PUT /api/classes/{id}`: Update class +- `DELETE /api/classes/{id}`: Delete class -```shell script -./mvnw package -Dnative -Dquarkus.native.container-build=true -``` +### Bookings -You can then execute your native executable with: `./target/gym-backend-1.0.0-SNAPSHOT-runner` +- `GET /api/bookings`: Get all bookings +- `GET /api/bookings/user/{userId}`: Get bookings by user ID +- `POST /api/bookings`: Create new booking +- `PUT /api/bookings/{id}/cancel`: Cancel booking -If you want to learn more about building native executables, please consult . +### File Upload -## Related Guides - -- Picocli ([guide](https://quarkus.io/guides/picocli)): Develop command line applications with Picocli -- RESTEasy Classic Multipart ([guide](https://quarkus.io/guides/rest-json#multipart-support)): Multipart support for RESTEasy Classic -- Hibernate ORM with Panache ([guide](https://quarkus.io/guides/hibernate-orm-panache)): Simplify your persistence code for Hibernate ORM via the active record or the repository pattern -- SmallRye JWT ([guide](https://quarkus.io/guides/security-jwt)): Secure your applications with JSON Web Token -- JDBC Driver - PostgreSQL ([guide](https://quarkus.io/guides/datasource)): Connect to the PostgreSQL database via JDBC - -## Provided Code - -### Hibernate ORM - -Create your first JPA entity - -[Related guide section...](https://quarkus.io/guides/hibernate-orm) - -[Related Hibernate with Panache section...](https://quarkus.io/guides/hibernate-orm-panache) - - -### Picocli Example - -Hello and goodbye are civilization fundamentals. Let's not forget it with this example picocli application by changing the command and parameters. - -[Related guide section...](https://quarkus.io/guides/picocli#command-line-application-with-multiple-commands) - -Also for picocli applications the dev mode is supported. When running dev mode, the picocli application is executed and on press of the Enter key, is restarted. - -As picocli applications will often require arguments to be passed on the commandline, this is also possible in dev mode via: - -```shell script -./mvnw quarkus:dev -Dquarkus.args='Quarky' -``` - -### RESTEasy JAX-RS - -Easily start your RESTful Web Services - -[Related guide section...](https://quarkus.io/guides/getting-started#the-jax-rs-resources) +- `POST /api/upload`: Upload files (for profile pictures and class images) \ No newline at end of file diff --git a/mvnw b/mvnw deleted file mode 100755 index 5e9618c..0000000 --- a/mvnw +++ /dev/null @@ -1,332 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Apache Maven Wrapper startup batch script, version 3.3.2 -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ]; then - - if [ -f /usr/local/etc/mavenrc ]; then - . /usr/local/etc/mavenrc - fi - - if [ -f /etc/mavenrc ]; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ]; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false -darwin=false -mingw=false -case "$(uname)" in -CYGWIN*) cygwin=true ;; -MINGW*) mingw=true ;; -Darwin*) - darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - JAVA_HOME="$(/usr/libexec/java_home)" - export JAVA_HOME - else - JAVA_HOME="/Library/Java/Home" - export JAVA_HOME - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ]; then - if [ -r /etc/gentoo-release ]; then - JAVA_HOME=$(java-config --jre-home) - fi -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin; then - [ -n "$JAVA_HOME" ] \ - && JAVA_HOME=$(cygpath --unix "$JAVA_HOME") - [ -n "$CLASSPATH" ] \ - && CLASSPATH=$(cygpath --path --unix "$CLASSPATH") -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw; then - [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] \ - && JAVA_HOME="$( - cd "$JAVA_HOME" || ( - echo "cannot cd into $JAVA_HOME." >&2 - exit 1 - ) - pwd - )" -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="$(which javac)" - if [ -n "$javaExecutable" ] && ! [ "$(expr "$javaExecutable" : '\([^ ]*\)')" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=$(which readlink) - if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then - if $darwin; then - javaHome="$(dirname "$javaExecutable")" - javaExecutable="$(cd "$javaHome" && pwd -P)/javac" - else - javaExecutable="$(readlink -f "$javaExecutable")" - fi - javaHome="$(dirname "$javaExecutable")" - javaHome=$(expr "$javaHome" : '\(.*\)/bin') - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ]; then - if [ -n "$JAVA_HOME" ]; then - if [ -x "$JAVA_HOME/jre/sh/java" ]; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="$( - \unset -f command 2>/dev/null - \command -v java - )" - fi -fi - -if [ ! -x "$JAVACMD" ]; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ]; then - echo "Warning: JAVA_HOME environment variable is not set." >&2 -fi - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - if [ -z "$1" ]; then - echo "Path not specified to find_maven_basedir" >&2 - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ]; do - if [ -d "$wdir"/.mvn ]; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=$( - cd "$wdir/.." || exit 1 - pwd - ) - fi - # end of workaround - done - printf '%s' "$( - cd "$basedir" || exit 1 - pwd - )" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - # Remove \r in case we run on Windows within Git Bash - # and check out the repository with auto CRLF management - # enabled. Otherwise, we may read lines that are delimited with - # \r\n and produce $'-Xarg\r' rather than -Xarg due to word - # splitting rules. - tr -s '\r\n' ' ' <"$1" - fi -} - -log() { - if [ "$MVNW_VERBOSE" = true ]; then - printf '%s\n' "$1" - fi -} - -BASE_DIR=$(find_maven_basedir "$(dirname "$0")") -if [ -z "$BASE_DIR" ]; then - exit 1 -fi - -MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -export MAVEN_PROJECTBASEDIR -log "$MAVEN_PROJECTBASEDIR" - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" -if [ -r "$wrapperJarPath" ]; then - log "Found $wrapperJarPath" -else - log "Couldn't find $wrapperJarPath, downloading it ..." - - if [ -n "$MVNW_REPOURL" ]; then - wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" - else - wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" - fi - while IFS="=" read -r key value; do - # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) - safeValue=$(echo "$value" | tr -d '\r') - case "$key" in wrapperUrl) - wrapperUrl="$safeValue" - break - ;; - esac - done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" - log "Downloading from: $wrapperUrl" - - if $cygwin; then - wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") - fi - - if command -v wget >/dev/null; then - log "Found wget ... using wget" - [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - else - wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" - fi - elif command -v curl >/dev/null; then - log "Found curl ... using curl" - [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" - if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" - else - curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" - fi - else - log "Falling back to using Java to download" - javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" - javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" - # For Cygwin, switch paths to Windows format before running javac - if $cygwin; then - javaSource=$(cygpath --path --windows "$javaSource") - javaClass=$(cygpath --path --windows "$javaClass") - fi - if [ -e "$javaSource" ]; then - if [ ! -e "$javaClass" ]; then - log " - Compiling MavenWrapperDownloader.java ..." - ("$JAVA_HOME/bin/javac" "$javaSource") - fi - if [ -e "$javaClass" ]; then - log " - Running MavenWrapperDownloader.java ..." - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -# If specified, validate the SHA-256 sum of the Maven wrapper jar file -wrapperSha256Sum="" -while IFS="=" read -r key value; do - case "$key" in wrapperSha256Sum) - wrapperSha256Sum=$value - break - ;; - esac -done <"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" -if [ -n "$wrapperSha256Sum" ]; then - wrapperSha256Result=false - if command -v sha256sum >/dev/null; then - if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c >/dev/null 2>&1; then - wrapperSha256Result=true - fi - elif command -v shasum >/dev/null; then - if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c >/dev/null 2>&1; then - wrapperSha256Result=true - fi - else - echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 - echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." >&2 - exit 1 - fi - if [ $wrapperSha256Result = false ]; then - echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 - echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 - echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 - exit 1 - fi -fi - -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$JAVA_HOME" ] \ - && JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") - [ -n "$CLASSPATH" ] \ - && CLASSPATH=$(cygpath --path --windows "$CLASSPATH") - [ -n "$MAVEN_PROJECTBASEDIR" ] \ - && MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") -fi - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -# shellcheck disable=SC2086 # safe args -exec "$JAVACMD" \ - $MAVEN_OPTS \ - $MAVEN_DEBUG_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd deleted file mode 100755 index 4136715..0000000 --- a/mvnw.cmd +++ /dev/null @@ -1,206 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.3.2 -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* -if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. >&2 -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. >&2 -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. >&2 -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. >&2 -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" - -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - if "%MVNW_VERBOSE%" == "true" ( - echo Found %WRAPPER_JAR% - ) -) else ( - if not "%MVNW_REPOURL%" == "" ( - SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar" - ) - if "%MVNW_VERBOSE%" == "true" ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %WRAPPER_URL% - ) - - powershell -Command "&{"^ - "$webclient = new-object System.Net.WebClient;"^ - "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ - "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ - "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ - "}" - if "%MVNW_VERBOSE%" == "true" ( - echo Finished downloading %WRAPPER_JAR% - ) -) -@REM End of extension - -@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file -SET WRAPPER_SHA_256_SUM="" -FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B -) -IF NOT %WRAPPER_SHA_256_SUM%=="" ( - powershell -Command "&{"^ - "Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash;"^ - "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ - "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ - " Write-Error 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ - " Write-Error 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ - " Write-Error 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ - " exit 1;"^ - "}"^ - "}" - if ERRORLEVEL 1 goto error -) - -@REM Provide a "standardized" way to retrieve the CLI args that will -@REM work with both Windows and non-Windows executions. -set MAVEN_CMD_LINE_ARGS=%* - -%MAVEN_JAVA_EXE% ^ - %JVM_CONFIG_MAVEN_PROPS% ^ - %MAVEN_OPTS% ^ - %MAVEN_DEBUG_OPTS% ^ - -classpath %WRAPPER_JAR% ^ - "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ - %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" -if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%"=="on" pause - -if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% - -cmd /C exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml index 32ca934..07744fd 100644 --- a/pom.xml +++ b/pom.xml @@ -1,81 +1,48 @@ - 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.2.4 + + com.valposystems gym-backend - 1.0.0-SNAPSHOT - + 0.0.1-SNAPSHOT + gym-backend + Gym backend application - 3.11.0 - 11 - UTF-8 - UTF-8 - quarkus-bom - io.quarkus.platform - 3.6.3 - true - 3.2.2 + 17 - - - - - ${quarkus.platform.group-id} - ${quarkus.platform.artifact-id} - ${quarkus.platform.version} - pom - import - - - - - io.quarkus - quarkus-arc + org.springframework.boot + spring-boot-starter-data-jpa - io.quarkus - quarkus-resteasy + org.springframework.boot + spring-boot-starter-web - io.quarkus - quarkus-resteasy-jackson + org.springframework.boot + spring-boot-starter-validation + + + + org.postgresql + postgresql + runtime - io.quarkus - quarkus-hibernate-orm-panache + org.projectlombok + lombok + true - io.quarkus - quarkus-jdbc-postgresql - - - io.quarkus - quarkus-resteasy-multipart - - - io.quarkus - quarkus-picocli - - - io.quarkus - quarkus-resteasy-jaxb - - - io.quarkus - quarkus-undertow - - - io.quarkus - quarkus-junit5 - test - - - io.rest-assured - rest-assured + org.springframework.boot + spring-boot-starter-test test @@ -83,52 +50,18 @@ - ${quarkus.platform.group-id} - quarkus-maven-plugin - ${quarkus.platform.version} - true - - - - build - generate-code - generate-code-tests - - - - - - maven-compiler-plugin - ${compiler-plugin.version} + org.springframework.boot + spring-boot-maven-plugin - true - - - - maven-surefire-plugin - ${surefire-plugin.version} - - - org.jboss.logmanager.LogManager - ${maven.home} - + + + org.projectlombok + lombok + + - - - native - - - native - - - - false - native - - - \ No newline at end of file diff --git a/src/main/docker/Dockerfile.jvm b/src/main/docker/Dockerfile.jvm deleted file mode 100644 index b12475f..0000000 --- a/src/main/docker/Dockerfile.jvm +++ /dev/null @@ -1,98 +0,0 @@ -#### -# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode -# -# Before building the container image run: -# -# ./mvnw package -# -# Then, build the image with: -# -# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/gym-backend-jvm . -# -# Then run the container using: -# -# docker run -i --rm -p 8080:8080 quarkus/gym-backend-jvm -# -# If you want to include the debug port into your docker image -# you will have to expose the debug port (default 5005 being the default) like this : EXPOSE 8080 5005. -# Additionally you will have to set -e JAVA_DEBUG=true and -e JAVA_DEBUG_PORT=*:5005 -# when running the container -# -# Then run the container using : -# -# docker run -i --rm -p 8080:8080 quarkus/gym-backend-jvm -# -# This image uses the `run-java.sh` script to run the application. -# This scripts computes the command line to execute your Java application, and -# includes memory/GC tuning. -# You can configure the behavior using the following environment properties: -# - JAVA_OPTS: JVM options passed to the `java` command (example: "-verbose:class") - Be aware that this will override -# the default JVM options, use `JAVA_OPTS_APPEND` to append options -# - JAVA_OPTS_APPEND: User specified Java options to be appended to generated options -# in JAVA_OPTS (example: "-Dsome.property=foo") -# - JAVA_MAX_MEM_RATIO: Is used when no `-Xmx` option is given in JAVA_OPTS. This is -# used to calculate a default maximal heap memory based on a containers restriction. -# If used in a container without any memory constraints for the container then this -# option has no effect. If there is a memory constraint then `-Xmx` is set to a ratio -# of the container available memory as set here. The default is `50` which means 50% -# of the available memory is used as an upper boundary. You can skip this mechanism by -# setting this value to `0` in which case no `-Xmx` option is added. -# - JAVA_INITIAL_MEM_RATIO: Is used when no `-Xms` option is given in JAVA_OPTS. This -# is used to calculate a default initial heap memory based on the maximum heap memory. -# If used in a container without any memory constraints for the container then this -# option has no effect. If there is a memory constraint then `-Xms` is set to a ratio -# of the `-Xmx` memory as set here. The default is `25` which means 25% of the `-Xmx` -# is used as the initial heap size. You can skip this mechanism by setting this value -# to `0` in which case no `-Xms` option is added (example: "25") -# - JAVA_MAX_INITIAL_MEM: Is used when no `-Xms` option is given in JAVA_OPTS. -# This is used to calculate the maximum value of the initial heap memory. If used in -# a container without any memory constraints for the container then this option has -# no effect. If there is a memory constraint then `-Xms` is limited to the value set -# here. The default is 4096MB which means the calculated value of `-Xms` never will -# be greater than 4096MB. The value of this variable is expressed in MB (example: "4096") -# - JAVA_DIAGNOSTICS: Set this to get some diagnostics information to standard output -# when things are happening. This option, if set to true, will set -# `-XX:+UnlockDiagnosticVMOptions`. Disabled by default (example: "true"). -# - JAVA_DEBUG: If set remote debugging will be switched on. Disabled by default (example: -# true"). -# - JAVA_DEBUG_PORT: Port used for remote debugging. Defaults to 5005 (example: "8787"). -# - CONTAINER_CORE_LIMIT: A calculated core limit as described in -# https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt. (example: "2") -# - CONTAINER_MAX_MEMORY: Memory limit given to the container (example: "1024"). -# - GC_MIN_HEAP_FREE_RATIO: Minimum percentage of heap free after GC to avoid expansion. -# (example: "20") -# - GC_MAX_HEAP_FREE_RATIO: Maximum percentage of heap free after GC to avoid shrinking. -# (example: "40") -# - GC_TIME_RATIO: Specifies the ratio of the time spent outside the garbage collection. -# (example: "4") -# - GC_ADAPTIVE_SIZE_POLICY_WEIGHT: The weighting given to the current GC time versus -# previous GC times. (example: "90") -# - GC_METASPACE_SIZE: The initial metaspace size. (example: "20") -# - GC_MAX_METASPACE_SIZE: The maximum metaspace size. (example: "100") -# - GC_CONTAINER_OPTIONS: Specify Java GC to use. The value of this variable should -# contain the necessary JRE command-line options to specify the required GC, which -# will override the default of `-XX:+UseParallelGC` (example: -XX:+UseG1GC). -# - HTTPS_PROXY: The location of the https proxy. (example: "myuser@127.0.0.1:8080") -# - HTTP_PROXY: The location of the http proxy. (example: "myuser@127.0.0.1:8080") -# - NO_PROXY: A comma separated lists of hosts, IP addresses or domains that can be -# accessed directly. (example: "foo.example.com,bar.example.com") -# -### -FROM registry.access.redhat.com/ubi9/openjdk-21:1.21 - -ENV LANGUAGE='en_US:en' - - -# We make four distinct layers so if there are application changes the library layers can be re-used -COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/ -COPY --chown=185 target/quarkus-app/*.jar /deployments/ -COPY --chown=185 target/quarkus-app/app/ /deployments/app/ -COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/ - -EXPOSE 8080 -USER 185 -ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" -ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" - -ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ] - diff --git a/src/main/docker/Dockerfile.legacy-jar b/src/main/docker/Dockerfile.legacy-jar deleted file mode 100644 index c25dcff..0000000 --- a/src/main/docker/Dockerfile.legacy-jar +++ /dev/null @@ -1,94 +0,0 @@ -#### -# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode -# -# Before building the container image run: -# -# ./mvnw package -Dquarkus.package.jar.type=legacy-jar -# -# Then, build the image with: -# -# docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/gym-backend-legacy-jar . -# -# Then run the container using: -# -# docker run -i --rm -p 8080:8080 quarkus/gym-backend-legacy-jar -# -# If you want to include the debug port into your docker image -# you will have to expose the debug port (default 5005 being the default) like this : EXPOSE 8080 5005. -# Additionally you will have to set -e JAVA_DEBUG=true and -e JAVA_DEBUG_PORT=*:5005 -# when running the container -# -# Then run the container using : -# -# docker run -i --rm -p 8080:8080 quarkus/gym-backend-legacy-jar -# -# This image uses the `run-java.sh` script to run the application. -# This scripts computes the command line to execute your Java application, and -# includes memory/GC tuning. -# You can configure the behavior using the following environment properties: -# - JAVA_OPTS: JVM options passed to the `java` command (example: "-verbose:class") - Be aware that this will override -# the default JVM options, use `JAVA_OPTS_APPEND` to append options -# - JAVA_OPTS_APPEND: User specified Java options to be appended to generated options -# in JAVA_OPTS (example: "-Dsome.property=foo") -# - JAVA_MAX_MEM_RATIO: Is used when no `-Xmx` option is given in JAVA_OPTS. This is -# used to calculate a default maximal heap memory based on a containers restriction. -# If used in a container without any memory constraints for the container then this -# option has no effect. If there is a memory constraint then `-Xmx` is set to a ratio -# of the container available memory as set here. The default is `50` which means 50% -# of the available memory is used as an upper boundary. You can skip this mechanism by -# setting this value to `0` in which case no `-Xmx` option is added. -# - JAVA_INITIAL_MEM_RATIO: Is used when no `-Xms` option is given in JAVA_OPTS. This -# is used to calculate a default initial heap memory based on the maximum heap memory. -# If used in a container without any memory constraints for the container then this -# option has no effect. If there is a memory constraint then `-Xms` is set to a ratio -# of the `-Xmx` memory as set here. The default is `25` which means 25% of the `-Xmx` -# is used as the initial heap size. You can skip this mechanism by setting this value -# to `0` in which case no `-Xms` option is added (example: "25") -# - JAVA_MAX_INITIAL_MEM: Is used when no `-Xms` option is given in JAVA_OPTS. -# This is used to calculate the maximum value of the initial heap memory. If used in -# a container without any memory constraints for the container then this option has -# no effect. If there is a memory constraint then `-Xms` is limited to the value set -# here. The default is 4096MB which means the calculated value of `-Xms` never will -# be greater than 4096MB. The value of this variable is expressed in MB (example: "4096") -# - JAVA_DIAGNOSTICS: Set this to get some diagnostics information to standard output -# when things are happening. This option, if set to true, will set -# `-XX:+UnlockDiagnosticVMOptions`. Disabled by default (example: "true"). -# - JAVA_DEBUG: If set remote debugging will be switched on. Disabled by default (example: -# true"). -# - JAVA_DEBUG_PORT: Port used for remote debugging. Defaults to 5005 (example: "8787"). -# - CONTAINER_CORE_LIMIT: A calculated core limit as described in -# https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt. (example: "2") -# - CONTAINER_MAX_MEMORY: Memory limit given to the container (example: "1024"). -# - GC_MIN_HEAP_FREE_RATIO: Minimum percentage of heap free after GC to avoid expansion. -# (example: "20") -# - GC_MAX_HEAP_FREE_RATIO: Maximum percentage of heap free after GC to avoid shrinking. -# (example: "40") -# - GC_TIME_RATIO: Specifies the ratio of the time spent outside the garbage collection. -# (example: "4") -# - GC_ADAPTIVE_SIZE_POLICY_WEIGHT: The weighting given to the current GC time versus -# previous GC times. (example: "90") -# - GC_METASPACE_SIZE: The initial metaspace size. (example: "20") -# - GC_MAX_METASPACE_SIZE: The maximum metaspace size. (example: "100") -# - GC_CONTAINER_OPTIONS: Specify Java GC to use. The value of this variable should -# contain the necessary JRE command-line options to specify the required GC, which -# will override the default of `-XX:+UseParallelGC` (example: -XX:+UseG1GC). -# - HTTPS_PROXY: The location of the https proxy. (example: "myuser@127.0.0.1:8080") -# - HTTP_PROXY: The location of the http proxy. (example: "myuser@127.0.0.1:8080") -# - NO_PROXY: A comma separated lists of hosts, IP addresses or domains that can be -# accessed directly. (example: "foo.example.com,bar.example.com") -# -### -FROM registry.access.redhat.com/ubi9/openjdk-21:1.21 - -ENV LANGUAGE='en_US:en' - - -COPY target/lib/* /deployments/lib/ -COPY target/*-runner.jar /deployments/quarkus-run.jar - -EXPOSE 8080 -USER 185 -ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" -ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" - -ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ] diff --git a/src/main/docker/Dockerfile.native b/src/main/docker/Dockerfile.native deleted file mode 100644 index 21e034b..0000000 --- a/src/main/docker/Dockerfile.native +++ /dev/null @@ -1,29 +0,0 @@ -#### -# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. -# -# Before building the container image run: -# -# ./mvnw package -Dnative -# -# Then, build the image with: -# -# docker build -f src/main/docker/Dockerfile.native -t quarkus/gym-backend . -# -# Then run the container using: -# -# docker run -i --rm -p 8080:8080 quarkus/gym-backend -# -# The ` registry.access.redhat.com/ubi8/ubi-minimal:8.10` base image is based on UBI 9. -# To use UBI 8, switch to `quay.io/ubi8/ubi-minimal:8.10`. -### -FROM registry.access.redhat.com/ubi8/ubi-minimal:8.10 -WORKDIR /work/ -RUN chown 1001 /work \ - && chmod "g+rwX" /work \ - && chown 1001:root /work -COPY --chown=1001:root --chmod=0755 target/*-runner /work/application - -EXPOSE 8080 -USER 1001 - -ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"] diff --git a/src/main/docker/Dockerfile.native-micro b/src/main/docker/Dockerfile.native-micro deleted file mode 100644 index d21bde5..0000000 --- a/src/main/docker/Dockerfile.native-micro +++ /dev/null @@ -1,32 +0,0 @@ -#### -# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode. -# It uses a micro base image, tuned for Quarkus native executables. -# It reduces the size of the resulting container image. -# Check https://quarkus.io/guides/quarkus-runtime-base-image for further information about this image. -# -# Before building the container image run: -# -# ./mvnw package -Dnative -# -# Then, build the image with: -# -# docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/gym-backend . -# -# Then run the container using: -# -# docker run -i --rm -p 8080:8080 quarkus/gym-backend -# -# The `quay.io/quarkus/quarkus-micro-image:2.0` base image is based on UBI 9. -# To use UBI 8, switch to `quay.io/quarkus/quarkus-micro-image:2.0`. -### -FROM quay.io/quarkus/quarkus-micro-image:2.0 -WORKDIR /work/ -RUN chown 1001 /work \ - && chmod "g+rwX" /work \ - && chown 1001:root /work -COPY --chown=1001:root --chmod=0755 target/*-runner /work/application - -EXPOSE 8080 -USER 1001 - -ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"] diff --git a/src/main/java/com/valposystems/GymApplication.java b/src/main/java/com/valposystems/GymApplication.java index 083020d..0150da1 100644 --- a/src/main/java/com/valposystems/GymApplication.java +++ b/src/main/java/com/valposystems/GymApplication.java @@ -1,18 +1,34 @@ package com.valposystems; -import io.quarkus.runtime.Quarkus; -import io.quarkus.runtime.QuarkusApplication; -import io.quarkus.runtime.annotations.QuarkusMain; -import jakarta.enterprise.context.ApplicationScoped; -import org.jboss.logging.Logger; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; -@QuarkusMain +import java.util.Arrays; + +@SpringBootApplication public class GymApplication { - - private static final Logger LOG = Logger.getLogger(GymApplication.class); - - public static void main(String... args) { - LOG.info("Iniciando aplicación Gym Backend..."); - Quarkus.run(args); + + public static void main(String[] args) { + SpringApplication.run(GymApplication.class, args); + } + + @Bean + public CorsFilter corsFilter() { + CorsConfiguration corsConfiguration = new CorsConfiguration(); + corsConfiguration.setAllowCredentials(true); + corsConfiguration.setAllowedOrigins(Arrays.asList("*")); + corsConfiguration.setAllowedHeaders(Arrays.asList("Origin", "Access-Control-Allow-Origin", "Content-Type", + "Accept", "Authorization", "Origin, Accept", "X-Requested-With", + "Access-Control-Request-Method", "Access-Control-Request-Headers")); + corsConfiguration.setExposedHeaders(Arrays.asList("Origin", "Content-Type", "Accept", "Authorization", + "Access-Control-Allow-Origin", "Access-Control-Allow-Origin", "Access-Control-Allow-Credentials", "Content-Disposition")); + corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); + UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource(); + urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); + return new CorsFilter(urlBasedCorsConfigurationSource); } } \ No newline at end of file diff --git a/src/main/java/com/valposystems/controller/BookingController.java b/src/main/java/com/valposystems/controller/BookingController.java new file mode 100644 index 0000000..d361fe8 --- /dev/null +++ b/src/main/java/com/valposystems/controller/BookingController.java @@ -0,0 +1,83 @@ +package com.valposystems.controller; + +import com.valposystems.dto.BookingDTO; +import com.valposystems.service.BookingService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/bookings") +@CrossOrigin +public class BookingController { + + private static final Logger logger = LoggerFactory.getLogger(BookingController.class); + + private final BookingService bookingService; + + @Autowired + public BookingController(BookingService bookingService) { + this.bookingService = bookingService; + } + + @GetMapping + public ResponseEntity> getAllBookings() { + try { + List bookings = bookingService.getAllBookings(); + return ResponseEntity.ok(bookings); + } catch (Exception e) { + logger.error("Error getting bookings", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(null); + } + } + + @GetMapping("/user/{userId}") + public ResponseEntity> getBookingsByUserId(@PathVariable Long userId) { + try { + List bookings = bookingService.getBookingsByUserId(userId); + return ResponseEntity.ok(bookings); + } catch (Exception e) { + logger.error("Error getting bookings for user: {}", userId, e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(null); + } + } + + @PostMapping + public ResponseEntity createBooking(@RequestBody BookingDTO dto) { + try { + BookingDTO created = bookingService.createBooking(dto); + if (created == null) { + return ResponseEntity.status(HttpStatus.CONFLICT) + .body("{\"message\": \"No spots available or the user/class doesn't exist\"}"); + } + return ResponseEntity.status(HttpStatus.CREATED).body(created); + } catch (Exception e) { + logger.error("Error creating booking", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body("{\"error\": \"" + e.getMessage() + "\"}"); + } + } + + @PutMapping("/{id}/cancel") + public ResponseEntity cancelBooking(@PathVariable Long id) { + try { + BookingDTO cancelled = bookingService.cancelBooking(id); + if (cancelled == null) { + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body("{\"message\": \"The booking doesn't exist or isn't in confirmed state\"}"); + } + return ResponseEntity.ok(cancelled); + } catch (Exception e) { + logger.error("Error cancelling booking with ID: {}", id, e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body("{\"error\": \"" + e.getMessage() + "\"}"); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/valposystems/controller/GymClassController.java b/src/main/java/com/valposystems/controller/GymClassController.java new file mode 100644 index 0000000..5936056 --- /dev/null +++ b/src/main/java/com/valposystems/controller/GymClassController.java @@ -0,0 +1,96 @@ +package com.valposystems.controller; + +import com.valposystems.dto.GymClassDTO; +import com.valposystems.service.GymClassService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/classes") +@CrossOrigin +public class GymClassController { + + private static final Logger logger = LoggerFactory.getLogger(GymClassController.class); + + private final GymClassService gymClassService; + + @Autowired + public GymClassController(GymClassService gymClassService) { + this.gymClassService = gymClassService; + } + + @GetMapping + public ResponseEntity> getAllClasses() { + try { + List classes = gymClassService.getAllClasses(); + return ResponseEntity.ok(classes); + } catch (Exception e) { + logger.error("Error getting classes", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(null); + } + } + + @GetMapping("/{id}") + public ResponseEntity getClassById(@PathVariable Long id) { + try { + GymClassDTO gymClass = gymClassService.getClassById(id); + if (gymClass == null) { + return ResponseEntity.notFound().build(); + } + return ResponseEntity.ok(gymClass); + } catch (Exception e) { + logger.error("Error getting class with ID: {}", id, e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(null); + } + } + + @PostMapping + public ResponseEntity createClass(@RequestBody GymClassDTO dto) { + try { + GymClassDTO created = gymClassService.createClass(dto); + return ResponseEntity.status(HttpStatus.CREATED).body(created); + } catch (Exception e) { + logger.error("Error creating class", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(null); + } + } + + @PutMapping("/{id}") + public ResponseEntity updateClass(@PathVariable Long id, @RequestBody GymClassDTO dto) { + try { + GymClassDTO updated = gymClassService.updateClass(id, dto); + if (updated == null) { + return ResponseEntity.notFound().build(); + } + return ResponseEntity.ok(updated); + } catch (Exception e) { + logger.error("Error updating class with ID: {}", id, e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(null); + } + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteClass(@PathVariable Long id) { + try { + boolean deleted = gymClassService.deleteClass(id); + if (!deleted) { + return ResponseEntity.notFound().build(); + } + return ResponseEntity.noContent().build(); + } catch (Exception e) { + logger.error("Error deleting class with ID: {}", id, e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .build(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/valposystems/controller/UploadController.java b/src/main/java/com/valposystems/controller/UploadController.java new file mode 100644 index 0000000..4178894 --- /dev/null +++ b/src/main/java/com/valposystems/controller/UploadController.java @@ -0,0 +1,76 @@ +package com.valposystems.controller; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.UUID; + +@RestController +@RequestMapping("/api/upload") +@CrossOrigin +public class UploadController { + + private static final Logger logger = LoggerFactory.getLogger(UploadController.class); + + @Value("${app.upload.dir:uploads}") + private String uploadDir; + + @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public ResponseEntity uploadFile(@RequestParam("file") MultipartFile file) { + try { + logger.info("Receiving file upload request"); + + if (file.isEmpty()) { + logger.warn("No file provided"); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body("{\"error\":\"No file uploaded\"}"); + } + + // Create directory if it doesn't exist + File directory = new File(uploadDir); + if (!directory.exists()) { + directory.mkdirs(); + logger.info("Upload directory created: {}", directory.getAbsolutePath()); + } + + // Get file extension + String originalFilename = file.getOriginalFilename(); + String extension = ""; + if (originalFilename != null && originalFilename.contains(".")) { + extension = originalFilename.substring(originalFilename.lastIndexOf(".")); + } else { + extension = ".jpg"; + } + + // Generate unique filename + String fileName = UUID.randomUUID().toString() + extension; + Path filePath = Paths.get(uploadDir, fileName); + + logger.info("Saving file as: {}", filePath); + + // Save file + Files.copy(file.getInputStream(), filePath); + + // Return file URL + String fileUrl = "/uploads/" + fileName; + logger.info("File uploaded successfully. URL: {}", fileUrl); + return ResponseEntity.ok("{\"url\":\"" + fileUrl + "\"}"); + + } catch (IOException e) { + logger.error("Error uploading file", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body("{\"error\":\"" + e.getMessage() + "\"}"); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/valposystems/controller/UserController.java b/src/main/java/com/valposystems/controller/UserController.java new file mode 100644 index 0000000..e2bf7af --- /dev/null +++ b/src/main/java/com/valposystems/controller/UserController.java @@ -0,0 +1,89 @@ +package com.valposystems.controller; + +import com.valposystems.dto.UserDTO; +import com.valposystems.service.UserService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/users") +@CrossOrigin +public class UserController { + + private static final Logger logger = LoggerFactory.getLogger(UserController.class); + + private final UserService userService; + + @Autowired + public UserController(UserService userService) { + this.userService = userService; + } + + @GetMapping + public ResponseEntity> getAllUsers() { + try { + logger.info("Getting all users"); + List users = userService.getAllUsers(); + return ResponseEntity.ok(users); + } catch (Exception e) { + logger.error("Error getting users", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(null); + } + } + + @GetMapping("/{id}") + public ResponseEntity getUserById(@PathVariable Long id) { + try { + logger.info("Getting user with ID: {}", id); + UserDTO user = userService.getUserById(id); + if (user == null) { + return ResponseEntity.notFound().build(); + } + return ResponseEntity.ok(user); + } catch (Exception e) { + logger.error("Error getting user with ID: {}", id, e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(null); + } + } + + @PostMapping + public ResponseEntity createUser(@RequestBody UserDTO dto) { + try { + logger.info("Creating new user: {}", dto.getEmail()); + UserDTO created = userService.createUser(dto); + if (created == null) { + return ResponseEntity.status(HttpStatus.CONFLICT) + .body("{\"message\": \"A user with that email already exists\"}"); + } + return ResponseEntity.status(HttpStatus.CREATED).body(created); + } catch (Exception e) { + logger.error("Error creating user", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body("{\"error\": \"" + e.getMessage() + "\"}"); + } + } + + @PutMapping("/{id}") + public ResponseEntity updateUser(@PathVariable Long id, @RequestBody UserDTO dto) { + try { + logger.info("Updating user with ID: {}", id); + UserDTO updated = userService.updateUser(id, dto); + if (updated == null) { + return ResponseEntity.notFound().build(); + } + return ResponseEntity.ok(updated); + } catch (Exception e) { + logger.error("Error updating user with ID: {}", id, e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body(null); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/valposystems/dto/BookingDTO.java b/src/main/java/com/valposystems/dto/BookingDTO.java index c00b5c3..9e8da0a 100644 --- a/src/main/java/com/valposystems/dto/BookingDTO.java +++ b/src/main/java/com/valposystems/dto/BookingDTO.java @@ -1,31 +1,34 @@ package com.valposystems.dto; import com.valposystems.model.Booking; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; import java.time.LocalDateTime; +@Data +@NoArgsConstructor +@AllArgsConstructor public class BookingDTO { - public Long id; - public Long userId; - public String userName; - public Long classId; - public String className; - public LocalDateTime bookingDate; - public String status; - - public BookingDTO() { - } + private Long id; + private Long userId; + private String userName; + private Long classId; + private String className; + private LocalDateTime bookingDate; + private String status; public static BookingDTO from(Booking booking) { BookingDTO dto = new BookingDTO(); - dto.id = booking.id; - dto.userId = booking.user.id; - dto.userName = booking.user.name; - dto.classId = booking.gymClass.id; - dto.className = booking.gymClass.name; - dto.bookingDate = booking.bookingDate; - dto.status = booking.status; + dto.setId(booking.getId()); + dto.setUserId(booking.getUser().getId()); + dto.setUserName(booking.getUser().getName()); + dto.setClassId(booking.getGymClass().getId()); + dto.setClassName(booking.getGymClass().getName()); + dto.setBookingDate(booking.getBookingDate()); + dto.setStatus(booking.getStatus()); return dto; } } \ No newline at end of file diff --git a/src/main/java/com/valposystems/dto/GymClassDTO.java b/src/main/java/com/valposystems/dto/GymClassDTO.java index 3d45d88..fa36b56 100644 --- a/src/main/java/com/valposystems/dto/GymClassDTO.java +++ b/src/main/java/com/valposystems/dto/GymClassDTO.java @@ -1,37 +1,40 @@ package com.valposystems.dto; - import com.valposystems.model.GymClass; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + import java.time.LocalDateTime; +@Data +@NoArgsConstructor +@AllArgsConstructor public class GymClassDTO { - public Long id; - public String name; - public String description; - public String instructor; - public LocalDateTime startTime; - public LocalDateTime endTime; - public int maxCapacity; - public int currentBookings; - public String category; - public String imageUrl; - - public GymClassDTO() { - } + private Long id; + private String name; + private String description; + private String instructor; + private LocalDateTime startTime; + private LocalDateTime endTime; + private int maxCapacity; + private int currentBookings; + private String category; + private String imageUrl; public static GymClassDTO from(GymClass gymClass) { GymClassDTO dto = new GymClassDTO(); - dto.id = gymClass.id; - dto.name = gymClass.name; - dto.description = gymClass.description; - dto.instructor = gymClass.instructor; - dto.startTime = gymClass.startTime; - dto.endTime = gymClass.endTime; - dto.maxCapacity = gymClass.maxCapacity; - dto.currentBookings = gymClass.currentBookings; - dto.category = gymClass.category; - dto.imageUrl = gymClass.imageUrl; + dto.setId(gymClass.getId()); + dto.setName(gymClass.getName()); + dto.setDescription(gymClass.getDescription()); + dto.setInstructor(gymClass.getInstructor()); + dto.setStartTime(gymClass.getStartTime()); + dto.setEndTime(gymClass.getEndTime()); + dto.setMaxCapacity(gymClass.getMaxCapacity()); + dto.setCurrentBookings(gymClass.getCurrentBookings()); + dto.setCategory(gymClass.getCategory()); + dto.setImageUrl(gymClass.getImageUrl()); return dto; } } \ No newline at end of file diff --git a/src/main/java/com/valposystems/dto/UserDTO.java b/src/main/java/com/valposystems/dto/UserDTO.java index de04bbb..7941bf7 100644 --- a/src/main/java/com/valposystems/dto/UserDTO.java +++ b/src/main/java/com/valposystems/dto/UserDTO.java @@ -1,25 +1,28 @@ package com.valposystems.dto; import com.valposystems.model.User; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +@Data +@NoArgsConstructor +@AllArgsConstructor public class UserDTO { - public Long id; - public String name; - public String email; - public String profilePicUrl; - public boolean notificationsEnabled; - - public UserDTO() { - } + private Long id; + private String name; + private String email; + private String profilePicUrl; + private boolean notificationsEnabled; public static UserDTO from(User user) { UserDTO dto = new UserDTO(); - dto.id = user.id; - dto.name = user.name; - dto.email = user.email; - dto.profilePicUrl = user.profilePicUrl; - dto.notificationsEnabled = user.notificationsEnabled; + dto.setId(user.getId()); + dto.setName(user.getName()); + dto.setEmail(user.getEmail()); + dto.setProfilePicUrl(user.getProfilePicUrl()); + dto.setNotificationsEnabled(user.isNotificationsEnabled()); return dto; } } \ No newline at end of file diff --git a/src/main/java/com/valposystems/model/Booking.java b/src/main/java/com/valposystems/model/Booking.java index a0ccc1e..231a6ba 100644 --- a/src/main/java/com/valposystems/model/Booking.java +++ b/src/main/java/com/valposystems/model/Booking.java @@ -1,30 +1,33 @@ package com.valposystems.model; -import io.quarkus.hibernate.orm.panache.PanacheEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.Table; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + import java.time.LocalDateTime; @Entity @Table(name = "bookings") -public class Booking extends PanacheEntity { +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Booking { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; @ManyToOne - public User user; + private User user; @ManyToOne - public GymClass gymClass; + private GymClass gymClass; - public LocalDateTime bookingDate; + private LocalDateTime bookingDate; - public String status; // 'confirmed', 'cancelled', 'pending' + private String status; // 'confirmed', 'cancelled', 'pending' - // Constructor vacío requerido por JPA - public Booking() { - } - - // Constructor para inicialización más sencilla public Booking(User user, GymClass gymClass, LocalDateTime bookingDate, String status) { this.user = user; this.gymClass = gymClass; diff --git a/src/main/java/com/valposystems/model/GymClass.java b/src/main/java/com/valposystems/model/GymClass.java index 5060c05..b0a339c 100644 --- a/src/main/java/com/valposystems/model/GymClass.java +++ b/src/main/java/com/valposystems/model/GymClass.java @@ -1,41 +1,45 @@ package com.valposystems.model; -import io.quarkus.hibernate.orm.panache.PanacheEntity; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Table; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + import java.time.LocalDateTime; @Entity @Table(name = "gym_classes") -public class GymClass extends PanacheEntity { +@Data +@NoArgsConstructor +@AllArgsConstructor +public class GymClass { - public String name; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; - public String description; + private String name; - public String instructor; + private String description; - public LocalDateTime startTime; + private String instructor; - public LocalDateTime endTime; + private LocalDateTime startTime; - public int maxCapacity; + private LocalDateTime endTime; - public int currentBookings; + private int maxCapacity; - public String category; + private int currentBookings; - public String imageUrl; + private String category; - // Constructor vacío requerido por JPA - public GymClass() { - } + private String imageUrl; - // Constructor para inicialización más sencilla public GymClass(String name, String description, String instructor, - LocalDateTime startTime, LocalDateTime endTime, - int maxCapacity, int currentBookings, - String category, String imageUrl) { + LocalDateTime startTime, LocalDateTime endTime, + int maxCapacity, int currentBookings, + String category, String imageUrl) { this.name = name; this.description = description; this.instructor = instructor; diff --git a/src/main/java/com/valposystems/model/User.java b/src/main/java/com/valposystems/model/User.java index 13a5a50..dc4d11f 100644 --- a/src/main/java/com/valposystems/model/User.java +++ b/src/main/java/com/valposystems/model/User.java @@ -1,30 +1,32 @@ package com.valposystems.model; -import io.quarkus.hibernate.orm.panache.PanacheEntity; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Table; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; @Entity @Table(name = "users") -public class User extends PanacheEntity { +@Data +@NoArgsConstructor +@AllArgsConstructor +public class User { - public String name; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; @Column(unique = true) - public String email; + private String email; - public String password; + private String password; - public String profilePicUrl; + private String profilePicUrl; - public boolean notificationsEnabled; + private boolean notificationsEnabled; - // Constructor vacío requerido por JPA - public User() { - } - - // Constructor para inicialización más sencilla public User(String name, String email, String password, String profilePicUrl, boolean notificationsEnabled) { this.name = name; this.email = email; diff --git a/src/main/java/com/valposystems/repository/BookingRepository.java b/src/main/java/com/valposystems/repository/BookingRepository.java new file mode 100644 index 0000000..d400555 --- /dev/null +++ b/src/main/java/com/valposystems/repository/BookingRepository.java @@ -0,0 +1,12 @@ +package com.valposystems.repository; + +import com.valposystems.model.Booking; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface BookingRepository extends JpaRepository { + List findByUserId(Long userId); +} \ No newline at end of file diff --git a/src/main/java/com/valposystems/repository/GymClassRepository.java b/src/main/java/com/valposystems/repository/GymClassRepository.java new file mode 100644 index 0000000..7d76d4f --- /dev/null +++ b/src/main/java/com/valposystems/repository/GymClassRepository.java @@ -0,0 +1,9 @@ +package com.valposystems.repository; + +import com.valposystems.model.GymClass; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface GymClassRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/com/valposystems/repository/UserRepository.java b/src/main/java/com/valposystems/repository/UserRepository.java new file mode 100644 index 0000000..a781b69 --- /dev/null +++ b/src/main/java/com/valposystems/repository/UserRepository.java @@ -0,0 +1,13 @@ +package com.valposystems.repository; + +import com.valposystems.model.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface UserRepository extends JpaRepository { + boolean existsByEmail(String email); + Optional findByEmail(String email); +} \ No newline at end of file diff --git a/src/main/java/com/valposystems/resource/BookingResource.java b/src/main/java/com/valposystems/resource/BookingResource.java deleted file mode 100644 index 1b11830..0000000 --- a/src/main/java/com/valposystems/resource/BookingResource.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.valposystems.resource; - -import com.valposystems.dto.BookingDTO; -import com.valposystems.service.BookingService; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; -import jakarta.transaction.Transactional; -import jakarta.ws.rs.*; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; -import java.util.List; - -@ApplicationScoped -@Path("/api/bookings") -@Produces(MediaType.APPLICATION_JSON) -@Consumes(MediaType.APPLICATION_JSON) -public class BookingResource { - - @Inject - BookingService bookingService; - - @GET - @Transactional - public Response getAllBookings() { - try { - List bookings = bookingService.getAllBookings(); - return Response.ok(bookings).build(); - } catch (Exception e) { - return Response.serverError().entity("Error: " + e.getMessage()).build(); - } - } - - @GET - @Path("/user/{userId}") - @Transactional - public Response getBookingsByUserId(@PathParam("userId") Long userId) { - try { - List bookings = bookingService.getBookingsByUserId(userId); - return Response.ok(bookings).build(); - } catch (Exception e) { - return Response.serverError().entity("Error: " + e.getMessage()).build(); - } - } - - @POST - @Transactional - public Response createBooking(BookingDTO dto) { - try { - BookingDTO created = bookingService.createBooking(dto); - if (created == null) { - return Response.status(Response.Status.CONFLICT) - .entity("{\"message\": \"No hay plazas disponibles o el usuario/clase no existe\"}").build(); - } - return Response.status(Response.Status.CREATED).entity(created).build(); - } catch (Exception e) { - return Response.serverError().entity("Error: " + e.getMessage()).build(); - } - } - - @PUT - @Path("/{id}/cancel") - @Transactional - public Response cancelBooking(@PathParam("id") Long id) { - try { - BookingDTO cancelled = bookingService.cancelBooking(id); - if (cancelled == null) { - return Response.status(Response.Status.NOT_FOUND) - .entity("{\"message\": \"La reserva no existe o no está en estado confirmado\"}").build(); - } - return Response.ok(cancelled).build(); - } catch (Exception e) { - return Response.serverError().entity("Error: " + e.getMessage()).build(); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/valposystems/resource/GymClassResource.java b/src/main/java/com/valposystems/resource/GymClassResource.java deleted file mode 100644 index 3450bea..0000000 --- a/src/main/java/com/valposystems/resource/GymClassResource.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.valposystems.resource; - -import com.valposystems.dto.GymClassDTO; -import com.valposystems.service.GymClassService; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; -import jakarta.transaction.Transactional; -import jakarta.ws.rs.*; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; -import java.util.List; - -@ApplicationScoped -@Path("/api/classes") -@Produces(MediaType.APPLICATION_JSON) -@Consumes(MediaType.APPLICATION_JSON) -public class GymClassResource { - - @Inject - GymClassService gymClassService; - - @GET - @Transactional - public Response getAllClasses() { - try { - List classes = gymClassService.getAllClasses(); - return Response.ok(classes).build(); - } catch (Exception e) { - return Response.serverError().entity("Error: " + e.getMessage()).build(); - } - } - - @GET - @Path("/{id}") - @Transactional - public Response getClassById(@PathParam("id") Long id) { - try { - GymClassDTO gymClass = gymClassService.getClassById(id); - if (gymClass == null) { - return Response.status(Response.Status.NOT_FOUND).build(); - } - return Response.ok(gymClass).build(); - } catch (Exception e) { - return Response.serverError().entity("Error: " + e.getMessage()).build(); - } - } - - @POST - @Transactional - public Response createClass(GymClassDTO dto) { - try { - GymClassDTO created = gymClassService.createClass(dto); - return Response.status(Response.Status.CREATED).entity(created).build(); - } catch (Exception e) { - return Response.serverError().entity("Error: " + e.getMessage()).build(); - } - } - - @PUT - @Path("/{id}") - @Transactional - public Response updateClass(@PathParam("id") Long id, GymClassDTO dto) { - try { - GymClassDTO updated = gymClassService.updateClass(id, dto); - if (updated == null) { - return Response.status(Response.Status.NOT_FOUND).build(); - } - return Response.ok(updated).build(); - } catch (Exception e) { - return Response.serverError().entity("Error: " + e.getMessage()).build(); - } - } - - @DELETE - @Path("/{id}") - @Transactional - public Response deleteClass(@PathParam("id") Long id) { - try { - boolean deleted = gymClassService.deleteClass(id); - if (!deleted) { - return Response.status(Response.Status.NOT_FOUND).build(); - } - return Response.noContent().build(); - } catch (Exception e) { - return Response.serverError().entity("Error: " + e.getMessage()).build(); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/valposystems/resource/UploadResource.java b/src/main/java/com/valposystems/resource/UploadResource.java deleted file mode 100644 index df0e99d..0000000 --- a/src/main/java/com/valposystems/resource/UploadResource.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.valposystems.resource; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.MultivaluedMap; -import jakarta.ws.rs.core.Response; -import org.jboss.logging.Logger; -import org.jboss.resteasy.plugins.providers.multipart.InputPart; -import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -@ApplicationScoped -@Path("/api/upload") -public class UploadResource { - - private static final Logger LOG = Logger.getLogger(UploadResource.class); - private static final String UPLOAD_DIR = "uploads"; - - @POST - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces(MediaType.APPLICATION_JSON) - public Response uploadFile(MultipartFormDataInput input) { - try { - LOG.info("Recibiendo solicitud de carga de archivo"); - - // Obtener los InputPart del mapa (no directamente InputStream) - Map> formDataMap = input.getFormDataMap(); - List inputParts = formDataMap.get("file"); - - if (inputParts == null || inputParts.isEmpty()) { - LOG.warn("No se ha proporcionado ningún archivo"); - return Response.status(Response.Status.BAD_REQUEST) - .entity("{\"error\":\"No file uploaded\"}").build(); - } - - // Obtener el InputPart y convertirlo a InputStream - InputPart inputPart = inputParts.get(0); - InputStream fileInputStream = inputPart.getBody(InputStream.class, null); - - // Crear directorio si no existe - File directory = new File(UPLOAD_DIR); - if (!directory.exists()) { - directory.mkdirs(); - LOG.info("Directorio de subida creado: " + directory.getAbsolutePath()); - } - - // Obtener información del archivo - MultivaluedMap headers = inputPart.getHeaders(); - String fileName = UUID.randomUUID().toString() + getFileExtension(headers); - String filePath = UPLOAD_DIR + "/" + fileName; - - LOG.info("Guardando archivo como: " + filePath); - - // Guardar archivo - Files.copy( - fileInputStream, - Paths.get(filePath), - StandardCopyOption.REPLACE_EXISTING - ); - - // Devolver URL del archivo subido - String fileUrl = "/uploads/" + fileName; - LOG.info("Archivo subido exitosamente. URL: " + fileUrl); - return Response.ok("{\"url\":\"" + fileUrl + "\"}").build(); - - } catch (IOException e) { - LOG.error("Error al subir archivo", e); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR) - .entity("{\"error\":\"" + e.getMessage() + "\"}").build(); - } - } - - private String getFileExtension(MultivaluedMap headers) { - String contentDisposition = headers.getFirst("Content-Disposition"); - if (contentDisposition != null) { - for (String part : contentDisposition.split(";")) { - if (part.trim().startsWith("filename")) { - String fileName = part.substring(part.indexOf('=') + 1).trim().replace("\"", ""); - int dot = fileName.lastIndexOf('.'); - if (dot > 0) { - return fileName.substring(dot); - } - break; - } - } - } - return ".jpg"; - } -} \ No newline at end of file diff --git a/src/main/java/com/valposystems/resource/UserResource.java b/src/main/java/com/valposystems/resource/UserResource.java deleted file mode 100644 index 3272e45..0000000 --- a/src/main/java/com/valposystems/resource/UserResource.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.valposystems.resource; - -import com.valposystems.dto.UserDTO; -import com.valposystems.service.UserService; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; -import jakarta.transaction.Transactional; -import jakarta.ws.rs.*; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; -import org.jboss.logging.Logger; -import java.util.List; - -@ApplicationScoped -@Path("/api/users") -@Produces(MediaType.APPLICATION_JSON) -@Consumes(MediaType.APPLICATION_JSON) -public class UserResource { - - private static final Logger LOG = Logger.getLogger(UserResource.class); - - @Inject - UserService userService; - - @GET - @Transactional - public Response getAllUsers() { - try { - LOG.info("Obteniendo todos los usuarios"); - List users = userService.getAllUsers(); - return Response.ok(users).build(); - } catch (Exception e) { - LOG.error("Error al obtener usuarios", e); - return Response.serverError().entity("Error: " + e.getMessage()).build(); - } - } - - @GET - @Path("/{id}") - @Transactional - public Response getUserById(@PathParam("id") Long id) { - try { - LOG.info("Obteniendo usuario con ID: " + id); - UserDTO user = userService.getUserById(id); - if (user == null) { - return Response.status(Response.Status.NOT_FOUND).build(); - } - return Response.ok(user).build(); - } catch (Exception e) { - LOG.error("Error al obtener usuario con ID: " + id, e); - return Response.serverError().entity("Error: " + e.getMessage()).build(); - } - } - - @POST - @Transactional - public Response createUser(UserDTO dto) { - try { - LOG.info("Creando nuevo usuario: " + dto.email); - UserDTO created = userService.createUser(dto); - if (created == null) { - return Response.status(Response.Status.CONFLICT) - .entity("{\"message\": \"Ya existe un usuario con ese email\"}").build(); - } - return Response.status(Response.Status.CREATED).entity(created).build(); - } catch (Exception e) { - LOG.error("Error al crear usuario", e); - return Response.serverError().entity("Error: " + e.getMessage()).build(); - } - } - - @PUT - @Path("/{id}") - @Transactional - public Response updateUser(@PathParam("id") Long id, UserDTO dto) { - try { - LOG.info("Actualizando usuario con ID: " + id); - UserDTO updated = userService.updateUser(id, dto); - if (updated == null) { - return Response.status(Response.Status.NOT_FOUND).build(); - } - return Response.ok(updated).build(); - } catch (Exception e) { - LOG.error("Error al actualizar usuario con ID: " + id, e); - return Response.serverError().entity("Error: " + e.getMessage()).build(); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/valposystems/service/BookingService.java b/src/main/java/com/valposystems/service/BookingService.java index 0e405c5..eb32f3d 100644 --- a/src/main/java/com/valposystems/service/BookingService.java +++ b/src/main/java/com/valposystems/service/BookingService.java @@ -4,76 +4,97 @@ import com.valposystems.dto.BookingDTO; import com.valposystems.model.Booking; import com.valposystems.model.GymClass; import com.valposystems.model.User; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.transaction.Transactional; +import com.valposystems.repository.BookingRepository; +import com.valposystems.repository.GymClassRepository; +import com.valposystems.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.util.List; import java.util.stream.Collectors; -@ApplicationScoped +@Service public class BookingService { - + + private final BookingRepository bookingRepository; + private final UserRepository userRepository; + private final GymClassRepository gymClassRepository; + + @Autowired + public BookingService( + BookingRepository bookingRepository, + UserRepository userRepository, + GymClassRepository gymClassRepository) { + this.bookingRepository = bookingRepository; + this.userRepository = userRepository; + this.gymClassRepository = gymClassRepository; + } + public List getAllBookings() { - return Booking.listAll().stream() - .map(b -> BookingDTO.from((Booking) b)) + return bookingRepository.findAll().stream() + .map(BookingDTO::from) .collect(Collectors.toList()); } - + public List getBookingsByUserId(Long userId) { - List bookings = Booking.list("user.id", userId); - return bookings.stream() - .map(booking -> BookingDTO.from(booking)) + return bookingRepository.findByUserId(userId).stream() + .map(BookingDTO::from) .collect(Collectors.toList()); } - + @Transactional public BookingDTO createBooking(BookingDTO dto) { - User user = User.findById(dto.userId); - GymClass gymClass = GymClass.findById(dto.classId); - + User user = userRepository.findById(dto.getUserId()).orElse(null); + GymClass gymClass = gymClassRepository.findById(dto.getClassId()).orElse(null); + if (user == null || gymClass == null) { return null; } - - // Verificar disponibilidad - if (gymClass.currentBookings >= gymClass.maxCapacity) { + + // Check availability + if (gymClass.getCurrentBookings() >= gymClass.getMaxCapacity()) { return null; } - - // Crear la reserva + + // Create booking Booking booking = new Booking(); - booking.user = user; - booking.gymClass = gymClass; - booking.bookingDate = LocalDateTime.now(); - booking.status = "confirmed"; - - // Actualizar contador de la clase - gymClass.currentBookings++; - - booking.persist(); - + booking.setUser(user); + booking.setGymClass(gymClass); + booking.setBookingDate(LocalDateTime.now()); + booking.setStatus("confirmed"); + + // Update class counter + gymClass.setCurrentBookings(gymClass.getCurrentBookings() + 1); + gymClassRepository.save(gymClass); + + booking = bookingRepository.save(booking); + return BookingDTO.from(booking); } - + @Transactional public BookingDTO cancelBooking(Long id) { - Booking booking = Booking.findById(id); + Booking booking = bookingRepository.findById(id).orElse(null); if (booking == null) { return null; } - - // Solo se pueden cancelar reservas confirmadas - if (!booking.status.equals("confirmed")) { + + // Only confirmed bookings can be cancelled + if (!"confirmed".equals(booking.getStatus())) { return null; } - - booking.status = "cancelled"; - - // Actualizar contador de la clase - GymClass gymClass = booking.gymClass; - gymClass.currentBookings--; - + + booking.setStatus("cancelled"); + + // Update class counter + GymClass gymClass = booking.getGymClass(); + gymClass.setCurrentBookings(gymClass.getCurrentBookings() - 1); + gymClassRepository.save(gymClass); + + booking = bookingRepository.save(booking); + return BookingDTO.from(booking); } } \ No newline at end of file diff --git a/src/main/java/com/valposystems/service/GymClassService.java b/src/main/java/com/valposystems/service/GymClassService.java index b5e8ecb..921328f 100644 --- a/src/main/java/com/valposystems/service/GymClassService.java +++ b/src/main/java/com/valposystems/service/GymClassService.java @@ -2,75 +2,78 @@ package com.valposystems.service; import com.valposystems.dto.GymClassDTO; import com.valposystems.model.GymClass; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.transaction.Transactional; +import com.valposystems.repository.GymClassRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.stream.Collectors; -@ApplicationScoped +@Service public class GymClassService { - + + private final GymClassRepository gymClassRepository; + + @Autowired + public GymClassService(GymClassRepository gymClassRepository) { + this.gymClassRepository = gymClassRepository; + } + public List getAllClasses() { - return GymClass.listAll().stream() - .map(c -> GymClassDTO.from((GymClass) c)) + return gymClassRepository.findAll().stream() + .map(GymClassDTO::from) .collect(Collectors.toList()); } - + public GymClassDTO getClassById(Long id) { - GymClass gymClass = GymClass.findById(id); - if (gymClass == null) { - return null; - } - return GymClassDTO.from(gymClass); + return gymClassRepository.findById(id) + .map(GymClassDTO::from) + .orElse(null); } - + @Transactional public GymClassDTO createClass(GymClassDTO dto) { GymClass gymClass = new GymClass(); - gymClass.name = dto.name; - gymClass.description = dto.description; - gymClass.instructor = dto.instructor; - gymClass.startTime = dto.startTime; - gymClass.endTime = dto.endTime; - gymClass.maxCapacity = dto.maxCapacity; - gymClass.currentBookings = dto.currentBookings; - gymClass.category = dto.category; - gymClass.imageUrl = dto.imageUrl; - - gymClass.persist(); - + gymClass.setName(dto.getName()); + gymClass.setDescription(dto.getDescription()); + gymClass.setInstructor(dto.getInstructor()); + gymClass.setStartTime(dto.getStartTime()); + gymClass.setEndTime(dto.getEndTime()); + gymClass.setMaxCapacity(dto.getMaxCapacity()); + gymClass.setCurrentBookings(dto.getCurrentBookings()); + gymClass.setCategory(dto.getCategory()); + gymClass.setImageUrl(dto.getImageUrl()); + + gymClass = gymClassRepository.save(gymClass); + return GymClassDTO.from(gymClass); } - + @Transactional public GymClassDTO updateClass(Long id, GymClassDTO dto) { - GymClass gymClass = GymClass.findById(id); - if (gymClass == null) { - return null; - } - - gymClass.name = dto.name; - gymClass.description = dto.description; - gymClass.instructor = dto.instructor; - gymClass.startTime = dto.startTime; - gymClass.endTime = dto.endTime; - gymClass.maxCapacity = dto.maxCapacity; - gymClass.currentBookings = dto.currentBookings; - gymClass.category = dto.category; - gymClass.imageUrl = dto.imageUrl; - - return GymClassDTO.from(gymClass); + return gymClassRepository.findById(id) + .map(gymClass -> { + gymClass.setName(dto.getName()); + gymClass.setDescription(dto.getDescription()); + gymClass.setInstructor(dto.getInstructor()); + gymClass.setStartTime(dto.getStartTime()); + gymClass.setEndTime(dto.getEndTime()); + gymClass.setMaxCapacity(dto.getMaxCapacity()); + gymClass.setCurrentBookings(dto.getCurrentBookings()); + gymClass.setCategory(dto.getCategory()); + gymClass.setImageUrl(dto.getImageUrl()); + return GymClassDTO.from(gymClassRepository.save(gymClass)); + }) + .orElse(null); } - + @Transactional public boolean deleteClass(Long id) { - GymClass gymClass = GymClass.findById(id); - if (gymClass == null) { - return false; + if (gymClassRepository.existsById(id)) { + gymClassRepository.deleteById(id); + return true; } - - gymClass.delete(); - return true; + return false; } } \ No newline at end of file diff --git a/src/main/java/com/valposystems/service/UserService.java b/src/main/java/com/valposystems/service/UserService.java index 4686682..744c0ae 100644 --- a/src/main/java/com/valposystems/service/UserService.java +++ b/src/main/java/com/valposystems/service/UserService.java @@ -2,59 +2,64 @@ package com.valposystems.service; import com.valposystems.dto.UserDTO; import com.valposystems.model.User; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.transaction.Transactional; +import com.valposystems.repository.UserRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.stream.Collectors; -@ApplicationScoped +@Service public class UserService { - + + private final UserRepository userRepository; + + @Autowired + public UserService(UserRepository userRepository) { + this.userRepository = userRepository; + } + public List getAllUsers() { - return User.listAll().stream() - .map(u -> UserDTO.from((User) u)) + return userRepository.findAll().stream() + .map(UserDTO::from) .collect(Collectors.toList()); } - + public UserDTO getUserById(Long id) { - User user = User.findById(id); - if (user == null) { - return null; - } - return UserDTO.from(user); + return userRepository.findById(id) + .map(UserDTO::from) + .orElse(null); } - + @Transactional public UserDTO createUser(UserDTO dto) { - // Verificar si ya existe un usuario con ese email - if (User.count("email", dto.email) > 0) { + // Check if a user with that email already exists + if (userRepository.existsByEmail(dto.getEmail())) { return null; } - + User user = new User(); - user.name = dto.name; - user.email = dto.email; - user.password = "password123"; // En una app real, esto se encriptaría - user.profilePicUrl = dto.profilePicUrl; - user.notificationsEnabled = dto.notificationsEnabled; - - user.persist(); - + user.setName(dto.getName()); + user.setEmail(dto.getEmail()); + user.setPassword("password123"); // In a real app, this would be encrypted + user.setProfilePicUrl(dto.getProfilePicUrl()); + user.setNotificationsEnabled(dto.isNotificationsEnabled()); + + user = userRepository.save(user); + return UserDTO.from(user); } - + @Transactional public UserDTO updateUser(Long id, UserDTO dto) { - User user = User.findById(id); - if (user == null) { - return null; - } - - user.name = dto.name; - user.profilePicUrl = dto.profilePicUrl; - user.notificationsEnabled = dto.notificationsEnabled; - - return UserDTO.from(user); + return userRepository.findById(id) + .map(user -> { + user.setName(dto.getName()); + user.setProfilePicUrl(dto.getProfilePicUrl()); + user.setNotificationsEnabled(dto.isNotificationsEnabled()); + return UserDTO.from(userRepository.save(user)); + }) + .orElse(null); } } \ No newline at end of file diff --git a/src/main/java/com/valposystems/util/DataLoader.java b/src/main/java/com/valposystems/util/DataLoader.java index 02ce684..1d61839 100644 --- a/src/main/java/com/valposystems/util/DataLoader.java +++ b/src/main/java/com/valposystems/util/DataLoader.java @@ -2,108 +2,121 @@ package com.valposystems.util; import com.valposystems.model.GymClass; import com.valposystems.model.User; -import io.quarkus.runtime.StartupEvent; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.event.Observes; -import jakarta.transaction.Transactional; -import org.jboss.logging.Logger; +import com.valposystems.repository.GymClassRepository; +import com.valposystems.repository.UserRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; -@ApplicationScoped -public class DataLoader { +@Component +public class DataLoader implements CommandLineRunner { - private static final Logger LOG = Logger.getLogger(DataLoader.class); - + private static final Logger logger = LoggerFactory.getLogger(DataLoader.class); + + private final UserRepository userRepository; + private final GymClassRepository gymClassRepository; + + @Autowired + public DataLoader(UserRepository userRepository, GymClassRepository gymClassRepository) { + this.userRepository = userRepository; + this.gymClassRepository = gymClassRepository; + } + + @Override @Transactional - public void loadData(@Observes StartupEvent evt) { - LOG.info("Verificando si es necesario cargar datos iniciales..."); + public void run(String... args) { + logger.info("Checking if initial data needs to be loaded..."); - // Verificar si ya hay datos - if (GymClass.count() > 0 || User.count() > 0) { - LOG.info("Ya existen datos en la base de datos, no se cargarán datos iniciales"); + // Check if data already exists + if (gymClassRepository.count() > 0 || userRepository.count() > 0) { + logger.info("Data already exists in the database, will not load initial data"); return; } - LOG.info("Cargando datos iniciales..."); - - // Crear usuario demo + logger.info("Loading initial data..."); + + // Create demo user User demoUser = new User( - "Usuario Demo", - "usuario@ejemplo.com", + "Demo User", + "user@example.com", "password123", "/uploads/default-avatar.jpg", true ); - demoUser.persist(); - LOG.info("Usuario demo creado con ID: " + demoUser.id); - - // Crear clases de ejemplo + userRepository.save(demoUser); + logger.info("Demo user created with ID: {}", demoUser.getId()); + + // Create example classes GymClass yoga = new GymClass( "Yoga", - "Clase de yoga para todos los niveles", + "Yoga class for all levels", "María López", LocalDateTime.now().plusDays(1).withHour(8).withMinute(0), LocalDateTime.now().plusDays(1).withHour(9).withMinute(0), 15, 8, - "Mente y Cuerpo", + "Mind and Body", "/uploads/yoga.png" ); - yoga.persist(); - + gymClassRepository.save(yoga); + GymClass spinning = new GymClass( "Spinning", - "Clase de alta intensidad de ciclismo estático", + "High intensity static cycling class", "Juan Pérez", LocalDateTime.now().plusDays(1).withHour(10).withMinute(0), LocalDateTime.now().plusDays(1).withHour(11).withMinute(0), 20, 15, - "Cardiovascular", + "Cardio", "/uploads/spinning.png" ); - spinning.persist(); - + gymClassRepository.save(spinning); + GymClass pilates = new GymClass( "Pilates", - "Fortalecimiento de core y flexibilidad", + "Core strength and flexibility", "Ana García", LocalDateTime.now().plusDays(1).withHour(16).withMinute(0), LocalDateTime.now().plusDays(1).withHour(17).withMinute(0), 12, 5, - "Mente y Cuerpo", + "Mind and Body", "/uploads/pilates.png" ); - pilates.persist(); - + gymClassRepository.save(pilates); + GymClass zumba = new GymClass( "Zumba", - "Baile y ejercicio cardiovascular", + "Dance and cardiovascular exercise", "Carlos Martínez", LocalDateTime.now().plusDays(2).withHour(18).withMinute(0), LocalDateTime.now().plusDays(2).withHour(19).withMinute(0), 25, 18, - "Baile", + "Dance", "/uploads/zumba.png" ); - zumba.persist(); - + gymClassRepository.save(zumba); + GymClass crossfit = new GymClass( "CrossFit", - "Entrenamiento funcional de alta intensidad", + "High intensity functional training", "Roberto Sánchez", LocalDateTime.now().plusDays(2).withHour(9).withMinute(0), LocalDateTime.now().plusDays(2).withHour(10).withMinute(0), 15, 12, - "Fuerza", + "Strength", "/uploads/crossfit.png" ); - crossfit.persist(); + gymClassRepository.save(crossfit); - LOG.info("Se han cargado " + GymClass.count() + " clases de ejemplo"); + logger.info("Loaded {} example classes", gymClassRepository.count()); } } \ No newline at end of file diff --git a/src/main/resources/META-INF/beans.xml b/src/main/resources/META-INF/beans.xml deleted file mode 100644 index f90fd8b..0000000 --- a/src/main/resources/META-INF/beans.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - \ No newline at end of file diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties new file mode 100644 index 0000000..0d9a804 --- /dev/null +++ b/src/main/resources/application-prod.properties @@ -0,0 +1,13 @@ +# Production profile configuration +spring.datasource.url=${SPRING_DATASOURCE_URL:jdbc:postgresql://db:5432/gymdb} +spring.datasource.username=${SPRING_DATASOURCE_USERNAME:postgres} +spring.datasource.password=${SPRING_DATASOURCE_PASSWORD:postgres} +spring.datasource.driver-class-name=org.postgresql.Driver + +# JPA/Hibernate +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=false + +# Server +server.port=8080 +server.address=0.0.0.0 \ No newline at end of file diff --git a/src/main/resources/application.prod.properties b/src/main/resources/application.prod.properties deleted file mode 100644 index 6056ec7..0000000 --- a/src/main/resources/application.prod.properties +++ /dev/null @@ -1,40 +0,0 @@ -# Configuración de la base de datos -quarkus.datasource.db-kind=postgresql -quarkus.datasource.username=${DB_USERNAME} -quarkus.datasource.password=${DB_PASSWORD} -quarkus.datasource.jdbc.url=jdbc:postgresql://${POSTGRESSHOST}:${POSTGRESSPORT}/{POSTGRESSDATABASE} - -# Configuración de Hibernate ORM -quarkus.hibernate-orm.database.generation=update -quarkus.hibernate-orm.log.sql=true -quarkus.hibernate-orm.jdbc.statement-batch-size=20 - -# Configuración CORS para permitir peticiones desde nuestra app Ionic -quarkus.http.cors=true -quarkus.http.cors.origins=* -quarkus.http.cors.methods=GET,POST,PUT,DELETE,OPTIONS -quarkus.http.cors.headers=Content-Type,Authorization -quarkus.http.cors.exposed-headers=Content-Disposition -quarkus.http.cors.access-control-max-age=24H - -# Configuración para archivos estáticos -quarkus.http.body.uploads-directory=uploads -quarkus.http.body.handle-file-uploads=true -quarkus.http.static.path=/uploads -quarkus.http.static.dir=uploads - -# Configuración de logging -quarkus.log.console.enable=true -quarkus.log.console.format=%d{HH:mm:ss} %-5p [%c{2.}] (%t) %s%e%n -quarkus.log.console.level=INFO -quarkus.log.category."org.hibernate".level=INFO -quarkus.log.category."io.quarkus.arc".level=INFO - -# Configuración de JSON binding -quarkus.jackson.write-dates-as-timestamps=false -quarkus.jackson.fail-on-unknown-properties=false - -# Configuración CDI -quarkus.arc.remove-unused-beans=false - -# Server host diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 973f661..3415bb9 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,41 +1,41 @@ -# Configuración de la base de datos -quarkus.datasource.db-kind=postgresql -quarkus.datasource.username=postgres -quarkus.datasource.password=postgres -quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/gymdb +# Database Configuration +spring.datasource.url=jdbc:postgresql://localhost:5432/gymdb +spring.datasource.username=postgres +spring.datasource.password=postgres +spring.datasource.driver-class-name=org.postgresql.Driver -# Configuración de Hibernate ORM -quarkus.hibernate-orm.database.generation=update -quarkus.hibernate-orm.log.sql=true -quarkus.hibernate-orm.jdbc.statement-batch-size=20 +# JPA / Hibernate +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.properties.hibernate.jdbc.batch_size=20 +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect -# Configuración CORS para permitir peticiones desde nuestra app Ionic -quarkus.http.cors=true -quarkus.http.cors.origins=* -quarkus.http.cors.methods=GET,POST,PUT,DELETE,OPTIONS -quarkus.http.cors.headers=Content-Type,Authorization -quarkus.http.cors.exposed-headers=Content-Disposition -quarkus.http.cors.access-control-max-age=24H +# Web +spring.servlet.multipart.max-file-size=10MB +spring.servlet.multipart.max-request-size=10MB -# Configuración para archivos estáticos -quarkus.http.body.uploads-directory=uploads -quarkus.http.body.handle-file-uploads=true -quarkus.http.static.path=/uploads -quarkus.http.static.dir=uploads +# File storage +app.upload.dir=uploads +spring.web.resources.static-locations=file:uploads/ -# Configuración de logging -quarkus.log.console.enable=true -quarkus.log.console.format=%d{HH:mm:ss} %-5p [%c{2.}] (%t) %s%e%n -quarkus.log.console.level=INFO -quarkus.log.category."org.hibernate".level=INFO -quarkus.log.category."io.quarkus.arc".level=INFO +# Jackson JSON +spring.jackson.serialization.write-dates-as-timestamps=false +spring.jackson.deserialization.fail-on-unknown-properties=false -# Configuración de JSON binding -quarkus.jackson.write-dates-as-timestamps=false -quarkus.jackson.fail-on-unknown-properties=false +# Logging +logging.level.root=INFO +logging.level.org.hibernate=INFO +logging.level.org.springframework.web=INFO +logging.pattern.console=%d{HH:mm:ss} %-5level [%logger{36}] - %msg%n -# Configuración CDI -quarkus.arc.remove-unused-beans=false +# Server +server.port=8080 +server.address=0.0.0.0 -# Server host -quarkus.http.host=0.0.0.0 \ No newline at end of file +# CORS +spring.web.cors.allowed-origins=* +spring.web.cors.allowed-methods=GET,POST,PUT,DELETE,OPTIONS +spring.web.cors.allowed-headers=Content-Type,Authorization +spring.web.cors.exposed-headers=Content-Disposition +spring.web.cors.max-age=3600 \ No newline at end of file diff --git a/src/main/resources/import.sql b/src/main/resources/import.sql deleted file mode 100644 index 16aa523..0000000 --- a/src/main/resources/import.sql +++ /dev/null @@ -1,6 +0,0 @@ --- This file allow to write SQL commands that will be emitted in test and dev. --- The commands are commented as their support depends of the database --- insert into myentity (id, field) values(1, 'field-1'); --- insert into myentity (id, field) values(2, 'field-2'); --- insert into myentity (id, field) values(3, 'field-3'); --- alter sequence myentity_seq restart with 4; \ No newline at end of file diff --git a/src/test/java/com/valposystems/GreetingResourceIT.java b/src/test/java/com/valposystems/GreetingResourceIT.java deleted file mode 100644 index 9c86a97..0000000 --- a/src/test/java/com/valposystems/GreetingResourceIT.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.valposystems; - -import io.quarkus.test.junit.QuarkusIntegrationTest; - -@QuarkusIntegrationTest -class GreetingResourceIT extends GreetingResourceTest { - // Execute the same tests but in packaged mode. -} diff --git a/src/test/java/com/valposystems/GreetingResourceTest.java b/src/test/java/com/valposystems/GreetingResourceTest.java deleted file mode 100644 index 564c692..0000000 --- a/src/test/java/com/valposystems/GreetingResourceTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.valposystems; - -import io.quarkus.test.junit.QuarkusTest; -import org.junit.jupiter.api.Test; - -import static io.restassured.RestAssured.given; -import static org.hamcrest.CoreMatchers.is; - -@QuarkusTest -class GreetingResourceTest { - @Test - void testHelloEndpoint() { - given() - .when().get("/hello") - .then() - .statusCode(200) - .body(is("Hello RESTEasy")); - } - -} \ No newline at end of file