8000
Skip to content

Latest commit

 

History

1,417 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Codacy Badge Webapp CI

LinkLift

A modern link management system built with Java and hexagonal architecture principles.

Overview

LinkLift is a RESTful web service for managing web links with comprehensive CRUD operations. It features a clean, maintainable architecture that separates business logic from infrastructure concerns, making it highly testable and adaptable to changing requirements.

Key Features

  • 🔗 Link Management: Create and list web links with metadata
    • 🔍 Vector Search: Semantic search powered by Ollama embeddings and ArcadeDB vector index
  • 🏗️ Clean Architecture: Hexagonal architecture with strict layer separation
  • 📊 Pagination & Sorting: Efficient data retrieval with flexible sorting options
  • ⚡ Event-Driven: Domain events for loose coupling and extensibility
  • 🧪 Comprehensive Testing: Unit, integration, and optional E2E tests with real Ollama
  • 🛡️ Error Handling: Centralized exception handling with meaningful error codes
  • 🔄 Database Agnostic: Repository pattern enables flexible data storage

Quick Start

Prerequisites

Installation

  1. Clone the repository

    git clone <repository-url>
    cd linklift
  2. Start with Docker Compose (Recommended)

    docker-compose up -d

    This starts all required services:

    • ArcadeDB (database)
    • Ollama (AI embeddings for vector search)
    • LinkLift API
    • LinkLift Webapp

    Note: First start takes 2-3 minutes to pull the Ollama model (~23MB)

  3. Verify installation

    curl http://localhost:7070/up
    # Expected: OK
    
    curl http://localhost:7070/api/v1/links
    # Expected: {"data": {"content": [], ...}, "message": "Links retrieved successfully"}
    
    curl http://localhost:11434/
    # Expected: Ollama is running

Alternative: Manual Setup

# 1. Start ArcadeDB
docker run -d --name arcadedb \
  -p 2480:2480 -p 2424:2424 \
  -e JAVA_OPTS="-Darcadedb.server.rootPassword=playwithdata" \
  arcadedata/arcadedb:25.7.1

# 2. Build and run application
mvn clean package
java -jar target/linklift-1.0-SNAPSHOT.jar

Usage Examples

Create a Link

curl -X PUT http://localhost:7070/api/v1/link \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://github.com",
    "title": "GitHub",
    "description": "The world'\''s leading software development platform"
  }'

Response:

{
  "link": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "url": "https://github.com",
    "title": "GitHub",
    "description": "The world's leading software development platform",
    "extractedAt": "2025-08-15T18:12:39",
    "contentType": "text/html"
  },
  "status": "Link received"
}

List Links with Pagination

# Basic listing
curl http://localhost:7070/api/v1/links

# With pagination and sorting
curl "http://localhost:7070/api/v1/links?page=0&size=10&sortBy=title&sortDirection=ASC"

Response:

{
  "data": {
    "content": [...],
    "page": 0,
    "size": 10,
    "totalElements": 25,
    "totalPages": 3,
    "hasNext": true,
    "hasPrevious": false
  },
  "message": "Links retrieved successfully"
}

Architecture

LinkLift follows Hexagonal Architecture (Ports and Adapters) with clear separation between:

  • Domain Layer: Pure business logic and rules
  • Application Layer: Use cases and service coordination
  • Infrastructure Layer: External adapters (web, database, events)
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Layer     │    │ Application     │    │   Persistence   │
│  (Javalin)      │◄───┤   Services      ├───►│   (ArcadeDB)    │
│                 │    │                 │    │                 │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                               │
                       ┌─────────────────┐
                       │  Domain Model   │
                       │  (Entities &    │
                       │   Events)       │
                       └─────────────────┘

Technology Stack

  • ☕ Java 17: Modern language features and performance
  • 🚀 Javalin: Lightweight, fast web framework
  • 🗄️ ArcadeDB: Multi-model database (Graph, Document, Key-Value) with vector search
  • 🤖 Ollama: Local AI embeddings generation (all-minilm:l6-v2)
  • 🔨 Maven: Build automation and dependency management
  • 🧪 JUnit 5: Modern testing framework with comprehensive assertions
  • 🐳 Docker: Containerization for consistent environments

