Java Developer Tools

Audit - Rules - Spring

Description
This group contains audit rules that look for code that violates the best practices specified for programs using the Spring framework.

Rules:

Details

Avoid Accessing the FactoryBean Directly

Summary
Avoid accessing the FactoryBean directly and invoking getObject() manually.

Description
This audit rule looks for places where a FactoryBean is accessed directly. Accessing the FactoryBean directly is actually very simple: you simply prefix the bean name with an ampersand in the call to getBean(). This feature is used in a few places in the Spring code, but your application should really have no reason to use it. The FactoryBean interface is intended to be used as a piece of supporting infrastructure to allow you to use more of your application's classes in an IoC setting. Avoid accessing the FactoryBean directly and invoking getObject() manually; if you do not, you are making extra work for yourself and are unnecessarily coupling your application to a specific implementation detail that could quite easily change in the future.

Example
The invocation factory.getBean("&shaDigest") in the following code would be flagged because it uses direct access to a FactoryBean:

    public class AccessingFactoryBeans {

        public static void main(String[] args) {
            BeanFactory factory = new XmlBeanFactory(new FileSystemResource("..."));

            MessageDigest digest = (MessageDigest) factory.getBean("shaDigest");

            MessageDigestFactoryBean factoryBean =
                    (MessageDigestFactoryBean) factory.getBean("&shaDigest");
        }
    }

Avoid Using Autowiring

Summary
Avoid using autowiring of dependencies through introspection of the bean classes.

Description
This audit rule looks for places where dependencies are being autowired. Spring can autowire dependencies through introspection of the bean classes so that you do not have to explicitly specify the bean properties or constructor arguments. Bean properties can be autowired either by property names or matching types. Constructor arguments can be autowired by matching types. Autowiring can potentially save some typing and reduce clutter.

However, you should not use it in real-world projects because it sacrifices the explicitness and maintainability of the configurations. Autowiring seems like a good idea to make the XML configuration file smaller, but this will actually increase the complexity down the road, especially when you are working on a large project where many beans are defined. Spring allows you to mix autowiring and explicit wiring, but the inconsistency will make the XML configurations even more confusing.

Example
The following bean declaration would be flagged:

    <bean id="orderService"
        class="com.test.spring.OrderService"
        autowire="byName"/>

Declare Setters for Bean Fields

Summary
Declare setter methods for all fields of bean class.

Description
This audit rule looks for fields declared in beans for which no setter methods are declared. Setter injection is the preferred type of dependency injection in Spring. Setter injection is more flexible and manageable. Your bean classes should have setters for all fields to use this technique.

Example
The field "text" would be flagged because it does not have a setter method:

    public class Bean {

        private String text;

        public String getText() {
            return text;
        }

        ...
    }

Don't Use Default Bean Names

Summary
Specify id as the bean identifier.

Description
This audit rule looks for places where the bean name is not explicitly given. If you give the tag an id attribute, then the value of that attribute is used as the name. If no id attribute is specified, Spring looks for a name attribute and, if one is defined, it uses the first name defined in the name attribute. (We say the first name because it is possible to define multiple names within the name attribute.) If neither the id nor the name attribute is specified, Spring uses the bean's class name as the name, provided, of course, that no other bean is using the same name.

Avoid using the automatic name by class behavior. This doesn't allow you much flexibility to define multiple beans of the same type, and it is much better to define your own names. That way, if Spring changes the default behavior in the future, your application will continue to work.

You can specify either an id or name as the bean identifier. Using ids will not increase readability, but it can leverage the XML parser to validate the bean references.

When choosing whether to use id or name, always use id to specify the bean's default name. The only drawback of using the id attribute is that you are limited to characters that are allowed within XML element IDs. If you find that you cannot use a character you want in your name, then you can specify that name using the name attribute, which does not have to adhere to the XML naming rules.

Example
Don't use

    <bean name="string2" class="java.lang.String"/>

or

    <bean class="java.lang.String"/>

