Verifying Configuration in Spring

A common practice that I used to follow, and made sure is followed in my projects is to have all configured beans in my application implement the InitializingBean interface. This was just to make sure that all configured beans were indeed fully configured in the application context. So for example, if I had a form controller which used a UserManager, it would look like this:

public class AddUserFormController extends SimpleFormController
    implements InitializingBean {

    // the user manager this controller uses to add users.
    private UserManager userManager;

    // more code comes here...

    // the setter for the user manager
    // (used to inject the user manager into this controller).
    public void setUserManager(UserManager userManager) {
        this.userManager = userManager;
    }

    // InitializingBean impl.
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(userManager, "Required property 'userManager' is not set");
    }
}

This approach works well, and it makes sure that the beans are configured correctly. But it’s a bit twisted way to achieve this goal. First, it makes your code tied to Spring. Not that it’s such a bad thing, after all, if you choose for spring in the first place, it’s probably not going to change. But it’s also a bit tedious to implement this interface in every bean and write these assertions over and over again.

Using java 5 annotations and spring’s BeanPostProcessor makes a much better solution. The idea is to have a @Required annotation and apply it on all configured fields of the configured classes. If we take the previous example, it looks somthing like this:

public class AddUserFormController extends SimpleFormController {

    // the user manager this controller uses to add users.
    @Required private UserManager userManager;

    // more code comes here...

    // the setter for the user manager (used to inject the user manager into this controller).
    public void setUserManager(UserManager userManager) {
        this.userManager = userManager;
    }

}

As you can see, this is a major time and code saver. The nice thing about it is that the @Required annotation is not related to spring or any other technology. It is actually one of the only real valid use cases for which annotations were introduced in the first place (along with validation :-)).

To make it work in spring, all is needed is to write a BeanPostProcessor that inspects every configured bean after initialization, and for each field which is marked as required, validate that indeed it is not set to null. Just put this bean post processor in the application context, and you’re done.

13 Responses to “Verifying Configuration in Spring”

  1. Keith Donald Says:

    Nice article, and nice example of a valid use case for a BeanPostProcessor, an important Spring container hook.

  2. A Couple of Dutch Rants » Re: Annotations vs Interoperability? Says:

    […] ** Update Have a look at Uri’s blog. He’s showing a perfectly valid @Required annotation in my opinion that doesn’t change anything to the behavior of the class and doesn’t impose any difficulties when using this class outside its natural habitat .   […]

  3. Magnus Heino Says:

    I have already done this.

    http://opensource2.atlassian.com/projects/spring/browse/SPR-1047 assigned to Rob for M3.

    The code in the jira is not the latest, I have added support for autowire since then. I don’t know if Rob’s intentions are to use simular code or to implement it in some other way.

  4. Magnus Heino Says:

    I just added my latest code to jira as it is in case anyone want to use it.

  5. Boness Says:

    Magnus,

    Indeed it would be great if this (and perhaps other such post processing tasks) will be added to spring

    I’m not sure that the BeanFactoryPostProcessor is the right thing to use here though. As I see it there are two major issues with it:
    1) Nested beans are not checked and validated
    2) The is applied only to the configured bean and to its configured dependencies. I think the non-configured fields should be validated as well.

    Using BeanPostProcessor can solve these issues. Of course, you wouldn’t want to check and validate all possible classes (like jdk classes), so a class filter can be configured on the processor.

  6. Magnus Heino Says:

    1. I do check for inner beans if thats what you mean by nested beans? I also check parent beans, beans contained in lists, maps etc.

    2. It is applied to all properties in beans with the @RequiredProperty annotation. It doesn’t matter if they are actually configured or not.

    You will get an exception if it cannot detect that a property declared as @RequiredProperty isn’t configured to receive a reference/value having the correct type when a instance is created later on. And this will happen at boot time, not sometime in the future when the instance is created.

    Using BeanPostProcessor will not solve anything, using BeanPostProcessor means that this isn’t possible at all. And I do want to check that “@RequiredProperty String foo;” is configured to receive a string when a instance is created. Otherwise I shouldn’t declare it as required.

  7. Boness Says:

    I understand what you say, and you’re right about the nested beans (inner beans)… I just didn’t see the latest impl. But as I see the @Required annotation has nothing to do with properties, but more with fields… a class can have fields which are not properties but are still required. I see it more as a sanity check for the developer. Besides that, how do you handle configuration of BeanFactories?

  8. A Couple of Dutch Rants » So when SHOULD you use annotations? Says:

    […] [1] Uri Boness in Dude, where’s my class? [2] Arjen Poutsma in Annotations/Attributes: How do they help us? [3] Rod Johnson in Ecsaping the Technology Cycle [4] Arjen Poutsma in Annotations vs. Interoperability [5] myself in Re: Annotations vs. Interoperability [6] Uri Boness in Verifying configuration in Spring   […]

  9. Aleks Seovic Says:

    Hi Uri,

    I’ve been talking to Rob about this exact thing at TSE in December, and he didn’t seem to like the idea too much. Part of the problem was that I believe we were thinking about different things: he was talking about @SpringConfigured and I was talking about this…

    Anyway, I agree that this is good use of annotations and this is what I’ve been planning to add to Spring.NET for a while. What I had in mind was slightly different though: instead of using @Required annotation, I was going to define @Dependency with an optional Required property. In .NET it would look something like this:

    [Dependency(Required = true)]
    private UserManager userManager;

    I think this approach has a couple of benefits:

    1. It documents what userManager field/property is, which is in my opinion one good use of annotations.

    2. It allows you to annotate dependencies that are not required as well, which, while not very useful for configuration verification example you used, can be *very* useful for tool support, such as Spring IDE.

    The real reason I’m replying to your post though, is that I don’t agree with is the assertion that annotations are good choice for validation (I’m assuming you are talking about general data validation, not Spring config validation in this case). While they seem like a perfect way to specify validation rules, they break apart very quickly.

    For example, same object often needs to be validated differently, based on the context in which it is used. If validation rules are hardcoded within the class itself, you loose this ability. Basically, what I’m trying to say is that validation rules are not tied to the object itself, but to the use case that uses an object.

    Second, validation rules are often conditional: ReturnDate property of the Trip object is only required if Trip.Type == “RoundTrip”. While simple cases like this could be specified using annotations, it would be very difficult to cover more complex cases where condition has dependency on other objects that are external to Trip.

    Finally, validation rules often need to be composed, which is impossible to do with annotations.

    Sorry for the long reply :)

    Aleks

  10. Boness Says:

    Aleks,

    I kind of’ like your idea of the dependency annotation. Indeed it provides more metadata over the specific field then just required - sort of distinguishes it from other internally managed fields.

    About the validation, well… I thought about these arguments myself for quite some time now and here’s my 5 cents:

    1. It’s not about annotations per-se… it’s about meta data. it can come in the form of annotations or an external xml configuration (which should always come along side with annotation usage anyway). As I see it, validation is part of your domain and therefore should be coupled with it. One interesting discussion I had with Arjen was about distinguishing between domain specific constraints and data constraints. While domain specific constraints should be coupled with the domain, it should be possible to add more (or override existing ones) externally with data constraints. For example, if the domain requires that a username field be at least 6 char. long - conceptually there’s no upper limit for this field. In practice, there is a data constraint (due to the database in use) that you’d like to add - say, username can have at most 50 chars.

    2. I thought about it a lot, and from some experiments I made, I realized that most times when the validation of you domain model is bound to the context, then probably the domain is not modeled correctly. Using your example, if you have a Trip class, then it would probably be wise to have a subclass called RoundTrip. Doing so, will model your domain more precisely and let you keep the static validation (constraint) in your model. I actually find this technique a quite helpful when designing your domain model in the first place. Of course, I didn’t think of all use cases, but it’s something I definitely want to experiment with.

    3. As mentioned above, it’s about meta-data not about annotations. Indeed annotations are very limited when it comes to composing validation rules (and, or, not..). Practically speaking - 90% of the time you only need the “and” notion. This is where specific validation annotations can be used (@MinLength @MaxLength @NotNull…), if a more sophisticated validation is needed, a more generic expression-based annotation can be used (using OGNL or Valang). If you define these annotations you can get away with quite a lot… I don’t know if you can get away with everything… but that’s part of my experiments now… after all you don’t know if something is working until you actually tried working with it in real-world projects.

    4. Dependencies between fields or any other conditional validation rules can also be applied using validation expressions.

    cheers,

    Uri

  11. Aleks Seovic Says:

    * quote *
    As I see it, validation is part of your domain and therefore should be coupled with it.
    * end quote *

    And that’s exactly the statement I have problem with :-) Validation is not part of the domain — validation rules *operate* on the domain, but they are separate.

    Let me give you an example that I often have to deal with. I do a lot of work in document management space, and documents usually go through a lifecycle. When document is created, it is typically in a Draft state, than as it progresses through different review and approval workflows its state might change to Routed for Review, Routed for Approval and Approved. Once there is a newer version of the same document, we might change its lifecycle state to Superseded, or if it is no longer needed but we still want to keep it around for historical purposes, we’d change its state to Obsolete.

    Each document has content and the metadata, such as name, authors, keywords, and other attributes that are necessary to describe particular document type.

    Here’s the thing — when document is initially created (in Draft state), users might be required to enter only a few attributes, such as name and description. As it moves through different states, each state might require different attributes to be defined — basically, validation rules are different based on the lifecycle state document is in.

    That said, I think we are on the same page — I do agree that validation rules are metadata. The only thing I was trying to point out is that attributes/annotations are not rich enough mechanism to capture their complexity, and are inappropriate for all but the simplest validation rules (in which case, my preference is not to use them at all, rather than to have validation rules scattered between annotations and some external mechanism, say XML config).

    Just to give you an idea, here is sample definition of the validation rules for Trip object discussed earlier that uses Spring.NET validation framework (all validator definitions are standard Spring objects, we just have a custom configuration parser registered for that schema — another thing those Spring Java guys stole from us ;-)

    = DateTime.Today” when=”StartingFrom.Date != DateTime.MinValue”>

    = StartingFrom.Date” when=”ReturningFrom.Date != DateTime.MinValue”>

    Later,

    Aleks

  12. Aleks Seovic Says:

    Damn, that’s not how validation rules for Trip object were supposed to look :)

    Not quite sure how to escape code here, maybe it will be easier to send you sample via email if you want to look at it. Just ping me at aleks at seovic dot com.

    Later,

    Aleks

  13. maysam Says:

    Hi
    Would you possibly tell me how it’s possible to check more than one condition in when statement?

    A && B doesn’t work for me!

Leave a Reply