Web Interface

After starting the application with Docker Compose, you can access the web UI at:

http://localhost:80

Or simply:

http://localhost

The web interface allows you to view and add new links through a user-friendly React interface.

React Frontend Development

The web UI is built with React. If you want to develop the frontend separately:

# Navigate to the webapp directory
cd webapp

# Install dependencies
npm install

# Start development server
npm start

# Run tests
npm test

# Build for production
npm run build

The React app includes:

  • Component tests with React Testing Library
  • API mocking for isolated testing
  • Material UI for component styling

API Reference

Endpoints Overview

Method Endpoint Description Status
GET /up Health check
PUT /api/v1/link Create new link
GET /api/v1/links List links (paginated)

Query Parameters for /api/v1/links

Parameter Type Default Description
page Integer 0 Page number (0-based)
size Integer 20 Items per page (max: 100)
sortBy String "extractedAt" Sort field: id, url, title, description, extractedAt, contentType
sortDirection String "DESC" Sort direction: ASC, DESC

Error Handling

All errors return a consistent JSON format:

{
  "status": 400,
  "code": 1001,
  "message": "Validation error",
  "fieldErrors": {
    "url": "URL cannot be empty"
  },
  "path": "/api/v1/link",
  "timestamp": "2025-08-15T18:12:39"
}

Common HTTP Status Codes:

  • 200 - Success
  • 201 - Created
  • 400 - Bad Request (validation errors)
  • 409 - Conflict (duplicate URL)
  • 500 - Internal Server Error

Development

Build Commands

# Clean and build
mvn clean package

# Run tests
mvn test

# Run specific test
mvn test -Dtest=NewLinkServiceTest

# Run with coverage (if configured)
mvn test jacoco:report

Project Structure

src/
├── main/java/it/robfrank/linklift/
│   ├── Application.java         # Main entry point
│   ├── adapter/                 # Infrastructure adapters
│   │   ├── in/web/             # REST 
729A
controllers
│   │   └── out/                # Database, event adapters
│   ├── application/            # Application layer
│   │   ├── domain/             # Business logic
│   │   └── port/               # Interface definitions
│   └── config/                 # Configuration
└── test/                       # Test classes (mirrors main structure)

Testing

LinkLift uses a modern testing approach that emphasizes integration testing with real implementations over mocking. This provides higher confidence and catches more bugs while maintaining reasonable execution times.

Test Types:

Type Count Execution Time Technology Purpose
Integration Tests 32 tests ~30 seconds Testcontainers + ArcadeDB Service tests with real database
HTTP Tests 15 tests ~500ms WireMock HTTP adapter tests with mocked responses
Unit Tests 300+ tests ~10 seconds JUnit 5 Domain models, validation, business logic
Controller Tests 50+ tests ~15 seconds JavalinTest REST API endpoints
E2E Tests 2 tests ~120 seconds Testcontainers + Ollama Optional full-stack validation

Prerequisites:

  • Docker Desktop - Required for integration tests (Testcontainers)

Running Tests:

# Run all tests (excludes E2E tests by default)
# Total execution time: ~2 minutes
mvn test

# Run specific test class
mvn test -Dtest=BackfillEmbeddingsServiceTest

# Run specific test method
mvn test -Dtest=SearchContentServiceTest#search_shouldReturnSimilarContent

# Run with coverage report
mvn test jacoco:report
open target/site/jacoco/index.html

# Run E2E tests (optional, requires Docker + Ollama image ~400MB)
mvn test -Pe2e-tests

