0

What basic recommendations for designing a Spring component?

Main purposes:

  • avoid NullPointerExceptions
  • flexibility for unit-testing
  • thread-safety

IMHO (based on Spring 4 official doc https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/beans.html#beans-constructor-injection (“constructor-based or setter-based DI?”)):

  • Optional fields should have default values. If required they should have annotations @Value (for simple types like int, String, etc) or @Autowired for complex objects.
  • Required fields should be final and declared in a sole contsructor with @Autowired annotation. If number of required fields more than 5, it is recommended to redesign classes. Every parameter in the constructor should be annotated with @Nonnull (e.g. javax.annotation.Nonnull) with null-checks inside.
  • (?) Set methods are not recommended. Though for unit-testing you can add some (but maybe better to add this field to constructor). Also, @Nonnull and null-checks should be used.
  • (?) Get methods are not recommended as well (why to open transitive access for internal fields?)

Example:

@Controller
@RequestMapping("/api/clients")
public final class ClientApiController {
    // optional field with a default value (simple type)
    @Value("${random.string.size}")
    private final int randomStringSize = 256;

    // optional field with a default value (complex type)
    @Autowired
    private final Charset defaultCharset = Charset.forName("UTF-8");

    // required field
    private final ClientService clientService;

    // sole constructor with required fields and NULL check
    @Autowired
    public ClientApiController(@Nonnull ClientService clientService) {
        Objects.requireNonNull(clientService, "clientService is null");
        this.clientService = clientService;
    }

    // no Set and Get methods
}
serg kunz
  • 505
  • 1
  • 4
  • 9

2 Answers2

1

I believe spring Component without any scope defined is just another class that has the only one instance when the application is created or also known as Singleton :) .

Just make sure that the dependencies injected are done using constructor. This will be very helpful in unit testing using any mocking framework.

Apart from this, just follow all the basic Object Oriented design facts that needs for a class. SOLID, DRY, etc..

Hope this helps. Cheers !!!

  • Partially, I agree with you. But I think not all dependencies should be injected via constructor. Some optional petty fields may be initialized in its declaration. I believe that the constructor with more than 5 parameters should be redesigned – serg kunz Nov 04 '18 at 08:12
0

I assume your assumption are made for Spring's Controller and not any Spring Component (because it'll be too general IMHO).

All fields in a Spring component should be final

Even if fields are effective final or better be final you don't have to do it

Optional fields should have default values

IMHO it depends on coding style

Required fields should be declared in a sole contsructor with @Autowired

Adding constructor for null checks can be consider unnecessary code, because Controller won't work well with/without constructor if there's an issue.

About get/set methods you didn't have it in your code so it's too general to answer

Ori Marko
  • 56,308
  • 23
  • 131
  • 233
  • _I assume your assumption are made for Spring's Controller and not any Spring Component (because it'll be too general IMHO)_ No, I’m looking for a general solution for any Spring component, not only controller. _Even if fields are effective final or better be final you don't have to do it_ I’m talking about recommendations; of course it is up to you. I think “final” will be a good marker for another programmers that work with your code – serg kunz Nov 04 '18 at 06:54
  • @sergkunz you can add final to any method parameter,but you don't do it, why? see https://stackoverflow.com/questions/2236599/final-keyword-in-method-parameters – Ori Marko Nov 04 '18 at 06:56
  • _No, Autowired Service/DAO classes shouldn't have default value_ I meant that for optional fields. Autowired Service/DAO classes are obviously required fields and should be declared in a constructor. – serg kunz Nov 04 '18 at 06:57
  • @sergkunz you are right, updated to IMHO it depends on coding style – Ori Marko Nov 04 '18 at 06:59
  • _you can add final to any method parameter,but you don't do it, why_ Generally It's another topic ;) – serg kunz Nov 04 '18 at 07:00
  • @sergkunz also if you want *flexibility for unit-testing* `final` may ruin it – Ori Marko Nov 04 '18 at 07:06
  • _@sergkunz you are right, updated to IMHO it depends on coding style_ you can get **NullPointerException** for **optional** fields with no-default values – serg kunz Nov 04 '18 at 07:07
  • _also if you want flexibility for unit-testing final may ruin it_ maybe better to add such field into the constructor? – serg kunz Nov 04 '18 at 07:17