Sign inSign up

wilfriedpapt89/facturationbe

By wilfriedpapt89

•Updated 11 days ago

Backend API for OBR Facturation System - Spring Boot 3.5 + Java 21

Image
0

7.6K

wilfriedpapt89/facturationbe repository overview

⁠Backend Pagination Implementation - Step by Step Guide

ā šŸ“‹ Overview

This directory contains the complete backend implementation for Option 1: Custom Pagination Response that eliminates the Spring warning about unstable JSON structure.

ā šŸ“ Files Included

  1. InvoiceController.java - Main controller with paginated /findall endpoint
  2. InvoiceService.java - Service layer with pagination methods
  3. InvoiceRepository.java - Repository with Spring Data pagination queries
  4. Invoice.java - Example entity model (adjust to match your schema)

ā šŸš€ Installation Steps

⁠Step 1: Locate Your Backend Project

Your backend is likely in a separate directory. Find it:

# Common locations:
d:\OBR\facturation\facturation\backend
d:\OBR\facturation\facturation\facturationbe
# Or similar
⁠Step 2: Copy Files to Your Backend

Copy the files from this BACKEND_IMPLEMENTATION folder to your backend project:

Your Backend Project Structure:
ā”œā”€ā”€ src/
│   └── main/
│       └── java/
│           └── com/obr/facturation/
│               ā”œā”€ā”€ controller/
│               │   └── InvoiceController.java      ← COPY THIS
│               ā”œā”€ā”€ service/
│               │   └── InvoiceService.java         ← COPY THIS
│               ā”œā”€ā”€ repository/
│               │   └── InvoiceRepository.java      ← COPY THIS
│               └── model/
│                   └── Invoice.java                ← REFERENCE ONLY (adjust your existing model)
⁠Step 3: Adjust Package Names

Open each file and update the package declaration at the top to match your project structure.

Example: If your controller is in com.yourcompany.facturation.controller, change:

package com.obr.facturation.controller;

to:

package com.yourcompany.facturation.controller;
⁠Step 4: Update Imports

Update the import statements to match your project's package structure:

// OLD
import com.obr.facturation.model.Invoice;
import com.obr.facturation.service.InvoiceService;

// NEW (example)
import com.yourcompany.facturation.model.Invoice;
import com.yourcompany.facturation.service.InvoiceService;
⁠Step 5: Review and Adjust InvoiceService.java

The service file contains TODO comments for methods that depend on your specific implementation:

// TODO: Implement based on your InvoiceItem model
public List<?> findInvoiceItems(Long invoiceId) {
    // Add your implementation here
}

Update these methods based on your existing code and database structure.

⁠Step 6: Verify Dependencies

Ensure your pom.xml (Maven) or build.gradle (Gradle) has these dependencies:

Maven (pom.xml):

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Spring Boot Starter Data JPA -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <!-- Lombok (optional, for @Data annotations) -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

Gradle (build.gradle):

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
}
⁠Step 7: Update Your Invoice Entity (If Needed)

If your Invoice.java entity is different, ensure it has these fields for pagination to work properly:

  • id (Long)
  • taxPayerId (Long)
  • userPosition (Integer)
  • Other fields as needed

The entity should extend Serializable and use JPA annotations (@Entity, @Table, @Id, etc.)

For better performance with large datasets, add indexes on frequently queried columns:

SQL:

-- Add indexes for better pagination performance
CREATE INDEX idx_invoice_tax_payer_id ON invoice(tax_payer_id);
CREATE INDEX idx_invoice_user_position ON invoice(user_position);
CREATE INDEX idx_invoice_date ON invoice(invoice_date);
CREATE INDEX idx_invoice_type ON invoice(invoice_type);
CREATE INDEX idx_invoice_payment_type ON invoice(invoice_payment_type);
CREATE INDEX idx_invoice_number ON invoice(invoice_number);

-- Composite index for common filter combination
CREATE INDEX idx_invoice_taxpayer_position ON invoice(tax_payer_id, user_position);
⁠Step 9: Build and Test
  1. Rebuild your backend project:
# Maven
mvn clean install

# Gradle
gradle clean build
  1. Start your backend server:
# Maven
mvn spring-boot:run

# Gradle
gradle bootRun
  1. Test the pagination endpoint:
# Test 1: Get first page (10 items)
curl "http://localhost:8080/api/invoices/findall?page=0&size=10&sort=id,desc"

# Test 2: Get second page
curl "http://localhost:8080/api/invoices/findall?page=1&size=10&sort=id,desc"

# Test 3: With filters
curl "http://localhost:8080/api/invoices/findall?page=0&size=20&taxPayerId=123&userPosition=1&sort=invoiceDate,desc"

# Test 4: Larger page size
curl "http://localhost:8080/api/invoices/findall?page=0&size=50&sort=invoiceNumber,asc"

ā āœ… Expected Response Format

Your API should now return this stable JSON structure:

