Skip to content

Commit

Permalink
Introduce netconf.databind.RequestError
Browse files Browse the repository at this point in the history
Promote restconf.server.api.ServerError for reuse by all components that
use netconf.databind.

Change-Id: I631219aff53b24c31acb5ab29844493266feef05
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
  • Loading branch information
rovarga committed Mar 2, 2025
1 parent b040318 commit c6455ce
Show file tree
Hide file tree
Showing 25 changed files with 100 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
import org.opendaylight.mdsal.dom.api.DOMMountPointService;
import org.opendaylight.netconf.databind.DatabindContext;
import org.opendaylight.netconf.databind.ErrorMessage;
import org.opendaylight.netconf.databind.RequestError;
import org.opendaylight.restconf.api.ApiPath;
import org.opendaylight.restconf.mdsal.spi.data.MdsalRestconfStrategy;
import org.opendaylight.restconf.server.api.ResourceBody;
import org.opendaylight.restconf.server.api.ServerError;
import org.opendaylight.restconf.server.api.ServerException;
import org.opendaylight.restconf.server.mdsal.MdsalMountPointResolver;
import org.opendaylight.restconf.server.mdsal.MdsalServerStrategy;
Expand Down Expand Up @@ -106,7 +106,7 @@ NotSupportedServerActionOperations.INSTANCE, new MdsalRestconfStrategy(IID_DATAB
}
}

