This commit is contained in:
root
2025-10-05 03:10:38 +05:00
parent 9c37f7b6cf
commit c24e17380a
2 changed files with 86 additions and 5 deletions
+62
View File
@@ -0,0 +1,62 @@
# Исправление NullPointerException в ReportGenerationService
## Проблема
Ошибка: `Cannot invoke "java.time.LocalDateTime.toLocalDate()" because "end" is null`
## Причина
В методах `generate()` и `simpleGenerate()` класса `ReportGenerationService` код пытался вызвать `end.toLocalDate()` без проверки на null, когда поле `endDate` в `ReportGenerateRequest` было null.
## Исправления
### 1. Добавлены значения по умолчанию для дат
```java
// Устанавливаем значения по умолчанию, если даты не указаны
if (start == null) {
start = LocalDateTime.now().minusDays(30); // 30 дней назад
}
if (end == null) {
end = LocalDateTime.now(); // сейчас
}
```
### 2. Исправлены вызовы format() в buildDocx и buildPdf
```java
// Было:
req.getStartDate().format(dt), req.getEndDate().format(dt)
// Стало:
req.getStartDate() != null ? req.getStartDate().format(dt) : "не указано",
req.getEndDate() != null ? req.getEndDate().format(dt) : "не указано"
```
### 3. Упрощено создание имени файла
```java
// Было:
String dateSuffix = end != null ? end.toLocalDate().toString() : "unknown_date";
// Стало:
String dateSuffix = end.toLocalDate().toString(); // end теперь всегда не null
```
## Затронутые методы
- `generate(ReportGenerateRequest req)`
- `simpleGenerate(ReportGenerateRequest req)`
- `buildDocx(ReportGenerateRequest req, List<MarketItem> items, Sections sections)`
- `buildPdf(ReportGenerateRequest req, List<MarketItem> items, Sections sections)`
## Результат
- ✅ Устранена ошибка NullPointerException
- ✅ Добавлена обработка случаев, когда даты не указаны
- ✅ Установлены разумные значения по умолчанию (последние 30 дней)
- ✅ Сохранена обратная совместимость
## Тестирование
После исправлений асинхронная генерация отчётов должна работать корректно даже при отсутствии дат в запросе.
@@ -103,6 +103,14 @@ public class ReportGenerationService {
LocalDateTime start = req.getStartDate();
LocalDateTime end = req.getEndDate();
// Устанавливаем значения по умолчанию, если даты не указаны
if (start == null) {
start = LocalDateTime.now().minusDays(30); // 30 дней назад
}
if (end == null) {
end = LocalDateTime.now(); // сейчас
}
List<MarketItem> items = marketItemRepository
.findByPublishedAtBetween(start, end, org.springframework.data.domain.Pageable.unpaged())
.getContent();
@@ -128,7 +136,7 @@ public class ReportGenerationService {
generated = "(Не удалось сгенерировать текст отчёта по предоставленным данным.)";
}
String filename = "report_simple_" + (end == null ? "date" : end.toLocalDate().toString()) + "-"
String filename = "report_simple_" + end.toLocalDate().toString() + "-"
+ System.currentTimeMillis() + ".txt";
return new ReportBinary(filename, MediaType.TEXT_PLAIN,
generated.getBytes(java.nio.charset.StandardCharsets.UTF_8));
@@ -150,6 +158,14 @@ public class ReportGenerationService {
LocalDateTime start = req.getStartDate();
LocalDateTime end = req.getEndDate();
// Устанавливаем значения по умолчанию, если даты не указаны
if (start == null) {
start = LocalDateTime.now().minusDays(30); // 30 дней назад
}
if (end == null) {
end = LocalDateTime.now(); // сейчас
}
List<MarketItem> items = marketItemRepository
.findByPublishedAtBetween(start, end, org.springframework.data.domain.Pageable.unpaged())
.getContent();
@@ -157,15 +173,16 @@ public class ReportGenerationService {
Sections sections = buildSections(req, items);
ReportBinary rb;
String dateSuffix = end.toLocalDate().toString();
if ("DOCX".equalsIgnoreCase(req.getFormat())) {
byte[] docx = buildDocx(req, items, sections);
String filename = "report_" + end.toLocalDate().toString() + "-" + System.currentTimeMillis() + ".docx";
String filename = "report_" + dateSuffix + "-" + System.currentTimeMillis() + ".docx";
rb = new ReportBinary(filename,
MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
docx);
} else {
byte[] pdf = buildPdf(req, items, sections);
String filename = "report_" + end.toLocalDate().toString() + "-" + System.currentTimeMillis() + ".pdf";
String filename = "report_" + dateSuffix + "-" + System.currentTimeMillis() + ".pdf";
rb = new ReportBinary(filename, MediaType.APPLICATION_PDF, pdf);
}
persistReport(req, rb);
@@ -279,7 +296,8 @@ public class ReportGenerationService {
addParagraph(doc, sections.getIntroduction().isBlank()
? String.format(
"Целью данного отчёта является анализ новостного фона в сфере маркетинга и бизнеса за период с %s по %s. Были проанализированы публикации из ключевых источников для выявления основных трендов.",
req.getStartDate().format(dt), req.getEndDate().format(dt))
req.getStartDate() != null ? req.getStartDate().format(dt) : "не указано",
req.getEndDate() != null ? req.getEndDate().format(dt) : "не указано")
: sections.getIntroduction());
// Main
@@ -362,7 +380,8 @@ public class ReportGenerationService {
pdf.add(new Paragraph(sections.getIntroduction().isBlank()
? String.format(
"Целью данного отчёта является анализ новостного фона в сфере маркетинга и бизнеса за период с %s по %s. Были проанализированы публикации из ключевых источников для выявления основных трендов.",
req.getStartDate().format(dt), req.getEndDate().format(dt))
req.getStartDate() != null ? req.getStartDate().format(dt) : "не указано",
req.getEndDate() != null ? req.getEndDate().format(dt) : "не указано")
: sections.getIntroduction()));
pdf.add(new Paragraph("Основная часть"));