Test Categories Explained:

  1. Integration Tests with Testcontainers (32 tests, ~30s)

    • Uses real ArcadeDB in Docker container
    • Tests actual SQL queries, vector indexing, and database behavior
    • Examples: BackfillEmbeddingsServiceTest, SearchContentServiceTest
    • Catches SQL errors, schema issues, and mapping bugs
  2. HTTP Tests with WireMock (15 tests, ~500ms)

    • Uses real HTTP client with mocked server responses
    • Tests JSON serialization, error handling, and retry logic
    • Examples: OllamaEmbeddingAdapterTest, HttpContentDownloaderTest
    • Fast and deterministic
  3. E2E Tests with Real Ollama (2 tests, ~120s, optional)

    • Uses real Ollama service for embeddings
    • Validates actual semantic similarity
    • Run separately for pre-release validation
    • Requires Docker + Ollama container

Testing Strategy:

  • Development: Run fast integration tests (mvn test)
  • Pre-commit: Ensure all tests pass before pushing
  • Pre-release: Run E2E tests to validate Ollama integration
  • CI/CD: All tests on PRs, E2E tests on main branch only

Troubleshooting:

Issue Solution
"Could not start container" Ensure Docker Desktop is running
Tests timeout Increase Docker resources (4GB+ RAM recommended)
Port conflicts Stop other containers: docker stop $(docker ps -q)
Slow execution Check Docker performance settings

For Contributors:

See CONTRIBUTING_TESTS.md for detailed guidance on:

  • When to use Testcontainers vs WireMock vs E2E tests
  • How to write effective integration tests
  • Best practices and common patterns
  • Test structure (Given/When/Then)
  • Async testing with Awaitility

Configuration

Environment Variables

Variable Default Description
linklift.arcadedb.host localhost ArcadeDB server hostname
LINKLIFT_JWT_SECRET Auto-generated (dev) JWT authentication secret
LINKLIFT_OLLAMA_URL http://localhost:11434 Ollama API endpoint
LINKLIFT_OLLAMA_MODEL all-minilm:l6-v2 Ollama embedding model
LINKLIFT_OLLAMA_DIMENSIONS 384 Expected embedding dimensions

Database Configuration

ArcadeDB Connection:

  • Host: localhost:2480 (HTTP API)
  • Database: linklift
  • Username: root
  • Password: playwithdata

Web UI: http://localhost:2480 (ArcadeDB Studio)

Ollama Configuration (Vector Search)

Ollama Service:

  • Host: localhost:11434 (Docker Compose) or linklift-ollama:11434 (Kamal)
  • Model: all-minilm:l6-v2 (384 dimensions)
  • Purpose: Generate embeddings for semantic search

Model Details:

  • The all-minilm:l6-v2 model produces 384-dimensional embeddings
  • This matches the vector index configuration in the database schema
  • Model is automatically pulled on first start via ollama-init service

Testing Ollama:

# Check Ollama is running
curl http://localhost:11434/

# Generate a test embedding
curl -X POST http://localhost:11434/api/embeddings \
  -H "Content-Type: application/json" \
  -d '{"model":"all-minilm:l6-v2","prompt":"test"}'

Documentation

Contributing

We welcome contributions! Please follow these steps:

  1. Fork the repository
  2. Create feature branch: git checkout -b feature/amazing-feature
  3. Make changes with tests
  4. Ensure tests pass: mvn test
  5. Commit with clear message: git commit -m "feat: add amazing feature"
  6. Push to fork: git push origin feature/amazing-feature
  7. Create Pull Request

Development Guidelines

  • ✅ Follow hexagonal architecture principles
  • ✅ Write tests for all new features
  • ✅ Use meaningful commit messages (Conventional Commits)
  • ✅ Update documentation as needed
  • ✅ Ensure code passes style checks

Stopping the Services

# Stop all services
docker-compose down

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support & Community

Getting Help:


Built with ❤️ using modern Java, clean architecture principles, and developer-friendly tools.

LinkLift is designed to be a solid foundation for link management that can evolve with your needs while maintaining clean architecture and high code quality.

About

No description, website, or topics provided.

Resources

Security policy

Stars

1 star

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages

0