How can we call fallback method of Hystrix in zeebe handler? - spring-boot

I have a service called payment-service which is down, and this is called inside a zeebe handler.Since the service is down it should call fallbackmethod of hystrix. But it is returning me success.
main class
controller class
delegate class
when I am executing localhost:8081/order-process it shows me success.
and in the console I get the error as
I/O error on GET request for "http://localhost:8080/payment-service": Connection refused:
Please let me know why this fallback method is not getting called.

The reason your REST service returns "success" is that you successfully started your job worker (https://docs.zeebe.io/basics/job-workers.html). The job worker then executing the jobs/service tasks from your BPMN processes.
Hystrix will be used WITHIN the handler to do the call, so a potential exception or default value needs to be taken into account WITHIN the handle method.

Related

Spring and Netflix DGS: Access SecurityContext from DgsSubscription Method

We have a custom SecurityService class that internally accesses the current SecurityContext and RequestAttributes via SecurityContextHolder and RequestContextHolder for every method call of the service.
Imagine the custom class User returned from securityService.getUser();
Given the following code:
#DgsSubscription
public Publisher<String> test() {
String s = securityService.getUser().getName();
return Flux.interval(Duration.ofSeconds(5)).map(t -> s);
}
That periodically triggers the test subscription and returns the User name.
I get the following error when a client tries to subscribe:
Exception while fetching data (/test) : No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
Apparently the test method is run in a new thread?
How do I make both context available to this thread?
SecurityService is autowired into the Datafetcher.

How to verify #Blocking annotatio is working for quarkus

We are using quarkus framework and https://quarkus.io/guides/getting-started-reactive mentions that we can use #Blocking on a method, class to instruct Quarkus to invoke this method on a worker thread.
But how exactly can we verify it is using a worker thread?
You can call io.quarkus.runtime.BlockingOperationControl.isBlockingAllowed() to see if blocking on the thread is allowed.
If you have used #Blocking correctly, the call should return true

com.sap.cloud.sdk.frameworks.hystrix.ScpNeoHystrixBootstrapListenerjava.lang.IllegalStateException

If I use ODataQueryBuilder in a servlet, I can call the servlet without any problem.
If I incorporated the code in a method and call this method within a ServletContextListener, I got first the following error.
2018 02 27 13:17:09#+00#ERROR#org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/]##anonymous#fs-watcher#na#afc186d33#firstapp#web##na#na#na#na#Exception sending context initialized event to listener instance of class com.sap.cloud.sdk.frameworks.hystrix.ScpNeoHystrixBootstrapListenerjava.lang.IllegalStateException: Another strategy was already registered.
at com.netflix.hystrix.strategy.HystrixPlugins.registerConcurrencyStrategy(HystrixPlugins.java:190)
at com.sap.cloud.sdk.frameworks.hystrix.ScpNeoHystrixBootstrapListener.bootstrap(ScpNeoHystrixBootstrapListener.java:43)
at com.sap.cloud.sdk.frameworks.hystrix.ScpNeoHystrixBootstrapListener.contextInitialized(ScpNeoHystrixBootstrapListener.java:74)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:5110)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5633)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:1015)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:991)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)
at org.eclipse.gemini.web.tomcat.internal.TomcatServletContainer.startWebApplication(TomcatServletContainer.java:125)
at org.eclipse.gemini.web.internal.StandardWebApplication.start(StandardWebApplication.java:109)
at org.eclipse.gemini.web.extender.WebContainerBundleCustomizer.addingBundle(WebContainerBundleCustomizer.java:49)
at org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:467)
at org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:1)
at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:256)
at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:229)
at org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:443)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.dispatchEvent(BundleContextImpl.java:847)
at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)
at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148)
at org.eclipse.osgi.framework.internal.core.Framework.publishBundleEventPrivileged(Framework.java:1568)
at org.eclipse.osgi.framework.internal.core.Framework.publishBundleEvent(Framework.java:1504)
at org.eclipse.osgi.framework.internal.core.Framework.publishBundleEvent(Framework.java:1499)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:391)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:300)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.start(AbstractBundle.java:292)
at org.eclipse.virgo.web.war.deployer.WARDeployer.start(WARDeployer.java:780)
at org.eclipse.virgo.nano.deployer.internal.StandardApplicationDeployer.startDeployables(StandardApplicationDeployer.java:325)
at org.eclipse.virgo.nano.deployer.internal.StandardApplicationDeployer.bulkDeploy(StandardApplicationDeployer.java:116)
at org.eclipse.virgo.nano.deployer.hot.HotDeploymentFileSystemListener.bulkDeployIfNotDeployed(HotDeployerFileSystemListener.java:143)
at org.eclipse.virgo.nano.deployer.hot.HotDeploymentFileSystemListener.onInitialEvent(HotDeployerFileSystemListener.java:105)
at org.eclipse.virgo.util.io.FileSystemChecker.notifyListenersOnInitialEvent(FileSystemChecker.java:207)
at org.eclipse.virgo.util.io.FileSystemChecker.handleInitialFiles(FileSystemChecker.java:177)
at org.eclipse.virgo.util.io.FileSystemChecker.check(FileSystemChecker.java:261)
at org.eclipse.virgo.nano.deployer.hot.WatchTask.run(WatchTask.java:49)
at java.lang.Thread.run(Thread.java:807)
Followed by:
One or more listeners failed to start. Full details will be found in
the appropriate container log file
Context [] startup failed due to previous errors
This will destroy my Servlet Context Listener and then failed to start web application in NEO.
It is strange because the method is called well and in the log I can see that the method is called without an error.
If I don't call the method in code, the application is starting up well.
Please let me know, how I can solve this issue, because I need to call the S/4 Hana system.
Update:
Version 2.0.0 of the SAP S/4HANA Cloud SDK changed the way how RequestContextListeners are initialized. It is now be possible to use the following code without additional effort:
new RequestContextExecutor().execute(...);
Original answer:
I guess that you want to run logic in some background task that is not triggered by a user request.
Can you try to wrap the logic calling the S/4HANA system in a Callable which is passed to the execute method of a RequestContextExecutor?
For example:
List<SomeData> result = new RequestContextExecutor()
.execute(new Callable<List<SomeData>>() {
#Override
public List<SomeData> call() {
return new GetSomeDataCommand().execute();
}
});
Note that this will require a technical user with Basic credentials in the destination configuration; principal propagation is not available in this case.
Also note that if you want to run the background task calling the external system in a ServletContextListener during application startup, you have to
either explicitly register the relevant RequestContextListener classes which are also subclasses of ServletContextListener (including, if you are using the SAP Cloud Platform Neo environment, initializing the ScpNeoHystrixBootstrapListener),
or specify the order of the ServletContextListener classes explicitly in the web.xml file.
You can register these listeners explictly as follows:
// ensure that the correct HystrixConcurrencyStrategy is used
new ScpNeoHystrixBootstrapListener().bootstrap();
// explicitly register RequestContextListeners
new RequestContextExecutor().withListeners(
new DestinationsRequestContextListener(),
new ScpNeoDestinationsRequestContextListener(),
new TenantRequestContextListener(),
new UserRequestContextListener()
).execute( /* callable */ );

