Skip to content

Commit

Permalink
Ensure UaMethodException is thrown for bad operation-level result
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinherron committed Apr 15, 2021
1 parent 9a2e0c0 commit 28b9dc2
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 3 deletions.
Expand Up @@ -84,7 +84,7 @@ public void browseWithBrowseDirection() throws UaException {

List<? extends UaNode> nodes = addressSpace.browseNodes(objectsFolderNode, browseOptions);

assertEquals(6, nodes.size());
assertEquals(7, nodes.size());
assertTrue(nodes.stream().anyMatch(n -> n.getNodeId().equals(Identifiers.RootFolder)));
assertTrue(nodes.stream().anyMatch(n -> n.getNodeId().equals(Identifiers.Server)));
}
Expand Down
Expand Up @@ -10,6 +10,8 @@

package org.eclipse.milo.opcua.sdk.client.methods;

import java.util.Arrays;

import org.eclipse.milo.opcua.sdk.client.AddressSpace;
import org.eclipse.milo.opcua.sdk.client.nodes.UaObjectNode;
import org.eclipse.milo.opcua.sdk.client.subscriptions.ManagedDataItem;
Expand Down Expand Up @@ -156,4 +158,25 @@ public void callMethodWithNoInputsOrOutputs() throws UaException {
assertEquals(0, outputs.length);
}

@Test
public void throwsUaMethodException() throws UaException {
AddressSpace addressSpace = client.getAddressSpace();

UaObjectNode objectsNode = addressSpace.getObjectNode(Identifiers.ObjectsFolder);

assertThrows(UaMethodException.class, () -> {
try {
objectsNode.callMethod(
new QualifiedName(2, "onlyAcceptsPositiveInputs()"),
new Variant[]{new Variant(-1)}
);
} catch (UaMethodException e) {
System.out.println("result: " + e.getStatusCode());
System.out.println("inputArgumentResults: " + Arrays.toString(e.getInputArgumentResults()));

throw e;
}
});
}

}
Expand Up @@ -16,6 +16,7 @@

import org.eclipse.milo.opcua.sdk.core.AccessLevel;
import org.eclipse.milo.opcua.sdk.core.Reference;
import org.eclipse.milo.opcua.sdk.core.ValueRanks;
import org.eclipse.milo.opcua.sdk.server.Lifecycle;
import org.eclipse.milo.opcua.sdk.server.OpcUaServer;
import org.eclipse.milo.opcua.sdk.server.UaNodeManager;
Expand All @@ -32,6 +33,7 @@
import org.eclipse.milo.opcua.sdk.server.nodes.UaVariableNode;
import org.eclipse.milo.opcua.sdk.server.nodes.factories.NodeFactory;
import org.eclipse.milo.opcua.stack.core.Identifiers;
import org.eclipse.milo.opcua.stack.core.StatusCodes;
import org.eclipse.milo.opcua.stack.core.UaException;
import org.eclipse.milo.opcua.stack.core.types.builtin.ByteString;
import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
Expand Down Expand Up @@ -205,6 +207,55 @@ protected Variant[] invoke(InvocationContext invocationContext, Variant[] inputV

return methodNode;
});

UaMethodNode.build(getNodeContext(), b -> {
b.setNodeId(newNodeId("onlyAcceptsPositiveInputs()"));
b.setBrowseName(newQualifiedName("onlyAcceptsPositiveInputs()"));
b.setDisplayName(LocalizedText.english("onlyAcceptsPositiveInputs()"));

b.addReference(new Reference(
b.getNodeId(),
Identifiers.HasOrderedComponent,
Identifiers.ObjectsFolder.expanded(),
Reference.Direction.INVERSE
));

UaMethodNode methodNode = b.buildAndAdd();

methodNode.setInvocationHandler(new AbstractMethodInvocationHandler(methodNode) {
@Override
public Argument[] getInputArguments() {
return new Argument[]{
new Argument(
"i",
Identifiers.Int32,
ValueRanks.Scalar,
null,
LocalizedText.NULL_VALUE)
};
}

@Override
public Argument[] getOutputArguments() {
return new Argument[0];
}

@Override
protected Variant[] invoke(
InvocationContext invocationContext,
Variant[] inputValues
) throws UaException {

int i = (int) inputValues[0].getValue();
if (i < 0) {
throw new UaException(StatusCodes.Bad_InvalidArgument, "invalid argument: i");
}
return new Variant[0];
}
});

return methodNode;
});
});
}

Expand Down
Expand Up @@ -94,9 +94,10 @@ public Argument[] getOutputArguments() {
*
* @param inputs an array of {@link Variant}s containing the input values.
* @return an array of {@link Variant}s containing the output values.
* @throws UaException if an operation- or service-level error occurs.
* @throws UaException if a service-level error occurs.
* @throws UaMethodException if the operation-level result was not good.
*/
public Variant[] call(Variant[] inputs) throws UaException {
public Variant[] call(Variant[] inputs) throws UaMethodException, UaException {
try {
return callAsync(inputs).get();
} catch (ExecutionException | InterruptedException e) {
Expand Down

0 comments on commit 28b9dc2

Please sign in to comment.