Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
services:
# Oracle Database service
oracle-db:
image: container-registry.oracle.com/database/express:21.3.0-xe
container_name: photoalbum-oracle
# PostgreSQL Database service (migrated from Oracle)
postgres-db:
image: postgres:16-alpine
container_name: photoalbum-postgres
environment:
- ORACLE_PWD=photoalbum
- ORACLE_CHARACTERSET=AL32UTF8
- POSTGRES_DB=postgres
- POSTGRES_USER=photoalbum
- POSTGRES_PASSWORD=photoalbum
- POSTGRES_INITDB_ARGS=--encoding=UTF-8
ports:
- "1521:1521"
- "5500:5500"
- "5432:5432"
volumes:
- oracle_data:/opt/oracle/oradata
- ./oracle-init:/opt/oracle/scripts/startup
- postgres_data:/var/lib/postgresql/data
- ./postgres-init:/docker-entrypoint-initdb.d
networks:
- photoalbum-network
healthcheck:
test: ["CMD-SHELL", "echo 'SELECT 1 FROM DUAL;' | sqlplus -s photoalbum/photoalbum@//localhost:1521/XE || exit 1"]
interval: 30s
timeout: 10s
retries: 15
start_period: 180s
test: ["CMD-SHELL", "pg_isready -U photoalbum"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s

# Photo Album Java Application
photoalbum-java-app:
Expand All @@ -29,20 +30,19 @@ services:
container_name: photoalbum-java-app
environment:
- SPRING_PROFILES_ACTIVE=docker
- SPRING_DATASOURCE_URL=jdbc:oracle:thin:@oracle-db:1521:XE
- SPRING_DATASOURCE_USERNAME=photoalbum
- SPRING_DATASOURCE_PASSWORD=photoalbum
- POSTGRES_USERNAME=photoalbum
- POSTGRES_PASSWORD=photoalbum
ports:
- "8080:8080"
depends_on:
oracle-db:
postgres-db:
condition: service_healthy
networks:
- photoalbum-network
restart: on-failure

volumes:
oracle_data:
postgres_data:

networks:
photoalbum-network:
Expand Down
36 changes: 0 additions & 36 deletions oracle-init/01-create-user.sql

This file was deleted.

14 changes: 0 additions & 14 deletions oracle-init/02-verify-user.sql

This file was deleted.

35 changes: 0 additions & 35 deletions oracle-init/create-user.sh

This file was deleted.

3 changes: 0 additions & 3 deletions oracle-init/healthcheck.sql

This file was deleted.

11 changes: 7 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<packaging>jar</packaging>

<name>Photo Album</name>
<description>A simple photo storage and gallery application built with Spring Boot and Oracle DB</description>
<description>A simple photo storage and gallery application built with Spring Boot and PostgreSQL</description>

<properties>
<java.version>1.8</java.version>
Expand Down Expand Up @@ -46,10 +46,13 @@
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<!-- Oracle JDBC Driver -->
<!-- Migrated from Oracle to PostgreSQL according to Build file check item 1: Replace Oracle JDBC driver with PostgreSQL driver dependency. -->
<!-- Migrated from Oracle to PostgreSQL according to Build file check item 5: Verify newly added dependencies are CVE-free. -->
<!-- PostgreSQL JDBC Driver - version overridden to fix CVE-2024-1597 and CVE-2025-49146 -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.7</version>
<scope>runtime</scope>
</dependency>

Expand Down
29 changes: 29 additions & 0 deletions postgres-init/01-init-db.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
-- Migrated from Oracle to PostgreSQL according to SQL check item 1: Use lowercase for identifiers (like table and column names) and data type (like varchar), use uppercase for SQL keywords (like SELECT, FROM, WHERE).
-- PostgreSQL initialization script for photoalbum database
-- This script runs automatically when PostgreSQL container starts

-- Note: The photoalbum user is created by the POSTGRES_USER environment variable
-- We only need to grant additional privileges if required

-- Create database if not exists (though it's created by POSTGRES_DB env var)
-- The default database 'postgres' is already created

-- Grant schema privileges to photoalbum user
GRANT ALL PRIVILEGES ON DATABASE postgres TO photoalbum;

-- Grant privileges on public schema
GRANT ALL ON SCHEMA public TO photoalbum;

-- Grant default privileges for future tables
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO photoalbum;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO photoalbum;

-- Extension for UUID generation (if needed in future)
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- Log successful initialization
DO $$
BEGIN
RAISE NOTICE 'PostgreSQL initialization completed successfully for photoalbum user';
END $$;

10 changes: 5 additions & 5 deletions src/main/java/com/photoalbum/controller/PhotoFileController.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import java.util.Optional;

/**
* Controller for serving photo files from Oracle database BLOB storage
* Controller for serving photo files from PostgreSQL database BLOB storage
*/
@Controller
@RequestMapping("/photo")
Expand All @@ -32,7 +32,7 @@ public PhotoFileController(PhotoService photoService) {
}

/**
* Serves a photo file by ID from Oracle database BLOB storage
* Serves a photo file by ID from PostgreSQL database BLOB storage
*/
@GetMapping("/{id}")
public ResponseEntity<Resource> servePhoto(@PathVariable String id) {
Expand All @@ -54,7 +54,7 @@ public ResponseEntity<Resource> servePhoto(@PathVariable String id) {
logger.info("Found photo: originalFileName={}, mimeType={}",
photo.getOriginalFileName(), photo.getMimeType());

// Get photo data from Oracle database BLOB
// Get photo data from PostgreSQL database BLOB
byte[] photoData = photo.getPhotoData();
if (photoData == null || photoData.length == 0) {
logger.error("No photo data found for photo ID {}", id);
Expand All @@ -68,7 +68,7 @@ public ResponseEntity<Resource> servePhoto(@PathVariable String id) {
// Create resource from byte array
Resource resource = new ByteArrayResource(photoData);

logger.info("Serving photo ID {} ({}, {} bytes) from Oracle database",
logger.info("Serving photo ID {} ({}, {} bytes) from PostgreSQL database",
id, photo.getOriginalFileName(), photoData.length);

// Return the photo data with appropriate content type and aggressive no-cache headers
Expand All @@ -82,7 +82,7 @@ public ResponseEntity<Resource> servePhoto(@PathVariable String id) {
.header("X-Photo-Size", String.valueOf(photoData.length))
.body(resource);
} catch (Exception ex) {
logger.error("Error serving photo with ID {} from Oracle database", id, ex);
logger.error("Error serving photo with ID {} from PostgreSQL database", id, ex);
return ResponseEntity.status(500).build();
}
}
Expand Down
8 changes: 5 additions & 3 deletions src/main/java/com/photoalbum/model/Photo.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class Photo {
private String originalFileName;

/**
* Binary photo data stored directly in Oracle database
* Binary photo data stored directly in PostgreSQL database
*/
@Lob
@Column(name = "photo_data", nullable = true)
Expand All @@ -57,10 +57,11 @@ public class Photo {

/**
* File size in bytes
* Migrated from Oracle to PostgreSQL according to java check item 1: Convert all table and column names from uppercase to lowercase in JPA annotations.
*/
@NotNull
@Positive
@Column(name = "file_size", nullable = false, columnDefinition = "NUMBER(19,0)")
@Column(name = "file_size", nullable = false)
private Long fileSize;

/**
Expand All @@ -73,9 +74,10 @@ public class Photo {

/**
* Timestamp of upload
* Migrated from Oracle to PostgreSQL according to java check item 1: Convert all table and column names from uppercase to lowercase in JPA annotations.
*/
@NotNull
@Column(name = "uploaded_at", nullable = false, columnDefinition = "TIMESTAMP DEFAULT SYSTIMESTAMP")
@Column(name = "uploaded_at", nullable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
private LocalDateTime uploadedAt;

/**
Expand Down
Loading