diff --git a/backend/Dockerfile b/backend/Dockerfile index 9a0dcdb..25752c6 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,15 +1,21 @@ -# Build stage +# Build stage --------------------------------------------------------------- FROM maven:3.9.12-eclipse-temurin-25 AS build WORKDIR /app COPY pom.xml . COPY src ./src RUN mvn clean package -# Run stage +# Run stage --------------------------------------------------------------- FROM eclipse-temurin:25-jre WORKDIR /app ARG APP_VERSION=dev ENV APP_VERSION=${APP_VERSION} + +# Install curl (required for the health‑check) +RUN apt-get update && \ + apt-get install -y curl && \ + rm -rf /var/lib/apt/lists/* + COPY --from=build /app/target/*.jar app.jar -EXPOSE 8080 +EXPOSE 8082 ENTRYPOINT ["java", "-jar", "app.jar"] diff --git a/backend/pom.xml b/backend/pom.xml index 0393658..c074245 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -65,6 +65,10 @@ spring-boot-starter-webmvc-test test + + org.springframework.boot + spring-boot-starter-actuator + diff --git a/backend/src/main/java/com/todo/backend/config/WebConfig.java b/backend/src/main/java/com/todo/backend/config/WebConfig.java index 9ab638b..6123059 100644 --- a/backend/src/main/java/com/todo/backend/config/WebConfig.java +++ b/backend/src/main/java/com/todo/backend/config/WebConfig.java @@ -10,8 +10,7 @@ public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") - .allowedOrigins("http://localhost:5173", "http://localhost:3000", "http://localhost:8081", - "http://localhost:80", "https://todo.almazlar.com") // Typical Vite/React/Docker ports + .allowedOrigins("http://localhost:5173", "https://todo.almazlar.com") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true); diff --git a/backend/src/main/java/com/todo/backend/controller/VersionController.java b/backend/src/main/java/com/todo/backend/controller/VersionController.java index 78f1ec3..6e643a4 100644 --- a/backend/src/main/java/com/todo/backend/controller/VersionController.java +++ b/backend/src/main/java/com/todo/backend/controller/VersionController.java @@ -10,7 +10,7 @@ import java.util.HashMap; import java.util.Map; @RestController -@RequestMapping("/api/version") +@RequestMapping("/version") public class VersionController { @Value("${APP_VERSION:dev}") diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 56d4a2d..3ccaa72 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -1,9 +1,11 @@ +# backend/src/main/resources/application.properties + server.port=8082 server.servlet.context-path=/api spring.application.name=backend -spring.datasource.url=jdbc:postgresql://localhost:5432/tododb -spring.datasource.username=postgres -spring.datasource.password=postgres + spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect +management.endpoints.web.exposure.include=health,info,metrics +management.endpoint.health.show-details=always \ No newline at end of file diff --git a/backend/src/test/java/com/todo/backend/controller/TodoControllerTest.java b/backend/src/test/java/com/todo/backend/controller/TodoControllerTest.java index 80ae3a5..e09979a 100644 --- a/backend/src/test/java/com/todo/backend/controller/TodoControllerTest.java +++ b/backend/src/test/java/com/todo/backend/controller/TodoControllerTest.java @@ -7,6 +7,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest; +import org.springframework.test.context.ActiveProfiles; // Spring Boot 3.4+ replaces @MockBean with @MockitoBean import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.http.MediaType; @@ -25,6 +26,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @WebMvcTest(TodoController.class) +@ActiveProfiles("test") public class TodoControllerTest { @Autowired @@ -52,7 +54,7 @@ public class TodoControllerTest { List todos = Arrays.asList(todo1, todo2); when(todoService.getAllTodos()).thenReturn(todos); - mockMvc.perform(get("/api/todos")) + mockMvc.perform(get("/todos")) .andExpect(status().isOk()) .andExpect(jsonPath("$", hasSize(2))) .andExpect(jsonPath("$[0].title", is(todo1.getTitle()))) @@ -63,7 +65,7 @@ public class TodoControllerTest { void getTodoById_WhenExists_ReturnsTodo() throws Exception { when(todoService.getTodoById(1L)).thenReturn(Optional.of(todo1)); - mockMvc.perform(get("/api/todos/1")) + mockMvc.perform(get("/todos/1")) .andExpect(status().isOk()) .andExpect(jsonPath("$.title", is(todo1.getTitle()))) .andExpect(jsonPath("$.id", is(1))); @@ -73,7 +75,7 @@ public class TodoControllerTest { void getTodoById_WhenNotExists_ReturnsNotFound() throws Exception { when(todoService.getTodoById(99L)).thenReturn(Optional.empty()); - mockMvc.perform(get("/api/todos/99")) + mockMvc.perform(get("/todos/99")) .andExpect(status().isNotFound()); } @@ -85,7 +87,7 @@ public class TodoControllerTest { when(todoService.createTodo(any(Todo.class))).thenReturn(savedTodo); - mockMvc.perform(post("/api/todos") + mockMvc.perform(post("/todos") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(newTodo))) .andExpect(status().isCreated()) @@ -101,7 +103,7 @@ public class TodoControllerTest { when(todoService.updateTodo(eq(1L), any(Todo.class))).thenReturn(updatedTodo); - mockMvc.perform(put("/api/todos/1") + mockMvc.perform(put("/todos/1") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(updatedInfo))) .andExpect(status().isOk()) @@ -115,7 +117,7 @@ public class TodoControllerTest { when(todoService.updateTodo(eq(99L), any(Todo.class))).thenReturn(null); - mockMvc.perform(put("/api/todos/99") + mockMvc.perform(put("/todos/99") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(updatedInfo))) .andExpect(status().isNotFound()); @@ -125,7 +127,7 @@ public class TodoControllerTest { void deleteTodo_WhenExists_ReturnsNoContent() throws Exception { when(todoService.deleteTodo(1L)).thenReturn(true); - mockMvc.perform(delete("/api/todos/1")) + mockMvc.perform(delete("/todos/1")) .andExpect(status().isNoContent()); } @@ -133,7 +135,9 @@ public class TodoControllerTest { void deleteTodo_WhenNotExists_ReturnsNotFound() throws Exception { when(todoService.deleteTodo(99L)).thenReturn(false); - mockMvc.perform(delete("/api/todos/99")) + mockMvc.perform(delete("/todos/99")) .andExpect(status().isNotFound()); } } + + diff --git a/backend/src/test/resources/application-test.properties b/backend/src/test/resources/application-test.properties index 5ba45fc..729d148 100644 --- a/backend/src/test/resources/application-test.properties +++ b/backend/src/test/resources/application-test.properties @@ -4,3 +4,4 @@ spring.datasource.username=sa spring.datasource.password= spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index e3d49ce..8b245ba 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,7 +22,7 @@ services: build: ./backend container_name: todo-backend ports: - - "8082:8080" + - "8082:8082" environment: - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/tododb - SPRING_DATASOURCE_USERNAME=postgres @@ -31,7 +31,7 @@ services: db: condition: service_healthy healthcheck: - test: ["CMD-SHELL", "curl -f http://localhost:8080/actuator/health || exit 1"] + test: ["CMD-SHELL", "curl -f http://localhost:8082/api/actuator/health || exit 1"] interval: 10s timeout: 5s retries: 5 @@ -43,7 +43,8 @@ services: ports: - "5173:80" depends_on: - - backend + backend: + condition: service_healthy volumes: