Members of Spring components should be injected - autowired=false - spring

To fix "Members of Spring components should be injected(https://rules.sonarsource.com/java/RSPEC-3749)" sonar qube issue, if i use #Autowired(required=false) for TestB so warning will go and initialize TestB in #PostConstruct. Does it has any negative impact.
#Component
public class Test {
#Autowired
private TestA testa;
private TestB testb;
#PostConstruct
private void doSomething() {
testb = new TestB();
....
}
}
Note - I am aware about actual sonar rule reason but injecting TestB dependency needs lot of code refactoring which is not possible currently. Also cannot remove/disable this rule. So looking for workaround to solve this issue.

Related

Singleton Class, Annotation

I want to create a lot of Singleton classes in my project,
Can anyone guide me how to create an Annotation that will do my task?
Similar to Lombok do like #Getter, by using this my getters methods are created at compile time
Same, I want
to create a static instance, private constructor, and static method as getInstance(){ }
public class AgeValidation{
-----
-----
}
I want to make it as Singleton with an annotation:
public class AgeValidation {
This is a boilerPlate Code for me:
private static final AgeValidation instance = new AgeValidation();
private AgeValidation() { }
public static AgeValidation getInstance() {
return instance;
}
}
If you are building project using Spring Boot, you can easily specify singleton as scope for your bean classes.
Alternatively, you can also experiment with Dagger 2 dependency to get annotation #Singleton that will almost do the same thing.

Spring Boot #Autowired - checkstyle / pmd / spotbugs rule to warn on non-interface usage

Having recently been bit by Spring CGLib vs JDK Dynamic proxying issues in a Spring Boot application (that when run on a Mac seems to use CGLib where as the same app when run on Linux is using JDK dynamic proxying).
I'm looking for a linter tool config / plugin (PMD, Checkstyle, Spotbugs etc) that can identify where an #Autowired annotated field / parameter is being used and the Class being autowired is defined with a class instance rather than an interface.
For example:
public interface MyService {
}
public class MyServiceImpl implements MyService {
}
#RestController
public class MyController {
#Autowired
private MyServiceImpl serviceImpl; // this should raise a warning in a linter as
// class is being used for injection type
#Autowired
private MyService service; // this should not raise a warning, as interface
// is used for type
}
I don't think this will be possible to check with PMD, Checkstyle, Spotbugs, etc. But there is a solution to check this.
ArchUnit offers writing custom rules, a custom rule can be written for this. Assuming you are using JUnit5 or JUnit4 for testing, you could do something like-
#ArchTest
public static final ArchRule archRule = noFields()
.that()
.areAnnotatedWith(Autowired.class)
.should()
.haveNameEndingWith("Impl");
This can be incorporated within your tests, you would have to read the documentation of arch unit and set up in your work environment, it super easy to integrate. You can create similar rules for setters or methods-
#ArchTest
public static final ArchRule archRule1 = noMethods()
.that()
.areAnnotatedWith(Autowired.class)
.should()
.haveRawParameterTypes(MyServiceImpl.class, MyDaoImpl.class);
As you integrate this into your code base, you can create custom rules for yourself. Using ArchUnit for spring projects is generally a great idea, they also have pre configured templates that you can use in your project. Hope this helps.
In addition to #VyomYdv's answer above, I stumbled on this github issue for spring: https://github.com/spring-projects/spring-boot/issues/8277
Essentially a bean that is annotated with #Validated and #ConfigurationProperties and also implements an interface will be a candidate for being a JDK proxy instance at runtime, and you can't autowire the class instance, you have to autowire as the interface.
So amend YyomYdv's rule as follows:
public static final ArchRule AUTOWIRE_PROXY_RULE = noFields()
.that()
.areAnnotatedWith(Autowired.class)
.should()
.haveRawType(new DescribedPredicate<>("that does not autowire an interface") {
#Override
public boolean apply(final JavaClass input) {
return !input.isInterface();
}
})
.andShould().haveRawType(new DescribedPredicate<>("class is not a JDK proxy candidate") {
#Override
public boolean apply(final JavaClass input) {
return !input.getAllRawInterfaces().isEmpty()
&& input.getPackageName().startsWith("com.mypackage")
&& input.isAnnotatedWith(Validated.class)
&& input.isAnnotatedWith(ConfigurationProperties.class);
}
});

Spring Boot - Testing - tearDown for a bean

I use #EmbeddedKafka annotation as follows to have a kafka mock:
#ExtendWith(SpringExtension.class)
#SpringBootTest
#EmbeddedKafka(partitions = 1,
topics = {"topic"},
brokerProperties = {
"auto.create.topics.enable=${topics.autoCreate:false}",
"delete.topic.enable=${topic.delete:true}",
"broker.id=2"})
public class KafkaUsersTest {
#Autowired
private EmbeddedKafkaBroker embeddedKafka;
#Test
public void test1() {
// test something
}
#Test
public void test2() {
// test something
}
...
}
Now, after The tests finish I'd like to close the embeddedKafka bean. Something like this:
#AfterAll
public void tearDown(){
embeddedKafka.getKafkaServers().forEach(KafkaServer::shutdown);
embeddedKafka.getKafkaServers().forEach(KafkaServer::awaitShutdown);
}
The problem is:
An #AfterAll method can only be static.
If I make it static - then also the embeddedKafka has to be static, and then #Autowired annotation will not work.
I guess I can the bean to a static field from one of the tests and then use it in the tearDown(), but it's really ugly.
What is the "good practice" for closing a bean only once after all tests have completed?
An #AfterAll method can only be static.
That's not true.
From the JUnit 5 User Guide:
Denotes that the annotated method should be executed after all #Test, #RepeatedTest, #ParameterizedTest, and #TestFactory methods in the current class; analogous to JUnit 4’s #AfterClass. Such methods are inherited (unless they are hidden or overridden) and must be static (unless the "per-class" test instance lifecycle is used).
An #AfterAll method can be non-static if you use #TestInstance(Lifecycle.PER_CLASS). This is also documented in the JUnit 5 User Guide:
The "per-class" mode has some additional benefits over the default "per-method" mode. Specifically, with the "per-class" mode it becomes possible to declare #BeforeAll and #AfterAll on non-static methods as well as on interface default methods.

