Spring #Autowired fields - which access modifier, private or package-private? - java

Let's say that we use the #Autowired annotation over various fields in a class, and that we didn't write setters or constructors that can also set the fields.
Question - what should the access modifier be, private or package-private (i.e. none) ?
For example:
public class MyClass {
#Autowired
private MyService myService;
}
vs
public class MyClass {
#Autowired
MyService myService;
}
In the first case (private fields) Spring uses reflection to wire up the field, even if it doesn't have a setter.
The second case (package-private fields) allows us to be able to access those fields (for example, to set up mocks) if we need to extend the class for testing purposes.
So both cases work fine, but which is more recommended, particularly with regards to testing?

So both cases work fine, but which is more recommended, particularly with regards to testing?
I think the properties should be private:
#Autowired
private MyService myService;
As it is always good to have getter methods to provide access to the properties instead of allowing other classes to have direct access to them.
And for testing purposes, injection of mocks of private properties will work the same way as that of package-private properties.
For example, with Mockito, you can inject a mock of private MyService into MyClass as this:
public class MyClassTest {
#Mock
MyService service;
#InjectMocks
MyClass serv = new MyClass();
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
}

I generally prefer having the field private and using setter injection:
public class MyClass {
private MyService myService;
#Autowired
public void setMyService(MyService myService) {
this.myService = myService;
}
}
allowing the service to be #Autowired, but set with a mocked instance for unit testing.

The first case also allows you to inject mocks depending on the framework. For example using the #InjectMocks annotation of Mockito. You also have ReflectionTestUtils.setField in Spring test, ...
I'm personally not too fond of modifying classes too much for testing purposes, so I would go for the first case. But at the end of the day this mostly depends on your preferred test framework.

I would generally NOT use #Autowired for private fields or methods. #Autowired means, somebody from outside will set this field. "Private" on the other hand means nobody except this class is allowed to use it.
Mixing #Autowired and private can theoretically cause problems, if the JIT compiler somehow optimizes this code. It can be a Java Memory Model concurrency related problem, which will be production-only and impossible-to-reproduce.
I would make the Autowired fields at least package visible. As free bonus it will allow to write unit tests without tricks and workarounds.
UPDATE: Additionally I would declare such fields as volatile to avoid Java Memory Model related visibility conflicts. Spring developers do some tricks to make autowired fields work without explicitly synchronizing the access, but I am not sure these tricks are working smoothly in any JVM on any hardware.

I would rather use private on #Autowired fields, for a few reasons:
I use these fields for dependency injection, generally in service classes, to use other service classes. In that case I want to keep those fields to the current class.
Also, extending this class can lead to different logic, so maybe another implementation of the #Autowired fields is needed, hence the private instead of package-private.
Furthermore, when refactoring, it helps to see when such a field is not used anymore, as package-private fields don't show a warning when unused (assuming your IDE is Eclipse - I actually don't know for other IDEs).

Related

Java Spring design: all in one component?

