====== Javalin - Zadania dla studentów ====== ===== Instrukcje ogólne ===== Poniżej znajduje się zestaw zadań do samodzielnego wykonania. Zadania są podzielone na trzy poziomy trudności: * **Poziom 1 (Łatwy)** - podstawowa wiedza o Javalin * **Poziom 2 (Średni)** - połączenie kilku konceptów * **Poziom 3 (Trudny)** - zaawansowane funkcjonalności Dla każdego zadania: * Przeczytaj opis * Zdefiniuj wymagania * Zaimplementuj rozwiązanie * Przetestuj w Postmanie lub przeglądarce --- ====== Poziom 1 - Zadania łatwe ====== ===== Zadanie 1.1: Calculator API ===== **Opis:** Utwórz API, które przyjmuje dwie liczby i operację (dodawanie, odejmowanie, mnożenie, dzielenie) i zwraca wynik. **Wymagania:** * GET endpoint: ''/calc?a=10&b=5&op=add'' zwraca ''15'' * Obsługiwane operacje: ''add'', ''sub'', ''mul'', ''div'' * Zwróć błąd 400, jeśli operacja jest nieznana * Obsłuż dzielenie przez zero (zwróć błąd) **Podpowiedź:** * Pobierz ''a'', ''b'' i ''op'' z query parameters * Użyj switch do obsługi różnych operacji * Zwróć wynik jako JSON --- ===== Zadanie 1.2: Echo Server ===== **Opis:** Utwórz serwer, który odbiera tekst i go powtarza. **Wymagania:** * POST ''/echo'' przyjmuje JSON: ''{"text": "hello"}'' * Zwraca: ''{"echo": "hello", "length": 5}'' * GET ''/echo/hello'' zwraca: ''{"text": "hello"}'' **Podpowiedź:** * Utwórz Record do deserializacji JSON * Zwróć JSON za pomocą ''ctx.json()'' --- ===== Zadanie 1.3: Time Server ===== **Opis:** Utwórz endpoint, który zwraca aktualny czas i datę. **Wymagania:** * GET ''/time'' zwraca: ''{"time": "14:30:45", "date": "2026-05-25"}'' * GET ''/time/millis'' zwraca: ''{"millis": 1748209845000}'' **Podpowiedź:** * Użyj ''LocalDateTime'' lub ''System.currentTimeMillis()'' * Zwróć JSON --- ===== Zadanie 1.4: Counter API ===== **Opis:** Utwórz API licznika, który można zwiększać i resetować. **Wymagania:** * GET ''/counter'' - zwraca obecną wartość * POST ''/counter/increment'' - zwiększa o 1 * POST ''/counter/decrement'' - zmniejsza o 1 * POST ''/counter/reset'' - zeruje **Podpowiedź:** * Przechowuj licznik jako statyczne pole klasy * Synchronizuj dostęp, jeśli będzie wiele żądań --- ===== Zadanie 1.5: Hello World Widget ===== **Opis:** Utwórz prostą stronę HTML z przyciskiem, który wyśle request do backendu. **Wymagania:** * Serwuj ''index.html'' ze strony głównej * Frontend: przycisk ''Click me'' * Backend: GET ''/api/hello'' zwraca ''{"message": "Hello from backend!"}'' * Frontend: wyświetla odpowiedź w alertu --- ====== Poziom 2 - Zadania średnie ====== ===== Zadanie 2.1: Book Library API ===== **Opis:** Utwórz API dla biblioteki książek z CRUD operacjami. **Wymagania:** * Record ''Book'' z polami: id, title, author, year, available (boolean) * GET ''/api/books'' - lista wszystkich * GET ''/api/books/{id}'' - szczegóły jednej * POST ''/api/books'' - dodaj nową * PUT ''/api/books/{id}'' - aktualizuj * DELETE ''/api/books/{id}'' - usuń * Obsłuż błędy 404, 400 **Wskazówki:** * Przechowuj książki w ''Map'' * Dla każdej operacji ustaw odpowiedni status HTTP * Zwróć JSON --- ===== Zadanie 2.2: User Registration ===== **Opis:** Utwórz system rejestracji użytkowników z walidacją. **Wymagania:** * POST ''/api/register'' z ''{"email": "...", "password": "..."}'' * Walidacja: email musi zawierać ''@'', hasło min 8 znaków * Zwróć błąd 400 jeśli walidacja nie pasa * Zwróć ID użytkownika jeśli sukces (status 201) * Email nie może się powtarzać (status 409) **Wskazówki:** * Przechowuj użytkowników w ''Map'' * Waliduj email prostym regex: ''email.contains("@")'' * Obsługuj exceptions z Map --- ===== Zadanie 2.3: Article Filtering ===== **Opis:** Utwórz API do artykułów z możliwością filtrowania. **Wymagania:** * GET ''/api/articles'' - wszystkie artykuły * GET ''/api/articles?category=tech'' - filtrowanie po kategorii * GET ''/api/articles?author=John'' - filtrowanie po autorze * GET ''/api/articles?limit=5'' - ograniczenie liczby wyników * Kombinowanie: ''/api/articles?category=tech&limit=3'' **Wskazówki:** * Pobierz query parameters * Filtruj listę za pomocą ''stream().filter()'' * Ogranicz wyniki za pomocą ''limit()'' --- ===== Zadanie 2.4: API with Logging ===== **Opis:** Dodaj logging do dowolnego API z wcześniejszych zadań. **Wymagania:** * Loguj każde żądanie: ''[INCOMING] GET /api/books'' * Loguj czas przetwarzania: ''[DONE] 200 OK (12ms)'' * Loguj błędy: ''[ERROR] 404 Not Found'' **Wskazówki:** * Użyj ''config.routes.before()'' i ''config.routes.after()'' * Przechowuj ''startTime'' w ''ctx.attribute()'' * System.out.println lub logger SLF4J --- ===== Zadanie 2.5: Protected API ===== **Opis:** Utwórz API, które wymaga autentykacji tokenem. **Wymagania:** * Publiczny endpoint: GET ''/api/public'' (bez tokenu) * Chroniony endpoint: GET ''/api/secret'' (wymaga tokenu) * Token przesyłany w nagłówku: ''Authorization: Bearer TOKEN123'' * Zwróć 401 bez ważnego tokenu * Zwróć 200 i dane z ważnym tokenem **Wskazówki:** * Używaj ''config.routes.before("/api/secret", ...)'' do walidacji * Pobierz nagłówek: ''ctx.header("Authorization")'' * Sprawdź format ''Bearer ...'' --- ====== Poziom 3 - Zadania trudne ====== ===== Zadanie 3.1: Database Integration (SQLite) ===== **Opis:** Zintegruj Javalin z bazą SQLite do trwałego przechowywania danych. **Wymagania:** * Dodaj zależność SQLite do Maven * Utwórz tabelę ''notes'' (id, title, content, created_at) * GET ''/api/notes'' - pobierz z bazy * POST ''/api/notes'' - zapisz w bazie * PUT ''/api/notes/{id}'' - aktualizuj w bazie * DELETE ''/api/notes/{id}'' - usuń z bazy **Wskazówki:** * Użyj JDBC lub biblioteki jak jOOQ/Hibernate * Obsłuż ''SQLException'' * Zamykaj połączenia (try-with-resources) --- ===== Zadanie 3.2: Pagination ===== **Opis:** Zaimplementuj paginację dla API zwracającego dużą liczbę wyników. **Wymagania:** * GET ''/api/products?page=1&size=10'' - pierwsza strona, 10 wyników * Zwróć: ''{"data": [...], "page": 1, "size": 10, "total": 47}'' * Jeśli page jest poza zakresem, zwróć 400 * Default: page=1, size=10 **Wskazówki:** * Oblicz offset: ''(page - 1) * size'' * Używaj ''stream().skip().limit()'' * Waliduj parametry --- ===== Zadanie 3.3: Multi-Language Support ===== **Opis:** Utwórz API, które zwraca wiadomości w różnych językach. **Wymagania:** * GET ''/api/message?lang=en'' zwraca: ''{"text": "Hello"}'' * GET ''/api/message?lang=pl'' zwraca: ''{"text": "Cześć"}'' * GET ''/api/message?lang=fr'' zwraca: ''{"text": "Bonjour"}'' * Domyślny: angielski * Nieznany język: zwróć 400 **Wskazówki:** * Przechowuj wiadomości w ''Map>'' * Lub plik properties dla każdego języka * Przechowaj: ''lang'' -> ''key'' -> ''value'' --- ===== Zadanie 3.4: Rate Limiting ===== **Opis:** Zaimplementuj rate limiting - ograniczenie liczby żądań na IP. **Wymagania:** * Max 10 żądań na minutę z jednego IP * Nagłówek ''X-RateLimit-Limit: 10'' * Nagłówek ''X-RateLimit-Remaining: 7'' * Po przekroczeniu: zwróć 429 Too Many Requests **Wskazówki:** * Pobierz IP: ''ctx.ip()'' * Przechowuj licznik i timestamp w ''Map'' * Czy minuta minęła? Zresetuj licznik * Załaduj w ''before()'' --- ===== Zadanie 3.5: WebSocket Chat ===== **Opis:** Utwórz prosty chat z WebSocket (opcjonalne - zaawansowane). **Wymagania:** * Serwer Javalin obsługuje WebSocket * Frontend: strona HTML z polem do wpisywania * Wiadomości wysyłane w real-time do wszystkich połączonych klientów * Przechowuj historię ostatnich 10 wiadomości **Wskazówki:** * ''app.ws()'' do obsługi WebSocket * Przechowuj sesje w ''Set'' * Broadcast: pętla po wszystkich sesjach --- ====== Dodatkowe wyzwania ====== ===== Zadanie Bonus 1: Full Stack Todo App ===== Utwórz kompletną aplikację TODO z: * Frontend: HTML/CSS/JavaScript * Backend API: CRUD operacje * Baza danych: SQLite * Autoryzacja: prostokrotny token * Walidacja: po stronie frontend i backend * Błędy: elegancka obsługa * Logging: pełne logowanie operacji --- ===== Zadanie Bonus 2: RESTful API dla E-Shopu ===== Utwórz API dla sklepu internetowego: * Produkty: GET, POST, PUT, DELETE, search, filtrowanie * Koszyk: dodaj, usuń, wyczyść, podsumowanie * Zamówienia: CREATE, status, historia * Użytkownicy: rejestracja, login (token) * Walidacja, obsługa błędów, logging --- ===== Zadanie Bonus 3: Microservice Architecture ===== Utwórz dwa mikroserwisy komunikujące się ze sobą: * **Serwis 1 (UserService):** zarządzanie użytkownikami * **Serwis 2 (OrderService):** zarządzanie zamówieniami * OrderService wysyła żądania do UserService * Obsłuż timeout i błędy komunikacji * Zaloguj wszystkie komunikaty między serwisami --- ====== Wskazówki do rozwiązywania zadań ====== **Ogólne:** 1. Przeczytaj zadanie do końca 2. Zidentyfikuj wymagane endpoints 3. Zaplanuj strukturę (Records, kontrolery, etc.) 4. Zacznij od prostych przypadków, potem rozszerz 5. Testuj każdy endpoint w Postmanie **Obsługa błędów:** * Zawsze obsłuż wyjątki * Zwróć JSON z opisem błędu: ''{"error": "..."}'' * Ustaw odpowiedni status HTTP **Testowanie:** * cURL: ''curl -X GET http://localhost:8080/api/...'' * Postman: wygodny GUI * IntelliJ HTTP Client: wbudowany w IDE **Debugowanie:** * Dodaj ''System.out.println()'' do logowania * Użyj debuggera (F5 w IntelliJ) * Sprawdź Network tab w DevTools przeglądarki --- ====== Rozwiązania ====== Rozwiązania do wszystkich zadań będą dostępne po zajęciach. Do każdego rozwiązania dołączony będzie opis: * Jakie koncepty Javalin zostały użyte * Jakie problemy mogą się pojawić * Jak można ulepszyć kod * Alternatywne podejścia --- **Powodzenia! 🚀**