eclipse-basyx / basyx-java-components

java-components
MIT License
25 stars 31 forks source link

AAS Server component not able to run "invoke operation" #104

Closed sagilar closed 2 years ago

sagilar commented 2 years ago

Hi there,

I have been doing some experiments with Eclipse BaSyx using the BaSyx Java Components and I found a problem when trying to invoke an operation of a submodel directly on the AAS Server component. It does work when running it on a BaSyxHTTPServer instance.

I'm using Docker containers with modified property files, but I don't think it makes the difference.

When I request an invoke, I get the following error (which I capture using docker logs aas):

12:34:19.142 [http-nio-4001-exec-5] ERROR org.eclipse.basyx.vab.coder.json.provider.JSONProvider - Unknown Exception in JSONProvider
java.lang.ClassCastException: org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection cannot be cast to org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.Operation
    at org.eclipse.basyx.components.aas.mongodb.MongoDBSubmodelAPI.invokeOperation(MongoDBSubmodelAPI.java:434)
    at org.eclipse.basyx.submodel.restapi.observing.ObservableSubmodelAPI.invokeOperation(ObservableSubmodelAPI.java:101)
    at org.eclipse.basyx.submodel.restapi.SubmodelProvider.invokeSync(SubmodelProvider.java:287)
    at org.eclipse.basyx.submodel.restapi.SubmodelProvider.invokeOperation(SubmodelProvider.java:279)
    at org.eclipse.basyx.aas.restapi.MultiSubmodelProvider.invokeOperation(MultiSubmodelProvider.java:430)
    at org.eclipse.basyx.aas.aggregator.restapi.AASAggregatorProvider.invokeOperation(AASAggregatorProvider.java:215)
    at org.eclipse.basyx.vab.coder.json.provider.JSONProvider.processBaSysInvoke(JSONProvider.java:263)
    at org.eclipse.basyx.vab.protocol.http.server.VABHTTPInterface.handleJSONPostRequest(VABHTTPInterface.java:382)
    at org.eclipse.basyx.vab.protocol.http.server.VABHTTPInterface.doPost(VABHTTPInterface.java:175)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:665)
    at org.eclipse.basyx.vab.protocol.http.server.BasysHTTPServlet.service(BasysHTTPServlet.java:71)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:808)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
12:34:19.144 [http-nio-4001-exec-5] DEBUG org.eclipse.basyx.vab.protocol.http.server.VABHTTPInterface - Exception in HTTP-POST. Response-code: 500
org.eclipse.basyx.vab.exception.provider.ProviderException: java.lang.ClassCastException: org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection cannot be cast to org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.Operation
    at org.eclipse.basyx.vab.coder.json.provider.JSONProvider.sendException(JSONProvider.java:153)
    at org.eclipse.basyx.vab.coder.json.provider.JSONProvider.processBaSysInvoke(JSONProvider.java:272)
    at org.eclipse.basyx.vab.protocol.http.server.VABHTTPInterface.handleJSONPostRequest(VABHTTPInterface.java:382)
    at org.eclipse.basyx.vab.protocol.http.server.VABHTTPInterface.doPost(VABHTTPInterface.java:175)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:665)
    at org.eclipse.basyx.vab.protocol.http.server.BasysHTTPServlet.service(BasysHTTPServlet.java:71)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:798)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:808)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassCastException: org.eclipse.basyx.submodel.metamodel.map.submodelelement.SubmodelElementCollection cannot be cast to org.eclipse.basyx.submodel.metamodel.map.submodelelement.operation.Operation
    at org.eclipse.basyx.components.aas.mongodb.MongoDBSubmodelAPI.invokeOperation(MongoDBSubmodelAPI.java:434)
    at org.eclipse.basyx.submodel.restapi.observing.ObservableSubmodelAPI.invokeOperation(ObservableSubmodelAPI.java:101)
    at org.eclipse.basyx.submodel.restapi.SubmodelProvider.invokeSync(SubmodelProvider.java:287)
    at org.eclipse.basyx.submodel.restapi.SubmodelProvider.invokeOperation(SubmodelProvider.java:279)
    at org.eclipse.basyx.aas.restapi.MultiSubmodelProvider.invokeOperation(MultiSubmodelProvider.java:430)
    at org.eclipse.basyx.aas.aggregator.restapi.AASAggregatorProvider.invokeOperation(AASAggregatorProvider.java:215)
    at org.eclipse.basyx.vab.coder.json.provider.JSONProvider.processBaSysInvoke(JSONProvider.java:263)
    ... 23 common frames omitted

This is very weird because I can run it if I create a BaSyx context with a servlet, where the content should be exactly the same:

BaSyxContext context = new BaSyxContext("/dtframeworkVAB", "", "localhost", 4005);
BaSyxHTTPServer vabServer = new BaSyxHTTPServer(context);
vabServer.start();

So if I use the BaSyxHTTPServer context it works, but it doesn't if the operation runs on the docker AAS server.

The element looks this way when using the docker AAS server: image

I do have the IVABRegistryService for both as follows:

context.addServletMapping("/KUKA/*", kukaServlet);
        IVABRegistryService directory = new VABInMemoryRegistry();
        directory.addMapping("KUKA", "http://localhost:4005/dtframeworkVAB/KUKA");
        IModelProvider directoryProvider = new VABRegistryModelProvider(directory);
        HttpServlet directoryServlet = new VABHTTPInterface<IModelProvider>(directoryProvider);
        context.addServletMapping("/directory/*", directoryServlet);

        IVABRegistryService directoryRegistry = new VABInMemoryRegistry();
        String testRS = "http://" + SERVER + ":" + String.valueOf(AAS_PORT)
                + "/dtframework/shells/urn:dtexamples.AU-AAS.Kuka_AAS";
        directoryRegistry.addMapping("KUKA", testRS);
        IModelProvider directoryRegistryProvider = new VABRegistryModelProvider(directoryRegistry);
        HttpServlet directoryRegistryServlet = new VABHTTPInterface<IModelProvider>(directoryRegistryProvider);
        context.addServletMapping("/directoryRegistry/*", directoryRegistryServlet);

And I can also see both resources in the RegistryService as follows:

image

image

I hope the provided information can guide you to the error.

Thanks in advance!

FrankSchnicke commented 2 years ago

Thanks for reporting this issue.

I guess you're uploading the Submodel with its operation on the AAS Server at runtime, right? The AAS Server Docker Image does not support the upload of operations. Instead, you have to programmatically start the Submodel.

However, if above is correct, the error message looks strange - we will take a look at it.

sagilar commented 2 years ago

Thanks for the reply.

Actually, I uploaded the operation programmatically and it's also called programmatically. Everything has been done using the Java Client SDK.

The procedure was the same for both the Docker AAS Server and also the BaSyxHTTPServer context instance. The latter only runs when I launch the Java app, while the former is always up and persistent with MongoDB for AAS and Registry; this one is the only difference I have identified.

FrankSchnicke commented 2 years ago

When using the off-the-shelf components, operations are not supported right now. Instead, we suggest to use a hybrid setup of hosting the submodel(s) containing the operation on a separate server and using the off-the-shelf component for the rest (cf. https://wiki.eclipse.org/BaSyx_/_Scenarios_/_Cloud_Edge_Deployment)