Sometimes Spring components may look like this:
#Service
public final class SomeService {
#Autowired
private SomeService2 someService2;
#Autowired
private SomeService3 someService3;
#Autowired
private SomeService4 someService4;
// … and many other services
#Autowired
private SomeDao someDao;
#Autowired
private SomeDao2 someDao2;
#Autowired
private SomeDao3 someDao3;
// … and many other DAOs
}
In other words Spring components have plenty services and DAOs that are mostly repeated in other Spring components. IMHO it has the following drawbacks:
Unnecessary (boilerplate) code for autowiring most of the same components
Sometimes Spring context loading error may occur due to circular references between components
What about to use all-in-one component that combine, say, all services or all DAOs. It will contain only links to Spring components with no any business logic inside:
#Service
public final class AllServices {
#Autowired
private SomeService2 someService2;
#Autowired
private SomeService3 someService3;
#Autowired
private SomeService4 someService4;
// … and many other services
// get methods to get some service
public someService getSomeService(){};
and inject it into other components:
#Service
public final class SomeService {
#Autowired
private AllServices serv;
#Autowired
private AllDaos daos;
#Autowired
private Environment env;
// inside some code
…
serv.getSomeService().processData();
IMHO it will look more succinct without circular references issues…
What pros and cons of this approach?
The second approach might look appealing, a well-known facade pattern comes to mind at first, so I can totally understand this.
However, I think the first pattern will work better in fact and here is why:
You say that the "all-mighty" service can solve circular dependencies
Well, circular dependencies usually point on a wrong / bad design and are code smell by there own, so hiding it behind a facade won't improve the system, resolving the circular dependencies will. In addition if from the actual services, called by "AllServices" you'll want to invoke additional service (again, bad design is preserved) then the code will probably pass through AllServices again, and hence the circular dependency is still there.
Using the second design assumes that this "AllServices" class will be used by all the components of the system, but in this case it becomes a "one-central-point" and refactoring in this class can turn to a madness - all the components / their tests might be affected
Initialization of this service can become a mess by itself, since you probably won't want to maintain a constructor that has 20-30 input parameters you'll resort to field injection (like in the example) which is bad by its own because if you want to initialize it somehow, probably from test, or something you want know what should be mocked and what not, in which order, and so forth.
Second approach may look cleaner, but it will be difficult to know which service is connected to service/DAO and therefore it will be hard to refactor or do/decide on which regression any change will cause. Meaning it effect software flexibility
This is the important difference which make the difference to choose first option IMHO

How to properly design a Spring component?

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

Is it good practice to use an Implementation instead of an Interface when testing with Mockito?

Mockito annotations #Spy or #InjectMocks won't work on Interfaces:
public interface MyService() {}
public class MyServiceImpl implements MyService {}
#RunWith(MockitoJUnitRunner.class)
public class MyServiceTest {
#Spy
#InjectMocks
private MyService myService; // won't work
#Mock
MyDao myDao;
// tests
}
From the documentation on Spy (something similar for #InjectMocks):
The field annotated with #Spy can be initialized by Mockito if a zero
argument constructor can be found in the type (even private). But
Mockito cannot instantiate inner classes, local classes, abstract
classes and interfaces. The field annotated with #Spy can be
initialized explicitly at declaration point. Alternatively, if you
don't provide the instance Mockito will try to find zero argument
constructor (even private) and create an instance for you. But Mockito
cannot instantiate inner classes, local classes, abstract classes and
interfaces.
So I understand that I cannot use an Interface to Spy on. It works when I use an actual implementation class when declaring/initializing the Interface.
Which of the solutions below would be the best to deal with these kind of issues?
Solution 1:
#InjectMocks
private MyService myService = new MyServiceImpl(); // Program against Interface
Solution 2:
#Spy
#InjectMocks
private MyServiceImpl myService; // Program against implementation
My question is whether it's a good idea to use solution 2 and let Mockito handle the instantiation (but that means declaring an implementation instead of an interface) OR use solution 1 with an interface and do the declaration of an implementation myself.
Thanks for all the responses guys. It helped me a lot. I'll close this question now.
Basically I should test against the Implementation. I also want to reference this question which contains some more useful information.

Spring Autowired Class

When we annotate a class as #Autowired, does it HAVE to be a interface or can it be a class?
All the examples of using Spring I have seen, use an interface and then implement it on a class. The interface type is then used to call a function on the Concrete class. Can we not just simply add #Autowired to a concrete class rather than an interface.
I know of the Programme to a interface analogy in JAVA, but if u are not depending on Polymorphism, then why to write an interface?
No, you don't have to use interfaces, this is completely fine as far as Spring is concerned:
#Service
public class FooService {
#Autowired
private FooDao fooDao;
}
or you can even go for construction injection:
#Service
public class FooService {
private final FooDao fooDao;
public FooService(FooDao fooDao) {
this.fooDao = fooDao;
}
}
Often interfaces are anachronic practice repeated by every subsequent generation. Don't use them if they are not required. And they aren't required if they will always have just one implementation or if you want to mock such a class (modern mocking frameworks mock classes without any problem).
There is also nothing wrong in injecting concrete classes, like FooDao in example above. It has some technical implications wrt. proxying, but nothing that can't be comprehended.
Technically #Autowired could be used for an implementation or an interface. Spring doesn't care about it. Injecting an interface is a design strategy.
#Autowired can also be used with a class instead of interface.
But, using interfaces would be a better practice , since it reduces hard coupling between the components.

Static Utility Class in spring 3 application

Is it a violation if I go ahead with utility methods as static rather than depending on DI of spring?
I just have to maintain a hashmap like below:
private static Map<String,JMSMessage> messageMap = Collections.synchronizedMap(new HashMap<String,JMSMessage>());
messageMap can be accessed by multiple threads. I have utility methods to play around messageMap. I made my class as final and declared all utility methods as static. Is it a violation according to spring IoC?
I would argue that, even though it is possible and will work correctly in Spring IOC, it is a violation of the principals of inversion-of-control.
It would be better to use a singleton bean that is managed by your IOC than use a static field, like this
#Component
#Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public class SimpleMessageManager implements MessageManager {
private Map messageMap = Collections.synchronizedMap(new HashMap());
#Override
void addMessage(...) { ... }
#Override
void getMessage(...) { ... }
}
You could then inject your MessageManager like this:
public class SomeBean {
#Resource
MessageManager messageManager;
}
There are many reasons why sticking to the IOC approach is better:
You may need more than one instance in future.
You can mock out the MessageManager interface in unit tests.
(Related to 2) If you use a static fields, you cannot be sure of the state of the messageMap during testing. This becomes even more complicated if you start running your tests in parallel (a standard option in Maven)
As an aside, I would recommend that you not use Collections.synchronizedMap. Have you considered using ConcurrentHashMap instead?
No it is not a violation against spring because the variable is static. Static variables are only accessible through class name. Spring IoC is useful when you want to remove dependency from the implementation, so that it can change later on without affecting anything else. In case of static variables and methods you have no choice but to access them through their class name.
And remember static variables and methods cannot be overriden.

Categories