The Spring illness to Java developers
Tags: java, spring, programming, codequality
Published: 2021-12-17 17:54:17

Here's what an anonymous spring developer once said &#x1F605;:
> Everything should be a component. 

If you have worked in any Java codebase using the spring framework, maybe you have found classes with some dependencies that can be avoided with minor changes. Let us see in the following example:

> In order to do the code less verbose I will use lombok annotations like **@AllArgsConstructor**

```Java
@AllArgsConstructor
@Component
public class AccountAdapter implements AccountPort {
    
    private final RestClient restClient;
    private final AccountAdapterTranslator translator;

    public Account createAccount(final CreateAccountEntity createAccount) {
       CreateAccountRequest request = translator.convertEntityToRequest(createAccount);
       Response<CreateAccountResponse> response = restClient.createAccount(request).execute();
       return translator.convertResponseToEntity(response);
    }
}

@Component
@NoArgsConstructor
public class AccountAdapterTranslator {

    public CreateAccountRequest convertEntityToRequest(final CreateAccountEntity createAccount){
        return CreateAccountRequest.builder()
            .field1(createAccount.getField1())
            .field2(createAccount.getField2())
            ...
            .build();
    }

    public Account convertResponseToEntity(final Response<CreateAccountResponse> response){
        return Account.builder()
        .fieldX(response.getFieldX())
        .fieldY(response.getFieldY())
        ...
        .build();
    }
}
```

I don't know if you see my point here, but why would be the **AccountAdapterTranslator** class a component?

Let's see how would be a possible unit test of the class **AccountAdapter** by a Java developer with the spring illness:
```Java
@ExtendsWith(MockitoExtension.class)
public class AccountAdapterTest{

    @Mock
    private RestClient restClient;

    @Mock
    private AccountAdapterTranslator translator;

    @InjectMocks
    private AccountAdapter adapter;

    @Test
    public void testCreateAccountSuccesfully_ShouldReturnAccount(){
        //SetUp data
        CreateAccountRequest request = CreateAccountRequest.builder().build();
        CreateAccountResponse bodyResponse = CreateAccountResponse.builder().build();
        RestCall<CreateAccountResponse> restCall = mock(RestCall.class);
        Response<CreateAccountResponse> restResponse = Response.success(bodyResponse);
        Account account = Account.builder().build();
        
        when(translator.convertEntityToRequest(any())).thenReturn(request);
        when(restClient.createAccount(any())).thenReturn(restCall);
        when(restCall.execute()).thenReturn(restResponse );
        when(translator.convertResponseToEntity(any())).thenReturn(account);
        
        //Execution
        Account result = adapter.createAccount(request);

        //Assertions
        assertEquals(result, account);

    }
}
```

> Oh God! &#x1F926; ¡Kill me now!

You don't need to do everything in a ***spring manner,*** creating every class as a **@Bean** or a **@Component**. You are a Java developer, and there are better ways to do your everyday job.

Use the language constructs, there are static methods, static classes that can do the job; for example, one possible refactor may be the following:

```Java
@AllArgsConstructor
public class AccountAdapter implements AccountPort {
    
    private final RestClient restClient;

    public Account createAccount(final CreateAccountEntity createAccount) {
       CreateAccountRequest request = AccountAdapterTranslator.convertEntityToRequest(createAccount);
       Response<CreateAccountResponse> response = restClient.createAccount(request).execute();
       return AccountAdapterTranslator.convertResponseToEntity(response);
    }
}


@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class AccountAdapterTranslator {

    public static CreateAccountRequest convertEntityToRequest(final CreateAccountEntity createAccount){
        return CreateAccountRequest.builder()
            .field1(createAccount.getField1())
            .field2(createAccount.getField2())
            ...
            .build();
    }

    public static Account convertResponseToEntity(final Response<CreateAccountResponse> response){
        return Account.builder()
        .fieldX(response.getFieldX())
        .fieldY(response.getFieldY())
        ...
        .build();
    }
}
```
**AccountAdapterTranslator** is not a @Bean or a @Component, and it doesn't need to be. Just a class with static methods is enough, and you don't need to create a mock for testing purposes; just let their methods complete the execution.

Some of those things happen because sometimes developers tend to do things automatically. Thinking twice is an excellent strategy to do the best that you can do when developing a feature.

There are always better ways to do the job. It would help if you didn't forget that before being a Spring developer, you are a Java developer, and before that, you are a Developer, and your job is to solve problems.

What do you think about the Spring illness? What other things do you think the Spring illness does to Java Developers?