Questions asked by vagabondhttps://answers.axonivy.com/questions/asked-by/1130/vagabond/?type=rssQuestions asked by <a href="/users/1130/vagabond" >vagabond</a>enTue, 14 May 2019 10:30:00 -0400Signal wildcards behave in an unexpected wayhttps://answers.axonivy.com/questions/3797/signal-wildcards-behave-in-an-unexpected-way<p>Hi Axon.ivy Team,</p> <p>I'm using Axon.ivy LTS 7.0.8 and I'm getting an issue related to <code>Signal</code>.</p> <p>I have 4 signal receivers:</p> <ol> <li> <p><code>one</code></p> </li> <li> <p><code>one:two</code></p> </li> <li> <p><code>one:two:three</code></p> </li> <li> <p><code>one:two:three:four</code></p> </li> </ol> <p>When I send the signal <code>one:two:three:four</code>, I expect that only the (4) receiver would be triggered. Unfortunately, I was surprised that <strong>all</strong> four of them were triggered.</p> <p><img alt="all four signal receivers are triggered" src="https://answers.axonivy.com/upfiles/image_(3).png"></p> <p>According to the official document, I would expect that only if I use the wildcard in the pattern of the Receiver, I will have the same behaviours (<code>one:*</code>, <code>one:two:*</code>, <code>one:two:three:*</code>) but in this case, the wildcard does not matter much here.</p> <p>Is it a bug or by design that the Signal Receivers behave like that?</p> <p>Thanks! Jack</p>vagabondTue, 14 May 2019 10:30:00 -0400https://answers.axonivy.com/questions/3797/signal-wildcards-behave-in-an-unexpected-waysignalsDelayed Task and Expiry Tasks timing is not correct if the interval is smaller 60 secondshttps://answers.axonivy.com/questions/3744/delayed-task-and-expiry-tasks-timing-is-not-correct-if-the-interval-is-smaller-60-seconds<p>Hi Axon.ivy Team,</p> <p>In our project, we have several use cases that we would like to use the Delayed Tasks or Expiry Tasks. Depends on the business needs, our delayed or expiration duration <strong>may be 30 seconds or less</strong>.</p> <p>However, we discovered that the duration <strong>does not work</strong> if it is smaller than 60 seconds. I had done our homework a little bit and discovered that the <code>WorkflowJob</code> which was the main module used to resolve expired or delayed tasks is scheduled to run periodically on every 60 seconds. This was done in <code>WorkflowManager</code>.</p> <p>I assumed this was done <em>by design</em> but it took me by surprise because I could not find anywhere mentioning this limitation. The interval, 60 seconds, is hardcoded and is not configurable like the <code>SystemTask.SearchJob.Interval</code>.</p> <p>Is there any recommended ways to overcome this limitation?</p> <p><strong>UPDATE</strong></p> <p>In our system, we want to communicate to a 3rd party system, namely ABC, via its RESTful API.</p> <ul> <li>The process starts when a User triggers a designated action on the UI. We then call the ABC's API to initiate a process on their system.</li> <li>Our system then have to poll ABC's API for result <strong>asynchronously</strong>.</li> <li>The ABC API requires that we have to poll for result at least after 30 seconds from the time the first request has been sent.</li> <li>We want to have at max 3 attempts to call ABC's API for checking the result. Each time will have an additional delay of 10 seconds.</li> <li>At the same time, the User UI may be also polling for the result. It is not required that they have to keep the UI open.</li> </ul> <p>Having the above requirements, we are using Signal to trigger the polling to ABC's API asynchronously. The Signal process makes uses of SYSTEM TaskElement whose DelayDuration set to <code>30S</code>. For triggering a retry, the process itself then send a new Signal with an additional delay duration.</p> <p>What would be your suggestion to implement such a use case then?</p> <p>Bump this up!</p> <p>Regard</p> <p>Jack</p>vagabondMon, 25 Mar 2019 06:31:06 -0400https://answers.axonivy.com/questions/3744/delayed-task-and-expiry-tasks-timing-is-not-correct-if-the-interval-is-smaller-60-secondstaskworkflowThere 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