Events subsystem¶
Events can occur in an application that require the response of loosely coupled objects.
For example: BSL Language Server configuration file (.bsl-language-server.json
) has a traceLog
field. In it, you can specify the path to the file to display a detailed log of the interaction between the server and the client. When a configuration is changed, a "server configuration changed" event is generated, and all components can reread it and reconfigure themselves if this event is important to them. In this example, the log output component changes the path to the output file.
The subsystem consists of three components:
- events;
- post events;
- event subscription.
The main difference from Spring Events is the transfer of event publishing from application code to an isolated layer using aspect-oriented programming.
A summary of Spring Events in the article https://www.baeldung.com/spring-events.
Events¶
All events are children of ApplicationEvent
. The event class must be placed in the events
subpackage of the package whose object can generate this event.
For example, change event com.github._1c_syntax.bsl.languageserver.configuration.LanguageServerConfiguration
is located in the package com.github._1c_syntax.bsl.languageserver.configuration.events
and and has the name LanguageServerConfigurationChangedEvent
.
In the event class it is recommended:
- declare a constructor that takes the "source" of the event (the object on which the event fired) and calls the
super
constructor; - override the
getSource
method, returningsource
cast to the source type.
/**
* Configuration change event.
* <p>
* Contains a link to the configuration as an event source.
*/
public class LanguageServerConfigurationChangedEvent extends ApplicationEvent {
public LanguageServerConfigurationChangedEvent(LanguageServerConfiguration configuration) {
super(configuration);
}
@Override
public LanguageServerConfiguration getSource() {
return (LanguageServerConfiguration) super.getSource();
}
}
Events publication¶
The EventPublisherAspect
aspect of the com.github._1c_syntax.bsl.languageserver.aop
package is used to publish events
Brief information about aspect-oriented programming you can find in page https://www.baeldung.com/aspectj.
To intercept events in an aspect, advice can be declared to intercept method calls and/or accesses to object properties.
An event object must be created in the advice body and published via ApplicationEventPublisher
.
To form a pointcut expression, you need to use templates in the
Pointcuts
class of thecom.github._1c_syntax.bsl.languageserver.aop
package
An example of intercepting the server configuration update event:
@Aspect
public class EventPublisherAspect {
@AfterReturning("Pointcuts.isLanguageServerConfiguration() && (Pointcuts.isResetCall() || Pointcuts.isUpdateCall())")
public void languageServerConfigurationUpdated(JoinPoint joinPoint) {
var configuration = (LanguageServerConfiguration) joinPoint.getThis();
applicationEventPublisher.publishEvent(new LanguageServerConfigurationChangedEvent(configuration));
}
}
Events subscriptions¶
To subscribe to an event, a component can implement the ApplicationListener
interface or declare a public method annotated with @EventListener
and taking a specific event class as a parameter.
Below is an example of handling the LanguageServerConfigurationChangedEvent
event via annotations:
@Component
public class FileAwarePrintWriter {
/**
* Обработчик события {@link LanguageServerConfigurationChangedEvent}.
*
* @param event Событие
*/
@EventListener
public void handleEvent(LanguageServerConfigurationChangedEvent event) {
setFile(event.getSource().getTraceLog());
}
}