Thanks to visit codestin.com
Credit goes to github.com

Skip to content

BeyondFootsteps API is a Spring Boot backend service for managing, analyzing, and visualizing global migration, asylum, and resettlement data. It provides REST and GraphQL endpoints for accessing statistics, summaries, and insights about refugee movements and related processes.

License

Notifications You must be signed in to change notification settings

ezepsosa/beyondfootsteps-api

Repository files navigation

Beyond Footsteps — GraphQL API (Server)

Beyond Footsteps

License Java Spring Boot GraphQL Docker PostgreSQL

This Spring Boot GraphQL API powers the Beyond Footsteps project by exposing migration and refugee indicators (derived from UNHCR data) via a strongly-typed schema. It is built using resolvers, services, repositories, DTOs, and mappers and is intended for educational and portfolio purposes only.
Note: This project is not affiliated with UNHCR.


Table of Contents


Overview

  • Purpose: Expose migration and refugee indicators through a GraphQL API.
  • Data Sources: Uses UNHCR-derived data to power various indicators on asylum decisions, requests, resettlement summaries, IDP displacements, refugee returnees, and naturalizations.
  • Design: The API uses a layered architecture that separates concerns among resolvers (GraphQL endpoints), services (business logic), repositories (data access), models (JPA entities), and mappers for DTO mapping.

Tech Stack

  • Programming Language: Java (version 17+)
  • Frameworks/Libraries:
    • Spring Boot
    • Spring Data JPA
    • Spring for GraphQL
    • JUnit 5, Mockito
  • Database: PostgreSQL (production) with H2 for testing
  • Build Tool: Maven
  • Containerization: Docker & Docker Compose

Architecture

flowchart LR
    A([UNHCR Statistics Portal]) --> B{{ETL: ingest • clean • normalize • derive metrics}}
    B --> C[(DB)]
    C --> D([GraphQL API<br/>Typed schema & resolvers])
    D --> E([Client React<br/>Maps • Dashboards • Modals])
Loading

The API layer abstracts data retrieval and aggregation (e.g., grouping by country and year) to support the visualization of migration and refugee trends.


Project Structure

src/
├─ main/
│  ├─ java/com/beyondfootsteps/beyondfootsteps/
│  │  ├─ BeyondfootstepsApplication.java             # Application entry-point
│  │  ├─ configuration/
│  │  │  └─ CorsConfig.java                           # CORS configuration
│  │  ├─ dto/
│  │  │  ├─ internal/                                # Internal DTOs (e.g., for grouped responses)
│  │  │  └─ response/                                # API response DTOs
│  │  ├─ exceptions/
│  │  │  ├─ CustomExceptionHandler.java              # Global exception handler (@ControllerAdvice)
│  │  │  └─ InvalidParamException.java               # Custom exception for invalid parameters
│  │  ├─ mappers/
│  │  │  └─ ResettlementSummaryOriginGroupedMapper.java  # Mapper for entity-to-DTO conversion
│  │  ├─ models/                                     # JPA entity
│  │  │  ├─ AsylumDecision.java
│  │  │  ├─ AsylumRequest.java
│  │  │  ├─ DashboardSummary.java
│  │  │  ├─ IdpDisplacement.java
│  │  │  ├─ IdpReturnees.java
│  │  │  ├─ RefugeeNaturalization.java
│  │  │  └─ ResettlementSummary.java
│  │  ├─ repositories/                               # Spring Data JPA repositories
│  │  │  ├─ AsylumDecisionRepository.java
│  │  │  ├─ AsylumRequestRepository.java
│  │  │  ├─ DashboardSummaryRepository.java
│  │  │  ├─ IdpDisplacementRepository.java
│  │  │  ├─ IdpReturneesRepository.java
│  │  │  ├─ RefugeeNaturalizationRepository.java
│  │  │  └─ ResettlementSummaryRepository.java
│  │  ├─ resolvers/                                  # GraphQL resolvers
│  │  │  ├─ AsylumDecisionResolver.java
│  │  │  ├─ AsylumRequestResolver.java
│  │  │  ├─ DashboardSummaryResolver.java
│  │  │  ├─ IdpDisplacementResolver.java
│  │  │  ├─ IdpReturneesResolver.java
│  │  │  ├─ RefugeeNaturalizationResolver.java
│  │  │  └─ ResettlementSummaryResolver.java
│  │  └─ services/                                  # Business logic (Services)
│  │     ├─ AsylumDecisionService.java
│  │     ├─ AsylumRequestService.java
│  │     ├─ DashboardSummaryService.java
│  │     ├─ IdpDisplacementService.java
│  │     ├─ IdpReturneesService.java
│  │     ├─ RefugeeNaturalizationService.java
│  │     └─ ResettlementSummaryService.java
│  └─ resources/
│     ├─ application.properties                     # General application configuration
│     ├─ graphql/
│     │  └─ schema.graphqls                         # GraphQL schema definition
│     ├─ static/
│     └─ templates/
└─ test/
   ├─ java/com/beyondfootsteps/beyondfootsteps/
   │  ├─ BeyondfootstepsApplicationTests.java         # Spring Boot context test
   │  ├─ mapper/
   │  │  └─ ResettlementSummaryOriginGroupedMapperTest.java
   │  ├─ repository/                                  # Repository tests with H2
   │  │  ├─ AsylumDecisionRepositoryTest.java
   │  │  ├─ AsylumRequestRepositoryTest.java
   │  │  ├─ DashboardSummaryRepositoryTest.java
   │  │  ├─ RefugeeNaturalizationRepositoryTest.java
   │  │  └─ ResettlementSummaryRepositoryTest.java
   │  ├─ resolvers/                                   # GraphQL resolver tests
   │  │  ├─ AsylumDecisionResolverTest.java
   │  │  ├─ AsylumRequestResolverTest.java
   │  │  ├─ DashboardSummaryResolverTest.java
   │  │  ├─ IdpDisplacementResolverTest.java
   │  │  ├─ IdpReturneesResolverTest.java
   │  │  ├─ RefugeeNaturalizationResolverTest.java
   │  │  └─ ResettlementSummaryResolverTest.java
   │  └─ services/                                    # Service layer tests; business logic validation
   │     ├─ AsylumDecisionServiceTest.java
   │     ├─ AsylumRequestServiceTest.java
   │     ├─ DashboardSummaryServiceTest.java
   │     ├─ IdpDisplacementServiceTest.java
   │     ├─ IdpReturneesServiceTest.java
   │     ├─ RefugeeNaturalizationServiceTest.java
   │     └─ ResettlementSummaryServiceTest.java

