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
}
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 !!!
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
Related
I have a simple URL builder class with a method that gets a field value from properties via #Value annotation.
#Getter
#Component
public class UrlBuilder {
#Value("${url.api}")
private String apiUrl;
#Value("${url.auth}")
private String authUrl;
public String buildApiUrl(String urlAppendix, Map<String, String> queryParams){
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(apiUrl + urlAppendix);
if (!isEmpty(queryParams)){
for (String key : queryParams.keySet()){
builder.queryParam(key, queryParams.get(key));
}
}
return builder.toUriString();
}
}
Is there a good reason to make the method static and use setter value injection on a static field? So far I had the UrlBuilder being injected via constructor.
Static fields and static injection are an anti-pattern in general, since they amount to global shared state, and create ordering dependencies and occasionally thread-safety issues. (It's hard to ensure that callers never call the buildApiUrl method before static injection takes place.) This is especially true if you're considering using a non-static setter method to set this static field, because that means that calling the setter on one instance will implicitly modify every other instance as well. It's a confusing API; clients will make assumptions based on common practice, and won't notice that their assumptions are wrong unless they really scrutinize the code.
The main reason to consider using a static field is if you have legacy code that isn't integrated with the dependency injection framework. In that sort of situation, you may need to work around the mismatch by creating singleton adapters that forward calls from static methods to dependency-injected beans. But you'll want to do as little of that as you can get away with; it's better to migrate legacy code to use dependency injection, when possible, than to migrate legacy code to use awkward static adapters around dependency injection.
I would never suggest creating static methods in spring bean classes, usually in spring framework until creating util classes i would not recommend static methods.
When to use static methods in Java?
The code in the method is not dependent on instance creation and is not using any instance variable.
A particular piece of code is to be shared by all the instance methods.
The definition of the method should not be changed or overridden.
you are writing utility classes which should not be changed.
I would say you don't need any iteration or util method here, just use the spring MultiValueMap
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("A", "B");
map.add("C", "D");
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://localhost:8080");
builder.queryParams(map); //http://localhost:8080?A=B&C=D
I read in some posts about Spring MVC and Portlets that field injection is not recommended. As I understand it, field injection is when you inject a Bean with #Autowired like this:
#Component
public class MyComponent {
#Autowired
private Cart cart;
}
During my research I also read about constructor injection:
#Component
public class MyComponent {
private final Cart cart;
#Autowired
public MyComponent(Cart cart){
this.cart = cart;
}
}
What are the advantages and the disadvantages of both of these types of injections?
EDIT 1: As this question is marked as duplicate of this question i checked it. Cause there aren't any code examples neither in the question nor in the answers it's not clear to me if i'm correct with my guess which injection type i'm using.
Injection types
There are three options for how dependencies can be injected into a bean:
Through a constructor
Through setters or other methods
Through reflection, directly into fields
You are using option 3. That is what is happening when you use #Autowired directly on your field.
Injection guidelines
A general guideline, which is recommended by Spring (see the sections on Constructor-based DI or Setter-based DI) is the following:
For mandatory dependencies or when aiming for immutability, use constructor injection
For optional or changeable dependencies, use setter injection
Avoid field injection in most cases
Field injection drawbacks
The reasons why field injection is frowned upon are as follows:
You cannot create immutable objects, as you can with constructor injection
Your classes have tight coupling with your DI container and cannot be used outside of it
Your classes cannot be instantiated (for example in unit tests) without reflection. You need the DI container to instantiate them, which makes your tests more like integration tests
Your real dependencies are hidden from the outside and are not reflected in your interface (either constructors or methods)
It is really easy to have like ten dependencies. If you were using constructor injection, you would have a constructor with ten arguments, which would signal that something is fishy. But you can add injected fields using field injection indefinitely. Having too many dependencies is a red flag that the class usually does more than one thing, and that it may violate the Single Responsibility Principle.
Conclusion
Depending on your needs, you should primarily use constructor injection or some mix of constructor and setter injection. Field injection has many drawbacks and should be avoided. The only advantage of field injection is that it is more convenient to write, which does not outweigh all the cons.
Further reading
I wrote a blog article about why field injection is usually not recommended: Field Dependency Injection Considered Harmful.
This is one of the never-ending discussions in software development, but major influencers in the industry are getting more opinionated about the topic and started to suggest constructor injection as the better option.
Constructor injection
Pros:
Better testability. You do not need any mocking library or a Spring context in unit tests. You can create an object that you want to test with the new keyword. Such tests are always faster because they do not rely on the reflection mechanism. (This question was asked 30 minutes later. If the author had used constructor injection it would not have appeared).
Immutability. Once the dependencies are set they cannot be changed.
Safer code. After execution of a constructor your object is ready to use as you can validate anything that was passed as a parameter. The object can be either ready or not, there is no state in-between. With field injection you introduce an intermediate step when the object is fragile.
Cleaner expression of mandatory dependencies. Field injection is ambiguous in this matter.
Makes developers think about the design. dit wrote about a constructor with 8 parameters, which actually is the sign of a bad design and the God object anti-pattern. It does not matter whether a class has 8 dependencies in its constructor or in fields, it is always wrong. People are more reluctant to add more dependencies to a constructor than via fields. It works as a signal to your brain that you should stop for a while and think about your code structure.
Cons:
More code (but modern IDEs alleviate the pain).
Basically, the field injection is the opposite.
Matter of taste. It is your decision.
But I can explain, why I never use constructor injection.
I don't want to implement a constructor for all my #Service, #Repository and #Controller beans. I mean, there are about 40-50 beans or more. Every time if I add a new field I would have to extend the constructor. No. I don't want it and I don't have to.
What if your Bean (Service or Controller) requires a lot of other beans to be injected? A constructor with 4+ parameters is very ugly.
If I'm using CDI, constructor does not concern me.
EDIT #1:
Vojtech Ruzicka said:
class has too many dependencies and is probably violating single
responsibility principle and should be refactored
Yes. Theory and reality.
Here is en example: DashboardController mapped to single path *:8080/dashboard.
My DashboardController collects a lot of informations from other services to display them in a dashboard / system overview page. I need this single controller. So I have to secure only this one path (basic auth or user role filter).
EDIT #2:
Since everyone is focused on the 8 parameters in the constructor... This was a real-world example - an customers legacy code. I've changed that. The same argumentation applies to me for 4+ parameters.
It's all about code injection, not instance construction.
One more comment - Vojtech Ruzicka stated that Spring injects beans in such three ways (the answer with the biggest numbers of points) :
Through a constructor
Through setters or other methods
Through reflection, directly into fields
This answer is WRONG - because FOR EVERY KIND OF INJECTION SPRING USES REFLECTION!
Use IDE, set breakpoint on setter / constructor, and check.
This can be a matter of taste but it can also be a matter of a CASE.
#dieter provided an excellent case when field injection is better. If You're using field injection in integration tests that are setting up Spring context - the argument with testability of the class is also invalid - unless You want to write later on tests to Your integration tests ;)
I have an Ingestion class that exposes a single method ingest. This method processes each section of a passed in form (section 1, section 2, etc, etc).
I have private methods for each section, saving the entity as it processes through. I'm aware that #Transactional has no effect on private methods, however I do not want to expose these methods but would like to use the functionality that #Transactional provides.
I'm looking to make sure each section completes in its own Transaction; I could do this through 'AspectJ' (as other SO answers have suggested) instead of Spring's out the box implementation, but I am trying to avoid due to the system wide changes it would cause.
Any thoughts on another approach?
The pseudo code provided below gives a general idea on the structure of the class:
public Class Ingestion {
// Autowired Repo's
...
...
#Transactional
public void ingest(Form form){
this.processSection1(form);
this.processSection2(form);
this.processSection3(form);
}
#Transactional
private void processSection1(Form form){
// do specific section 1 logic
section1Repo.save(form);
}
#Transactional
private void processSection2(Form form){
// do specific section2 logic
section2Repo.save(form);
}
#Transactional
private void processSection3(Form form){
// do specific section3 logic
section3Repo.save(form);
}
}
=========================================================================
This is not a duplicate question as marked in the comments. I know #Transactional doesnt work on private methods. My question is more along the lines of 'how do we get around this Spring AOP issue without having to use AspectJ'
The reason this doesn't work is that annotations like #Transactional add additional functionality that is intercepted by Spring's proxy object that wraps the actual object. But when you call a private method on an object with the this keyword, you're going straight to the real object and bypassing the proxy.
One way to solve this is to #Autowire the object into itself, and make the transactional calls via that autowired variable. You can still access private methods that way, and the call will be to a Spring-managed proxy instead of the bare object.
You may extract these three processing methods in another class, make them public, but set the class constructor access level to package-local (but not private, since Spring can't proxy classes with private constructors), so no classes from other packages could access these methods just because they are not able to instantiate their class. It doesn't hide these methods completely, but may fit your needs. This trick can be done with an inner class as well (note that it must be declared with package-local access).
To completely hide these methods, you may make use of declarative transaction management by injecting TransactionTemplate bean and using its execute method in private methods. This feature comes out-of-the-box. See more here.
Also, take note that for creating new transaction on executing method B from method A, method B must be declared #Transactional with propagation type REQUIRES_NEW. Otherwise, any nested methods will be invoked in the same transaction started by initial calling method.
I couldn't find any reasonable answer here on SO so I hope it's not a duplicate. So why should I prefer setter or constructor injection over simple
#Inject
MyBean bean;
I get the usage of the constructor injection if you need to do something with injected bean during your class initialization like
public void MyBean(#Inject OtherBean bean) {
doSomeInit(bean);
//I don't need to use #PostConstruct now
}
but still, it's almost the same like #PostConstruct method and I don't get setter injection at all, isn't it just a relic after Spring and other DI frameworks?
Constructor and property injection gives you the option to initialize the object even in a non CDI environment easily, e.g a unit test.
In a non-CDI environment you can still simply use the object by just passing the constructor arg.
OtherBean b = ....;
new MyBean(b);
If you just use field injection you usually must use reflection to access the field, because fields are usually private.
If you use property injection you can also write code in the setter. E.g. validation code or you clear internal caches that hold values which are derived from the property that the setter modifies. What you want to do depends on your implementation needs.
Setter vs constructor injection
In object-oriented programming an object must be in a valid state after construction and every method invocation changes the state to another valid state.
For setter injection this means that you might require a more complex state handling, because an object should be in a valid state after construction, even if the setter has not been invoked yet. Thus the object must be in a valid state even if the property is not set. E.g. by using a default value or a null object.
If you have a dependency between the object's existence and the property, the property should either be a constructor argument. This will also make the code more clean, because if you use a constructor parameter you document that the dependency is necessary.
So instead of writing a class like this
public class CustomerDaoImpl implements CustomerDao {
private DataSource dataSource;
public Customer findById(String id){
checkDataSource();
Connection con = dataSource.getConnection();
...
return customer;
}
private void checkDataSource(){
if(this.dataSource == null){
throw new IllegalStateException("dataSource is not set");
}
}
public void setDataSource(DataSource dataSource){
this.dataSource = dataSource;
}
}
you should either use constructor injection
public class CustomerDaoImpl implements CustomerDao {
private DataSource dataSource;
public CustomerDaoImpl(DataSource dataSource){
if(dataSource == null){
throw new IllegalArgumentException("Parameter dataSource must not be null");
}
this.dataSource = dataSource;
}
public Customer findById(String id) {
Customer customer = null;
// We can be sure that the dataSource is not null
Connection con = dataSource.getConnection();
...
return customer;
}
}
My conclusion
Use properties for every optional dependency.
Use constructor args for every mandatory dependency.
PS: My blog The difference between pojos and java beans explains my conclusion in more detail.
EDIT
Spring also suggests to use constructor injection as I found in the spring documentation, section Setter-based Dependency Injection.
The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null. Furthermore, constructor-injected components are always returned to the client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns.
Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection.
Constructor injection is also a better way when you think about unit tests, because it is easier to call the constructor instead of setting private (#Autowired) fields.
When using CDI, there is no reason whatsoever to use constructor or setter injection. As noted in the question, you add a #PostConstruct method for what would otherwise be done in a constructor.
Others may say that you need to use Reflection to inject fields in unit tests, but that is not the case; mocking libraries and other testing tools do that for you.
Finally, constructor injection allows fields to be final, but this isn't really a disadvantage of #Inject-annotated fields (which can't be final). The presence of the annotation, combined with the absence of any code explicitly setting the field, should make it clear it is to be set by the container (or testing tool) only. In practice, no one will be re-assigning an injected field.
Constructor and setter injection made sense in the past, when developers usually had to manually instantiate and inject dependencies into a tested object. Nowadays, technology has evolved and field injection is a much better option.
Accepted answer is great, however it doesn't give credit to the main advantage of constructor injection - class immutability, which helps to achieve thread-safety, state safety, and better readability on the classes.
Consider you have class with dependencies and all of those dependencies are provided as constructor arguments, then you can know that the object will never exist in a state where dependencies are invalid. There is no need for setters for those dependencies (as long as they are private), so the object is instantiated to a full state or is not instantiated at all.
An immutable object is much more likely to well behave in an multithreaded application. Although the class still needs to be made internally thread-safe, you don't have to worry about external clients coordinating access to the object.
Of course this can be usefull only in certain scenarios. Setter injection is great for partial depencdency, where for example we have 3 properties in a class and 3 arg constructor and setters methods. In such case, if you want to pass information for only one property, it is possible by setter method only. Very useful for testing purposes.
I have an abstract class with two Map fields. One I would like to mock and inject into an object of a subclass of AbstractClass for unit testing. The other I really don't care much about, but it has a setter.
public abstract class AbstractClass {
private Map<String, Object> mapToMock;
private Map<String, Object> dontMockMe;
private void setDontMockMe(Map<String, Object> map) {
dontMockMe = map;
}
}
When using #InjectMocks, it automatically tries to inject in the order: constructor, setter, field. It checks if it can inject in each of these places by checking types, then names if there are multiple type possibilities. This doesn't work well for me, because my mocked mapToMock is actually injected into dontMockMe via its setter. I cannot edit this abstract class. Is there any way for me to get around the setter injection? Thank you in advance!
Well this is a corner case, where automatic injection won't work in the way Mockito injection is currently designed. Also Mockito suffer from some shortcomings when there is multiple fields with the same types.
So to understand why this doesn't work let's dive a bit in the way Mockito performs injection :
It will try to inject dependencies via constructor injection, if it successes it won't try the following steps in order to protect the newly created instance from eventual side effects.
Then if constructor injection did not happen (no arg constructor, or object already instantiated), then Mockito will look for matches between mocks and setters. But it has to make some choices for it to happen automatically.
If there is only mock of type A and only one setter with type A then setter injection will happen.
If there is either multiple mocks or setters of type A it will try to find match using the type and the name of the mock (usually the #Mock field name). If matches are found then injection will happen.
Then if there is still some mocks left for injection, field injection might happen, using the same algorithm as with setter :
If there is only mock of type A and only one field with type A then field injection will happen.
If there is either multiple mocks or field of type A it will try to find match using the type and the name of the mock (usually the #Mock field name). If matches are found then injection will happen.
At the moment your code is stuck at stage 2.1 because there is probably only one mock available.
That being said with the current implementation of Mockito there is no real elegant solution, it is necessary to write yourself the injection code. And that is actually the wanted point with Mockito injection, if injection is too complex or weird, then you will have to write it out ; writing this boilerplate code is actually the best tool to question the current design.
Mockito injection is really designed for simple, straight designs.
In my opinion, I find wrong :
to mock a Map, a type you don't own, that might cause many problems.
to mock only a single map in tested object, that means your test knows too much about the inner working of the tested object.
It would benefit the design if you refactor the code and make the collaborators emerge. With clear dependencies/collaborators it will most certainly make the injection clearer too. Also the test should focus on asserting the interactions with the collaborators not how data how the implementation is done, data should only be tested as a result to a given input.