Trying to generate error about Spring's #Autowired field injection for JUnit

I am working with Spring 4.0.7, and with JUnit about testing of course.
About DI Spring offers #Autowired to be used in three locations
constructor
setter
field
I always work through the two first, why never the third option?
Because I remember have read long time ago about field injection should not be used, because it has a negative consequence about Testing. It does JUnit fails.
Note: Only for Testing is the problem. To runtime or production all goes well
Objective: For demonstration/academic purposes I want generate this problem.
I have the following:
Repository
public interface PersonRepository extends JpaRepository<Person, String>{
}
A Service
#Service
#Transactional
#Profile("failure")
public class PersonFailTestServiceImpl implements PersonService {
private static final Logger logger = ...
#Autowired
private PersonRepository personRepository;
Other Service (calling or using the service shown above)
#Service
#Transactional
#Profile("failure")
public class PersonFailTestProcessImpl implements PersonProcess {
private static final Logger logger = ...
#Autowired
private PersonService personService;
How you can see the two services are based on Field Injection.
Now the testing:
How the beans are loaded
#Configuration
#ComponentScan( basePackages={"com.manuel.jordan.server.infrastructure"},
basePackageClasses={PersonProcess.class,PersonRepository.class, PersonService.class})
public class CentralConfigurationEntryPoint {
}
#ContextConfiguration(classes=CentralConfigurationEntryPoint.class)
public class CentralTestConfigurationEntryPoint {
}
Now the two testing classes
#Transactional
#RunWith(SpringJUnit4ClassRunner.class)
#ActiveProfiles({"development","failure"})
public class PersonServiceImplDevelopmentFailureTest extends CentralTestConfigurationEntryPoint {
#Autowired
private PersonService personService;
#Test
public void savePerson01(){
Person person01 = PersonFactory.createPerson01();
personService.save(person01);
personService.printPerson(personService.findOne("1"));
}
#Transactional
#RunWith(SpringJUnit4ClassRunner.class)
#ActiveProfiles({"development","failure"})
public class PersonProcessImplDevelopmentFailureTest extends CentralTestConfigurationEntryPoint{
#Autowired
private PersonProcess personProcess;
Well all the testing methods pass, all green. I don't know if I am missing something or through Spring 4 the problem has been fixed
If this was your premise or problem
Because I remember have read long time ago about field injection
should not be used, because it has a negative consequence about
Testing. It does JUnit fails.
then you thought wrong. There is nothing inherently wrong with using field injection, definitely nothing that would cause JUnit tests to fail in and of itself. If a bean exists, Spring will be able to inject it whether it's in a constructor, a setter method, or a field.
Since you've activated your failure profile, your PersonFailTestServiceImpl bean will be found.
I think I can help. The example code you've posted here is a good example of a system / integration test, not a UNIT test.
If you were UNIT testing PersonFailTestProcessImpl, you would have to set the personRepository dependency yourself through code. But it is private, so how do you do this? You cannot use a constructor or setter since none is provided. This is what is meant by 'hard to unit test'.
Java 5+ provides a way to set private variables like this via reflection (the so-called privileged accessor). Basically, you obtain the class, get the declared field, call its setAccessible method, then you can set its value directly. There are libraries that will do these steps for you, but the point is that this is a pain compared to X.setSomething();
So there is nothing that 'makes jUnit fails' by using #Autowired on a private field. But building an object model without constructors or setters for establishing dependencies is unnecessarily constraining.

spring aspect being applied outside of app context (in stubbed out unit test)

Here's a weird one. I've got a few tests failing because an aspect is being applied, so an autowired service is null, bad things ensue. The issue is that I can't understand how the aspect is even being applied, since in the test I construct the object under test with new.
#RunWith(MockitoJUnitRunner.class)
public class TheControllerTest {
#Spy
private TheController controller = new TheController();
#Mock
private HttpServletRequest request;
#Mock
private ConfigService configService;
....
#Before
public void setup() {
controller.setConfigService(configService);
....
}
#Test
public void testGetAccountsList() throws Exception {
Mockito.when(accountService.getAllAccounts()).thenReturn(Arrays.asList(account1, account2));
Map<String, Object> result = controller.getAccountsList(request);
...
}
}
I'm obviously omitting plenty of code, but really, I just don't understand how, given how controller is instantiated, it could have had the advice applied.
One possible reason could be if you are running this in Eclipse - in a project with ajbuilder enabled, even if you are explicitly expecting Spring AOP through dynamic proxies, ajbuilder would actually perform compile team weaving, and hence you would see advice enhanced classes even using normal "new". Can you please check this, the fix would be to disable "ajbuilder" - here is one reference - JUnit weaving wrong Spring AOP Bean

Resources