Jersey Exception Java 1.8

I am calling a REST service and the provider has supplied a client. Client's specification is to use Jersey 2.18. So i have used the below jersey dependencies
Jersey-client-2.18.jar
Jersey-common-2.18.jar
Jersey-entity-filtering-2.18.jar
Jersey-guava-2.18.jar
jersey-media-json-jackson-2.18.jar
I am making calls using scheduledThreadPoolExecutor and my application is running in tc server and JDK 1.8. Sporadically i get the below exception. I tried searching this exception in google but no luck. But i see the below for almost everytime
Cannot create new registration for component type class > org.glassfish.jersey.client.authentication.HttpAuthenticationFeature
Exception
java.lang.NullPointerException at
org.glassfish.jersey.model.internal.CommonConfig.configureFeatures(CommonConfig.java:694)
at
org.glassfish.jersey.model.internal.CommonConfig.configureMetaProviders(CommonConfig.java:644)
at
org.glassfish.jersey.client.ClientConfig$State.configureMetaProviders(ClientConfig.java:365)
at
org.glassfish.jersey.client.ClientConfig$State.initRuntime(ClientConfig.java:398)
at
org.glassfish.jersey.client.ClientConfig$State.access$000(ClientConfig.java:88)
at
org.glassfish.jersey.client.ClientConfig$State$3.get(ClientConfig.java:120)
at
org.glassfish.jersey.client.ClientConfig$State$3.get(ClientConfig.java:117)
at
org.glassfish.jersey.internal.util.collection.Values$LazyValueImpl.get(Values.java:340)
at
org.glassfish.jersey.client.ClientConfig.getRuntime(ClientConfig.java:726)
at
org.glassfish.jersey.client.ClientRequest.getConfiguration(ClientRequest.java:285)
at
org.glassfish.jersey.client.JerseyInvocation.validateHttpMethodAndEntity(JerseyInvocation.java:126)
at
org.glassfish.jersey.client.JerseyInvocation.(JerseyInvocation.java:98)
at
org.glassfish.jersey.client.JerseyInvocation.(JerseyInvocation.java:91)
at
org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:411)
at
org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:307)
I resolved this issue. My implementation was wrong. The client object was defined as a class level variable and it was initialized during every method call. During parallel call. every thread concurrent call attacks the same class level object and tries to modify and hence the object was not properly initialized. Now i fixed it by injecting the class from spring so that it is not modified during every call.

