A Spring Boot application that manages GitHub Gists while demonstrating multiple integration styles in one system: REST, GraphQL, SOAP, and gRPC. Built as part of the Interoperability of information systems (IIS) course at Algebra Bernays University.
The same domain (gists, authentication, weather lookup) is exposed through different protocols so clients can compare how each style handles data exchange, contracts, validation, and security.
| Area | Implementation |
|---|---|
| REST | CRUD on /api/gists with application/json and application/xml |
| GraphQL | Queries and mutations at /graphql, GraphiQL at /graphiql |
| SOAP | SearchGists endpoint at /ws, JAXB models from XSD |
| gRPC | WeatherService.GetForecast on port 9090, consumed via REST gateway |
| GitHub API | Optional live integration with api.github.com using a per-user PAT |
| Auth | JWT access tokens + HttpOnly refresh cookies, role-based access |
| Validation | JSON Schema (gist-schema.json) and XSD (gist.xsd) before persistence |
| Web UI | Thymeleaf client at /app/gists exercising all protocols from the browser |
Browser (Thymeleaf + JS)
│
├── REST ──────────────► GistController ──► GistService ──► H2 / GitHub API
├── GraphQL ────────────► GistGraphqlController ──► GistService
├── SOAP search ────────► GistSearchEndpoint ──► XmlFileService
└── Weather (REST) ─────► WeatherRestController ──► gRPC stub ──► WeatherGrpcService
│
▼
DHMZ XML feed (vrijeme.hr)
When app.use-public-api is true and the signed-in user has saved a valid GitHub personal access token (PAT), gist operations call the real GitHub API. Otherwise, data is served from the local H2 database.
- Java 21, Spring Boot 3.3.5
- Spring Web, WebFlux (
WebClient), Data JPA, Security, Validation, GraphQL, Thymeleaf - Spring WS + JAXB (XSD → Java, SOAP endpoints)
- gRPC + Protocol Buffers (
grpc-server-spring-boot-starter) - H2 in-memory database
- JJWT for access/refresh tokens
- Bucket4j for rate limiting
- networknt JSON Schema validator
- JDK 21
- Maven 3.9+
mvn spring-boot:run| Service | URL |
|---|---|
| Web client | http://localhost:8080/app/gists |
| Login page | http://localhost:8080/app/login |
| REST API | http://localhost:8080/api/gists |
| GraphQL | http://localhost:8080/graphql |
| GraphiQL | http://localhost:8080/graphiql |
| SOAP WSDL | http://localhost:8080/ws/gists.wsdl |
| Weather (REST → gRPC) | http://localhost:8080/api/weather/forecast?city=Zagreb |
| gRPC server | localhost:9090 |
| H2 console | http://localhost:8080/h2-console |
| Username | Password | Role | Permissions |
|---|---|---|---|
admin |
admin123 |
FULL_ACCESS |
GET, POST, PUT, DELETE on gists |
reader |
reader123 |
READ_ONLY |
GET only |
- Login —
POST /api/auth/loginwith{ "username", "password" }returns a short-lived access token (JSON) and sets an HttpOnly refresh cookie (SameSite=Strict). - Refresh —
POST /api/auth/refreshrotates the refresh token using the cookie. - Logout —
POST /api/auth/logoutrevokes refresh tokens and clears the cookie. - Protected calls — send
Authorization: Bearer <access_token>on REST and GraphQL requests.
Authenticated users can store a GitHub PAT via PUT /api/auth/github-pat. The token is validated against GitHub (gist scope required) and kept server-side. With app.use-public-api: true, gist CRUD then targets the live GitHub API as that user.
GET /api/gists,GET /api/gists/{id}—READ_ONLYorFULL_ACCESSPOST,PUT,DELETE—FULL_ACCESSonly- Request bodies validated against JSON Schema or XSD depending on
Content-Type
query { gists { id description owner { login } files { filename } } }
mutation {
createGist(input: {
description: "Hello"
isPublic: true
owner: { login: "me" }
files: [{ filename: "demo.txt" }]
}) { id }
}SearchGistsRequest searches gists (local XML files and/or GitHub-backed data). WSDL is published at /ws/gists.wsdl.
Dynamic WSDL preview — POST /api/soap/wsdl/preview generates WSDL from a SOAP envelope or namespace/element names (useful for learning contract-first vs. envelope-driven design).
- gRPC:
WeatherService.GetForecastreads Croatian DHMZ observations fromhttps://vrijeme.hr/hrvatska_n.xml - REST:
GET /api/weather/forecast?city=Zagrebcalls the gRPC service internally
- Stateless JWT authentication with refresh-token rotation
- Role-based authorization (
READ_ONLY/FULL_ACCESS) - Rate limiting on auth and API routes (Bucket4j)
- Content Security Policy headers (relaxed for H2 console only)
- CORS configuration via
app.security.cors-allowed-origins - Optional HSTS (
app.security.hsts-enabled) - Invalid GitHub PAT handling with clear client-facing errors
Key settings in src/main/resources/application.yml:
app:
use-public-api: true # false = local H2 only
jwt:
access-expiry-ms: 900000 # 15 minutes
refresh-expiry-ms: 604800000 # 7 days
security:
rate-limit-auth-per-minute: 15
rate-limit-api-per-minute: 400
server:
port: 8080
grpc:
server:
port: 9090Replace app.jwt.secret with a real Base64-encoded 256-bit key before any production deployment.
Through building this project I practiced:
- Interoperability patterns — exposing the same business logic through REST, GraphQL, SOAP, and gRPC, and understanding when each fits.
- Contract-driven development — XSD and JSON Schema validation, JAXB code generation,
.protodefinitions, and GraphQL schema design. - External API integration — calling GitHub’s REST API with
WebClient, handling PAT validation, timeouts, and error mapping. - Security in depth — JWT access/refresh flow with HttpOnly cookies, RBAC, rate limiting, CSP, and secure cookie attributes.
- Hybrid architectures — REST as a gateway over gRPC; SOAP search over XML with optional GitHub-backed results.
- Spring ecosystem — Spring Security filter chains,
@PreAuthorize, Spring GraphQL, Spring WS endpoints, and JPA persistence. - Real-world XML — parsing DHMZ weather feeds and mapping them into protobuf messages for a typed gRPC API.
- Developer experience — a single Thymeleaf UI to exercise every protocol, plus GraphiQL and WSDL preview for exploration.
src/main/java/hr/projekt/gists/
├── controller/ REST controllers (gists, auth, weather, SOAP WSDL preview)
├── graphql/ GraphQL resolvers and inputs
├── grpc/ gRPC weather service
├── soap/ SOAP endpoint, XML search, dynamic WSDL tools
├── github/ GitHub API client and PAT validation
├── security/ JWT, filters, token service
├── validation/ JSON Schema and XSD validators
├── service/ Gist business logic (local DB ↔ GitHub)
└── web/ Thymeleaf page controllers
src/main/resources/
├── graphql/ gist.graphqls
├── schemas/ gist.xsd, gist-schema.json, gists-service.xsd
├── templates/ login.html, gists.html
└── static/ CSS and JS for the web client