Is it possible to inject a bean into a Singleton with Enum?

Asked

Viewed 550 times

0

We have a system that uses Struts 1 and enum-based singletons.

Now we have a dependency that was written using Spring 4.3.6.RELEASE that should only be used with other systems that also use Spring, so all declared Spring dependencies have their scope as provided.

Now the system that uses Struts 1 must use this dependency. I have declared all necessary Spring dependencies, created my applicationContext, but unfortunately I am not able to inject the Beans into my singletons because they are enums.

These dependency does not offer me Rest services.

Follow my applicationContext:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">

    <import resource="classpath:/applicationContext-dependency.xml" />

</beans>

Here a class that demonstrates my problem:

public enum ItemRemessaUtil {

    INSTANCIA;

    @Autowired
    private BeneficiarioBS beneficiarioBS;

    @Autowired
    private ItemRemessaBS itemRemessaBS;

    @Autowired
    public Boleto inserirItemRemessaMultaDesassociacao(final MultaBean multa) throws BOException, DataAccessException {
        return this.inserirItemRemessa(multa.getNroFatura(), multa.getNossoNumeroItemRemessa(),
                multa.getDataEmissaoBoleto(), multa.getDataVencimentoBoleto(),
                multa.getValorFatura().subtract(multa.getValorDesconto()), multa.getComprador(), TipoOrigem.MULTA);
    }

    @Autowired
    public Boleto inserirItemRemessaOrdemCancelamento(final OrdCancelBean ordCancel)
            throws BOException, DataAccessException {
        return this.inserirItemRemessa(ordCancel.getNrOrdCancel(), ordCancel.getNossoNumeroItemRemessa(),
                ordCancel.getDataEmissaoBoleto(), ordCancel.getDataVencimentoBoleto(),
                BigDecimal.valueOf(ordCancel.getVlOrdem()), ordCancel.getComprd(), TipoOrigem.CANCELAMENTO_VT);
    }

    @Autowired
    private Boleto inserirItemRemessa(final long numeroPedido, final Long nossoNumeroItemRemessa,
            final Date dataDocumento, final Date dataVencimentoBoleto, final BigDecimal valorTotal,
            final ComprdBean comprdBean, final TipoOrigem tipoOrigem) throws BOException, DataAccessException {
        final Boleto boleto = BoletoBancarioFactory.criarBoletoSantander(
                this.beneficiarioBS.construirBeneficiario(tipoOrigem, ConstantesBoleto.CNPJ_RIOPAR, numeroPedido,
                        nossoNumeroItemRemessa, dataVencimentoBoleto),
                BoletoUtil.construirPagador(comprdBean),
                Datas.novasDatas(dataDocumento,
                        TipoOrigem.MULTA.equals(tipoOrigem)
                                ? ParamMultaDesassociacaoBO.retornarQuantidadeDiasVencimentoMultaDesassociacao()
                                : ConstantesBoleto.QUANTIDADE_DIAS_VENCIMENTO_BOLETO_SANTANDER),
                valorTotal);

        if (nossoNumeroItemRemessa == null
                || DateUtil.retornarDataSemHorario(dataVencimentoBoleto).before(boleto.getDatas().getVencimento())) {
            this.itemRemessaBS.inserirItemRemessa(boleto);
        }

        return boleto;
    }
}

I’ve read some of the American OS questions as Inject bean into Enum and Using Singleton Enum in Spring MVC and tried the solutions listed, but my attributes of Enum are never injected and, unfortunately, only through them can I enter the dependency.

What I can do to inject the dependencies of these attributes?

1 answer

1

The most practical way for you to inject dependencies within Enum is to create a component that will actually set these dependencies to be used as below:

public enum ItemRemessaUtil {

    INSTANCIA;

    private BeneficiarioBS beneficiarioBS;
    private ItemRemessaBS itemRemessaBS;

    public Boleto inserirItemRemessaMultaDesassociacao(final MultaBean multa) throws BOException, DataAccessException {
        return this.inserirItemRemessa(multa.getNroFatura(), multa.getNossoNumeroItemRemessa(),
                multa.getDataEmissaoBoleto(), multa.getDataVencimentoBoleto(),
                multa.getValorFatura().subtract(multa.getValorDesconto()), multa.getComprador(), TipoOrigem.MULTA);
    }

    public Boleto inserirItemRemessaOrdemCancelamento(final OrdCancelBean ordCancel)
            throws BOException, DataAccessException {
        return this.inserirItemRemessa(ordCancel.getNrOrdCancel(), ordCancel.getNossoNumeroItemRemessa(),
                ordCancel.getDataEmissaoBoleto(), ordCancel.getDataVencimentoBoleto(),
                BigDecimal.valueOf(ordCancel.getVlOrdem()), ordCancel.getComprd(), TipoOrigem.CANCELAMENTO_VT);
    }

    private Boleto inserirItemRemessa(final long numeroPedido, final Long nossoNumeroItemRemessa,
            final Date dataDocumento, final Date dataVencimentoBoleto, final BigDecimal valorTotal,
            final ComprdBean comprdBean, final TipoOrigem tipoOrigem) throws BOException, DataAccessException {
        final Boleto boleto = BoletoBancarioFactory.criarBoletoSantander(
                this.beneficiarioBS.construirBeneficiario(tipoOrigem, ConstantesBoleto.CNPJ_RIOPAR, numeroPedido,
                        nossoNumeroItemRemessa, dataVencimentoBoleto),
                BoletoUtil.construirPagador(comprdBean),
                Datas.novasDatas(dataDocumento,
                        TipoOrigem.MULTA.equals(tipoOrigem)
                                ? ParamMultaDesassociacaoBO.retornarQuantidadeDiasVencimentoMultaDesassociacao()
                                : ConstantesBoleto.QUANTIDADE_DIAS_VENCIMENTO_BOLETO_SANTANDER),
                valorTotal);

        if (nossoNumeroItemRemessa == null
                || DateUtil.retornarDataSemHorario(dataVencimentoBoleto).before(boleto.getDatas().getVencimento())) {
            this.itemRemessaBS.inserirItemRemessa(boleto);
        }

        return boleto;
    }

    // Componente que irá injetar suas dependencias dentro do enum
    @Component
    public static class ServiceInjector {
        @Autowired
        private BeneficiarioBS beneficiarioBS;

        @Autowired
        private ItemRemessaBS itemRemessaBS;

        @PostConstruct
        public void postConstruct() {
            for (ItemRemessaUtil item : EnumSet.allOf(ItemRemessaUtil.class)) {
                item.setBeneficiarioBS(beneficiarioBS);
                item.setItemRemessaBS(itemRemessaBS);
            }
        }
    }

    // Set's
    private void setBeneficiarioBS(BeneficiarioBS beneficiarioBS) {
        this.beneficiarioBS = beneficiarioBS;
    }

    private void setItemRemessaBS(ItemRemessaBS itemRemessaBS) {
        this.itemRemessaBS = itemRemessaBS;
    }
}
  • The sets can be private since I don’t want anyone modifying this on the outside, right? I think your answer might be the right one for my problem!

  • 1

    a yes, true sets must be private for better security and control of this dependency injections

  • The Serviceinjector and the method annotated with Postconstruct can be private too, right? I believe that Spring can see them by Reflection.

  • Yes, the components can be private, the only requirement is that there is a constructor without arguments or at least receiving dependency injection arguments public @Autowired Construtor(Interface i) for example

  • You can add that to your answer?

  • Oops, you can, thank you

Show 1 more comment

Browser other questions tagged

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