Difference between RefreshScopeRefreshedEvent Vs EnvironmentChangeEvent - spring-boot

As per the class level comment
org.springframework.cloud.context.environment.EnvironmentChangeEvent
Event published to signal a change in the {#link Environment}.
This is too generic and I do not know what are all included when we say change in the Environment.
org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent
Sadly this class does not have a class comment.
My understanding is that RefreshScopeRefreshedEvent handles changes in property values in config-server but looks like it does not instead such event is available through EnvironmentChangeEvent.
I did hit /refresh endpoint but it does not call my listener class with RefreshScopeRefreshedEvent event. Instead EnvironmentChangeEvent got a call for /refresh

EnvironmentChangeEvent is fired when there's a change in Environment. In terms of Spring Cloud Config it means it's triggered when /env actuator endpoint is called.
RefreshScopeRefreshedEvent is fired when refresh of #RefreshScope beans has been initiated, e.g. /refresh actuator endpoint is called.
You can by registering ApplicationListener like that:
#Configuration
public class ApplicationConfig {
#EventListener(RefreshScopeRefreshedEvent.class)
public void onRefresh(RefreshScopeRefreshedEvent event) {
// Your code goes here...
}
}

Related

How does Hystrix Command annotation work in the application

When I annotated a method with #HystrixCommand Annotation then how is it working
#HystrixCommand(fallbackMethod="getfallBackdisplayDoctorsAndProducts_lipid",
commandProperties= {
#HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="150"),
#HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value="25"),
#HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value="50"),
#HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value="5000")
})
public List<DoctorsAndProducts> displayDoctorsAndProducts(LipidProfile lipidProfile)
{
}
You have your API class and the method inside the API class which is annotated with #HystrixCommand.
Hystrix wraps your API class in a proxy class.
When you ask an instance of API class then the instance of the proxy class will be gotten
The proxy class contains the circuit breaker logics.
When somebody makes a call Hystrix is constantly monitoring that what is returning back.
Proxy class - > get a call and passing to the actual method in the API class and get the response back and examining make sure and returning back.
7.When things fail then the proxy class call fallback method until recovery back.

Spring web run after startup

I run a spring web application (not spring boot).
On startup the application requests a dataset from another server. This dataset takes about a minute to be processed. When I deploy this application to the tomcat, it takes a minute. The website itself will not be available until the dataset request has been processed completely. But actually I would like to see, that users are already able to login and the dataset is processed without stopping the rest of the application from working.
Currently I have a service class and use the #PostConstruct-Annotation.
#Service
public class StartupService {
#PostConstruct
public void load() {
//perform the dataset request
...
}
}
I found similar article here on stackoverflow, that suggested trying the ApplicationListener. But this has the same effect. HTTP Requests to the website are not answered unless the dataset request has finished.
#Service
public class StartupService implements ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(final ContextRefreshedEvent event) {
//perform the dataset request
...
}
}
Of course it would be possible, to start a new Thread, but I would like to know, what the best approach for this problem would be.
From the PostConstruct doc:
... This method MUST be invoked before the class is put into service...
So Spring cannot service a request until the #PostContruct method finishes.
As you suggested, start a new thread manually, or:
from the #PostConstruct method, call a public method in another bean annotated with #Async and Spring will asynchronously invoke the method which will allow the #PostConstruct method to finish immediately and start servicing requests
from the #PostConstruct method, #Schedule a one time task - for example 1 minute from now
See also: #EnableAsync and/or #EnableScheduling

JerseyConfig and #Profile to hide a REST endpoint

I'm trying to hide a REST endpoint based on runtime configuration in Spring and Jersey. The most straightforward way is to throw the NotFoundException from the controller itself but maybe there's more kosher. The controller is registered in the constructor of the config class which extends org.glassfish.jersey.server.ResourceConfig.
I thought of using the #Profile annotation on the controller but I can still access the endpoint. When I hit that endpoint, I get the following error:
o.g.j.s.s.SpringComponentProvider - None or multiple beans found in Spring context
but then Jersey manages to access that controller, which I confirmed by attaching a debugger to the Spring process. So Jersey does not honor the #Profile setting.
On a separate note, I also have Swagger plugged into Jersey and when accessing the definition endpoint (.../swagger.json) I can see the endpoint provided by the #Profile-disabled controller.
Is there anything better I can do here is is throwing the NotFoundException the best option?
Note: Sorry, I thought I saw that you were using Spring Boot. The following answer is only relevant for Spring Boot.
#Profile is only good for Spring bean registration, but you are still registering the service with Jersey as a resource. What you can do is use a ResourceConfigCustomizer and add the #Profile to the customizer. This way it will only register the resource with Jersey ResourceConfig if the correct profile is active.
#Component
#Profile("..")
public class MyResourceConfigCustomizer implements ResourceConfigCustomizer {
#Override
public void customize(ResourceConfig config) {
config.register(MyResource.class);
}
}

Spring MVC #Configuration class constructor

As part of the Spring MVC initialization, I need to run an action (just calling a method on a 3rd party library) once as a setup operation. I'm working in Spring MVC environment where I don't really have control over the web.xml or anything, so I can't add a servlet context listener or anything. I tried making an implementation of a WebApplicationInitializer but it never seems to get called (no idea why though, or how to try and debug that any further).
If I annotate a class with #Configuration it does get created, so I'm wondering if I can use the class's constructor to perform that setup operation (calling a 3rd party setup method). Is this appropriate/safe to do? Are there any other alternatives for this kind of thing? I'm new to Spring, so I might just be missing something that's meant for this kind of thing.
Thanks
Configuration class would be an appropriate place to contain some initialization logic. You can place it in a constructor, method annotated with #PostConstruct or afterPropertiesSet() method if you implement the InitializingBean interface for example. The difference is that the constructor code will be called before the beans in your configuration class are instantiated, so if your initialization code depends on some Spring beans, go with the #PostConstruct / InitializingBean approach.
Example:
#Configuration
public class Config {
#PostConstruct
public void initialize() {
// Run some action
}
}

Spring session handling: HttpSessionDestroyedEvent not received

I have a web app where in the web.xml I have added the HttpSessionEventPublisher as listener. The web app runs on Jetty 7.x and we are using Spring 3.1.1.
This is supposed to fire HttpSessionCreatedEvent and HttpSessionDestroyedEvent to Spring context event listeners.
I have a Bean (#Controller) that implements ApplicationListener<ApplicationEvent>. ApplicationEvent is the common parent class of HttpSessionCreatedEvent and HttpSessionDestroyedEvent. When I now login to my web application or log out from it I'd expect these events to be fired to the onApplicationEvent(ApplicationEvent event) method. I have received other events like some request handling event, but the expected event's didn't show up. I have traced the app a bit, the HttpSessionEventPublisher definitely fires the event to the context, but the listener isn't approached. what do I miss here?
The issue is that HttpSessionEventPublisher publishes events on the "Spring Root WebApplicationContext" per the javadoc, this is the application context registered through ContextLoaderListener entry in your web.xml file. Your #Controller on the other hand is probably registered through a different application context altogether - the one registered through the DispatcherServlet. So I would suggest that you create a different ApplicationListener, register it to the Root WebapplicationContext, the events should come through then.
Facing a similar problem, if it not possible to move your ApplicationListener to the root context, you can use the org.springframework.security.context.DelegatingApplicationListener.
Just autowire a DelegatingApplicationListener in your Bean and use constructor / #PostConstruct to register your listener against the DelegatingApplicationListener (one should be already in place by spring-security)

Resources