OpenSILEX / opensilexClientToolsPython

1 stars 0 forks source link

Presumed bug in OrganisationsAPI.create_infrastructure_facility #2

Open Dryocopus opened 3 years ago

Dryocopus commented 3 years ago

It looks like there is a bug in API-client for OrganisationsAPI.create_infrasturcture_facility.

1. If I use the API-client and don’t provide an uri, like this:

{'body': {'name': 'Module 5, Compartment 71',
 'organisation': 'os-infra:NPEC',
 'rdf_type': 'vocabulary:Greenhouse',
 'rdf_type_name': 'greenhouse',
 'uri': None}}

I get an error:

(500) Reason: HTTP response headers: HTTPHeaderDict({'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'origin, content-type, accept, authorization', 'Access-Control-Allow-Credentials': 'true', 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS, HEAD', 'Vary': 'accept-encoding,accept-encoding', 'Content-Type': 'application/json', 'Content-Length': '7216', 'Date': 'Mon, 05 Jul 2021 07:57:58 GMT', 'Connection': 'close'}) HTTP response body: { "metadata" : { "pagination" : { "pageSize" : 0, "currentPage" : 0, "totalCount" : 0, "totalPages" : 0 }, "status" : [ ], "datafiles" : [ ] }, "result" : { "title" : "Unexpected internal error - java.lang.NullPointerException", "message" : null, "stack" : [ "org.opensilex.core.organisation.dal.InfrastructureFacilityModel.getUriSegments(InfrastructureFacilityModel.java:57)", "org.opensilex.core.organisation.dal.InfrastructureFacilityModel.getUriSegments(InfrastructureFacilityModel.java:14)", "org.opensilex.sparql.utils.ClassURIGenerator.getInstanceURI(ClassURIGenerator.java:18)", "org.opensilex.sparql.utils.URIGenerator.generateURI(URIGenerator.java:26)", "org.opensilex.sparql.service.SPARQLService.generateUniqueUriIfNullOrValidateCurrent(SPARQLService.java:1006)", "org.opensilex.sparql.service.SPARQLService.prepareInstanceCreation(SPARQLService.java:915)", "org.opensilex.sparql.service.SPARQLService.create(SPARQLService.java:885)", "org.opensilex.sparql.service.SPARQLService.create(SPARQLService.java:857)", "org.opensilex.sparql.service.SPARQLService.create(SPARQLService.java:849)", "org.opensilex.sparql.service.SPARQLService.create(SPARQLService.java:845)", "org.opensilex.core.organisation.dal.InfrastructureDAO.createFacility(InfrastructureDAO.java:222)", "org.opensilex.core.organisation.api.facitity.FacilityAPI.createInfrastructureFacility(FacilityAPI.java:78)" ], "fullstack" : [ "org.opensilex.core.organisation.dal.InfrastructureFacilityModel.getUriSegments(InfrastructureFacilityModel.java:57)", "org.opensilex.core.organisation.dal.InfrastructureFacilityModel.getUriSegments(InfrastructureFacilityModel.java:14)", "org.opensilex.sparql.utils.ClassURIGenerator.getInstanceURI(ClassURIGenerator.java:18)", "org.opensilex.sparql.utils.URIGenerator.generateURI(URIGenerator.java:26)", "org.opensilex.sparql.service.SPARQLService.generateUniqueUriIfNullOrValidateCurrent(SPARQLService.java:1006)", "org.opensilex.sparql.service.SPARQLService.prepareInstanceCreation(SPARQLService.java:915)", "org.opensilex.sparql.service.SPARQLService.create(SPARQLService.java:885)", "org.opensilex.sparql.service.SPARQLService.create(SPARQLService.java:857)", "org.opensilex.sparql.service.SPARQLService.create(SPARQLService.java:849)", "org.opensilex.sparql.service.SPARQLService.create(SPARQLService.java:845)", "org.opensilex.core.organisation.dal.InfrastructureDAO.createFacility(InfrastructureDAO.java:222)", "org.opensilex.core.organisation.api.facitity.FacilityAPI.createInfrastructureFacility(FacilityAPI.java:78)", "jdk.internal.reflect.GeneratedMethodAccessor771.invoke(Unknown Source)", "java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)", "java.base/java.lang.reflect.Method.invoke(Method.java:566)", "org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:52)", "org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:124)", "org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:167)", "org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:176)", "org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:79)", "org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:469)", "org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:391)", "org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:80)", "org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:255)", "org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)", "org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)", "org.glassfish.jersey.internal.Errors.process(Errors.java:292)", "org.glassfish.jersey.internal.Errors.process(Errors.java:274)", "org.glassfish.jersey.internal.Errors.process(Errors.java:244)", "org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265)", "org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:234)", "org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:680)", "org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:394)", "org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346)", "org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:366)", "org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:319)", "org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205)", "org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)", "org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)", "org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)", "org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)", "org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)", "org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)", "org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)", "org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)", "org.apache.catalina.valves.StuckThreadDetectionValve.invoke(StuckThreadDetectionValve.java:206)", "org.apache.catalina.valves.rewrite.RewriteValve.invoke(RewriteValve.java:295)", "org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)", "org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)", "org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)", "org.apache.catalina.valves.rewrite.RewriteValve.invoke(RewriteValve.java:552)", "org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)", "org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)", "org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)", "org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)", "org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)", "org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)", "org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)", "org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)", "org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)", "java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)", "java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)", "org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)", "java.base/java.lang.Thread.run(Thread.java:829)" ] } }

2. If I use the API and fill with an empty string, like this:

{'body': {'name': 'Module 5, Compartment 91',
 'organisation': 'os-infra:NPEC',
 'rdf_type': 'vocabulary:Greenhouse',
 'rdf_type_name': 'greenhouse',
 'uri': ''}}

I get the same error.

CONCLUSION: It seems not possible to work with autogenerated uris via the API

3. If I use the API and add a manually generated uri

{'body': 
{'name': 'Module 5, Compartment 71',
 'organisation': 'os-infra:NPEC',
 'rdf_type': 'vocabulary:Greenhouse',
 'rdf_type_name': 'greenhouse',
 'uri': 'os-infra:npec.facilities.npec-greenhouse-compartment-71'
}
}

Result is this: {'result': ['os-infra:npec.facilities.npec-greenhouse-compartment-71'], 'metadata': {'pagination': {'pageSize': 0, 'currentPage': 0, 'totalCount': 0, 'totalPages': 0}, 'status': [], 'datafiles': ['os-infra:npec.facilities.npec-greenhouse-compartment-71']}}

So it looks like the entity is added to PHIS correclty. Also, it appears in RDF4j: image

However, it is not visible in the PHIS web-application.

image

Reason seems to be that it is not associated with the NPEC organisation. The facilities that are shown have been added via the online interface. These have an additional association with os-infra:npec in RDF4J

image

CONCLUSION: The API doesn’t seem to load the association with the organisation, while it does via the online web interface

Isabelle-inrae commented 3 years ago

Hello Peter, if you want to create an entity (organisation, project, experiment, etc.) without providing an URI, just leave the line out.

So the correct file to send will be this one:

{'body': {'name': 'Module 5, Compartment 71', 'organisation': 'os-infra:NPEC', 'rdf_type': 'vocabulary:Greenhouse', 'rdf_type_name': 'greenhouse', } }

We take note of this feedback, as we should state this more clearly in the swagger documentation or at least in the error feedback. Isabelle

Dryocopus commented 3 years ago

Sorry, I wasn't clear. I tried all kinds of things, including leaving the uri out. What I missed that is it is still in the example above. I now tried it again with this model in my JSON:

{
"name": "Module 5, Compartment 91",
 "organisation": "os-infra:NPEC",
 "rdf_type": "vocabulary:Greenhouse",
 "rdf_type_name": "greenhouse"

 }

Interesting thing is that just before the call it looks like this:

 {'body': {'name': 'Module 5, Compartment 91',
 'organisation': 'os-infra:NPEC',
 'rdf_type': 'vocabulary:Greenhouse',
 'rdf_type_name': 'greenhouse',
 'relations': None,
 'uri': None}}

What happens is that the constructor of the InfrastructureFacilityCreationDTO adds the uri.

Look at my code below (which is part of a bigger process, but this is reduced to the core:

for infrastructure_facility_creation_dto_as_dict in infrastructure_facility_creation_dto_list_as_dict:
       print("OrganisationsBatchLoader.read_infrastructure_facility_creation_dto_list_from_json_file() Before: ", infrastructure_facility_creation_dto_as_dict)
       infrastructure_facility_creation_dto =  opensilexClientToolsPython.InfrastructureFacilityCreationDTO(**infrastructure_facility_creation_dto_as_dict)
       print("OrganisationsBatchLoader.read_infrastructure_facility_creation_dto_list_from_json_file() After: ", infrastructure_facility_creation_dto)

Output:

OrganisationsBatchLoader.read_infrastructure_facility_creation_dto_list_from_json_file() Before:  
{'name': 'Module 5, Compartment 91',
'organisation': 'os-infra:NPEC', 
'rdf_type': 'vocabulary:Greenhouse', 
'rdf_type_name': 'greenhouse'}

OrganisationsBatchLoader.read_infrastructure_facility_creation_dto_list_from_json_file() After:  
{'name': 'Module 5, Compartment 91',
 'organisation': 'os-infra:NPEC',
 'rdf_type': 'vocabulary:Greenhouse',
 'rdf_type_name': 'greenhouse',
 'relations': None,
 'uri': None}

Interesting problem because that might be difficult to fix if you generate the logic...

Isabelle-inrae commented 3 years ago

Thank you for this documented and complete feedback Peter, it will help us to fix the problem... We'll have a look on it and let you know.

Dryocopus commented 3 years ago

By the way, though I have some (unrelated) problems with storing devices (issue #6), the DevicesAPI doesn’t have the problem described above. The Swagger-generated interface has the same behaviour as described above, it generates an uri field.

Logic in my script:

print("As dict: ", device_creation_dto_as_dict)
device_creation_dto =  opensilexClientToolsPython.DeviceCreationDTO(**device_creation_dto_as_dict)
print("As device_creation_dto: ", device_creation_dto)

Before the constructor is called:

As dict:  
{'rdf_type': 'vocabulary:RGBCamera', 
'name': 'RGB camera 8', 'brand': 'SMO', 'constructor_model': '', 
'serial_number': '', 'start_up': '2021-05-01', 'removal': '', 'relations': [], 
'description': 'RGBCamera8'}

Output from the constructor:

As device_creation_dto:  {'brand': 'SMO',
 'constructor_model': '',
 'description': 'RGBCamera8',
 'metadata': None,
 'name': 'RGB camera 8',
 'person_in_charge': None,
 'rdf_type': 'vocabulary:RGBCamera',
 'relations': [],
 'removal': '',
 'serial_number': '',
 'start_up': '2021-05-01',
 'uri': None}

But the device can still be stored, so apparently the server logic works differently. That might guide you to a solution.