How to send an event to another bean in spring? - java

In spring it is possible to do this. Does anybody have code samples?

If you want to notify a bean about something, simply call a method:
#Service
public class Notifier {
#Autowired
private Notified notified;
public void something() {
notified.notify(..);
}
}
But event handling is usually asynchronous. In that case you will have to create a new Thread (or use the executors framework since Java 5), pass a reference to / inject the target bean, and let it notify it.
And if instead you want to notify multiple beans, without knowing which exactly, then use the event mechanism that spring provides as an implementation of the observer pattern.

You can use Spring Integration for messaging between beans in your context. Look at MessageChannel and ServiceActivator. You can route, filter, split messages to your beans how ever you need.

Related

scope of #kafkaListener

I just want to understand that what is the scope of #kafkaListener, either prototype or singleton. In case of multiple consumers of a single topic, is it return the single instance or multiple instances. In my case, I have multiple customers are subscribed to single topic and get the reports. I just wanted to know, what would happen, if
multiple customers wants to query for the report on the same time. In
my case, I am closing the container after successful consumption of
messages but at the same time if some other person wants to fetch
reports, the container should be open.
how to change the scope to prototype (if it is not) associated with Id's of
container, so that each time a separate instance can be generated.
#KafkaListener(id = "id1", topics = "testTopic" )
public void listen() {
// code goes here
}
A Single Listener Instance is invoked for all consuming Threads.
The annotation #KafkaListener is not Prototype scoped, and it is not possible with this annotation either.
4.1.10. Thread Safety
When using a concurrent message listener container, a single listener instance is invoked on all consumer threads. Listeners, therefore, need to be thread-safe, and it is preferable to use stateless listeners. If it is not possible to make your listener thread-safe or adding synchronization would significantly reduce the benefit of adding concurrency, you can use one of a few techniques:
Use n containers with concurrency=1 with a prototype scoped MessageListener bean so that each container gets its own instance (this is not possible when using #KafkaListener).
Keep the state in ThreadLocal<?> instances.
Have the singleton listener delegate to a bean that is declared in SimpleThreadScope (or a similar scope).
To facilitate cleaning up thread state (for the second and third items in the preceding list), starting with version 2.2, the listener container publishes a ConsumerStoppedEvent when each thread exits. You can consume these events with an ApplicationListener or #EventListener method to remove ThreadLocal<?> instances or remove() thread-scoped beans from the scope. Note that SimpleThreadScope does not destroy beans that have a destruction interface (such as DisposableBean), so you should destroy() the instance yourself.
By default, the application context’s event multicaster invokes event listeners on the calling thread. If you change the multicaster to use an async executor, thread cleanup is not effective.
https://docs.spring.io/spring-kafka/reference/html/
=== Edited ===
Lets take their 3rd option (Delcaring a SimpleThreadScope and delegating to it)
Register SimpleThreadScope . It is not picked up automatically. You need to register it like below:
#Bean
public static BeanFactoryPostProcessor beanFactoryPostProcessor() {
return new BeanFactoryPostProcessor() {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
beanFactory.registerScope("thread", new SimpleThreadScope());
}
};
}
Create a component with scopeName = "thread"
#Component
#Scope(scopeName = "thread", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class KafkaDelegate{
public void handleMessageFromKafkaListener(String message){
//Do some stuff here with Message
}
}
Create a #Service
public class KafkaListenerService{
#Autowired
private KafkaDelegate kafkaDelegate;
#KafkaListener(id = "id1", topics = "testTopic" )
public void listen(String message) {
kafkaDelete.handleMessageFromKafkaListener(message);
}
}
Another example: How to implement a stateful message listener using Spring Kafka?
See this answer for an example of how to use a prototype scoped #KafkaListener bean.

Does Spring Webflux invokes single HandlerFunction in a single thread per request?

Considering the snippet below - is it safe to pass simple not thread-safe HashMap to a SomeHandlerFunction that will use it in other autowired beans in SomeHandlerFunction?
#Bean
RouterFunction<ServerResponse> request(SomeHandlerFunction handlerFunction) {
handlerFunction.setSimpleMapProperties(new HashMap());
return route(GET("/dummy"), handlerFunction);
}
#Service
class SomeHandlerFunction implements HandlerFunction {
#Autowired
List<AnotherBeans> anotherBeans;
Mono<T> handle(ServerRequest var1) {
// code...
}
}
I'm a bit aware about multithreading model in WebFlux, but this case made me confusing.
If that HashMap is mutable, it's not a good idea - not even with Spring MVC.
What should you do instead? It really depends on the use case at hand.
If you're trying to setup a local in-memory cache, you could use a library like Caffeine, or simply a ConcurrentMapCache.
If you'd like to share configuration keys with that bean, you could wrap that map with Collections.unmodifiableMap or even better, make that a proper immutable POJO.
If this is meant to carry temporary data that's linked with the request being processed, you should instead use request attributes or Reactor Context for that.

Spring Async for batch insertion

