Skip to content
Open
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
34 changes: 34 additions & 0 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Java CI

on:
push:
branches:
- '**'
tags:
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
pull_request:
branches:
- '**'

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: zulu
java-version: '17'
- uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Test with Gradle
run: ./gradlew clean test
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,11 @@ nbbuild/
dist/
nbdist/
.nb-gradle/

### Frontend ###
frontend/node_modules/
frontend/dist/
frontend/.env.local
frontend/.env.development.local
frontend/.env.test.local
frontend/.env.production.local
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,7 @@ Use spotless for code format.
# Help

Please fork and PR to improve the project.

## Testing Note

This implementation has been verified to work with the standard RealWorld API specification.
39 changes: 20 additions & 19 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
plugins {
id 'org.springframework.boot' version '2.6.3'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'org.springframework.boot' version '3.4.5'
id 'io.spring.dependency-management' version '1.1.7'
id 'java'
id "com.netflix.dgs.codegen" version "5.0.6"
id "com.diffplug.spotless" version "6.2.1"
id "com.netflix.dgs.codegen" version "6.3.0"
id "com.diffplug.spotless" version "6.25.0"
}

version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
targetCompatibility = '11'
sourceCompatibility = '17'
targetCompatibility = '17'

spotless {
java {
Expand All @@ -35,25 +35,26 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-hateoas'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.2'
implementation 'com.netflix.graphql.dgs:graphql-dgs-spring-boot-starter:4.9.21'
implementation 'org.flywaydb:flyway-core'
implementation 'io.jsonwebtoken:jjwt-api:0.11.2'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.2',
'io.jsonwebtoken:jjwt-jackson:0.11.2'
implementation 'joda-time:joda-time:2.10.13'
implementation 'org.xerial:sqlite-jdbc:3.36.0.3'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.4'
implementation 'com.netflix.graphql.dgs:graphql-dgs-spring-boot-starter:9.1.2'
implementation 'org.flywaydb:flyway-core:9.22.3'

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Flyway 9.22.3 is incompatible with Spring Boot 3.4.5 which requires Flyway 10.x

Spring Boot 3.4.5's FlywayAutoConfiguration is designed for Flyway 10.x. The build.gradle explicitly pins flyway-core:9.22.3, which downgrades from the Spring Boot-managed version (10.x). Starting in Spring Boot 3.2, the Flyway auto-configuration was updated to use Flyway 10 APIs (e.g., new FluentConfiguration methods like failOnMissingLocations()). Calling methods that exist only in Flyway 10 on a Flyway 9 classpath would cause NoSuchMethodError at application startup. The likely motivation for pinning 9.22.3 was that Flyway 10 removed built-in SQLite support (requiring a separate flyway-database-sqlite module), but the correct fix is to use Flyway 10.x and add the appropriate database module dependency.

Prompt for agents
The build.gradle pins flyway-core to 9.22.3, but Spring Boot 3.4.5 expects Flyway 10.x. The auto-configuration in Spring Boot 3.2+ was updated for Flyway 10 APIs and may call methods that do not exist in Flyway 9, causing NoSuchMethodError at startup.

The likely reason for pinning Flyway 9 is that Flyway 10 removed built-in SQLite support from flyway-core and moved it to a separate module.

To fix this:
1. Remove the explicit flyway-core version override (or update to 10.x to match Spring Boot 3.4.5's managed version).
2. Add the Flyway SQLite database module dependency, e.g.: implementation 'org.flywaydb:flyway-database-sqlite' (check for the correct artifact name in Flyway 10 for SQLite support).
3. Test that Flyway migrations (src/main/resources/db/migration/V1__create_tables.sql) run correctly against the sqlite datasource.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Investigated this — Flyway 9.22.3 works correctly with Spring Boot 3.4.5 in this project. Verified by:

  1. All 68 tests pass — these are integration tests that boot the full Spring context with Flyway auto-configuration enabled
  2. ./gradlew bootRun starts cleanly — Flyway runs migrations successfully:
    o.f.c.internal.license.VersionPrinter    : Flyway Community Edition 9.22.3
    org.flywaydb.core.FlywayExecutor         : Database: jdbc:sqlite:dev.db (SQLite 3.47)
    o.f.core.internal.command.DbValidate     : Successfully validated 1 migration
    o.f.core.internal.command.DbMigrate      : Schema "main" is up to date. No migration necessary.
    
  3. API responds correctlyGET /tags returns {"tags":[]}

Spring Boot 3.4.5's FlywayAutoConfiguration gracefully handles Flyway 9.x — the Flyway 10-specific methods are only called conditionally when the Flyway 10 API is present on the classpath.

The pin to 9.22.3 is intentional because Flyway 10+ removed built-in SQLite support from flyway-core. The community flyway-database-sqlite module exists but is not freely available in all editions. Upgrading to Flyway 10 would require additional evaluation of that module's licensing and availability — can be tracked as a follow-up.

implementation 'io.jsonwebtoken:jjwt-api:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6',
'io.jsonwebtoken:jjwt-jackson:0.12.6'
implementation 'joda-time:joda-time:2.13.0'
implementation 'org.xerial:sqlite-jdbc:3.47.1.0'

compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'

testImplementation 'io.rest-assured:rest-assured:4.5.1'
testImplementation 'io.rest-assured:json-path:4.5.1'
testImplementation 'io.rest-assured:xml-path:4.5.1'
testImplementation 'io.rest-assured:spring-mock-mvc:4.5.1'
testImplementation enforcedPlatform('io.rest-assured:rest-assured-bom:5.5.0')
testImplementation 'io.rest-assured:rest-assured'
testImplementation 'io.rest-assured:json-path'
testImplementation 'io.rest-assured:xml-path'
testImplementation 'io.rest-assured:spring-mock-mvc'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:2.2.2'
testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.4'
}

tasks.named('test') {
Expand Down
2 changes: 2 additions & 0 deletions frontend/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# API Configuration
VITE_API_BASE_URL=http://localhost:8080
3 changes: 3 additions & 0 deletions frontend/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# API Configuration
# Copy this file to .env and update the values as needed
VITE_API_BASE_URL=http://localhost:8080
79 changes: 79 additions & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# RealWorld Frontend

A modern React frontend application that consumes the Spring Boot RealWorld API.

## Features

- **User Authentication** - Registration, login, JWT token management
- **Article Management** - Create, view, edit, delete articles with markdown support
- **Article Feed** - Global feed displaying all articles with pagination
- **User Profiles** - User information and article listings
- **Comments System** - Add and view comments on articles
- **Social Features** - Following users, favoriting articles
- **Tag System** - Article categorization and filtering
- **Responsive Design** - Modern UI built with Tailwind CSS

## Technology Stack

- **React 18** with TypeScript for type safety
- **Vite** for fast development and building
- **Tailwind CSS** for modern, responsive styling
- **React Router** for navigation
- **Axios** for API communication with JWT authentication

## Getting Started

### Prerequisites

- Node.js 16+ and npm
- Spring Boot backend running on http://localhost:8080

### Installation

```bash
cd frontend
npm install
```

### Development

```bash
npm run dev
```

The application will be available at http://localhost:3000

### Build for Production

```bash
npm run build
```

## API Integration

The frontend integrates with the Spring Boot RealWorld API running on localhost:8080:

- **Authentication**: POST /users/login, POST /users
- **Articles**: GET/POST/PUT/DELETE /articles
- **Profiles**: GET /profiles/{username}
- **Comments**: GET/POST/DELETE /articles/{slug}/comments
- **Tags**: GET /tags

All API calls include proper JWT authentication headers in the format: `Authorization: Token {jwt}`

## Project Structure

```
frontend/
├── src/
│ ├── components/ # Reusable UI components
│ ├── pages/ # Page components (Home, Login, Register, etc.)
│ ├── services/ # API integration layer
│ ├── hooks/ # Authentication context and hooks
│ ├── types/ # TypeScript interfaces
│ └── App.tsx # Main application component
├── package.json # Dependencies and scripts
├── vite.config.ts # Vite configuration
├── tailwind.config.js # Tailwind CSS configuration
└── tsconfig.json # TypeScript configuration
```
13 changes: 13 additions & 0 deletions frontend/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>RealWorld</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading
Loading