Always use the following instead

    <bean id="string1" class="java.lang.String"/>

Implement BeanNameAware Interface

Summary
Implement the BeanNameAware interface in your bean classes.

Description
This audit rule looks for beans that do not implement the BeanNameAware interface. Being able to have a bean find out its name at runtime is really useful for logging. Consider a situation where you have many beans of the same type running under different configurations. The bean name can be included in log messages to help you differentiate between which one is generating errors and which ones are working fine when something goes wrong.

Implementation is fairly trivial and no special configuration is required to take advantage of the BeanNameAware interface.

Example
Implementation looks like following:

    public class LoggingBean implements BeanNameAware {
        private String beanName = null;

        public void setBeanName(String beanName) {
            this.beanName = beanName;
        }
    }

Missing Application Context File

Summary
XML files referenced in 'contextConfigLocation' attribute of <context-param> section in web.xml configuration file should exist.

Description
This audit rule looks for references to application context configuration files that do not exist. The application context configuration files are referenced in the contextConfigLocation attribute of a <context-param> section in the web.xml configuration file.

Example
Given the following content in a web.xml file:

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/dataAccessContext.xml
            /WEB-INF/applicationContext.xml
        </param-value>
    </context-param>

The file /WEB-INF/dataAccessContext.xml would be flagged if the file does not exist, as would the file /WEB-INF/applicationContext.xml.

Missing Bean Description

Summary
Every bean declaration should have a description.

Description
This audit rule looks for bean declarations that do not include a description. The advantage of using the description element is that it is easy for tools to pick up the description from this element.

Example
Bean declarations will be flagged unless they contain a description element such as the following:

    <beans>
        <description>
            ...
        </description>
        ...
    </beans>

Property File Must Exist

Summary
Property file referenced for the placeholder configurer bean must exists.

Description
If a bean uses one of the following classes:

    org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
    org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer
    org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer

this audit rule checks for a 'location' property and the existence of the property file referenced in this property.

Example
The file name jdbc.properties would be flagged if the file jdbc.properties does not exist:

    <bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location">
            <value>jdbc.properties</value>
        </property>
    </bean>

Referenced Class Not Defined

Summary
Classes referenced in Spring configuration files should be declared.

Description
This audit rule checks for references within a configuration file to classes that are not declared in the associated project. Either the references should be removed or the classes should be declared.

Example
In the following entry (from a XML configuration file), the value of the "class" attribute would be flagged:

    <bean
        id="test"
        class="class.not.exists/">

Undefined Placeholder

Summary
All properties used in placeholders should be defined in the property file.

Description
This audit rule looks for properties used in placeholders that are not defined in the associated property file.

Example
The string jdbc.missed would be flagged if "jdbc.missed" doesn't exist in the property file.

    <bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location">
            <value>/WEB-INF/jdbc.properties</value>
        </property>
    </bean>

    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName">
            <value>${jdbc.driver}</value>
        </property>
        <property name="url">
            <value>${jdbc.url}</value>
        </property>
        <property name="username">
            <value>${jdbc.user}</value>
        </property>
        <property name="missed">
            <value>${jdbc.missed}</value>
        </property>
    </bean>

Use Additional Attribute in Tag

Summary
Use an additional attribute in the <constructor-arg> tag in your configuration file.

Description
When you have more than one constructor argument or your class has more than one constructor you should specify an additional attribute (index or type, prefer type) in the <constructor-arg> tag. This audit rule looks for tags that need an additional argument but do not have one.

Example
If you have following class:

    public class ConstructorConfusion {

        private String someValue;

        public ConstructorConfusion(String someValue) {
            this.someValue = someValue;
        }

        public ConstructorConfusion(int someValue) {
            this.someValue = "Number: " + Integer.toString(someValue);
        }

        ...
    }

then the following <constructor-arg> tag would be flagged because the class has more than one constructor

    <bean id="constructorConfusion"
            class="com.test.spring.ConstructorConfusion">
        <constructor-arg>
            <value>90</value>
        </constructor-arg>
    </bean>

