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

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 */ );

Related

Mule connector config needs dynamic attributes

I have develop a new Connector. This connector requires to be configured with two parameters, lets say:
default_trip_timeout_milis
default_trip_threshold
Challenge is, I want read ${myValue_a} and ${myValue_a} from an API, using an HTTP call, not from a file or inline values.
Since this is a connector, I need to make this API call somewhere before connectors are initialized.
FlowVars aren't an option, since they are initialized with the Flows, and this is happening before in the Mule app life Cycle.
My idea is to create an Spring Bean implementing Initialisable, so it will be called before Connectors are init, and here, using any java based libs (Spring RestTemplate?) , call API, get values, and store them somewhere (context? objectStore?) , so the connector can access them.
Make sense? Any other ideas?
Thanks!
mmm you could make a class that will create the properties in the startup and in this class obtain the API properties via http request. Example below:
public class PropertyInit implements InitializingBean,FactoryBean {
private Properties props = new Properties();
#Override
public Object getObject() throws Exception {
return props;
}
#Override
public Class getObjectType() {
return Properties.class;
}
}
Now you should be able to load this property class with:
<context:property-placeholder properties-ref="propertyInit"/>
Hope you like this idea. I used this approach in a previous project.
I want to give you first a strong warning on doing this. If you go down this path then you risk breaking your application in very strange ways because if any other components depend on this component you are having dynamic components on startup, you will break them, and you should think if there are other ways to achieve this behaviour instead of using properties.
That said the way to do this would be to use a proxy pattern, which is a proxy for the component you recreate whenever its properties are changed. So you will need to create a class which extends Circuit Breaker, which encapsulates and instance of Circuit Breaker which is recreated whenever its properties change. These properties must not be used outside of the proxy class as other components may read these properties at startup and then not refresh, you must keep this in mind that anything which might directly or indirectly access these properties cannot do so in their initialisation phase or your application will break.
It's worth taking a look at SpringCloudConfig which allows for you to have a properties server and then all your applications can hot-reload those properties at runtime when they change. Not sure if you can take that path in Mule if SpringCloud is supported yet but it's a nice thing to know exists.

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 Cloud Bus - Custom Event Received but not handled by Event Handler

I am using Spring Cloud Bus (1.2.1.RELEASE, Camden.SR2). I have a custom event (call it CustomEvent) that I have created and registered via #RemoteApplicationEventScan as well as a custom AbstractBusEndpoint implementation to publish the event. I am able to publish events to the bus just fine.
My remote application receives the event and acknowledges (I verified this using the trace endpoint). I have verified via debugging that the CustomEvent is published via the ApplicationEventPublisher provided in BusAutoConfiguration#acceptRemote. I have a bean with an event handler in my remote application (I have this auto-configured into all of my micro-services):
#Component
public class EventListener {
#EventHandler(CustomEvent.class)
public void handleCustomEvent(CustomEvent event) {
..
}
}
Despite this, the event handler will not receive the event. I traced within the AbstractApplicationEventMulticaster class and despite my bean being created (verified via beans endpoint), the listener is not in the list of ApplicationListeners retrieved by ListenerRetriever. I do see the BusAutoConfiguration.acceptLocal listener in this list, but not my custom listener.
This event handler is also registered on the source application (the one I am accessing the bus endpoint from to initiate the event). The custom listener receives the event in this application, but not the remote application.
Essentially, both applications are configured the exact same except one is configured to send the CustomEvent using an implementation of AbstractBusEndpoint.
I am out of ideas of where else to look within the Spring code to debug this problem. If anyone has a thread they can lead me on it would be appreciated.
I've come up with the exact same problem, and debugging it revealed that ApplicationListener which handles the custom remote event not returned among candidate listeners within ApplicationEventMulticaster due to eventType was loaded by two different classloaders, one of them was devtools related classloader. Removing devtools dependency from classpath simply resolved issue for me.

Grails session-scoped Service throwing NotSerializable Exception

