Skip to content

Commit dc85e41

Browse files
feat(QTDI-1291): extend error payload
1 parent 555bb6f commit dc85e41

6 files changed

Lines changed: 128 additions & 669 deletions

File tree

component-server-parent/component-server-model/src/main/java/org/talend/sdk/component/server/front/model/error/ErrorPayload.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,11 @@ public class ErrorPayload {
2828

2929
private ErrorDictionary code;
3030

31+
private String subCode;
32+
3133
private String description;
34+
35+
public ErrorPayload(final ErrorDictionary code, final String description) {
36+
this(code, null, description);
37+
}
3238
}

component-server-parent/component-server/src/main/java/org/talend/sdk/component/server/front/ActionResourceImpl.java

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
import javax.ws.rs.core.Response;
4343

4444
import org.talend.sdk.component.api.exception.ComponentException;
45+
import org.talend.sdk.component.api.exception.ComponentException.ErrorOrigin;
46+
import org.talend.sdk.component.api.exception.DiscoverSchemaException;
4547
import org.talend.sdk.component.runtime.manager.ComponentManager;
4648
import org.talend.sdk.component.runtime.manager.ContainerComponentRegistry;
4749
import org.talend.sdk.component.runtime.manager.ServiceMeta;
@@ -212,32 +214,42 @@ private CompletableFuture<Response> doExecuteLocalAction(final String family, fi
212214

213215
private Response onError(final Throwable re) {
214216
log.warn(re.getMessage(), re);
215-
if (re.getCause() instanceof WebApplicationException) {
216-
return ((WebApplicationException) re.getCause()).getResponse();
217+
if (re.getCause() instanceof WebApplicationException webException) {
218+
return webException.getResponse();
217219
}
218220

219-
if (re instanceof ComponentException) {
220-
final ComponentException ce = (ComponentException) re;
221+
final String description = "Action execution failed with: " + ofNullable(re.getMessage())
222+
.orElseGet(() -> re instanceof NullPointerException
223+
? "unexpected null"
224+
: "no error message");
225+
if (re instanceof final DiscoverSchemaException eSchema) {
226+
// we send reason to recognize the error on client side
227+
final String subCode = eSchema.getPossibleHandleErrorWith().toString();
221228
throw new WebApplicationException(Response
222-
.status(ce.getErrorOrigin() == ComponentException.ErrorOrigin.USER ? 400
223-
: ce.getErrorOrigin() == ComponentException.ErrorOrigin.BACKEND ? 456 : 520,
224-
"Unexpected callback error")
225-
.entity(new ErrorPayload(ErrorDictionary.ACTION_ERROR,
226-
"Action execution failed with: " + ofNullable(re.getMessage())
227-
.orElseGet(() -> re instanceof NullPointerException ? "unexpected null"
228-
: "no error message")))
229+
.status(400, subCode)
230+
.entity(new ErrorPayload(ErrorDictionary.ACTION_ERROR, subCode, description))
231+
.build());
232+
} else if (re instanceof final ComponentException eComponent) {
233+
throw new WebApplicationException(Response
234+
.status(evaluateStatusCodeForException(eComponent), "Unexpected callback error")
235+
.entity(new ErrorPayload(ErrorDictionary.ACTION_ERROR, description))
229236
.build());
230237
}
231238

232239
throw new WebApplicationException(Response
233240
.status(520, "Unexpected callback error")
234-
.entity(new ErrorPayload(ErrorDictionary.ACTION_ERROR,
235-
"Action execution failed with: " + ofNullable(re.getMessage())
236-
.orElseGet(() -> re instanceof NullPointerException ? "unexpected null"
237-
: "no error message")))
241+
.entity(new ErrorPayload(ErrorDictionary.ACTION_ERROR, description))
238242
.build());
239243
}
240244

245+
private static int evaluateStatusCodeForException(final ComponentException eComponent) {
246+
return switch (eComponent.getErrorOrigin()) {
247+
case USER -> 400;
248+
case BACKEND -> 456;
249+
default -> 520;
250+
};
251+
}
252+
241253
private Stream<ActionItem> findVirtualActions(final Predicate<String> typeMatcher,
242254
final Predicate<String> componentMatcher, final Locale locale) {
243255
return virtualActions

component-server-parent/component-server/src/main/java/org/talend/sdk/component/server/service/PropertiesService.java

Lines changed: 76 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.Collection;
2525
import java.util.Comparator;
2626
import java.util.HashMap;
27+
import java.util.LinkedHashMap;
2728
import java.util.List;
2829
import java.util.Locale;
2930
import java.util.Map;
@@ -70,57 +71,81 @@ public Stream<SimplePropertyDefinition> buildProperties(final List<ParameterMeta
7071

7172
private Stream<SimplePropertyDefinition> buildProperties(final List<ParameterMeta> meta, final ClassLoader loader,
7273
final Locale locale, final DefaultValueInspector.Instance rootInstance, final ParameterMeta parent) {
73-
return meta.stream().flatMap(p -> {
74-
final String path = sanitizePropertyName(p.getPath());
75-
final String name = sanitizePropertyName(p.getName());
76-
final String type = p.getType().name();
77-
final boolean isEnum = p.getType() == ParameterMeta.Type.ENUM;
78-
PropertyValidation validation = propertyValidationService.map(p.getMetadata());
79-
if (isEnum) {
80-
if (validation == null) {
81-
validation = new PropertyValidation();
82-
}
83-
validation.setEnumValues(p.getProposals());
84-
}
85-
final Map<String, String> sanitizedMetadata = ofNullable(p.getMetadata())
86-
.map(m -> m
87-
.entrySet()
88-
.stream()
89-
.filter(e -> !e.getKey().startsWith(ValidationParameterEnricher.META_PREFIX))
90-
.collect(toLinkedMap(e -> e.getKey().replace("tcomp::", ""), Map.Entry::getValue)))
91-
.orElse(null);
92-
final Map<String, String> metadata;
93-
if (parent != null) {
94-
metadata = sanitizedMetadata;
95-
} else {
96-
metadata = ofNullable(sanitizedMetadata).orElseGet(HashMap::new);
97-
metadata.put("definition::parameter::index", String.valueOf(meta.indexOf(p)));
98-
if (p.getJavaType() instanceof Class clazzType && Schema.class.isAssignableFrom(clazzType)) {
99-
metadata.put("definition::parameter::schema", "");
100-
}
101-
}
102-
final DefaultValueInspector.Instance instance = defaultValueInspector
103-
.createDemoInstance(
104-
ofNullable(rootInstance).map(DefaultValueInspector.Instance::getValue).orElse(null), p);
105-
final ParameterBundle bundle = p.findBundle(loader, locale);
106-
final ParameterBundle parentBundle = parent == null ? null : parent.findBundle(loader, locale);
107-
return Stream
108-
.concat(Stream
109-
.of(new SimplePropertyDefinition(path, name,
110-
bundle.displayName(parentBundle).orElse(p.getName()), type, toDefault(instance, p),
111-
validation, rewriteMetadataForLocale(metadata, parentBundle, bundle),
112-
bundle.placeholder(parentBundle).orElse(p.getName()),
113-
!isEnum ? null
114-
: p
115-
.getProposals()
116-
.stream()
117-
.collect(toLinkedMap(identity(),
118-
key -> bundle
119-
.enumDisplayName(parentBundle, key)
120-
.orElse(key))))),
121-
buildProperties(p.getNestedParameters(), loader, locale, instance, p));
122-
}).sorted(Comparator.comparing(SimplePropertyDefinition::getPath)); // important cause it is the way you want to
123-
// see it
74+
return meta.stream()
75+
.flatMap(p -> buildProperty(p, meta, loader, locale, rootInstance, parent))
76+
// important cause it is the way you want to see it
77+
.sorted(Comparator.comparing(SimplePropertyDefinition::getPath));
78+
}
79+
80+
private Stream<SimplePropertyDefinition> buildProperty(final ParameterMeta p,
81+
final List<ParameterMeta> siblings,
82+
final ClassLoader loader,
83+
final Locale locale,
84+
final DefaultValueInspector.Instance rootInstance,
85+
final ParameterMeta parent) {
86+
final String path = sanitizePropertyName(p.getPath());
87+
final String name = sanitizePropertyName(p.getName());
88+
final String type = p.getType().name();
89+
final PropertyValidation validation = buildValidation(p);
90+
final Map<String, String> metadata = buildMetadata(p, siblings, parent);
91+
final DefaultValueInspector.Instance instance = defaultValueInspector
92+
.createDemoInstance(ofNullable(rootInstance)
93+
.map(DefaultValueInspector.Instance::getValue)
94+
.orElse(null), p);
95+
final ParameterBundle bundle = p.findBundle(loader, locale);
96+
final ParameterBundle parentBundle = parent == null ? null : parent.findBundle(loader, locale);
97+
final String displayName = bundle.displayName(parentBundle).orElse(p.getName());
98+
final String placeholder = bundle.placeholder(parentBundle).orElse(p.getName());
99+
final LinkedHashMap<String, String> enumValues = buildEnumDisplayNames(p, bundle, parentBundle);
100+
final SimplePropertyDefinition def = new SimplePropertyDefinition(path, name, displayName, type,
101+
toDefault(instance, p), validation, rewriteMetadataForLocale(metadata, parentBundle, bundle),
102+
placeholder, enumValues);
103+
return Stream.concat(
104+
Stream.of(def),
105+
buildProperties(p.getNestedParameters(), loader, locale, instance, p));
106+
}
107+
108+
private PropertyValidation buildValidation(final ParameterMeta p) {
109+
PropertyValidation validation = propertyValidationService.map(p.getMetadata());
110+
if (p.getType() != ParameterMeta.Type.ENUM) {
111+
return validation;
112+
}
113+
if (validation == null) {
114+
validation = new PropertyValidation();
115+
}
116+
validation.setEnumValues(p.getProposals());
117+
return validation;
118+
}
119+
120+
private Map<String, String> buildMetadata(final ParameterMeta p, final List<ParameterMeta> siblings,
121+
final ParameterMeta parent) {
122+
final Map<String, String> sanitized = ofNullable(p.getMetadata())
123+
.map(m -> m
124+
.entrySet()
125+
.stream()
126+
.filter(e -> !e.getKey().startsWith(ValidationParameterEnricher.META_PREFIX))
127+
.collect(toLinkedMap(e -> e.getKey().replace("tcomp::", ""), Map.Entry::getValue)))
128+
.orElse(null);
129+
if (parent != null) {
130+
return sanitized;
131+
}
132+
133+
final Map<String, String> metadata = ofNullable(sanitized).orElseGet(HashMap::new);
134+
metadata.put("definition::parameter::index", String.valueOf(siblings.indexOf(p)));
135+
if (p.getJavaType() instanceof Class<?> clazzType && Schema.class.isAssignableFrom(clazzType)) {
136+
metadata.put("definition::parameter::schema", "");
137+
}
138+
return metadata;
139+
}
140+
141+
private LinkedHashMap<String, String> buildEnumDisplayNames(final ParameterMeta p, final ParameterBundle bundle,
142+
final ParameterBundle parentBundle) {
143+
if (p.getType() != ParameterMeta.Type.ENUM) {
144+
return null;
145+
}
146+
return p.getProposals()
147+
.stream()
148+
.collect(toLinkedMap(identity(), key -> bundle.enumDisplayName(parentBundle, key).orElse(key)));
124149
}
125150

126151
private Map<String, String> rewriteMetadataForLocale(final Map<String, String> metadata,

0 commit comments

Comments
 (0)