Use ApplicationContext to Assemble Beans

Summary
Use the ApplicationContext, rather than imports, to assemble beans.

Description
This audit rule looks for places where imports are used to assemble beans. Like imports in Ant scripts, Spring import elements are useful for assembling modularized bean definitions. However, instead of pre-assembling them in the XML configurations using imports, it is more flexible to configure them through the ApplicationContext. Using the ApplicationContext also makes the XML configurations easier to manage.

Example
Given the following bean declaration:

    <beans>
        <import resource="billingServices.xml"/>
        <import resource="orderServices.xml"/>
        <import resource="shippingServices.xml"/>

        <bean id="orderService"
            class="com.test.spring.OrderService"/>
    <beans>

the import lines would be flagged.

You can pass an array of bean definitions to the ApplicationContext constructor as follows:

    String[] serviceResources = { "orderServices.xml",
            "billingServices.xml", "shippingServices.xml" };
    ApplicationContext orderServiceContext = new ClassPathXmlApplicationContext(
            serviceResources);

Use idref Element

Summary
Use the idref element to pass the id of another bean in the container.

Description
The idref element is an error-proof way to pass the id of another bean in the container (to a <constructor-arg/> or <property/> element):

    <bean id="theTargetBean" class="..."/>

    <bean id="theClientBean" class="...">
        <property name="targetName">
            <idref bean="theTargetBean"/>
        </property>
    </bean>

The above bean definition snippet is exactly equivalent (at runtime) to the following snippet:

    <bean id="theTargetBean" class="..."/>

    <bean id="client" class="...">
        <property name="targetName">
            <value>theTargetBean</value>
        </property>
    </bean>

The main reason the first form is preferable to the second is that using the idref tag allows the container to validate at deployment time that the referenced, named bean actually exists. In the second variation, no validation is performed on the value that is passed to the 'targetName' property of the 'client' bean. Any typo will only be discovered (with most likely fatal results) when the 'client' bean is actually instantiated. If the 'client' bean is a prototype bean, this typo (and the resulting exception) might only be discovered long after the container is actually deployed.

Example
The <value> tag in the following bean declaration would be flagged:

    <bean id="client" class="...">
        <property name="targetName">
            <value>theTargetBean</value>
        </property>
    </bean>

Use Setter Injection

Summary
Use setter injection rather than constructor injection.

Description
This audit rule looks for beans that use constructor injection when they could be using setter injection. Spring provides three types of dependency injection: constructor injection, setter injection, and method injection. Typically we only use the first two types. Constructor injection can ensure that a bean cannot be constructed in an invalid state, but setter injection is more flexible and manageable, especially when the class has multiple properties and some of them are optional.

Example
The following bean declaration would be flagged because it uses constructor injection:

    <bean id="orderService"
        class="com.test.spring.OrderService">
        <constructor-arg ref="orderDAO"/>
    </bean>

it should be changed to:

    <bean id="orderService"
        class="com.test.spring.OrderService">
        <property name="orderDAO" ref="orderDAO">
    </bean>

Use Type for Constructor Argument Matching

Summary
Use the type attribute, rather than the index attribute, for constructor argument matching.

Description
Spring allows you to use a zero-based index to solve the ambiguity problem when a constructor has more than one arguments of the same type, or when value tags are used. Using an index is somewhat less verbose, but it is more error-prone and hard to read compared to using the type attribute. You should only use the index attribute when there is an ambiguity problem in the constructor arguments.

Example
For example, instead of using the index attribute as in the following:

    <bean name="billingService" class="example.test.BillingService">
        <constructor-arg index="0">
            <value>90</value>
        </constructor-arg>
    </bean>

it is better to use the type attribute like this:

    <bean name="billingService" class="example.test.BillingService">
        <constructor-arg type="int">
            <value>90</value>
        </constructor-arg>
    </bean>

Use XmlBeanFactory

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.