Questions Tagged With business-datahttps://answers.axonivy.com/tags/business-data/?type=rss&user=vagabondquestions tagged <span class="tag">business-data</span>enFri, 22 Feb 2019 01:16:25 -0500There is a 1-second latency between ivy.repo.save(object) and ivy.repo.search(Object.class)https://answers.axonivy.com/questions/3681/there-is-a-1-second-latency-between-ivy-repo-save-object-and-ivy-repo-search-object-class<p>Hi Axon.ivy Team,</p> <p>Given the snippet of code:</p> <pre><code>Person p = new Person(); p.id = UUID.randomUUID().toString(); p.name = "John Doe"; p.birthdate = LocalDate.now(); ivy.repo.save(p); Object result = ivy.repo.search(Person.class) .textField("id").containsPhrase(p.id) .execute().getFirst(); ivy.log.error("HHH - it is null " + #result); Thread.sleep(TimeUnit.SECONDS.toMillis(1)); result = ivy.repo.search(Person.class) .textField("id").containsPhrase(p.id) .execute().getFirst(); ivy.log.error("HHH - it is null " + #result); </code></pre> <p>I found that there was a <em>1-second</em> latency between the call to <code>ivy.repo.save()</code> and <code>ivy.repo.search()</code>. This is super annoying because we had to wait for <em>1-second</em> every time until the saved object can be searched via the API. Blocking the execution for 1-second to wait until it is indexed to ES <em>every</em> <em>time</em> we save the object into the <code>BusinessDataRepository</code> is a terrible hack.</p> <p>Is it by design? Can this be fixed so that the two calls work?</p> <blockquote> <p>P.S: Please don't advise me to use the returned BusinessData id because it doesn't address my issue. I want to <em>search</em> back the data I save based on the object's field, not fetching it again.</p> <p>P.P.S: Tested with Axon.ivy Designer 7.2.1 on my local workstation.</p> </blockquote> <p><strong>UPDATE</strong></p> <p><em>25.2.2019</em>:</p> <p>In our project, we were able to develop RESTful API for other parties. As we already have persisted our objects (for example <code>Dossier</code>), in <code>BusinessDataRespository</code>, we would want to preserve that behavior.</p> <p>An excerpt from of our OpenAPI spec:</p> <pre><code>paths: /dossiers/{dossier_id}/persons/: post: operationId: addPersonToDossier description: add a single person into an existing Dossier requestbody: 'application/json': schema: $ref: '#/components/schemas/Person' responses: '201': get: operationId: getAllPersonsInDossier description: get *all* existing persons of an existing Dossier responses: '200': content: 'application/json': schema: type: array items: $ref: '#/components/schemas/Person' </code></pre> <p>From our client, after they have already invoked several calls to <code>addPersonToDossier</code>, they may want to invoke <code>getAllPersonsInDossier</code> to fetch all <code>Person</code>s of a <code>Dossier</code>. </p> <p>We persists <code>Person</code> separately from our <code>Dossier</code> to avoid <code>ConcurrentModificationException</code>, each <code>Person</code> holds a reference to its <code>Dossier</code>. Now in order to implement <code>getAllPersonsInDossier</code>, we have to use <code>Ivy.repo().search(..)</code>.</p> <p>Unfortunately, due to the 1-second latency, calling <code>getAllPersonsInDossier</code> too soon will probably return an empty result. This forces us to either:</p> <ul> <li>Require our clients to WAIT on their side for <em>1-second</em> until they can call <code>getAllPersonsInDossier</code>.</li> <li>On the server side, we somehow have to implement a <code>while</code> loop to check until the <code>Person</code> could be found via search API, then we consider the <code>addPersonToDossier</code> finishes (or worse, a <code>Thread.sleep(1000)</code>).</li> </ul> <p>Jack</p>vagabondFri, 22 Feb 2019 01:16:25 -0500https://answers.axonivy.com/questions/3681/there-is-a-1-second-latency-between-ivy-repo-save-object-and-ivy-repo-search-object-classbusiness-dataelasticsearchrepositoryCannot use BusinessDataRepository in JAX-RS resourceshttps://answers.axonivy.com/questions/3641/cannot-use-businessdatarepository-in-jax-rs-resources<p>Hi Axon.ivy team,</p> <p>I know this questions had been asked long time ago at <a href="https://answers.axonivy.com/questions/2777/can-not-use-ivy-repo-in-resfulapi.">https://answers.axonivy.com/questions/2777/can-not-use-ivy-repo-in-resfulapi.</a> But the question was for Axon.ivy 6.3.0 and there was never a resolution of the issue.</p> <p>I am using Axon.ivy 7.0.8 LTS and I still encountered the same issue.</p> <p>I introduce a JAX-RS resource:</p> <pre><code>package com.example.lab; @PermitAll @Path("awesome") public class TheAwesomeApi { @POST @Consume("application/json") @Produces("text/plain") public String saveAwesomeMessage(AwesomeMessage message) { return Ivy.repo().save(message).getId(); } public static class AwesomeMessage { private String content; // getter, setter } } </code></pre> <p>When I tried to call this API, the exception was returned.</p> <pre><code>curl <a href="http://localhost:8081/ivy/api/designer/awesome">http://localhost:8081/ivy/api/designer/awesome</a> \ -H 'Content-Type: application/json' \ -d '{ "content" : "This is an awesome message" }' </code></pre> <blockquote> <p>full stacktrace can be found here: <a href="https://pastebin.com/hXcyQq6h">https://pastebin.com/hXcyQq6h</a></p> </blockquote> <p>Unable to provision, see the following errors:</p> <pre><code>1) Error in custom provider, java.lang.NullPointerException while locating ch.ivyteam.ivy.scripting.dataclass.internal.di.IvyCaseProjectClassLoaderProvider while locating java.lang.ClassLoader annotated with interface ch.ivyteam.ivy.scope.restricted.FromCaseScope Caused by: java.lang.NullPointerException at ch.ivyteam.ivy.scripting.dataclass.internal.di.IvyCaseProjectClassLoaderProvider.get(IvyCaseProjectClassLoaderProvider.java:20) at ch.ivyteam.ivy.scripting.dataclass.internal.di.IvyCaseProjectClassLoaderProvider.get(IvyCaseProjectClassLoaderProvider.java:1) at com.google.inject.internal.ProviderInternalFactory.provision(ProviderInternalFactory.java:81) at com.google.inject.internal.BoundProviderFactory.provision(BoundProviderFactory.java:72) at com.google.inject.internal.ProviderInternalFactory.circularGet(ProviderInternalFactory.java:61) at com.google.inject.internal.BoundProviderFactory.get(BoundProviderFactory.java:62) at com.google.inject.internal.InjectorImpl$2$1.call(InjectorImpl.java:1019) at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1085) at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1015) at ch.ivyteam.ivy.business.data.store.restricted.BusinessDataTypeLoader.getContextClassLoader(BusinessDataTypeLoader.java:60) at ch.ivyteam.ivy.business.data.store.internal.BusinessDataRepositoryImpl.serialize(BusinessDataRepositoryImpl.java:369) at ch.ivyteam.ivy.business.data.store.internal.BusinessDataRepositoryImpl.lambda$0(BusinessDataRepositoryImpl.java:196) at ch.ivyteam.ivy.business.data.store.internal.ElasticSystemDbPersistence.lambda$14(ElasticSystemDbPersistence.java:439) at ch.ivyteam.ivy.persistence.base.AbstractPersistencyService.execute(AbstractPersistencyService.java:177) at ch.ivyteam.ivy.persistence.base.ClassPersistencyService.execute(ClassPersistencyService.java:673) at ch.ivyteam.ivy.business.data.store.internal.ElasticSystemDbPersistence.executeInTransaction(ElasticSystemDbPersistence.java:435) at ch.ivyteam.ivy.business.data.store.internal.BusinessDataRepositoryImpl.create(BusinessDataRepositoryImpl.java:194) at ch.ivyteam.ivy.business.data.store.internal.BusinessDataRepositoryImpl.save(BusinessDataRepositoryImpl.java:177) at com.example.lab.axonivy.api.TheAwesomeApi.saveAwesomeMessage(TheAwesomeApi.java:35) .... at java.lang.Thread.run(Thread.java:748) 2) Error in custom provider, com.google.inject.OutOfScopeException: No case available in the current scope/context while locating ch.ivyteam.ivy.workflow.internal.di.CaseProvider while locating ch.ivyteam.ivy.workflow.ICase for field at ch.ivyteam.ivy.scripting.dataclass.internal.di.IvyCaseProjectClassLoaderProvider.caze(IvyCaseProjectClassLoaderProvider.java:1) while locating ch.ivyteam.ivy.scripting.dataclass.internal.di.IvyCaseProjectClassLoaderProvider while locating java.lang.ClassLoader annotated with interface ch.ivyteam.ivy.scope.restricted.FromCaseScope Caused by: com.google.inject.OutOfScopeException: No case available in the current scope/context at ch.ivyteam.ivy.workflow.internal.di.CaseProvider.get(CaseProvider.java:24) at ch.ivyteam.ivy.workflow.internal.di.CaseProvider.get(CaseProvider.java:1) at com.google.inject.internal.ProviderInternalFactory.provision(ProviderInternalFactory.java:81) at com.google.inject.internal.ProvidedByInternalFactory.provision(ProvidedByInternalFactory.java:82) at com.google.inject.internal.ProviderInternalFactory.circularGet(ProviderInternalFactory.java:61) at com.google.inject.internal.ProvidedByInternalFactory.get(ProvidedByInternalFactory.java:71) at com.google.inject.internal.SingleFieldInjector.inject(SingleFieldInjector.java:54) at com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:132) at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:120) at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:90) at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:268) at com.google.inject.internal.BoundProviderFactory.get(BoundProviderFactory.java:61) at com.google.inject.internal.InjectorImpl$2$1.call(InjectorImpl.java:1019) at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1085) at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1015) at ch.ivyteam.ivy.business.data.store.restricted.BusinessDataTypeLoader.getContextClassLoader(BusinessDataTypeLoader.java:60) at ch.ivyteam.ivy.business.data.store.internal.BusinessDataRepositoryImpl.serialize(BusinessDataRepositoryImpl.java:369) at ch.ivyteam.ivy.business.data.store.internal.BusinessDataRepositoryImpl.lambda$0(BusinessDataRepositoryImpl.java:196) at ch.ivyteam.ivy.business.data.store.internal.ElasticSystemDbPersistence.lambda$14(ElasticSystemDbPersistence.java:439) at ch.ivyteam.ivy.persistence.base.AbstractPersistencyService.execute(AbstractPersistencyService.java:177) at ch.ivyteam.ivy.persistence.base.ClassPersistencyService.execute(ClassPersistencyService.java:673) at ch.ivyteam.ivy.business.data.store.internal.ElasticSystemDbPersistence.executeInTransaction(ElasticSystemDbPersistence.java:435) at ch.ivyteam.ivy.business.data.store.internal.BusinessDataRepositoryImpl.create(BusinessDataRepositoryImpl.java:194) at ch.ivyteam.ivy.business.data.store.internal.BusinessDataRepositoryImpl.save(BusinessDataRepositoryImpl.java:177) at com.example.lab.axonivy.api.TheAwesomeApi.saveAwesomeMessage(TheAwesomeApi.java:35) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at ch.ivyteam.ivy.webserver.internal.rest.resource.project.RestPmvInvocationHandler$PmvAwareInvocator.lambda$0(RestPmvInvocationHandler.java:38) at ch.ivyteam.ivy.webserver.internal.rest.resource.project.RestPmvInvocationHandler.executeWithIvyContext(RestPmvInvocationHandler.java:70) at ch.ivyteam.ivy.webserver.internal.rest.resource.project.RestPmvInvocationHandler.access$1(RestPmvInvocationHandler.java:65) at ch.ivyteam.ivy.webserver.internal.rest.resource.project.RestPmvInvocationHandler$PmvAwareInvocator.invoke(RestPmvInvocationHandler.java:50) ... at java.lang.Thread.run(Thread.java:748) 2 errors" </code></pre> <p>Is this issue still a known limitation even with the 7.0 LTS?</p> <p>Thanks for your support!</p> <p>Jack</p>vagabondThu, 24 Jan 2019 00:49:27 -0500https://answers.axonivy.com/questions/3641/cannot-use-businessdatarepository-in-jax-rs-resourcesbusiness-data