14

I have a scenario configuring Spring Security on embedded Jetty which seems to be somewhat solved if I make use of JavaConfig to configure the Jetty server.

As a result, it's looking like JavaConfig rather than XML might be the better option for large chunks of the project. However, there are some niceties in the XML namespaces, like <context:component-scan /> which aren't readily available in a @Configuration setting.

I have discovered that ApplicationContextAware is honored for @Configuration classes, so the following is possible

@Configuration
public class FooConfig implements ApplicationContextAware {
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        ((AnnotationConfigApplicationContext) applicationContext).scan("org.example");
    }
}

The alternative, which is documented, is to have the @Configuration class use an @ImportResource annotation and pull in an existing XML file:

@Configuration
@ImportResource("applicationContext-withComponentScan.xml")
public class BarConfig {}

I guess the question is "Is it bad form to abuse ApplicationContextAware in this way, or is it really not abuse"? Something just feels oddly dirty about the approach so I'd not be surprised if the Spring guys had covered this in some way or another that I've not spotted.

For the interested, the problem relates to scanning a Jersey setup with @Resource and @Provider classes that I'd rather not have to manually manage entries in a class/XML configuration.

Community
  • 1
  • 1
ptomli
  • 11,730
  • 4
  • 40
  • 68

3 Answers3

36

Now that Spring 3.1 is ready and out, you can safely use @ComponentScan if you are on Spring 3.1. It's not only for Spring MVC as one of the outdated answers mentions. You can use it as follows:

@Configuration
@ComponentScan({"com.foo.bar", "org.foo.bar"})
public class AppConfig{ /** config code */ }

Here is the documentation http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/context/annotation/ComponentScan.html

user1713413
  • 361
  • 3
  • 3
5

Is it bad form to abuse ApplicationContextAware in this way, or is it really not abuse

Yes, this is bad form. If you're going to fetch things out of the context manually, you may as well not bother with dependency injection in the first place.

However, your second option (@ImportResource("applicationContext-withComponentScan.xml")) is a good one - this is current best practice when you want to use these XML macros in combination with annotation-style config.

A third option is to use the current milestone build of Spring 3.1, which adds a way of doing these things all in Java, using @Feature. This is not yet production-ready, though.

skaffman
  • 398,947
  • 96
  • 818
  • 769
  • Yes, 3.1 offers some nice shiny. But I'm not trying to "fetch things out of the context" but rather register things with the context, so not sure if you've understood correctly. scan("package") is the same as (give or take) context:component-scan, and the class doing so is specifically a configuration class. I'm still uneasy, but your argument doesn't really hold. Odd, I'm usually very impressed with your answers, so I'm expecting I've missed your point rather than you missing mine :) – ptomli Jul 13 '11 at 19:13
  • @ptomli: Yes, "fetch things out of the context" wasn't right; I was referring to the more general practice of getting injected with the context, (casting it), and then invoking a method in it. It couples your config class with the Spring SPI class, which isn't very elegant. I still recommend option 2. – skaffman Jul 13 '11 at 19:17
  • Yeah, even though the "load some XML to manage the JavaConfig" seems wrong, I think it's just because 3.0 didn't completely cover the bases. I have the same issue with a property configurer but strangely don't feel so weird about that. Cheers, stellar guidance as always! – ptomli Jul 13 '11 at 19:30
4

Check this link out as well. It is a bit more specific (for a web application) but it has a very nice code example for the scanning, specifically: http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/EnableWebMvc.html

from that link:

@ComponentScan(basePackages = { "org.example"} )
Donal Fellows
  • 133,037
  • 18
  • 149
  • 215