How to expose a bean method to use spring dependency injection

Asked

Viewed 396 times

5

I need to expose a method like a bean on ApplicationContext of Spring to use it in the injection of an attribute, which has more than one implementation. What I did was the following:

  1. I added the method that will create my object using the annotation @Bean:

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public CsrfTokenRepository csrfTokenRepository() {
        return CookieCsrfTokenRepository.withHttpOnlyFalse();
    }
    
    [...]
    
    }
    
  2. I added the @Autowired to inject the attribute that has the interface type CsrfTokenRepository which is returned by the method I have expounded as Spring bean:

    public final class RestClient<T> {
    private Class<T> type;
    @Autowired
    private CsrfTokenRepository csrfTokenRepository;
    
    [...]
    
    }
    
  3. When I try to use the attribute, it occurs NPE because it was not injected by Spring:

    public final class RestClient<T> {
    private Class<T> type;
    @Autowired
    private CsrfTokenRepository csrfTokenRepository;
    
    public HttpHeaders csrfHeaders() throws IOException {
        CsrfToken csrfToken = csrfTokenRepository.generateToken(null); //Aqui ocorre o NPE!
        HttpHeaders headers = createHeaders();
        headers.add(csrfToken.getHeaderName(), csrfToken.getToken());
        headers.add("Cookie", "XSRF-TOKEN=" + csrfToken.getToken());
        return headers;
    }
    }
    

java.lang.Nullpointerexception at br.com.restclientjersey.RestClient.csrfHeaders(Restclient.java:61) at br.com.restclientjersey.RestClient.postCall(Restclient.java:47) at br.com.restclientjersey.RestClientTest.testPostCallStatus200(Restclienttest.java:83)

Still the attribute is not injected. I even tried to add a Qualifier but it still doesn’t work. What remains to be done to inject this attribute by calling the method csrfTokenRepository?

  • Some error or Exception?

  • Nullpointerexception when trying to use the injected attribute, I will add in question.

  • You have tried creating a separate class, using some bean annotation (@Repository etc.) to see if it works or not is an option?

  • The problem is replicating the implementation by adding another level of inheritance. That’s why I wanted something more elegant, like injecting a method as a constructor. So I avoid creating a "wrapper" class just for this.

  • Your class CsrfTokenRepository is annotated to be a bean (@Component, @Repository etc.) as well?

  • This Csrftokenrepository is a Spring interface, so there it declares.

  • 1

    As the instance of RestClient is created? The package br.com.restclientjersey is "scanned" by Spring? Note: there is no "method as bean", the bean is the return of the method, this is what is managed by Spring as bean.

  • I found the problem, @Brunocésar. What happened was that in the tests Restclient was created with new and not injected. When I injected him into the test he was able to carry the dependency! Thank you.

  • Cool, it was what I had imagined even when I questioned how the instance was created ;)

  • @Brunocésar, as you helped, I suggest you include your answer (discovered in the comments) to the question :)

Show 5 more comments

1 answer

0


Your mistake shows that the class RestClient failed to obtain the Spring Bean to inject the dependency of csrfTokenRepository.

How you didn’t show how you’re using the class RestClient and she’s not marked with any Spring stereotype (@Component, @Service or @Repository), then the problem may be in the way it is instantiating her.

For Spring to do the dependency injection csrfTokenRepository, the class in which you are asking for this injection also needs to be controlled by Spring. That is, it also needs to be injected into the class in which it is being used.

Imagining you have a class CrsftTokenService, this would be the way correct to use RestClient, injecting her with @Autowired:

@Service
class CrsftTokenService {
    @Autowired
    private RestClient restClient;

    public void call() {
        restClient.csrfHeaders();
    }
}

And this would be the way incorrect, Dependency injection will not work:

@Service
class CrsftTokenService {
    public void call() {
        RestClient restClient = new RestClient();
        restClient.csrfHeaders();
    }
}

And remembering again that your class RestClient need to have some Spring stereotype to be injectable in other classes.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.