static final ServerError assertError(final Executable executable) {
static final RequestError assertError(final Executable executable) {
final var ex = assertThrows(ServerException.class, executable);
final var errors = ex.errors();
assertEquals(1, errors.size());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import org.opendaylight.netconf.databind.ErrorInfo;
import org.opendaylight.netconf.databind.ErrorMessage;
import org.opendaylight.netconf.databind.ErrorPath;
import org.opendaylight.restconf.server.api.ServerError;
import org.opendaylight.netconf.databind.RequestError;
import org.opendaylight.restconf.server.api.YangErrorsBody;
import org.opendaylight.restconf.server.api.testlib.AbstractJukeboxTest;
import org.opendaylight.yangtools.yang.common.ErrorTag;
Expand All @@ -34,11 +34,11 @@ class YangErrorsBodyTest extends AbstractJukeboxTest {
@Test
void sampleComplexError() {
final var body = new YangErrorsBody(List.of(
new ServerError(ErrorType.APPLICATION, ErrorTag.BAD_ATTRIBUTE, new ErrorMessage("message 1"), "app tag #1",
new RequestError(ErrorType.APPLICATION, ErrorTag.BAD_ATTRIBUTE, new ErrorMessage("message 1"), "app tag #1",
null, null),
new ServerError(ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, new ErrorMessage("message 2"),
new RequestError(ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, new ErrorMessage("message 2"),
"app tag #2", null, new ErrorInfo("my info")),
new ServerError(ErrorType.RPC, ErrorTag.DATA_MISSING, new ErrorMessage("message 3"), " app tag #3",
new RequestError(ErrorType.RPC, ErrorTag.DATA_MISSING, new ErrorMessage("message 3"), " app tag #3",
new ErrorPath(DATABIND, YangInstanceIdentifier.builder()
.node(QName.create(MONITORING_MODULE_INFO, "patch-cont"))
.node(QName.create(MONITORING_MODULE_INFO, "my-list1"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
import org.opendaylight.mdsal.dom.api.DOMActionException;
import org.opendaylight.mdsal.dom.api.DOMRpcResult;
import org.opendaylight.netconf.databind.DatabindPath.OperationPath;
import org.opendaylight.netconf.databind.RequestError;
import org.opendaylight.restconf.server.api.InvokeResult;
import org.opendaylight.restconf.server.api.ServerError;
import org.opendaylight.restconf.server.api.ServerException;
import org.opendaylight.restconf.server.api.ServerRequest;
import org.opendaylight.restconf.server.spi.InterceptingServerRpcOperations;
Expand Down Expand Up @@ -51,7 +51,7 @@ public void onSuccess(final DOMRpcResult result) {
}
return true;
})
.map(ServerError::ofRpcError)
.map(RequestError::ofRpcError)
.collect(Collectors.toList());
if (errors.isEmpty()) {
request.completeWith(InterceptingServerRpcOperations.invokeResultOf(path, result.value()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
import org.opendaylight.mdsal.dom.api.DOMRpcResult;
import org.opendaylight.mdsal.dom.api.DOMRpcService;
import org.opendaylight.netconf.databind.DatabindPath.Rpc;
import org.opendaylight.netconf.databind.RequestError;
import org.opendaylight.restconf.server.api.InvokeResult;
import org.opendaylight.restconf.server.api.ServerError;
import org.opendaylight.restconf.server.api.ServerException;
import org.opendaylight.restconf.server.api.ServerRequest;
import org.opendaylight.restconf.server.spi.InterceptingServerRpcOperations;
Expand Down Expand Up @@ -54,7 +54,7 @@ public void onSuccess(final DOMRpcResult result) {
} else {
LOG.debug("RPC invocation reported {}", result.errors());
request.completeWith(new ServerException(result.errors().stream()
.map(ServerError::ofRpcError)
.map(RequestError::ofRpcError)
.collect(Collectors.toList()), null, "Opereation implementation reported errors"));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import org.opendaylight.mdsal.common.api.ReadFailedException;
import org.opendaylight.mdsal.dom.api.DOMDataTreeReadOperations;
import org.opendaylight.netconf.databind.DatabindContext;
import org.opendaylight.restconf.server.api.ServerError;
import org.opendaylight.netconf.databind.RequestError;
import org.opendaylight.restconf.server.api.ServerException;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
Expand Down Expand Up @@ -108,7 +108,7 @@ public void onFailure(final Throwable throwable) {
// are okay -- they differ only in what we report. We rely on SettableFuture's synchronization faculties to
// reconcile any conflict with onSuccess() failure path.
future.completeExceptionally(new ServerException(cause.getErrorList().stream()
.map(ServerError::ofRpcError)
.map(RequestError::ofRpcError)
.collect(Collectors.toList()), cause, "Could not determine the existence of path %s", parentPath));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.opendaylight.netconf.databind.DatabindContext;
import org.opendaylight.netconf.databind.DatabindPath.Data;
import org.opendaylight.netconf.databind.ErrorPath;
import org.opendaylight.netconf.databind.RequestError;
import org.opendaylight.restconf.api.ApiPath;
import org.opendaylight.restconf.api.query.ContentParam;
import org.opendaylight.restconf.api.query.WithDefaultsParam;
Expand All @@ -50,7 +51,6 @@
import org.opendaylight.restconf.server.api.PatchContext;
import org.opendaylight.restconf.server.api.PatchStatusContext;
import org.opendaylight.restconf.server.api.PatchStatusEntity;
import org.opendaylight.restconf.server.api.ServerError;
import org.opendaylight.restconf.server.api.ServerException;
import org.opendaylight.restconf.server.api.ServerRequest;
import org.opendaylight.restconf.server.spi.AbstractServerDataOperations;
Expand Down Expand Up @@ -499,7 +499,7 @@ public final void patchData(final ServerRequest<DataYangPatchResult> request, fi
break;
default:
editCollection.add(new PatchStatusEntity(editId, false, List.of(
new ServerError(ErrorType.PROTOCOL, ErrorTag.OPERATION_NOT_SUPPORTED,
new RequestError(ErrorType.PROTOCOL, ErrorTag.OPERATION_NOT_SUPPORTED,
"Not supported Yang Patch operation"))));
noError = false;
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,21 @@
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.restconf.server.api;
package org.opendaylight.netconf.databind;

import static java.util.Objects.requireNonNull;

import com.google.common.base.MoreObjects;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.netconf.databind.DatabindContext;
import org.opendaylight.netconf.databind.ErrorInfo;
import org.opendaylight.netconf.databind.ErrorMessage;
import org.opendaylight.netconf.databind.ErrorPath;
import org.opendaylight.yangtools.yang.common.ErrorTag;
import org.opendaylight.yangtools.yang.common.ErrorType;
import org.opendaylight.yangtools.yang.common.RpcError;

/**
* Encapsulates a single {@code error} within the
* <a href="https://www.rfc-editor.org/rfc/rfc8040#section-3.9">"errors" YANG Data Template</a> as bound to a particular
* {@link DatabindContext}.
* A basic request error, as defined in both
* <a href="https://www.rfc-editor.org/rfc/rfc6241#section-4.3">RFC6241 rpc-error element</a> and a single {@code error}
* within the <a href="https://www.rfc-editor.org/rfc/rfc8040#section-3.9">RFC8040 "errors" YANG Data Template</a>.
*
* @param type value of {@code error-type} leaf
* @param tag value of {@code error-tag} leaf
Expand All @@ -33,27 +29,27 @@
* @param info optional content of {@code error-info} anydata
*/
@NonNullByDefault
public record ServerError(
public record RequestError(
ErrorType type,
ErrorTag tag,
@Nullable ErrorMessage message,
@Nullable String appTag,
@Nullable ErrorPath path,
@Nullable ErrorInfo info) {
public ServerError {
public RequestError {
requireNonNull(type);
requireNonNull(tag);
}

public ServerError(final ErrorType type, final ErrorTag tag, final String message) {
public RequestError(final ErrorType type, final ErrorTag tag, final String message) {
this(type, tag, new ErrorMessage(message), null, null, null);
}

public static ServerError ofRpcError(final RpcError rpcError) {
public static RequestError ofRpcError(final RpcError rpcError) {
final var tag = rpcError.getTag();
final var errorTag = tag != null ? tag : ErrorTag.OPERATION_FAILED;
final var errorMessage = rpcError.getMessage();
return new ServerError(rpcError.getErrorType(), errorTag,
return new RequestError(rpcError.getErrorType(), errorTag,
errorMessage != null ? new ErrorMessage(errorMessage) : null, rpcError.getApplicationTag(), null,
extractErrorInfo(rpcError));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.netconf.databind.RequestError;

/**
* Holder of patch status context.
Expand All @@ -20,7 +21,7 @@ public record PatchStatusContext(
@NonNull String patchId,
@NonNull List<PatchStatusEntity> editCollection,
boolean ok,
@Nullable List<ServerError> globalErrors) {
@Nullable List<RequestError> globalErrors) {

public PatchStatusContext {
requireNonNull(patchId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@
import static java.util.Objects.requireNonNull;

import java.util.List;
import org.opendaylight.netconf.databind.RequestError;

public class PatchStatusEntity {
private final String editId;
private final List<ServerError> editErrors;
private final List<RequestError> editErrors;
private final boolean ok;

public PatchStatusEntity(final String editId, final boolean ok, final List<ServerError> editErrors) {
public PatchStatusEntity(final String editId, final boolean ok, final List<RequestError> editErrors) {
this.editId = requireNonNull(editId);
this.ok = ok;
this.editErrors = editErrors;
Expand All @@ -30,7 +31,7 @@ public boolean isOk() {
return ok;
}

public List<ServerError> getEditErrors() {
public List<RequestError> getEditErrors() {
return editErrors;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.opendaylight.netconf.databind.DatabindPath;
import org.opendaylight.netconf.databind.ErrorMessage;
import org.opendaylight.netconf.databind.ErrorPath;
import org.opendaylight.netconf.databind.RequestError;
import org.opendaylight.restconf.api.ConsumableBody;
import org.opendaylight.yangtools.yang.common.ErrorTag;
import org.opendaylight.yangtools.yang.common.ErrorType;
Expand Down Expand Up @@ -59,11 +60,12 @@ private static ServerException newServerParseException(final DatabindPath path,
final ErrorTag tag, final String messagePrefix, final Exception caught) {
final var message = requireNonNull(messagePrefix) + ": " + caught.getMessage();
final var errors = exceptionErrors(path.databind(), caught);
return new ServerException(message, errors != null ? errors : List.of(new ServerError(type, tag, message)),
return new ServerException(message, errors != null ? errors : List.of(new RequestError(type, tag, message)),
caught);
}

private static @Nullable List<ServerError> exceptionErrors(final DatabindContext databind, final Exception caught) {
private static @Nullable List<RequestError> exceptionErrors(final DatabindContext databind,
final Exception caught) {
Throwable cause = caught;
do {
if (cause instanceof YangNetconfErrorAware infoAware) {
Expand All @@ -72,7 +74,7 @@ private static ServerException newServerParseException(final DatabindPath path,
final var message = error.message();
final var path = error.path();

return new ServerError(error.type(), error.tag(),
return new RequestError(error.type(), error.tag(),
message != null ? new ErrorMessage(message) : null, error.appTag(),
path != null ? new ErrorPath(databind, path) : null,
// FIXME: pass down error.info()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@
import org.opendaylight.netconf.databind.ErrorInfo;
import org.opendaylight.netconf.databind.ErrorMessage;
import org.opendaylight.netconf.databind.ErrorPath;
import org.opendaylight.netconf.databind.RequestError;
import org.opendaylight.yangtools.yang.common.ErrorTag;
import org.opendaylight.yangtools.yang.common.ErrorType;

/**
* A server-side processing exception, reporting a single {@link ServerError}. This exception is not serializable on
* A server-side processing exception, reporting a single {@link RequestError}. This exception is not serializable on
* purpose.
*/
@NonNullByDefault
Expand All @@ -34,15 +35,15 @@ public final class ServerException extends Exception {
private static final long serialVersionUID = 0L;

@SuppressWarnings("serial")
private final List<ServerError> errors;
private final List<RequestError> errors;

ServerException(final String message, final List<ServerError> errors, final @Nullable Throwable cause) {
ServerException(final String message, final List<RequestError> errors, final @Nullable Throwable cause) {
super(message, cause);
this.errors = requireNonNull(errors);
verify(!errors.isEmpty());
}

private ServerException(final String message, final ServerError error, final @Nullable Throwable cause) {
private ServerException(final String message, final RequestError error, final @Nullable Throwable cause) {
super(message, cause);
errors = List.of(error);
}
Expand All @@ -68,14 +69,14 @@ public ServerException(final ErrorType type, final ErrorTag tag, final String me
}

public ServerException(final ErrorType type, final ErrorTag tag, final Throwable cause) {
this(cause.toString(), new ServerError(type, tag, new ErrorMessage(cause.getMessage()), null, null, null),
this(cause.toString(), new RequestError(type, tag, new ErrorMessage(cause.getMessage()), null, null, null),
cause);
}

public ServerException(final ErrorType type, final ErrorTag tag, final String message,
final @Nullable Throwable cause) {
this(requireNonNull(message),
new ServerError(type, tag, new ErrorMessage(message), null, null, errorInfoOf(cause)), cause);
new RequestError(type, tag, new ErrorMessage(message), null, null, errorInfoOf(cause)), cause);
}

public ServerException(final ErrorType type, final ErrorTag tag, final String format,
Expand All @@ -90,24 +91,24 @@ public ServerException(final ErrorType type, final ErrorTag tag, final String me

public ServerException(final ErrorType type, final ErrorTag tag, final String message,
final @Nullable ErrorPath path, final @Nullable Throwable cause) {
this(message, new ServerError(type, tag, new ErrorMessage(message), null, path, null), cause);
this(message, new RequestError(type, tag, new ErrorMessage(message), null, path, null), cause);
}

public ServerException(final List<ServerError> errors, final @Nullable Throwable cause, final String message) {
public ServerException(final List<RequestError> errors, final @Nullable Throwable cause, final String message) {
this(message, errors, cause);
}

public ServerException(final List<ServerError> errors, final @Nullable Throwable cause, final String format,
public ServerException(final List<RequestError> errors, final @Nullable Throwable cause, final String format,
final Object... args) {
this(errors, cause, format.formatted(args));
}

/**
* Return the reported {@link ServerError}.
* Return the reported {@link RequestError}.
*
* @return the reported {@link ServerError}
* @return the reported {@link RequestError}
*/
public List<ServerError> errors() {
public List<RequestError> errors() {
return errors;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.util.List;
import javax.xml.stream.XMLStreamException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.opendaylight.netconf.databind.RequestError;
import org.opendaylight.restconf.api.FormattableBody;
import org.opendaylight.restconf.api.query.PrettyPrintParam;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.rev170126.errors.Errors;
Expand All @@ -35,16 +36,16 @@ public final class YangErrorsBody extends FormattableBody {
private static final String ERROR_INFO = "error-info";
private static final String ERROR_PATH = "error-path";

private final List<ServerError> errors;
private final List<RequestError> errors;

public YangErrorsBody(final List<ServerError> errors) {
public YangErrorsBody(final List<RequestError> errors) {
if (errors.isEmpty()) {
throw new IllegalArgumentException("empty errors");
}
this.errors = List.copyOf(errors);
}

public YangErrorsBody(final ServerError error) {
public YangErrorsBody(final RequestError error) {
this(List.of(error));
}

Expand All @@ -53,7 +54,7 @@ public YangErrorsBody(final ServerError error) {
*
* @return reported errors, guaranteed to have at least one element
*/
public List<ServerError> errors() {
public List<RequestError> errors() {
return errors;
}

Expand Down
Loading

0 comments on commit c6455ce

Please sign in to comment.