I have a Grails 3 application (3.1.1) that implements a Breadcrumb system. I based it on this plugin for an earlier version of Grails.
It runs fine locally (using Grails command line command run-app), however, when I build and run on Tomcat 7, I get the following exception:
Jul 08, 2016 5:10:34 PM org.apache.catalina.ha.session.DeltaManager requestCompleted
SEVERE: Unable to serialize delta request for sessionid [6605EAC9C04DF7E2512493CABDFB1AD2]
java.io.NotSerializableException: au.packagename.BreadCrumbService
The above named service has a scope set to session, and is specified as a proxy. I have even added the Serializable implementation, however that does not seem to help.
class BreadCrumbService implements Serializable {
static transactional = false
static scope = 'session'
static proxy = true
}
I have an Interceptor that uses the Service to write the current controller and action as a Crumb object to the session. I have added the Serializable implementation to the Crumb and BreadCrumbType Enum (used in the Controllers annotation) that gets written to the session.
Is anyone able to indicate to me why this might be happening (I understand the concept of Serializable) and how I might go about resolving it?
#Hoàng Long's comment put me the right track.
When writing the Crumb object (all of which were made Serializable) to the session, I was using a static variable in the BreadCrumbService for the session map's key.
session[BreadCrumbService.NAMESPACE].crumb = new Crumb()
When I moved this variable to the Crumb object, the issue was resolved.
Even though the Service itself hasn't being written to the session. The mere reference to a variable inside the Service in the writing to the session required the service and every member to be Serializable.

Restarting Apache Felix

I am doing a self updating application using Apache Felix and I can't seem to forcibly restart Felix after update. I did some tricks to simulate the restart process by using some kind of application State.
public class LauncherActivator implements BundleActivator {
public static LauncherState State;
#Override
public void start(BundleContext context) throws Exception {
...
LauncherApplication.State = LauncherState.READY;
Platform.runLater(() -> {
try {
new LauncherApplication().start();
} catch (Exception ex) {
Logger.getLogger(LauncherActivator.class.getName()).log(Level.SEVERE, null, ex);
}
});
}
}
If there are updates detected I would just change the global state to LauncherAppliation.State = LauncherState.RESTART; if the application detects the change in State I will just simply call BUNDLE_MAP.get('application.activator').update();, BUNDLE_MAP is some kind of a HashMap that stores all running bundles on start.
I tested it and it worked, I can see in the logs that the activator bundle is being updated and the simple restart mechanism reruns the activator bundle but there are times that it doesn't rerun the activator bundle and the bundle state is already ACTIVE.
So what would be the right way to restart Apache Felix using the activator bundle or any bundle in general?
It is all in the documentation all this time!
Starting the Framework Instance
The start() method is used to start the framework instance. If the init() method was not invoked prior to calling start(), then it is invoked by start(). The two methods result in two different framework state transitions:
init() results in the framework instance in the Bundle.STARTING state.
start() results in the framework instance in the Bundle.ACTIVE state.
The init() method is necessary since the framework does not have a BundleContext when it is first created, so a transition to the Bundle.STARTING state is required to acquire its context (via Bundle.getBundleContext()) for performing various tasks, such as installing bundles. Note that the Felix framework also provides the felix.systembundle.activators property that serves a similar purpose, but is not standard. After the init() method completes, the follow actions have been performed:
Event handling is enabled.
The security manager is installed if it is enabled.
The framework is set to start level 0.
All bundles in the bundle caches are reified and their state is set to Bundle.INSTALLED.
The framework gets a valid BundleContext.
All framework-provided services are made available (e.g., PackageAdmin, StartLevel, etc.).
The framework enters the Bundle.STARTING state.
A call to start() is necessary to start the framework instance, if the init() method is invoked manually. Invoking init() or start() on an already started framework as no effect.
Stopping the Framework Instance
To stop the framework instance, invoke the stop() method, which will asynchronously stop the framework. To know when the framework has finished its shutdown sequence, use the waitForStop() method to wait until it is complete. A stopped framework will be in the Bundle.RESOLVED state. It is possible to restart the framework, using the normal combination of init()/start() methods as previously described.
Launching a Framework
Launching a framework is fairly simple and involves only four steps:
Define some configuration properties.
Obtain framework factory.
Use factory to create framework with the configuration properties.
Invoke the Framework.start() method.
In reality, the first step is optional, since all properties will have reasonable defaults, but if you are creating a launcher you will generally want to more than that, such as automatically installing and starting bundles when you start the framework instance. The default Felix launcher defines reusable functionality to automatically install and/or start bundles upon framework startup.

Resources