Skip to content

[BUG] Backend 500 Error: Contact List API #333

@africanitem

Description

@africanitem

Backend 500 Error: Contact List API

Issue Type: Bug
Priority: High
Component: Backend API
Related Task: #170 (Contact Management Screens Migration)

Description

The GET /rest/contact/getContactList endpoint returns a 500 Internal Server Error with an empty response body. This is blocking Task #170 (Contact Management Screens Migration).

Error Details

Endpoint: GET /rest/contact/getContactList?pageNo=0&pageSize=10&paginationDisable=false
Status Code: 500
Response Body: Empty (no JSON response)
Headers: Standard HTTP headers, no error details in response

Reproduction Steps

  1. Start backend: docker compose -f deploy/docker/docker-compose.yml up -d backend
  2. Wait for backend to start (35 seconds)
  3. Get authentication token:
    TOKEN=$(curl -s -X POST http://localhost:8080/auth/token \
      -H "Content-Type: application/json" \
      -d '{"username":"test@example.com","password":"Test@1234"}' \
      | python3 -c "import sys, json; print(json.load(sys.stdin)['token'])")
  4. Call the endpoint:
    curl -X GET "http://localhost:8080/rest/contact/getContactList?pageNo=0&pageSize=10&paginationDisable=false" \
      -H "Authorization: Bearer $TOKEN"
  5. Expected: JSON response with contact list
    Actual: 500 error with empty response body

Investigation Summary

What Was Tested

  1. Test Endpoint Works: /rest/contact/testContactList (returns empty PaginationResponseModel) - ✅ Works
  2. Product Endpoint Works: /rest/product/getList (similar structure) - ✅ Works
  3. Contact Endpoint Fails: /rest/contact/getContactList - ❌ 500 error

Code Structure

The ContactController.getContactList method follows the same pattern as ProductRestController.getProductList:

  • Both use @LogRequest annotation
  • Both return ResponseEntity<PaginationResponseModel>
  • Both convert entities to models using helper classes
  • Both use the same PaginationResponseModel structure

Attempted Fixes (All Reverted)

  1. ✅ Removed @AllArgsConstructor from ContactListModel (matched ProductListModel)
  2. ✅ Added @JsonIgnore to unused fields (nextDueDate, dueAmount, exchangeRate)
  3. ✅ Ensured totalRecords is set correctly in PaginationResponseModel
  4. ✅ Added null checks and defensive coding
  5. ✅ Simplified code to match ProductRestController exactly
  6. ✅ Tested with minimal ContactListModel (only basic fields)
  7. ✅ Disabled @LogRequest aspect temporarily
  8. ✅ Added extensive logging (no logs appeared in Docker output)

Key Observations

  • Hibernate queries execute: Service layer is called successfully
  • No exceptions in logs: No error messages appear in backend logs
  • Empty response: 500 error with no response body suggests serialization failure
  • Test endpoint works: Empty PaginationResponseModel serializes correctly
  • Product endpoint works: Similar structure works fine

Hypothesis

The error likely occurs during Spring's response serialization after the method returns successfully. Possible causes:

  1. Serialization Issue: ContactListModel or ContactHelper.getModel() creates objects that can't be serialized
  2. Lazy Loading Exception: Hibernate lazy-loaded associations accessed outside transaction
  3. Circular Reference: Jackson serialization encounters circular reference
  4. Type Mismatch: Database field types don't match model field types

Environment

  • Backend: Spring Boot 3.4.1
  • Database: PostgreSQL 14+
  • Java: 21
  • Container: Docker Compose
  • Build: docker compose -f deploy/docker/docker-compose.yml build backend --no-cache

Related Files

  • apps/backend/src/main/java/com/simpleaccounts/rest/contactcontroller/ContactController.java
  • apps/backend/src/main/java/com/simpleaccounts/rest/contactcontroller/ContactHelper.java
  • apps/backend/src/main/java/com/simpleaccounts/rest/contactcontroller/ContactListModel.java
  • apps/backend/src/main/java/com/simpleaccounts/rest/PaginationResponseModel.java
  • apps/backend/src/main/java/com/simpleaccounts/entity/Contact.java

Comparison with Working Endpoint

ProductRestController.getProductList (✅ Works):

@LogRequest
@GetMapping(value = "/getList")
public ResponseEntity<PaginationResponseModel> getProductList(...) {
    // Same structure as ContactController
    // Returns successfully
}

ContactController.getContactList (❌ Fails):

@LogRequest
@GetMapping(value = "/getContactList")
public ResponseEntity<PaginationResponseModel> getContactList(...) {
    // Same structure as ProductRestController
    // Returns 500 error
}

Next Steps

  1. Enable detailed logging in Spring Boot to capture serialization errors
  2. Check database schema for type mismatches
  3. Test with minimal contact (single record with minimal fields)
  4. Compare ContactHelper.getModel() with ProductRestHelper.getListModel()
  5. Check for lazy-loaded associations that might cause LazyInitializationException
  6. Review Jackson configuration for custom serializers/deserializers

Impact

Additional Notes

  • All debugging instrumentation has been removed
  • Code structure matches working ProductRestController
  • No compilation errors
  • Backend builds successfully
  • Issue persists even with minimal data

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions