In this article, we'll demonstrate a few ways to dramatically simplify configuration task to configure similar components.
Problem
Normally, one top level tag registers one component. If we have 1000 components to register into the container, we need at least 1000 top level tags to finish the task. This is fine if the configuration of these components differ from each other. It is however a pain if they share the same pattern.
For instance, the following configuration declares a bunch of domain classes as Java Bean using auto-wiring:
These definitions share very similar pattern. The only thing different is the class name and the id.
Solution
For this case, there are two out-of-box optional Nut classes that can help:
- jfun.yan.xml.nuts.optional.ForeachRegisterNut
- jfun.yan.xml.nuts.optional.PropertiesRegisterNut
If we load the ForeachRegisterNut as <define>:
We can simplify the definitions into one tag:
<define> will repeatedly call the nested function by passing every name into it. The result will be dynamically registered into the container. Just in case you don't already know, the "${name}" is string interpolation. It evaluates to "com.mycompany.Customer" when the value of variable "name" is "Customer".
Now, all we have to do is just listing the simple class names in the "names" attribute.
The PropertiesRegisterNut is slightly different than ForeachRegisterNut in that it doesn't require you explicitly listing all the names. Instead, it accepts a property file name and read the keys and values from this file.
So, if we have a properties file named "domains.properties" located in the classpath under "/com/mycompany/":
we can load the PropertiesRegisterNut and use it as:
Sometimes, we may want to register Customer under fully qualified name "com.mycompany.Customer". This can be done with the "prefix" attribute of these two Nut classes. For example:
Or,
Restrictions
- These dynamic registration tags can only be used at the top level. They can't be nested inside another tag.
- The ids of these dynamically registered components cannot be referenced using the standard "$" variable names. They are determined dynamically hence unknown at compile time.
In order to reference them, another optional Nut class "jfun.yan.xml.nuts.optional.RefNut" needs to be used. For example:The id specified by the <ref> tag is not checked at compile time. So runtime error could occur when there's a typo.
More Extension
ForeachRegisterNut and PropertiesRegisterNut both extend from AbstractLoopRegisterNut. In case these two tags cannot handle your case, just extend from them or from AbstractLoopRegisterNut to provide your own implementation. You may for example implement auto-registration of classes from a jar file, or any other mechanism.