GraphQL API

  • Endpoint: /graphql (HTTP POST)
  • Schema: Located in src/main/resources/graphql/schema.graphqls
  • GraphiQL: Optionally available if enabled (e.g., at /graphiql)

Sample Query: Asylum Decisions by Year and Country

query GetAsylumDecisionsByYearAndCountry(
  $year: Int!
  $countryOfOriginIso: String
  $countryOfAsylumIso: String
) {
  asylumDecisionsByYearAndCountry(
    year: $year
    countryOfOriginIso: $countryOfOriginIso
    countryOfAsylumIso: $countryOfAsylumIso
  ) {
    id
    year
    countryOfOrigin
    countryOfOriginIso
    countryOfAsylum
    countryOfAsylumIso
    decRecognized
    decOther
    decRejected
    decClosed
    decTotal
    acceptanceRate
    decPc
  }
}

Sample Query: Resettlement Summaries Grouped by Origin

query getResettlementSummariesByYearGroupedBy($year: Int!, $grouping: String!) {
  resettlementSummariesByYearGroupedBy(year: $year, grouping: $grouping) {
    countriesIso
    countriesNames
    totalCases
    totalDepartures
    totalPersons
    totalNeeds
    totalSubmissions
    coverageRate
    resettlementGap
    requestVsNeedsRatio
    submissionsEfficiency
    realizationRate
  }
}

Configuration

Application Properties

  • General Config: Located in src/main/resources/application.properties
  • Test Config: Use src/test/resources/application-test.properties (for example, set spring.jpa.hibernate.ddl-auto=create to auto-generate database schema in H2)

Reserved Column Escaping

If a column name conflicts with reserved keywords (e.g., year), escape it in your entities:

@Column(name = "\"year\"")
private Integer year;

This ensures compatibility with both H2 (for tests) and PostgreSQL.


Build & Run

Using Maven on Windows

  • Run in Development Mode:

    .\mvnw.cmd spring-boot:run
  • Package the Application:

    .\mvnw.cmd package
    java -jar target\beyondfootsteps-<version>.jar

Docker

The project includes a Dockerfile to containerize the application.

Dockerfile Key Points

  • Test Execution:
    It is recommended to remove the -DskipTests parameter so that tests run during the image build.

  • Building with Docker:

    RUN --mount=type=bind,source=pom.xml,target=pom.xml \
        --mount=type=cache,target=/root/.m2 \
        ./mvnw package && \
        mv target/$(./mvnw help:evaluate -Dexpression=project.artifactId -q -DforceStdout)-$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout).jar target/app.jar

Running with Docker Compose

docker compose up --build

Testing

The project includes a comprehensive suite of tests across different layers:

  1. Service Tests: Validate business logic (e.g., AsylumDecisionServiceTest.java, ResettlementSummaryServiceTest.java).
  2. Resolver Tests: Test GraphQL endpoint integration (e.g., RefugeeNaturalizationResolverTest.java, ResettlementSummaryResolverTest.java).
  3. Repository Tests: Use H2 with @DataJpaTest to verify repository queries, including handling of null parameters.
    Example: AsylumDecisionRepositoryTest.java ensures queries correctly return results when filter parameters are null.
  4. Mapper Tests: Ensure entities are correctly mapped to response DTOs (e.g., ResettlementSummaryOriginGroupedMapperTest.java).
  5. Application Context Tests: Check that the Spring Boot context loads without issues (e.g., BeyondfootstepsApplicationTests.java).

Run all tests with:

.\mvnw.cmd test

CORS & Error Handling

  • CORS: Configured via configuration/CorsConfig.java. Adjust allowed origins, methods, and headers as needed.
  • Global Error Handling: Implemented in exceptions/CustomExceptionHandler.java, ensuring smooth error responses for GraphQL and REST endpoints.

Related Repositories


License

MIT License – see the LICENSE file for details.

About

BeyondFootsteps API is a Spring Boot backend service for managing, analyzing, and visualizing global migration, asylum, and resettlement data. It provides REST and GraphQL endpoints for accessing statistics, summaries, and insights about refugee movements and related processes.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published