Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions spring-jasper-example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Includes loading `.jasper` templates, populating them with mock data, and export

## Profiles you can activate

- **client-list-dev** – Used in Docker, in the future, it will use pre-compiled `.jasper` files instead of `.jrxml`. Activates the internal module that generates a simple client report.
- **client-list-dev** – Used in Docker, Activates the internal module that generates a simple client report.
- **client-list-local** – Used locally, activates the internal module that generates a simple client report and use `.jrxml`.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Grammar nit: “uses” (not “use”).

Keep it consistent with the bill-local entry.

-**client-list-local** – Used locally, activates the internal module that generates a simple client report and use `.jrxml`.
+**client-list-local** – Used locally, activates the internal module that generates a simple client report and uses `.jrxml`.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- **client-list-local** – Used locally, activates the internal module that generates a simple client report and use `.jrxml`.
**client-list-local** – Used locally, activates the internal module that generates a simple client report and uses `.jrxml`.
🧰 Tools
🪛 LanguageTool

[grammar] ~23-~23: Make sure you are using the right part of speech
Context: ...at generates a simple client report and use .jrxml. - bill-dev – Used in Dock...

(QB_NEW_EN_OTHER_ERROR_IDS_21)


[grammar] ~23-~23: There might be a mistake here.
Context: ...a simple client report and use .jrxml. - bill-dev – Used in Docker, Activates t...

(QB_NEW_EN)

🤖 Prompt for AI Agents
In spring-jasper-example/README.md around line 23, the description for
"client-list-local" uses incorrect verb agreement ("use"); change it to "uses"
to match grammar and keep the phrasing consistent with the "bill-local"
entry—update the sentence to read that it "activates the internal module that
generates a simple client report and uses `.jrxml`."


- **bill-dev** – Used in Docker, Activates the internal module that generates a simple bill report.
- **bill-local** – Used locally, activates the internal module that generates a simple bill report and use `.jrxml`.
Comment on lines +22 to +25
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Fix casing/grammar in profile descriptions.

Lowercase “activates” and use “uses” for JRXML.

-- **client-list-dev** – Used in Docker, Activates the internal module that generates a simple client report.
+- **client-list-dev** – Used in Docker, activates the internal module that generates a simple client report.
 - **client-list-local** – Used locally, activates the internal module that generates a simple client report and use `.jrxml`.
-- **bill-dev** – Used in Docker, Activates the internal module that generates a simple bill report.
-- **bill-local** – Used locally, activates the internal module that generates a simple bill report and use `.jrxml`.
+- **bill-dev** – Used in Docker, activates the internal module that generates a simple bill report.
+- **bill-local** – Used locally, activates the internal module that generates a simple bill report and uses `.jrxml`.

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 LanguageTool

[grammar] ~22-~22: There might be a mistake here.
Context: ...e that generates a simple client report. - client-list-local – Used locally, acti...

(QB_NEW_EN)


[grammar] ~23-~23: Make sure you are using the right part of speech
Context: ...at generates a simple client report and use .jrxml. - bill-dev – Used in Dock...

(QB_NEW_EN_OTHER_ERROR_IDS_21)


[grammar] ~23-~23: There might be a mistake here.
Context: ...a simple client report and use .jrxml. - bill-dev – Used in Docker, Activates t...

(QB_NEW_EN)


[grammar] ~24-~24: There might be a mistake here.
Context: ...ule that generates a simple bill report. - bill-local – Used locally, activates t...

(QB_NEW_EN)


[grammar] ~25-~25: Make sure you are using the right part of speech
Context: ...that generates a simple bill report and use .jrxml.

(QB_NEW_EN_OTHER_ERROR_IDS_21)


[grammar] ~25-~25: There might be a mistake here.
Context: ...s a simple bill report and use .jrxml.

(QB_NEW_EN)

🤖 Prompt for AI Agents
In spring-jasper-example/README.md around lines 22 to 25, fix casing and grammar
in the four profile descriptions: change "Activates" to "activates" and change
"use `.jrxml`" to "uses `.jrxml`" so each line reads e.g. "Used in Docker,
activates the internal module..." or "Used locally, activates the internal
module... and uses `.jrxml`".

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.io.example.base;

import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.util.JRLoader;
import org.springframework.core.io.ClassPathResource;

import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;

Comment on lines +8 to +11
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Replace unused HashMap import; prefer Collections.

