From 47176499fe498e29656a5a74f102f7355193e283 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Thu, 2 Apr 2026 23:00:04 +0300 Subject: [PATCH 1/3] Add some null-safety conditions --- .../java/com/epam/reportportal/service/LaunchImpl.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/epam/reportportal/service/LaunchImpl.java b/src/main/java/com/epam/reportportal/service/LaunchImpl.java index f49da1b3..1b2b8c45 100644 --- a/src/main/java/com/epam/reportportal/service/LaunchImpl.java +++ b/src/main/java/com/epam/reportportal/service/LaunchImpl.java @@ -358,14 +358,17 @@ public TemplateConfiguration getTemplateConfiguration() { } private void truncateName(@Nonnull final StartRQ rq, int limit) { - if (rq.getName() == null || rq.getName().isEmpty()) { + String name = rq.getName(); + if (name == null || name.isEmpty()) { return; } - String name = rq.getName(); ListenerParameters params = getParameters(); if (params.isReplaceBinaryCharacters()) { name = cleanBinaryCharacters(name); + if (name == null || name.isEmpty()) { + return; + } rq.setName(name); } @@ -385,6 +388,9 @@ private String truncateDescription(@Nullable String description, int maxLength) String myDescription = description; if (params.isReplaceBinaryCharacters()) { myDescription = cleanBinaryCharacters(myDescription); + if (myDescription == null || myDescription.isEmpty()) { + return description; + } } if (!params.isTruncateFields()) { From 61cfaaf133d0bb3a42cc009a89252cb91c436b89 Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Thu, 2 Apr 2026 23:42:49 +0300 Subject: [PATCH 2/3] Refactoring --- .../epam/reportportal/service/LaunchImpl.java | 49 ++++++------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/epam/reportportal/service/LaunchImpl.java b/src/main/java/com/epam/reportportal/service/LaunchImpl.java index 1b2b8c45..0082d787 100644 --- a/src/main/java/com/epam/reportportal/service/LaunchImpl.java +++ b/src/main/java/com/epam/reportportal/service/LaunchImpl.java @@ -357,62 +357,45 @@ public TemplateConfiguration getTemplateConfiguration() { return templateConfiguration; } - private void truncateName(@Nonnull final StartRQ rq, int limit) { - String name = rq.getName(); - if (name == null || name.isEmpty()) { - return; + @Nullable + private String sanitizeField(@Nullable final String field, int limit) { + if (field == null || field.isEmpty()) { + return field; } ListenerParameters params = getParameters(); + String myField = field; if (params.isReplaceBinaryCharacters()) { - name = cleanBinaryCharacters(name); - if (name == null || name.isEmpty()) { - return; + myField = cleanBinaryCharacters(field); + if (myField == null || myField.isEmpty()) { + return field; } - rq.setName(name); } if (!params.isTruncateFields()) { - return; + return myField; } - rq.setName(truncateString(name, limit, params.getTruncateReplacement())); + return truncateString(myField, limit, params.getTruncateReplacement()); } - @Nullable - private String truncateDescription(@Nullable String description, int maxLength) { - if (description == null || description.isEmpty()) { - return description; - } - - ListenerParameters params = getParameters(); - String myDescription = description; - if (params.isReplaceBinaryCharacters()) { - myDescription = cleanBinaryCharacters(myDescription); - if (myDescription == null || myDescription.isEmpty()) { - return description; - } - } - - if (!params.isTruncateFields()) { - return myDescription; - } - return truncateString(myDescription, maxLength, params.getTruncateReplacement()); + private void truncateName(@Nonnull final StartRQ rq, int limit) { + rq.setName(sanitizeField(rq.getName(), limit)); } private void truncateDescription(@Nonnull StartLaunchRQ rq) { - rq.setDescription(truncateDescription(rq.getDescription(), MAX_LAUNCH_DESCRIPTION_LENGTH)); + rq.setDescription(sanitizeField(rq.getDescription(), MAX_LAUNCH_DESCRIPTION_LENGTH)); } private void truncateDescription(@Nonnull StartTestItemRQ rq) { - rq.setDescription(truncateDescription(rq.getDescription(), MAX_DESCRIPTION_LENGTH)); + rq.setDescription(sanitizeField(rq.getDescription(), MAX_DESCRIPTION_LENGTH)); } private void truncateDescription(@Nonnull FinishExecutionRQ rq) { - rq.setDescription(truncateDescription(rq.getDescription(), MAX_LAUNCH_DESCRIPTION_LENGTH)); + rq.setDescription(sanitizeField(rq.getDescription(), MAX_LAUNCH_DESCRIPTION_LENGTH)); } private void truncateDescription(@Nonnull FinishTestItemRQ rq) { - rq.setDescription(truncateDescription(rq.getDescription(), MAX_DESCRIPTION_LENGTH)); + rq.setDescription(sanitizeField(rq.getDescription(), MAX_DESCRIPTION_LENGTH)); } private void applyNameFormat(@Nonnull StartTestItemRQ rq) { From f175916a6c9d96972862b464899867b9f1a9d0ac Mon Sep 17 00:00:00 2001 From: Vadzim Hushchanskou Date: Wed, 8 Apr 2026 12:12:56 +0300 Subject: [PATCH 3/3] Fixes #319 --- CHANGELOG.md | 2 ++ .../com/epam/reportportal/service/LaunchImpl.java | 12 +++++++++--- .../com/epam/reportportal/service/LaunchTest.java | 11 +++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88c6b4aa..bf713aca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Changelog ## [Unreleased] +### Fixed +- Issue [#319](https://github.com/reportportal/client-java/issues/319): RP client threw exception on Launch finish if the Launch wasn't started, by @HardNorth ## [5.4.12] ### Added diff --git a/src/main/java/com/epam/reportportal/service/LaunchImpl.java b/src/main/java/com/epam/reportportal/service/LaunchImpl.java index 0082d787..0b0056ac 100644 --- a/src/main/java/com/epam/reportportal/service/LaunchImpl.java +++ b/src/main/java/com/epam/reportportal/service/LaunchImpl.java @@ -635,10 +635,16 @@ protected void completeLogEmitter() { if (logEmitter.hasComplete()) { return; } - // To ensure we sent all logs post one message (for the case when there were no logs at all) and wait for it to be sent - // Use blocking get, since we are at the end of the flow and Maybe.map(..) will be stopped by system exit - String launchUUID = getLaunch().blockingGet(); + String launchUUID; + try { + // Use blocking get, since we are at the end of the flow and Maybe.map(..) will be stopped by system exit + launchUUID = getLaunch().blockingGet(); + } catch (Throwable e) { + LOGGER.error("Unable to finish the Launch", e); + return; // Nothing to finish, we are unable to even start the Launch + } int logBatchesSent = loggingSubscriber.getProcessedCount(); + // To ensure we sent all logs post one message (for the case when there were no logs at all) and wait for it to be sent emitLog(StaticStructuresUtils.getLastLogRQ(launchUUID)); logEmitter.onComplete(); Waiter waiter = new Waiter("Wait for last log batch sent").duration(getParameters().getReportingTimeout(), TimeUnit.SECONDS) diff --git a/src/test/java/com/epam/reportportal/service/LaunchTest.java b/src/test/java/com/epam/reportportal/service/LaunchTest.java index deb379fa..6049f829 100644 --- a/src/test/java/com/epam/reportportal/service/LaunchTest.java +++ b/src/test/java/com/epam/reportportal/service/LaunchTest.java @@ -64,6 +64,7 @@ import static com.epam.reportportal.test.TestUtils.*; import static com.epam.reportportal.util.test.CommonUtils.shutdownExecutorService; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.endsWith; @@ -663,6 +664,16 @@ public void launch_should_not_throw_exceptions_or_hang_if_finished_and_started_a verify(rpClient, times(1)).finishTestItem(same(id.blockingGet()), any()); } + @Test + public void launch_should_not_throw_exception_if_launch_start_failed_on_finish() { + when(rpClient.startLaunch(any(StartLaunchRQ.class))).thenReturn(Maybe.error(new IllegalStateException("Unable to start launch"))); + Launch launch = createLaunch(); + launch.start(); + + assertDoesNotThrow(() -> launch.finish(standardLaunchFinishRequest())); + verify(rpClient, never()).log(anyList()); + } + @Test public void test_noop_launch_not_null() { assertThat(Launch.NOOP_LAUNCH, notNullValue());