diff --git a/component-api/src/main/java/org/talend/sdk/component/api/exception/ComponentException.java b/component-api/src/main/java/org/talend/sdk/component/api/exception/ComponentException.java
index 3cf1bd5b4f6dd..d85358972b845 100644
--- a/component-api/src/main/java/org/talend/sdk/component/api/exception/ComponentException.java
+++ b/component-api/src/main/java/org/talend/sdk/component/api/exception/ComponentException.java
@@ -36,7 +36,8 @@ public static enum ErrorOrigin {
public ComponentException(final ErrorOrigin errorOrigin, final String type, final String message,
final StackTraceElement[] stackTrace, final Throwable cause) {
- super((type != null ? "(" + type + ") " : "") + message, cause);
+ super((type != null ? "(" + type + ") " : "") + message);
+ this.initCause(toGenericThrowable(cause));
this.errorOrigin = errorOrigin;
originalType = type;
originalMessage = message;
@@ -70,4 +71,35 @@ public ComponentException(final Throwable cause) {
this(ErrorOrigin.UNKNOWN, cause.getMessage(), cause);
}
+ /**
+ * Convert all exception stack to generic throwable stack to avoid unknown exception at deserialization time..
+ *
+ * @param t
+ * @return An Throwable.
+ */
+ protected Throwable toGenericThrowable(final Throwable t) {
+ if (t == null) {
+ return null;
+ }
+ if (t instanceof ComponentException) {
+ return t;
+ }
+ Throwable generic = new Throwable(String.format("(%s) : %s", t.getClass().getName(), t.getMessage()));
+ generic.setStackTrace(t.getStackTrace());
+
+ Throwable cause = t.getCause();
+ Throwable genericCause = null;
+ if (cause != null) {
+ genericCause = toGenericThrowable(cause);
+ } else {
+ return generic;
+ }
+
+ if (genericCause != null) {
+ generic = new Throwable(generic.getMessage(), genericCause);
+ }
+
+ return generic;
+ }
+
}
diff --git a/component-api/src/test/java/org/talend/sdk/component/api/exception/ComponentExceptionTest.java b/component-api/src/test/java/org/talend/sdk/component/api/exception/ComponentExceptionTest.java
new file mode 100644
index 0000000000000..b7cfbfc1ad279
--- /dev/null
+++ b/component-api/src/test/java/org/talend/sdk/component/api/exception/ComponentExceptionTest.java
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 2006-2024 Talend Inc. - www.talend.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.talend.sdk.component.api.exception;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class ComponentExceptionTest {
+
+ @Test
+ void testTypedCauseExceptionTransformation() {
+ IndexOutOfBoundsException indexOutOfBoundsException = new IndexOutOfBoundsException("AAA");
+ IllegalArgumentException illegalArgumentException =
+ new IllegalArgumentException("BBB", indexOutOfBoundsException);
+ IllegalStateException illegalStateException = new IllegalStateException("CCC", illegalArgumentException);
+
+ ComponentException componentException = new ComponentException("DDD", illegalStateException);
+
+ Throwable ccc = componentException.getCause();
+ Assertions.assertEquals(Throwable.class, ccc.getClass());
+
+ Throwable bbb = ccc.getCause();
+ Assertions.assertEquals(Throwable.class, bbb.getClass());
+
+ Throwable aaa = bbb.getCause();
+ Assertions.assertEquals(Throwable.class, aaa.getClass());
+ }
+
+ @Test
+ void testConstructor() {
+ ComponentException componentException = new ComponentException("message");
+ Assertions.assertNull(componentException.getCause());
+ }
+
+ @Test
+ void testParameters() {
+ ComponentException componentException = new ComponentException(new IndexOutOfBoundsException("cause"));
+ Assertions.assertNotNull(componentException.getCause());
+ Assertions.assertEquals("java.lang.IndexOutOfBoundsException", componentException.getOriginalType());
+ Assertions.assertEquals(ComponentException.ErrorOrigin.UNKNOWN, componentException.getErrorOrigin());
+
+ componentException = new ComponentException(ComponentException.ErrorOrigin.USER, "message");
+ Assertions.assertEquals(ComponentException.ErrorOrigin.USER, componentException.getErrorOrigin());
+ }
+
+}
\ No newline at end of file
diff --git a/sample-parent/sample-connector/pom.xml b/sample-parent/sample-connector/pom.xml
index 7f7d7b811ffcd..cc0626b840eb6 100644
--- a/sample-parent/sample-connector/pom.xml
+++ b/sample-parent/sample-connector/pom.xml
@@ -55,6 +55,12 @@
${project.version}
provided
+
+ org.talend.sdk.component
+ component-runtime-impl
+ 1.65.0M6-SNAPSHOT
+ compile
+
diff --git a/sample-parent/sample-connector/src/main/java/org/talend/sdk/component/test/connectors/config/InputConfig.java b/sample-parent/sample-connector/src/main/java/org/talend/sdk/component/test/connectors/config/InputConfig.java
index 84542fbd48bdd..d6c69056c5859 100644
--- a/sample-parent/sample-connector/src/main/java/org/talend/sdk/component/test/connectors/config/InputConfig.java
+++ b/sample-parent/sample-connector/src/main/java/org/talend/sdk/component/test/connectors/config/InputConfig.java
@@ -19,13 +19,18 @@
import java.time.ZonedDateTime;
import org.talend.sdk.component.api.configuration.Option;
+import org.talend.sdk.component.api.configuration.ui.DefaultValue;
import org.talend.sdk.component.api.configuration.ui.layout.GridLayout;
import org.talend.sdk.component.api.configuration.ui.widget.DateTime;
import org.talend.sdk.component.api.meta.Documentation;
+import lombok.Data;
+
+@Data
@GridLayout({
@GridLayout.Row({ "date" }),
- @GridLayout.Row({ "dataset" }) })
+ @GridLayout.Row({ "dataset" }),
+ @GridLayout.Row({ "generateException" }) })
@GridLayout(
names = GridLayout.FormType.ADVANCED,
value = {
@@ -43,4 +48,13 @@ public class InputConfig implements Serializable {
@Documentation("Doc: default date documentation without Internationalization.")
private ZonedDateTime date;
+ @Option
+ @Documentation("Doc: Use the generate exception service or not.")
+ @DefaultValue("false")
+ private Boolean generateException = false;
+
+ @Option
+ @Documentation("Doc: Use the generate runtime exception service or not.")
+ @DefaultValue("false")
+ private Boolean generateRuntimeException = false;
}
diff --git a/sample-parent/sample-connector/src/main/java/org/talend/sdk/component/test/connectors/input/TheInput1.java b/sample-parent/sample-connector/src/main/java/org/talend/sdk/component/test/connectors/input/TheInput1.java
index 2cbfacae7cbba..afea1fb3c7242 100644
--- a/sample-parent/sample-connector/src/main/java/org/talend/sdk/component/test/connectors/input/TheInput1.java
+++ b/sample-parent/sample-connector/src/main/java/org/talend/sdk/component/test/connectors/input/TheInput1.java
@@ -26,6 +26,7 @@
import org.talend.sdk.component.api.input.Producer;
import org.talend.sdk.component.api.meta.Documentation;
import org.talend.sdk.component.test.connectors.config.InputConfig;
+import org.talend.sdk.component.test.connectors.service.GenerateExceptionServices;
@Icon(value = Icon.IconType.CUSTOM, custom = "input")
@Documentation("Doc: default TheInput1 documentation without Internationalization.")
@@ -41,12 +42,19 @@ public class TheInput1 implements Serializable {
InputConfig config;
- public TheInput1(final @Option("configin") InputConfig config) {
+ private final GenerateExceptionServices exceptionServices;
+
+ public TheInput1(final @Option("configin") InputConfig config,
+ final GenerateExceptionServices exceptionServices) {
this.config = config;
+ this.exceptionServices = exceptionServices;
}
@PostConstruct
public void init() {
+ if (config.getGenerateException()) {
+ exceptionServices.generateException();
+ }
}
@PreDestroy
@@ -55,7 +63,9 @@ public void release() {
@Producer
public Object next() {
-
+ if (config.getGenerateRuntimeException()) {
+ exceptionServices.generateRuntimeException();
+ }
return LocalDate.now();
}
diff --git a/sample-parent/sample-connector/src/main/java/org/talend/sdk/component/test/connectors/input/TheMapper1.java b/sample-parent/sample-connector/src/main/java/org/talend/sdk/component/test/connectors/input/TheMapper1.java
index 4c07ce0a573da..95ab2560f9de8 100644
--- a/sample-parent/sample-connector/src/main/java/org/talend/sdk/component/test/connectors/input/TheMapper1.java
+++ b/sample-parent/sample-connector/src/main/java/org/talend/sdk/component/test/connectors/input/TheMapper1.java
@@ -30,6 +30,7 @@
import org.talend.sdk.component.api.meta.Documentation;
import org.talend.sdk.component.test.connectors.config.InputConfig;
import org.talend.sdk.component.test.connectors.migration.AbstractMigrationHandler;
+import org.talend.sdk.component.test.connectors.service.GenerateExceptionServices;
@Version(value = InputConfig.INPUT_CONFIG_VERSION,
migrationHandler = AbstractMigrationHandler.InputMigrationHandler.class)
@@ -47,9 +48,12 @@ public class TheMapper1 implements Serializable {
private InputConfig config;
- public TheMapper1(final @Option("configin") InputConfig config) {
+ private final GenerateExceptionServices exceptionServices;
+ public TheMapper1(final @Option("configin") InputConfig config,
+ final GenerateExceptionServices exceptionServices) {
this.config = config;
+ this.exceptionServices = exceptionServices;
}
@Assessor
@@ -66,7 +70,7 @@ public List split(@PartitionSize final int desiredNbSplits) {
@Emitter
public TheInput1 createSource() {
- return new TheInput1(this.config);
+ return new TheInput1(this.config, this.exceptionServices);
}
}
diff --git a/sample-parent/sample-connector/src/main/java/org/talend/sdk/component/test/connectors/service/GenerateExceptionServices.java b/sample-parent/sample-connector/src/main/java/org/talend/sdk/component/test/connectors/service/GenerateExceptionServices.java
new file mode 100644
index 0000000000000..99fe6d646757e
--- /dev/null
+++ b/sample-parent/sample-connector/src/main/java/org/talend/sdk/component/test/connectors/service/GenerateExceptionServices.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright (C) 2006-2024 Talend Inc. - www.talend.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.talend.sdk.component.test.connectors.service;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+
+import org.talend.sdk.component.api.exception.ComponentException;
+import org.talend.sdk.component.api.service.Service;
+import org.talend.sdk.component.runtime.base.lang.exception.InvocationExceptionWrapper;
+
+@Service
+public class GenerateExceptionServices implements Serializable {
+
+ public void generateException() throws ComponentException {
+ IndexOutOfBoundsException indexOutOfBoundsException =
+ new IndexOutOfBoundsException("This is an index out of bound exception");
+ IllegalArgumentException illegalArgumentException =
+ new IllegalArgumentException("This is an illegal argument exception", indexOutOfBoundsException);
+ IllegalStateException illegalStateException =
+ new IllegalStateException("This is an illegal state exception", illegalArgumentException);
+ throw new ComponentException("This is component exception", illegalStateException);
+ }
+
+ public void generateRuntimeException() throws ComponentException {
+ throw InvocationExceptionWrapper
+ .toRuntimeException(new InvocationTargetException(new CustomException("custom for test")));
+ }
+
+ public static class CustomException extends RuntimeException {
+
+ public CustomException(final String message) {
+ super(message, new AnotherException("other"));
+ }
+ }
+
+ public static class AnotherException extends RuntimeException {
+
+ public AnotherException(final String message) {
+ super(message);
+ }
+ }
+}
\ No newline at end of file
diff --git a/sample-parent/sample-connector/src/main/resources/org/talend/sdk/component/test/connectors/config/Messages.properties b/sample-parent/sample-connector/src/main/resources/org/talend/sdk/component/test/connectors/config/Messages.properties
index 51cdeeac32576..e32ded9bb01ba 100644
--- a/sample-parent/sample-connector/src/main/resources/org/talend/sdk/component/test/connectors/config/Messages.properties
+++ b/sample-parent/sample-connector/src/main/resources/org/talend/sdk/component/test/connectors/config/Messages.properties
@@ -58,6 +58,10 @@ InputConfig.dataset._displayName = Name: Dataset
InputConfig.dataset._documentation = Doc: The dataset.
InputConfig.date._displayName = Name: Date
InputConfig.date._documentation = Doc: Retrieve only data after the given date.
+InputConfig.generateException._displayName = Generate Exception
+InputConfig.generateException._documentation = Doc: Use the generate exception service or not.
+InputConfig.generateRuntimeException._displayName = Generate Runtime Exception
+InputConfig.generateRuntimeException.._documentation = Doc: Use the generate runtime exception service or not.
# Output
OutputConfig._documentation = Doc: The output config for the connector.