{
  "content": [
    {
      "id": 1,
      "invoiceNumber": "INV-001",
      "invoiceType": "FN",
      "invoiceDate": "2024-01-15T10:30:00",
      "client": {
        "id": 1,
        "name": "Client Name"
      },
      "total": 5000,
      "invoiceCurrency": "BIF",
      "invoicePaymentType": "CASH",
      ...
    }
    // ... more invoices
  ],
  "currentPage": 0,
  "totalItems": 150,
  "totalPages": 15,
  "pageSize": 10,
  "hasNext": true,
  "hasPrevious": false,
  "isFirst": true,
  "isLast": false
}

ā šŸ” Testing Checklist

  • Backend builds without errors
  • Backend starts successfully
  • /api/invoices/findall returns paginated data
  • Page navigation works (page parameter)
  • Page size changes work (size parameter)
  • Sorting works (sort parameter)
  • Filters work (taxPayerId, userPosition)
  • No Spring warning about unstable JSON structure
  • Frontend displays invoice list correctly
  • Pagination controls work in frontend

ā šŸ› Troubleshooting

⁠Issue 1: "Cannot resolve symbol 'Invoice'"

Solution: Update the import statement to match your project's package structure.

⁠Issue 2: "Method findByTaxPayerId not found"

Solution: Ensure InvoiceRepository extends JpaRepository<Invoice, Long>

⁠Issue 3: "No property 'taxPayerId' found"

Solution: Check that your Invoice entity has a field named taxPayerId or update the repository methods to match your field names.

⁠Issue 4: Still getting Spring warning

Solution: Make sure you're returning the Map<String, Object> response structure, NOT the Page<Invoice> directly.

⁠Issue 5: Frontend shows empty list

Solution:

  1. Check browser console for errors
  2. Verify API returns data: curl http://localhost:8080/api/invoices/findall
  3. Check CORS configuration in controller: @CrossOrigin(origins = "*")
⁠Issue 6: Slow pagination

Solution: Add database indexes (see Step 8)

ā šŸ“Š Performance Tips

  1. Use proper page sizes:

    • Small: 10-20 items for mobile
    • Medium: 20-50 items for desktop
    • Large: 50-100 items for data exports
  2. Add indexes on sorted columns:

    CREATE INDEX idx_invoice_date ON invoice(invoice_date DESC);
    
  3. Avoid JOIN FETCH with pagination:

    • Load related entities in separate queries if needed
    • Or use DTO projections
  4. Use database-level pagination:

    • The current implementation uses database LIMIT/OFFSET
    • This is more efficient than loading all data and slicing in Java
  5. Monitor query performance:

    # application.yml
    spring:
      jpa:
        show-sql: true
        properties:
          hibernate:
            format_sql: true
    

ā šŸ”— API Documentation

⁠Endpoint: GET /api/invoices/findall

Query Parameters:

ParameterTypeRequiredDefaultDescription
pageIntegerNo0Page number (0-indexed)
sizeIntegerNo10Items per page (1-100)
sortString[]Noid,descSort format: "field,direction"
taxPayerIdLongNo-Filter by tax payer ID
userPositionIntegerNo-Filter by user position

Sort Examples:

  • sort=id,desc - Sort by ID descending
  • sort=invoiceDate,asc - Sort by date ascending
  • sort=total,desc - Sort by total descending
  • sort=invoiceNumber,asc - Sort by invoice number ascending

Example Requests:

# Basic pagination
GET /api/invoices/findall?page=0&size=10

# With sorting
GET /api/invoices/findall?page=0&size=20&sort=invoiceDate,desc

# With filters
GET /api/invoices/findall?page=1&size=50&taxPayerId=123&userPosition=2

# Complex query
GET /api/invoices/findall?page=2&size=25&taxPayerId=123&userPosition=1&sort=total,desc

ā šŸ“ž Support

If you encounter issues:

  1. Check the console logs for detailed error messages
  2. Verify database connection
  3. Ensure all dependencies are properly installed
  4. Review the Spring Boot version compatibility
  5. Check that your entity annotations are correct

ā šŸŽ‰ Success Indicators

You'll know it's working when:

āœ… No Spring warning about unstable JSON structure in logs āœ… API returns stable JSON format with content and pagination metadata āœ… Frontend displays paginated invoice list āœ… Page navigation works smoothly āœ… Sorting updates the data correctly āœ… Filters apply without issues āœ… Performance is fast even with many invoices


ā šŸ“ Next Steps After Implementation

  1. āœ… Test thoroughly with various scenarios
  2. āœ… Add integration tests
  3. āœ… Monitor API performance
  4. āœ… Consider adding caching for frequently accessed pages
  5. āœ… Implement search functionality if needed
  6. āœ… Add export functionality (CSV, PDF) if needed

Good luck with your implementation! šŸš€

Tag summary

Content type

Image

Digest

sha256:7ce95da30…

Size

161.8 MB

Last updated

11 days ago

docker pull wilfriedpapt89/facturationbe