We’ll switch to Collections.emptyMap() below; update imports accordingly.

 import java.io.InputStream;
 import java.util.Collection;
-import java.util.HashMap;
+import java.util.Collections;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.io.InputStream;
import java.util.Collection;
import java.util.Collections;
🤖 Prompt for AI Agents
In spring-jasper-example/src/main/java/com/io/example/base/JasperReader.java
around lines 8 to 11, remove the unused import of java.util.HashMap and replace
it with java.util.Collections so you can call Collections.emptyMap() below;
update the import list by deleting HashMap and adding Collections (or import
java.util.* if project style allows) and then change any usage of new
HashMap<>() to Collections.emptyMap() where appropriate.

public class JasperReader {

Comment on lines +12 to +13
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Make utility class non-instantiable.

Mark class final and add a private constructor.

-public class JasperReader {
+public final class JasperReader {
+
+    private JasperReader() {}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public class JasperReader {
public final class JasperReader {
private JasperReader() {}
🤖 Prompt for AI Agents
In spring-jasper-example/src/main/java/com/io/example/base/JasperReader.java
around lines 12 to 13, the utility class is currently instantiable; make it
non-instantiable by marking the class as final and adding a private no-args
constructor to prevent instantiation and subclassing, keeping existing static
utility methods intact.

public static byte[] exportReportJrxmlToPdf(Collection<?> beanCollection, String path){
try {
InputStream stream = new ClassPathResource(path).getInputStream();
JasperReport jasperReport = JasperCompileManager.compileReport(stream);
JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(beanCollection);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, new HashMap<>(), dataSource);
return JasperExportManager.exportReportToPdf(jasperPrint);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Comment on lines +14 to +24
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Close JRXML InputStream; avoid resource leak and improve robustness.

Use try-with-resources, guard null data, and avoid allocating a new HashMap on the hot path.

-    public static byte[] exportReportJrxmlToPdf(Collection<?> beanCollection, String path){
-        try {
-            InputStream stream = new ClassPathResource(path).getInputStream();
-            JasperReport jasperReport = JasperCompileManager.compileReport(stream);
-            JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(beanCollection);
-            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, new HashMap<>(), dataSource);
-            return JasperExportManager.exportReportToPdf(jasperPrint);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
+    public static byte[] exportReportJrxmlToPdf(Collection<?> beanCollection, String path){
+        try (InputStream stream = new ClassPathResource(path).getInputStream()) {
+            JasperReport jasperReport = JasperCompileManager.compileReport(stream);
+            Collection<?> data = (beanCollection == null) ? java.util.Collections.emptyList() : beanCollection;
+            JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(data);
+            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, java.util.Collections.emptyMap(), dataSource);
+            return JasperExportManager.exportReportToPdf(jasperPrint);
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to export JRXML report to PDF: " + path, e);
+        }
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public static byte[] exportReportJrxmlToPdf(Collection<?> beanCollection, String path){
try {
InputStream stream = new ClassPathResource(path).getInputStream();
JasperReport jasperReport = JasperCompileManager.compileReport(stream);
JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(beanCollection);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, new HashMap<>(), dataSource);
return JasperExportManager.exportReportToPdf(jasperPrint);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static byte[] exportReportJrxmlToPdf(Collection<?> beanCollection, String path) {
try (InputStream stream = new ClassPathResource(path).getInputStream()) {
JasperReport jasperReport = JasperCompileManager.compileReport(stream);
Collection<?> data = (beanCollection == null)
? java.util.Collections.emptyList()
: beanCollection;
JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(data);
JasperPrint jasperPrint = JasperFillManager.fillReport(
jasperReport,
java.util.Collections.emptyMap(),
dataSource
);
return JasperExportManager.exportReportToPdf(jasperPrint);
} catch (Exception e) {
throw new RuntimeException(
"Failed to export JRXML report to PDF: " + path,
e
);
}
}
🤖 Prompt for AI Agents
In spring-jasper-example/src/main/java/com/io/example/base/JasperReader.java
around lines 14 to 24, replace the current try/catch with a try-with-resources
that opens the ClassPathResource InputStream so it is always closed, ensure the
JRBeanCollectionDataSource is constructed with a non-null collection (e.g., use
Optional.ofNullable(beanCollection).orElse(Collections.emptyList())) to guard
null data, and avoid allocating a new HashMap on the hot path by using
Collections.emptyMap() for report parameters; keep the same exception behavior
but ensure resources are closed and nulls handled.


public static byte[] exportReportJasperToPdf(Collection<?> beanCollection, String path){
try (InputStream stream = new ClassPathResource(path).getInputStream()) {
JasperReport jasperReport = (JasperReport) JRLoader.loadObject(stream);
JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(beanCollection);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, new HashMap<>(), dataSource);
return JasperExportManager.exportReportToPdf(jasperPrint);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Comment on lines +14 to +35
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Optional: de-duplicate fill/export logic.

Consider a private helper that accepts a JasperReport and collection, returning the PDF; both public methods would prepare the JasperReport and delegate.

🤖 Prompt for AI Agents
In spring-jasper-example/src/main/java/com/io/example/base/JasperReader.java
around lines 14 to 35, the fill-and-export-to-PDF logic is duplicated between
exportReportJrxmlToPdf and exportReportJasperToPdf; extract a private helper
method that accepts a JasperReport and Collection<?> (or JRDataSource) and
returns byte[] PDF, then have each public method prepare/compile/load the
JasperReport, build the JRBeanCollectionDataSource, and delegate to that helper;
ensure the helper handles JasperFillManager.fillReport and
JasperExportManager.exportReportToPdf and propagates exceptions consistently.

Comment on lines +26 to +35
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Harmonize map allocation and null-safety with the .jasper path.

Use emptyMap(), add null guard, and include context in the exception message.

     public static byte[] exportReportJasperToPdf(Collection<?> beanCollection, String path){
         try (InputStream stream = new ClassPathResource(path).getInputStream()) {
             JasperReport jasperReport = (JasperReport) JRLoader.loadObject(stream);
-            JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(beanCollection);
-            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, new HashMap<>(), dataSource);
+            Collection<?> data = (beanCollection == null) ? java.util.Collections.emptyList() : beanCollection;
+            JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(data);
+            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, java.util.Collections.emptyMap(), dataSource);
             return JasperExportManager.exportReportToPdf(jasperPrint);
         } catch (Exception e) {
-            throw new RuntimeException(e);
+            throw new RuntimeException("Failed to export compiled Jasper report to PDF: " + path, e);
         }
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public static byte[] exportReportJasperToPdf(Collection<?> beanCollection, String path){
try (InputStream stream = new ClassPathResource(path).getInputStream()) {
JasperReport jasperReport = (JasperReport) JRLoader.loadObject(stream);
JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(beanCollection);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, new HashMap<>(), dataSource);
return JasperExportManager.exportReportToPdf(jasperPrint);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static byte[] exportReportJasperToPdf(Collection<?> beanCollection, String path){
try (InputStream stream = new ClassPathResource(path).getInputStream()) {
JasperReport jasperReport = (JasperReport) JRLoader.loadObject(stream);
Collection<?> data = (beanCollection == null) ? java.util.Collections.emptyList() : beanCollection;
JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(data);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, java.util.Collections.emptyMap(), dataSource);
return JasperExportManager.exportReportToPdf(jasperPrint);
} catch (Exception e) {
throw new RuntimeException("Failed to export compiled Jasper report to PDF: " + path, e);
}
}
🤖 Prompt for AI Agents
In spring-jasper-example/src/main/java/com/io/example/base/JasperReader.java
around lines 26 to 35, the report export currently uses new HashMap<>() and
doesn't guard against a null/empty path nor include context in thrown
exceptions; change the parameter/path null-safety by validating (e.g.,
Objects.requireNonNull or an explicit null/empty check) before loading the
ClassPathResource, use Collections.emptyMap() instead of new HashMap<>() when
passing parameters to fillReport, and when catching exceptions rethrow a
RuntimeException that includes contextual information (the path and cause) so
the original error is preserved and easier to debug.


}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.io.example.clientList.controller;

import com.io.example.clientList.service.ReportService;
import com.io.example.clientList.service.ClientsReportService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpHeaders;
Expand All @@ -12,13 +12,13 @@
@RestController
@Profile({"client-list-dev", "client-list-local"})
@RequiredArgsConstructor
public class ReportController {
public class ClientsController {

private final ReportService reportService;
private final ClientsReportService clientsReportService;

@GetMapping("/reports/clients")
public ResponseEntity<byte[]> getClientsReport() {
byte[] pdf = this.reportService.generateClientReport();
byte[] pdf = this.clientsReportService.generateClientsPdf();
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=clients.pdf")
.contentType(MediaType.APPLICATION_PDF)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.io.example.clientList.service;

import com.io.example.clientList.dto.ClientDto;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
import java.util.*;

import static com.io.example.base.JasperReader.exportReportJasperToPdf;

@Service
@Profile({"client-list-dev"})
public class ClientsReportDevServiceImpl implements ClientsReportService {

private static final List<ClientDto> clients = Arrays.asList(
new ClientDto(1, "Alice", "Brazil"),
new ClientDto(2, "Bob", "USA"),
new ClientDto(3, "Carlos", "Spain")
);

@Override
public byte[] generateClientsPdf() {
return exportReportJasperToPdf(clients, "reports/client-list-template.jasper");
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.io.example.clientList.service;

import com.io.example.clientList.dto.ClientDto;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
import java.util.*;

import static com.io.example.base.JasperReader.exportReportJrxmlToPdf;

@Service
@Profile({"client-list-local"})
public class ClientsReportLocalServiceImpl implements ClientsReportService {

private static final List<ClientDto> clients = Arrays.asList(
new ClientDto(1, "Alice", "Brazil"),
new ClientDto(2, "Bob", "USA"),
new ClientDto(3, "Carlos", "Spain")
);
Comment on lines +14 to +18
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Minor cleanup: use List.of and extract template path constant.

Keeps the class immutable and avoids magic strings.

Apply:

-    private static final List<ClientDto> clients = Arrays.asList(
+    private static final List<ClientDto> clients = List.of(
             new ClientDto(1, "Alice", "Brazil"),
             new ClientDto(2, "Bob", "USA"),
             new ClientDto(3, "Carlos", "Spain")
     );
+    private static final String TEMPLATE = "reports/client-list-template.jrxml";
@@
-        return exportReportJrxmlToPdf(clients, "reports/client-list-template.jrxml");
+        return exportReportJrxmlToPdf(clients, TEMPLATE);

Also applies to: 22-22

🤖 Prompt for AI Agents
In
spring-jasper-example/src/main/java/com/io/example/clientList/service/ClientsReportLocalServiceImpl.java
around lines 14-18 and 22, replace the mutable Arrays.asList(...) with an
immutable List.of(...) for the static clients list, and extract any hard-coded
template path at line 22 into a private static final String TEMPLATE_PATH
constant at the top of the class; then reference TEMPLATE_PATH where the magic
string was used. Ensure the clients list remains static and final and the new
TEMPLATE_PATH constant is used consistently.


@Override
public byte[] generateClientsPdf() {
return exportReportJrxmlToPdf(clients, "reports/client-list-template.jrxml");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.io.example.clientList.service;

public interface ClientsReportService {
byte[] generateClientsPdf();
}
Comment on lines +3 to +5
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Consider neutral method naming for reuse.

Renaming to generatePdf() (or aligning with BillReportService) makes the interface reusable and reduces coupling to “clients”.

-public interface ClientsReportService {
-    byte[] generateClientsPdf();
+public interface ClientsReportService {
+    byte[] generatePdf();
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public interface ClientsReportService {
byte[] generateClientsPdf();
}
public interface ClientsReportService {
byte[] generatePdf();
}
🤖 Prompt for AI Agents
In
spring-jasper-example/src/main/java/com/io/example/clientList/service/ClientsReportService.java
around lines 3-5 the method name generateClientsPdf() is overly specific; rename
it to generatePdf() to make the interface reusable and align with
BillReportService. Update the interface method signature to byte[]
generatePdf(); then refactor all implementing classes, unit tests and any call
sites to use generatePdf(), adjust imports and method references, and run the
build/tests to ensure no breakage.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.io.example.dataUsageBill.controller;

import com.io.example.clientList.service.ClientsReportService;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Remove unused import.

-import com.io.example.clientList.service.ClientsReportService;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import com.io.example.clientList.service.ClientsReportService;
🤖 Prompt for AI Agents
In
spring-jasper-example/src/main/java/com/io/example/dataUsageBill/controller/BillController.java
around line 3, there is an unused import statement for
com.io.example.clientList.service.ClientsReportService; remove this import line
and then organize/import-optimize the file (or run mvn/IDE quick-fix) to ensure
no unused imports remain and the file compiles cleanly.

import com.io.example.dataUsageBill.service.BillReportService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Profile({"bill-dev", "bill-local"})
@RequiredArgsConstructor
public class BillController {

private final BillReportService billReportService;

@GetMapping("/reports/bill")
public ResponseEntity<byte[]> getBillData() {
Comment on lines +20 to +21
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Declare produced media type on the mapping.

Improves explicitness and content negotiation.

-    @GetMapping("/reports/bill")
+    @GetMapping(value = "/reports/bill", produces = MediaType.APPLICATION_PDF_VALUE)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@GetMapping("/reports/bill")
public ResponseEntity<byte[]> getBillData() {
@GetMapping(value = "/reports/bill", produces = MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> getBillData() {
🤖 Prompt for AI Agents
In
spring-jasper-example/src/main/java/com/io/example/dataUsageBill/controller/BillController.java
around lines 20-21, the @GetMapping for /reports/bill lacks an explicit produced
media type; update the mapping to declare the produced content type (e.g.
application/pdf or the correct MIME type for the returned byte[]), add the
corresponding MediaType import, and ensure the method signature and
ResponseEntity use that media type so Spring can perform proper content
negotiation.

byte[] pdf = this.billReportService.generateBillPdf();
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=bill.pdf")
.contentType(MediaType.APPLICATION_PDF)
.body(pdf);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.io.example.dataUsageBill.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BillDto {
Comment on lines +8 to +12
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Adopt proper types and fix typo: BigDecimal for amounts, LocalDate for dates, totalAmount name.

Prevents rounding errors and clarifies semantics.

+import java.math.BigDecimal;
+import java.time.LocalDate;
@@
-    private String dayStart;
-    private String dayEnd;
+    private LocalDate dayStart;
+    private LocalDate dayEnd;
@@
-    private Integer dtoOMamount;
-    private Integer dtoONamount;
-    private Integer dtoOLamount;
-    private Integer dtoDLamount;
-    private Integer dtoDNamount;
-    private Integer dtoDamount;
+    private BigDecimal dtoOMamount;
+    private BigDecimal dtoONamount;
+    private BigDecimal dtoOLamount;
+    private BigDecimal dtoDLamount;
+    private BigDecimal dtoDNamount;
+    private BigDecimal dtoDamount;
@@
-    private Integer totalHrs;
-    private Integer toltalAm;
+    private Integer totalHrs;
+    private BigDecimal totalAmount;

Note: update builders/usages and the JRXML field types/expressions accordingly.

Also applies to: 27-35

🤖 Prompt for AI Agents
In
spring-jasper-example/src/main/java/com/io/example/dataUsageBill/dto/BillDto.java
around lines 8-12 (and similarly lines 27-35), the DTO uses incorrect/typo-prone
types and a misnamed field: change monetary fields to java.math.BigDecimal,
change date fields to java.time.LocalDate, and rename the mis-typed totalAmount
field to totalAmount (fixing any typo). After changing types and name, update
the Lombok builder/usages, constructors, equals/hashCode if needed, and adjust
any JRXML field definitions and expressions to match BigDecimal and LocalDate
semantics.

private String orgName;
private String depName;
private String devName;
private String groupName;
private String dayStart;
private String dayEnd;

private Integer dtoOM;
private Integer dtoON;
private Integer dtoOL;
private Integer dtoDL;
private Integer dtoDN;
private Integer dtoD;

private Integer dtoOMamount;
private Integer dtoONamount;
private Integer dtoOLamount;
private Integer dtoDLamount;
private Integer dtoDNamount;
private Integer dtoDamount;

private Integer totalHrs;
private Integer toltalAm;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.io.example.dataUsageBill.service;

import com.io.example.dataUsageBill.dto.BillDto;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

import java.util.List;

import static com.io.example.base.JasperReader.exportReportJasperToPdf;

@Service
@Profile({"bill-dev"})
public class BillReportDevServiceImpl implements BillReportService {

@Override
public byte[] generateBillPdf() {
return exportReportJasperToPdf(getBillDto(), "reports/bill-template.jasper");
}

private List<BillDto> getBillDto(){
BillDto bill = BillDto.builder()
.orgName("My Organization")
.depName("IT Department")
.devName("Development Team")
.groupName("Network Group")
.dayStart("2025-08-01")
.dayEnd("2025-08-31")
.dtoOM(10)
.dtoON(5)
.dtoOL(3)
.dtoDL(7)
.dtoDN(2)
.dtoD(1)
.dtoOMamount(100)
.dtoONamount(50)
.dtoOLamount(30)
.dtoDLamount(70)
.dtoDNamount(20)
.dtoDamount(10)
.totalHrs(28)
.toltalAm(280)
.build();
return List.of(bill);
}
Comment on lines +20 to +44
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Typo in field ‘toltalAm’ — rename to ‘totalAmount’ (align DTO/jrxml).
This will otherwise calc/report the right value under a misspelled field, risking silent drift.

Apply here (and update BillDto + templates accordingly):

-                .toltalAm(280)
+                .totalAmount(280)

Also consider:

  • Use BigDecimal for monetary fields instead of int.
  • Prefer LocalDate for dayStart/dayEnd over String.

Verify resources/field consistency:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# Templates present?
fd -a 'bill-template.jasper' spring-jasper-example
fd -a 'bill-template.jrxml' spring-jasper-example
# Field usage consistency (expect either all 'toltalAm' today, or all 'totalAmount' after refactor)
rg -nS 'toltalAm|totalAmount' spring-jasper-example -C2

Length of output: 3670


Fix typo ‘toltalAm’ → ‘totalAmount’ across DTO, builders, and JRXML templates
Update the following to prevent silent data drift:

  • In src/main/java/com/io/example/dataUsageBill/dto/BillDto.java, rename private Integer toltalAm; to private Integer totalAmount;
  • In both BillReportDevServiceImpl.java and BillReportLocalServiceImpl.java, change .toltalAm(…) to .totalAmount(…)
  • In src/main/resources/reports/bill-template.jrxml, replace all field name="toltalAm", variable name="toltalAm1", and <expression>$F{toltalAm}</expression> with their totalAmount equivalents

Consider also using BigDecimal for monetary fields and LocalDate for dayStart/dayEnd.


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.io.example.dataUsageBill.service;

import com.io.example.dataUsageBill.dto.BillDto;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

import java.util.List;

import static com.io.example.base.JasperReader.exportReportJrxmlToPdf;

@Service
@Profile({"bill-local"})
public class BillReportLocalServiceImpl implements BillReportService {

@Override
public byte[] generateBillPdf() {
return exportReportJrxmlToPdf(getBillDto(), "reports/bill-template.jrxml");
}

private List<BillDto> getBillDto(){
BillDto bill = BillDto.builder()
.orgName("My Organization")
.depName("IT Department")
.devName("Development Team")
.groupName("Network Group")
.dayStart("2025-08-01")
.dayEnd("2025-08-31")
.dtoOM(10)
.dtoON(5)
.dtoOL(3)
.dtoDL(7)
.dtoDN(2)
.dtoD(1)
.dtoOMamount(100)
.dtoONamount(50)
.dtoOLamount(30)
.dtoDLamount(70)
.dtoDNamount(20)
.dtoDamount(10)
.totalHrs(28)
.toltalAm(280)
.build();
Comment on lines +20 to +42
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Fix naming and money types: rename toltalAm; use BigDecimal for amounts.

“toltalAm” is a typo and all monetary fields should be BigDecimal to avoid precision issues. Consider LocalDate for dayStart/dayEnd.

Minimal change here (requires coordinated updates to DTO and JRXML):

-                .toltalAm(280)
+                .totalAmount(new java.math.BigDecimal("280.00"))

Follow-up (outside this file): rename field in BillDto and bill-template.jrxml, and change all dto*amount fields to BigDecimal.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
spring-jasper-example/src/main/java/com/io/example/dataUsageBill/service/BillReportLocalServiceImpl.java
around lines 20 to 42, fix the typo and types: rename the field "toltalAm" to
"totalAm" and switch all monetary literal fields (dtoOMamount, dtoONamount,
dtoOLamount, dtoDLamount, dtoDNamount, dtoDamount, totalAm) to use BigDecimal
values (e.g., BigDecimal.valueOf(...)) instead of integers; also consider
changing dayStart/dayEnd from String to LocalDate (use LocalDate.parse or
LocalDate.of) to match DTO expected types. After this change, update the BillDto
class and bill-template.jrxml to rename the field and change the monetary field
types to BigDecimal to keep everything consistent.

return List.of(bill);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.io.example.dataUsageBill.service;

public interface BillReportService {
byte[] generateBillPdf();
}
Loading