0

I've read questions here in stackoverflow such as:

I've also read links provided in these questions such as 3.9.3 Fine-tuning annotation-based autowiring with qualifiers but nothing that I tried worked.

Here's my class:

public class UmbrellaRestClient implements UmbrellaClient {

    private static final Logger LOGGER = LoggerFactory.getLogger(UmbrellaRestClient.class);
    private static final Map<String, String> PARAMETROS_INFRA_UMBRELLA = ApplicationContextProvider.getApplicationContext().getBean(ParametrosInfraComponent.class)
            .findByIdParametroLikeAsMap("%UMBRELLA%");

    private final HttpConnectionRest conexaoHttp;

    @Autowired
    @Qualifier
    private TemplateLoaderImpl templateLoader;

    public UmbrellaRestClient(final String url) {
        this.conexaoHttp = new HttpConnectionRest(UmbrellaRestClient.PARAMETROS_INFRA_UMBRELLA.get("UMBRELLA_HOST") + url, "POST", true);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String enviarNfe(final String cnpjFilial, final String idPedido, final BigDecimal valorGNRE, final String arquivoNfe) {
        if (StringUtils.isBlank(arquivoNfe)) {
            throw new ClientException("Arquivo de NF-e não carregado.");
        }

        final String usuario = StringUtils.defaultIfBlank(UmbrellaRestClient.PARAMETROS_INFRA_UMBRELLA.get("USUARIO_UMBRELLA"), "WS.INTEGRADOR");

        Map<String, String> parametrosTemplate = new HashMap<>(6);
        parametrosTemplate.put("usuario", usuario);
        parametrosTemplate.put("senha", StringUtils.defaultIfBlank(UmbrellaRestClient.PARAMETROS_INFRA_UMBRELLA.get("SENHA_UMBRELLA"), "WS.INTEGRADOR"));
        parametrosTemplate.put("valorGNRE", valorGNRE.toPlainString());
        parametrosTemplate.put("idPedido", idPedido);
        parametrosTemplate.put("cnpjFilial", cnpjFilial);
        parametrosTemplate.put("arquivoNfe", arquivoNfe);

        final String xmlRequisicao = ConverterUtils.retornarXMLNormalizado(this.templateLoader.preencherTemplate(TemplateType.ENVIO_XML_NFE, parametrosTemplate));

        this.conexaoHttp.setXmlEnvio(xmlRequisicao);

        UmbrellaRestClient.LOGGER.info("XML ENVIO #####################: {}", xmlRequisicao);

        return this.conexaoHttp.enviarXML();
    }
}

The field templateLoader does not get injected. I tested in other classes that have dependency injection and works. I guess this is happening because I have a constructor that depends on a parameter and this parameter is really passed by each class that needs to use it so I cannot use dependency injection to the parameter of the constructor in applicationContext for example.

What should I do to get field injected?

Community
  • 1
  • 1
Philippe Gioseffi
  • 1,488
  • 3
  • 24
  • 41

2 Answers2

1

Using Rest APIs with Spring framework needs to be handled differently. Here is brief explanation.

Spring is a framework that maintains the lifecycle of the component beans and is fully responsible from bean creation to their destruction.

REST APIs are also responsible for maintaining the life cycle of the web services they create.

So, Spring and REST container are working independently to manage the components they have created effeciently.

In my recent project what I did to use both technologies, by creating a seperate class which implements Spring's ApplicationContextAware interface, and collect the beans in a HashMap. This resource can be accessed statically from REST contexts.

The weak point about this is we have to use beans.xml file and register the beans and in the class that implements ApplicationContextAware interface getting the beans by name etc.

Kamal Singh
  • 990
  • 8
  • 13
-1

The easiest way to create a Spring controlled bean is directly through the ApplicationContext:

@Autowired
private ApplicationContext context;

private UmbrellaRestClient getNewUmbrellaRestClient(String url) {
  return context.getBean("umbrellaRestClient", new Object[]{url});
}

Basically this is a factory method. For this to work the UmbrellaRestClient must be declared a bean of scope prototype. As all beans that have a non default constructor must be of scope prototype.

In the case where the class is in a package that is component scanned, this will suffice:

@Service
@Scope("prototype")
public class UmbrellaRestClient implements UmbrellaClient {
    ...
hotzst
  • 7,238
  • 9
  • 41
  • 64