Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

321
Views
Spring 4.2+ : How to reference a Spring bean instance from inside an @EventListener condition expression

In Spring 4.2+, we can use @EventListener annotation with a "condition" expression.

In my scenario, I need to match the id of the event object with a regular expression that is configured in a .properties file.

However, it seems impossible to reference any bean's property or method from the condition's regular expression, as the root context seems to be the event object itself.

So far, I have an abstract class, that sets the event id pattern property based on the class name. The goal is to make the implementation of each Event Listener as clean and simple as possible.

@Service
@PropertySource(value = "classpath:subscriberEventMapping.properties")
public abstract class AbstractEventHandler implements IEventHandler {

    private String eventIdPattern;

    @Autowired
    Environment env;

    @Autowired(required = true)
    public void configureEventIdPattern() {
        String simpleClassName = this.getClass().getSimpleName();
        String resolvedEventIdPattern = env.getProperty(
            simpleClassName.substring(0,1).toLowerCase() + 
            simpleClassName.substring(1, simpleClassName.length()));
        this.eventIdPattern = resolvedEventIdPattern == null ? ".*" : resolvedEventIdPattern;
    }

    public String getEventIdPattern() {
        return eventIdPattern;
    }
}

The properties file looks like this:

regExpEventHandler=^(901|909|998|1000)$
dummyEventHandler=^([1-9][0-9]{0,2}|1000)$

And then, I have a sample Event Listener that extends the above Abstract class:

@Service
public class RegExpEventHandler extends AbstractEventHandler {

    @Log
    private ILog logger;

    @Override
    @EventListener(condition = "#event.eventid matches @regExpEventHandler.getEventIdPattern()")
    public void onEvent(Event event) {
        logger.debug("RegExpEventHandler processing : {} with event pattern : {}", event, getEventIdPattern());
    }
}

The problem is that the expression

"#event.eventid matches @regExpEventHandler.getEventIdPattern()"

does not work, because the bean "@regExpEventHandler" cannot be found in the context used by the @EventListener.

Is there a way to access methods or properties of an existing Spring Bean here? Any other better approach for this scenario ?

I know I can easily access STATIC constants or methods by using something like:

#event.eventid matches T(my.package.RegExpEventHandler.MY_CONSTANT)

But a String constant (static final) cannot be initialized from a properties file using a @Value expression.

Using NON-FINAL static constants can work, but then EACH Event Listener needs to add boiler-plate to initialize the static constant from a non-static variable using a @Value expression, which we want to avoid.

Thanks a lot in advance !

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

It works for me - I looked at the EventExpressionEvaluator and saw that it added a bean resolver to the evaluation context...

public EvaluationContext createEvaluationContext(ApplicationEvent event, Class<?> targetClass,
        Method method, Object[] args, BeanFactory beanFactory) {

    Method targetMethod = getTargetMethod(targetClass, method);
    EventExpressionRootObject root = new EventExpressionRootObject(event, args);
    MethodBasedEvaluationContext evaluationContext = new MethodBasedEvaluationContext(
            root, targetMethod, args, getParameterNameDiscoverer());
    if (beanFactory != null) {
        evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
    }
    return evaluationContext;
}

So I wrote a quick test...

@SpringBootApplication
public class So43225913Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(So43225913Application.class, args);
        context.publishEvent("foo");
    }

    @EventListener(condition = "@bar.accept(event)")
    public void listen(Object event) {
        System.out.println("handler:" + event);
    }

    @Bean
    public Bar bar() {
        return new Bar();
    }

    public static class Bar {

        public boolean accept(Object o) {
            System.out.println("bar:" + o);
            return true;
        }
    }

}

and it works just fine...

bar:org.springframework.context.PayloadApplicationEvent[...
handler:foo

(This was with 4.3.7; boot 1.5.2).

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!