I'm using spring boot. I was new to spring and started a spring project. So I didn't know about pre defined repositories (JPA, CRUD) which can be easily implemented. In case, I wanted to save a bulk data, so I use for loop and save one by one, Its taking more time. So I tried to use #Async. But it doesn't also work, is my concept wrong?
#Async has two limitation
it must be applied to public methods only
self-invocation – calling the async method from within the same class won’t work
1) Controller
for(i=0;i < array.length();i++){
// Other codes
gaugeCategoryService.saveOrUpdate(getEditCategory);
}
2) Dao implementation
#Repository
public class GaugeCategoryDaoImpl implements GaugeCategoryDao {
// Other codings
#Async
#Override
public void saveOrUpdate(GaugeCategory GaugeCategory) {
sessionFactory.getCurrentSession().saveOrUpdate(GaugeCategory);
}
}
After removing #Async , it working normally. But with that annotation it doesn't work. Is there any alternative method for time consuming? Thanks in advance.
the #Async annotation creates a thread for every time you call that method. but you need to enable it in your class using this annotation #EnableAsync
You also need to configure the asyncExecutor Bean.
You can find more details here : https://spring.io/guides/gs/async-method/
In my opinion, there are several issues with your code:
You overwrite the saveOrUpdate() method without any need to do so. A simple call to "super()" should have been enough to make #Async work.
I guess that you somewhere (within your controller class?) declare a transactional context. That one usually applies to the current thread. By using #Async, you might leave this transaction context as (because of the async DAO execution), the main thread may already be finished when saveOrUpdate() is called. And even though I currently don't know it exactly, there is a good change that the declared transaction is only valid for the current thread.
One possble fix: create an additional component like AsyncGaugeCategoryService or so like this:
#Component
public class AsyncGaugeCategoryService {
private final GaugeCategoryDao gaugeCategoryDao;
#Autowired
public AsyncGaugeCategoryService(GaugeCategoryDao gaugeCategoryDao) {
this.gaugeCategoryDao = gaugeCategoryDao;
}
#Async
#Transactional
public void saveOrUpdate(GaugeCategory gaugeCategory) {
gaugeCategoryDao.saveOrUpdate(gaugeCategory);
}
}
Then inject the service instead of the DAO into your controller class. This way, you don't need to overwrite any methods, and you should have a valid transactional context within your async thread.
But be warned that your execution flow won't give you any hint if something goes wrong while storing into the database. You'll have to check the log files to detect any problems.

Using hystrix-javanica annotations on interfaces

I am integrating Hystrix into SilverWare microservices platform and I want to use hystrix-javanica annotations. These annotations are meant to be applied on the actual implementation of the methods that need to be executed using Hystrix. The problem is that I need to implement a generic solution where you only have a service interface. It has to be done this way in order to let developers use annotated references to other microservices (when they implement their own service) without any need to deal with the implementation of those services.
I came up with a solution where you annotate your microservice reference with something like this:
#Inject
#MicroserviceReference
#HystrixConfiguration(MyServiceHystrix.class)
private MyService myService;
And then you implement (or extend) the service interface and put Hystrix annotations on its methods:
public interface HystrixedMyService extends MyService {
#HystrixCommand
doSomething();
}
When there is #HystrixConfiguration annotation on a field in your microservice referencing another service, SilverWare will scan the class given as a parameter of this annotation and prepare a Hystrix command for every method of the service. The command will also receive a callable with an actual method invocation which will be executed in its run() method.
My question is: Is it possible to reuse some (internal) parts of hystrix-javanica so I do not need to scan all the annotations and create those Hystrix commands myself? I can see that most of the classes are designed to be used only with AOP.

Spring Framework Events

I was reading through Spring Framework documentation and found a section on raising events in Spring using ApplicationContext. After reading a few paragraphs I found that Spring events are raised synchronously. Is there any way to raise asynchronous events? your help is much appreciated. I am looking something similar which would help me to complete my module.
Simplest asynchronous ApplicationListener:
Publisher:
#Autowired
private SimpleApplicationEventMulticaster simpleApplicationEventMulticaster;
#Autowired
private AsyncTaskExecutor asyncTaskExecutor;
// ...
simpleApplicationEventMulticaster.setTaskExecutor(asyncTaskExecutor);
// ...
ApplicationEvent event = new ApplicationEvent("");
simpleApplicationEventMulticaster.multicastEvent(event);
Listener:
#Component
static class MyListener implements ApplicationListener<ApplicationEvent>
public void onApplicationEvent(ApplicationEvent event) {
// do stuff, typically check event subclass (instanceof) to know which action to perform
}
}
You should subclass ApplicationEvent with your specific events. You can configure SimpleApplicationEventMulticaster and its taskExecutor in an XML file.
You might want to implement ApplicationEventPublisherAware in your listener class and pass a source object (instead of empty string) in the event constructor.
Alternative notification strategies can be achieved by implementing ApplicationEventMulticaster (see Javadoc) and its underlying (helper) class hierarchy. Typically you use either a JMS based notification mechanism (as David already suggested) or attach to Spring's TaskExecuter abstraction (see Javadoc).
Spring itself (AFAIK) work synchronously, but what you can do is to create your own ApplicationListener proxy - a class that implements this interface but instead of handling the event it just delegates it by sending to another (or new) thread, sending JMS message, etc.
Try this override the ApplicationEventMulticaster bean in resources.groovy so that it uses a thread pool:
Some thing like this worked for me, i.e. I used
import java.util.concurrent.*
import org.springframework.context.event.*
beans = {
applicationEventMulticaster(SimpleApplicationEventMulticaster) {
taskExecutor = Executors.newCachedThreadPool()
}
}

Categories

Resources