spring deferredresult

I am new to spring and want to implement long polling for a website to display admin message immediately when it becomes available to all clients,i searched google for hours and could only find out deferredresult(spring 3.2) can be used to implement it.my question is how i can achieve long polling with deferredresult, I would appreciate it if anyone could refer me to such a tutorial.
Another option is to use AsyncContext. This will keep the initial GET request "open" and enable you to send multiple messages as part of the response, unlike DeferredResult which allows to send only ONE response message. Here is a good-link that explains how !
Straight from the horses mouth.
You have two basic options: Option 1 is a Callable
, where the Callable returns the String view name (you may also be able to use #ResponseBody or some of the other normal Spring return types like ModelAndView, but I have never investigated that).
Option two is to return DeferredResult, which is like Callable. except you can pass that off to a separate thread and fill in the results there. Again, not sure if you can return a ModelAndView or use #ResponseBody to return XML/JSON, but I am sure you can.
Short background about DeferredResult:
Your controller is eventually a function executed by the servlet container (for that matter, let's assume that the server container is Tomcat) worker thread. Your service flow start with Tomcat and ends with Tomcat. Tomcat gets the request from the client, holds the connection, and eventually returns a response to the client. Your code (controller or servlet) is somewhere in the middle.
Consider this flow:
Tomcat get client request.
Tomcat executes your controller.
Release Tomcat thread but keep the client connection (don't return response) and run heavy processing on different thread.
When your heavy processing complete, update Tomcat with its response and return it to the client (by Tomcat).
Because the servlet (your code) and the servlet container (Tomcat) are different entities, then to allow this flow (releasing tomcat thread but keep the client connection) we need to have this support in their contract, the package javax.servlet, which introduced in Servlet 3.0 . Spring MVC use this new Servlet 3.0 capability when the return value of the controller is DeferredResult or Callable, although they are two different things. Callable is an interface that is part of java.util, and it is an improvement for the Runnable interface. DeferredResult is a class designed by Spring to allow more options (that I will describe) for asynchronous request processing in Spring MVC, and this class just holds the result (as implied by its name) while your Callable implementation holds the async code. So it means you can use both in your controller, run your async code with Callable and set the result in DeferredResult, which will be the controller return value. So what do you get by using DeferredResult as the return value instead of Callable? DeferredResult has built-in callbacks like onError, onTimeout, and onCompletion. It makes error handling very easy. In addition, as it is just the result container, you can choose any thread (or thread pool) to run on your async code. With Callable, you don't have this choice.
Here you can find a simple working examples I created with both options, Callable and DeferredResult.

Resources