International-Data-Spaces-Association / IDS-ConfigurationManager

-- End-Of-Support: 21.07.2021 -- Archived Repo! -- Has been integrated directly into the Dataspace Connector.
https://www.youtube.com/watch?v=zk0N6u5ewOA
Apache License 2.0
2 stars 2 forks source link

Parallel API calls result in an IOException #25

Closed BastianWel closed 3 years ago

BastianWel commented 3 years ago

Multiple API endpoints (i.e. POST /api​/ui​/approute​/step and PUT ​/api​/ui​/configmodel) cause the config manager to crash with an IOException when called parallel. As a temporary workaround the user interface calls all API endpoints sequentially.

Stack trace: java.io.IOException: The following mandatory field(s) of ConfigurationModel are not filled or invalid: ids:configurationModelLogLevel, ids:connectorDeployMode, ids:connec at de.fraunhofer.iais.eis.ids.jsonld.Parser.handleObject(Parser.java:380) at de.fraunhofer.iais.eis.ids.jsonld.Parser.parseMessage(Parser.java:917) at de.fraunhofer.iais.eis.ids.jsonld.Parser.parseMessage(Parser.java:932) at de.fraunhofer.iais.eis.ids.jsonld.Serializer.deserialize(Serializer.java:103) at de.fraunhofer.isst.configmanager.configmanagement.entities.converter.ConfigModelConverter.convertToEntityAttribute(ConfigModelConverter.java:44) at de.fraunhofer.isst.configmanager.configmanagement.entities.converter.ConfigModelConverter.convertToEntityAttribute(ConfigModelConverter.java:13) at org.hibernate.metamodel.model.convert.internal.JpaAttributeConverterImpl.toDomainValue(JpaAttributeConverterImpl.java:45) at org.hibernate.type.descriptor.converter.AttributeConverterMutabilityPlanImpl.deepCopyNotNull(AttributeConverterMutabilityPlanImpl.java:33) at org.hibernate.type.descriptor.java.MutableMutabilityPlan.deepCopy(MutableMutabilityPlan.java:35) at org.hibernate.type.AbstractStandardBasicType.deepCopy(AbstractStandardBasicType.java:308) at org.hibernate.type.AbstractStandardBasicType.deepCopy(AbstractStandardBasicType.java:304) at org.hibernate.type.TypeHelper.deepCopy(TypeHelper.java:55) at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntityFromEntityEntryLoadedState(TwoPhaseLoad.java:369) at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:183) at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:151) at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1200) at org.hibernate.loader.Loader.processResultSet(Loader.java:1001) at org.hibernate.loader.Loader.doQuery(Loader.java:959) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:319) at org.hibernate.loader.Loader.loadEntity(Loader.java:2422) at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:72) at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:61) at org.hibernate.persister.entity.AbstractEntityPersister.doLoad(AbstractEntityPersister.java:4442) at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4432) at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:569) at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:537) at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:208) at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:332) at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:108) at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:74) at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:113) at org.hibernate.internal.SessionImpl.fireLoadNoChecks(SessionImpl.java:1186) at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1175) at org.hibernate.internal.SessionImpl.access$2100(SessionImpl.java:193) at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.doLoad(SessionImpl.java:2786) at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.lambda$load$1(SessionImpl.java:2767) at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.perform(SessionImpl.java:2723) at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2767) at org.hibernate.internal.SessionImpl.get(SessionImpl.java:988) at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:306) at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:172) at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:70) at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102) at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:793) at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:780) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:567) at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:362) at com.sun.proxy.$Proxy125.merge(Unknown Source) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:567) at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:311) at com.sun.proxy.$Proxy125.merge(Unknown Source) at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:560) at org.springframework.data.jpa.repository.support.SimpleJpaRepository.saveAndFlush(SimpleJpaRepository.java:572) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:567) at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:289) at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137) at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121) at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:524) at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:285) at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:531) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:156) at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:131) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProc at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) at com.sun.proxy.$Proxy132.saveAndFlush(Unknown Source) at de.fraunhofer.isst.configmanager.configmanagement.service.ConfigModelService.saveState(ConfigModelService.java:164) at de.fraunhofer.isst.configmanager.configmanagement.service.AppRouteService.createAppRouteStep(AppRouteService.java:270) at de.fraunhofer.isst.configmanager.controller.AppRouteUIController.createAppRouteStep(AppRouteUIController.java:177)

goekhanKahriman commented 3 years ago

The problem persists. The error was reproduced with the latest dev-branch of the config manager, with the master branch of the DSC and with the config manager ui (dev-branch: commitID: 3b2343cf) and with the latest infomodel serializer - "4.2.0-SNAPSHOT". If the API calls are parallel you get the following error message in the configmanager:

ERROR - The following mandatory field(s) of ConfigurationModel are not filled or invalid: ids:configurationModelLogLevel, ids:connectorDeployMode, ids:connectorStatus. Note that the value of "@id" fields MUST be a valid URI (e.g. emails preceded by "mailto:"). Mandatory fields are: configurationModelLogLevel, connectorDeployMode, connectorStatus

In addition, the API calls on the UI side also fail: >>> POST http://localhost:8081/api/ui/resource?title=t&description=d&language=DE&keyword=K&version=2&standardlicense=http://p&publisher=http://p 1] Error on POST /resource 500 1] >>> PUT http://localhost:8081/api/ui/resource/contract?resourceId=undefined 1] Error on PUT /contract 400 1] >>> POST http://localhost:8081/api/ui/resource/representation?resourceId=undefined&endpointId=https://w3id.org/idsa/autogen/genericEndpoint/073e419d-fb3b-4774-8f4f-5d9c56e8dfce&language=DE&filenameExtension=json&bytesize=1234&sourceType=LOCAL 1] Error on POST /representation 500

tmberthold commented 3 years ago

Please pay attention to which API calls can be executed in parallel and asynchronously at all. Some API calls, like when creating a resource, have to follow a certain order, so that we don't get into race-conditions that a resource-representation should be added to a resource, although the API call to create the resource itself is not yet finished. We need to examine the APIs and define the order in which they should be used.

Or we need to provide a single API for a logic like creating a resource and then internally implement the order so the frontend doesn't have to worry about the order and just needs to call exactly 1 API to create a resource with all information.

BastianWel commented 3 years ago

It is no problem to keep this order in the UI. But what happens if several users use the UI at the same time via their browsers. Parallel API calls cannot be prevented then.

tmberthold commented 3 years ago

Should be resolved by integration into the Dataspace Connector v6.


-- End-Of-Support: 21.07.2021 -- Has been integrated directly into the Dataspace Connector.