Endpoint startup notification in Liberty - websphere-liberty

Using Microprofile Liberty server, I need to notify another service on startup that will callback my service on https endpoint. By the way the https endpoint is not always started and inbound service may receive some connection errors.
Options I could imagine are: retry on other service or verify https availability doing rest calls before notifying other service.
Is there any built in way to be notified that endpoint is started or available using MBean notification or CDI event ?

I'm not totally clear on the use case, but it seems like you need to perform an operation (attempting to call another service) on startup? If that's the case, you could try using a CDI bean that listens to the startup event like this:
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Initialized;
import javax.enterprise.event.Observes;
#ApplicationScoped
public class StartupNotification {
public void notifyOtherService(#Observes #Initialized(ApplicationScoped.class) Object context) {
// this will be invoked on application startup
// run code here to notify the other service on startup
}
}

Related

Micrometer with Prometheus Pushgateway not sending the recent metrics

I have a Spring boot application based on CommandLineRunner, when it starts it does some calculations, sends the metrics to Prometheus and shuts down.
I am using Prometheus Push Gateway with Micrometer, mainly based on this tutorial:
https://luramarchanjo.tech/2020/01/05/spring-boot-2.2-and-prometheus-pushgateway-with-micrometer.html
This works fine if I leave the application running however with my particular Spring boot application, it looses the metrics sent just before the shutdown.
I have had similar issue with CloudWatch however it was clear with the Registry implementation CloudWatchMeterRegistry, that it starts a thread in the background and it uses the property cloudwatch.step to schedule the dispatch of the collected metrics. I am struggling to see how PrometheusMeterRegistry is working and not sending the metrics before the application shutsdown.
I have tried to add meterRegistry.close(); just before the shutdown, however it still has the same issue!
After some investigation resolved this by calling the shutdown() method on PrometheusPushGatewayManager.
#SpringBootApplication
public class SpringBootConsoleApplication implements CommandLineRunner {
#Autowired
PrometheusPushGatewayManager prometheusPushGatewayManager;
#PreDestroy
public void onExit() {
System.out.println("Exiting..");
prometheusPushGatewayManager.shutdown();
}
...
And add following in the application.properties:
management.metrics.export.prometheus.pushgateway.shutdown-operation=PUSH

Is it possible for my Spring EventListener to wait for 2 events to progress?

I have a SpringBoot application and have to connect to a websocket server to receive messages, which my application then processes internally using an inbuilt FinitStateMachine (FSM).
What I want is to start the connect() call to the websocket server only after:
my spring application has initialized
my FSM builder has completed the build() call
I have used Spring's ApplicationEventPublisher to publish a custom event (FSMInitializedEvent) when my FSM is built. And the code which initiates connection to websocket server waits for this custom event, but I want my websocket connector code to ALSO wait for Spring's ApplicationReadyEvent. Is there a neat way to do this?
From my FSM's build():
applicationEventPublisher.publishEvent( new FSMInitializedEvent() );
Within my WebSocket connector class:
#EventListener(FSMInitializedEvent.class) <-- HERE i want to listen for this other event too before progressing - ApplicationReadyEvent.class
public void init() {
// code to initiate the connection
}
I could programmatically handle this but looking for some ready to use elegant solution. Also, my question is different what's been suggested here: Use #EventListener annotation on multiple events in Spring, as I want my listener to wait for multiple events to have happened as a precondition, before proceeding.

how can i do for an MDB to deploy last on my wildfly

What is happening to me is that the MDB receives messages and tries to process them and even my server has not started completely
any idea how to solve this?
You can find out if your server startup is completed by one of the following two techniques:
use ServletContextListener, once your application deployment is complete, server would call ServletContextListener.contextInitialized method
Use mbean support from wildfly, you can query mBean via JMX interface of wildfly and figure out if the server state is 'started'. But mind you, your code would be tied down to wildfly only in this case.
Once you decide the option to figure out the server startup state, you need to check for it in your MDB's postconstruct method and go ahead only if the server is started.
#MessageDriven(...)
public class MyMdb implements MessageListener {
#PostConstruct
public void init() {
// check if server has started here
//if server is not started, sleep and re-check again.
}
public void onMessage(Message message) {
}
}

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.

How to get request info on session created in Spring MVC?

I'm hoping to save some client info (IP address, etc) to a database on session created in Spring MVC.
I created a class implementing HttpSessionListener and configured it in web.xml. However, I'm not sure where to go after that.
Would like to be able to inject a bean as well (Spring Data JPA repository).
I've seen How to get the IP address when a session is created? , however if I try to access RequestContextHolder.currentRequestAttributes() I get the following exception:
SEVERE: Session event listener threw exception
java.lang.IllegalStateException: 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/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
You can create a bean this way with Spring java config:
#Bean
#Named ("IP")
#Scope ("session")
public String ip (HttpServletRequest request) {
return request.getRemoteAddr ();
}
If all you want to do is log stuff then you should use the HttpSessionListener, please provide your source and full stack trace. Use pastebin.com if necessary.

Resources