Pergunta

Quero criar um Produtor que possibilite injetar um java.util.ResourceBundle em qualquer classe para obter Strings localizadas facilmente.Meu ResourceBundle-Producer se parece com isto:

public class ResourceBundleProducer {
  @Inject       
  public Locale locale;

  @Inject       
  public FacesContext facesContext;

  @Produces
  public ResourceBundle getResourceBundle() {
    return ResourceBundle.getBundle("/messages", locale )
  }
}

A injeção de Locale e FacesContext funciona (retirou os produtores correspondentes do Seam 3 Alpha Source).Mas, infelizmente, ResourceBundle não é serializável e, portanto, não pode ser produzido dessa forma.Estou recebendo o seguinte erro do Weld ao tentar acessar uma página JSF que chama um bean que usa meu ResourceBundle:

Caused by: org.jboss.weld.IllegalProductException: WELD-000054 Producers cannot produce non-serializable instances for injection into non-transient fields of passivating beans\\n\\nProducer\: org.jboss.weld.bean-/D:/Program Files (x86)/GlassFish-Tools-Bundle-For-Eclipse-1.2/glassfishv3/glassfish/domains/teachernews/applications/teachernews/-ProducerMethod-services.producers.ResourceBundleProducer.getResourceBundle()\\nInjection Point\: field web.PersonHome.bundle

Existe alguma maneira de fazer meu ResourceBundleResolver funcionar?Ou existem outros mecanismos para obter uma funcionalidade semelhante?Desde já, obrigado!

EDITAR:

Ok, gastarei alguns dos meus pontos dificilmente conquistados;) também aceitará uma boa solução alternativa para este problema!

Tenho outro exemplo em que criar um Produtor não funciona:um FlashProdutor.Um FacesContext-Flash também não pode ser produzido porque o Flash não é serializável.

Foi útil?

Solução

Bem, antes de tudo o ResourceBundle não é serializável. Ver aqui. E a mensagem é clara

não pode produzir não serializável Instâncias de injeção em não-transitório campos de feijão passivador

feijão passivador ??? Eu acho que Web.Pernsonhome é um feijão de sessão com estado ou um feijão @ConversationScoped. Estou certo ??? Se sim, você deveria Marque sua propriedade de pacote como transitória

private transient @Inject ResourceBundle bundle;

Outras dicas

De acordo com o tópico de comentários na resposta aceita de Arthur.eu segui este blog assim como Este para realizar um experimento de passivação/ativação.O experimento provou que o MrD comentou que a propriedade transitória será NULA na ativação.Assim, para lidar com propriedades de membros não serializáveis ​​de um bean com capacidade de passivação (ou seja, beans de sessão com escopo de sessão, escopo de conversação e estado), sugiro a seguinte solução:

private ResourceBundle bundle;

@PostConstruct
@PostActivate
public void getResourceBundle() {
    bundle = ResourceBundle.getBundle("/messages", locale );
}

Esta solução garante que os membros da propriedade não serializável sejam reinicializados sempre que entrarem no estado READY.

Uma última questão a abordar

Um último problema a ser resolvido é a injeção de um registrador SLF4j que não era serializável antes do slf4j 1.5.3, e Eu cito:

A partir do SLF4J versão 1.5.3, as instâncias do logger sobrevivem à serialização.Assim, a serialização da classe host não requer mais nenhuma ação especial, mesmo quando os madeireiros são declarados como variáveis ​​de instância.

Assim, desde que sua dependência slf4j seja 1.5.3 ou posterior, você pode injetar com segurança um registrador SLF4j da seguinte maneira:

@Produces
@LogbackLogger
public Logger produceLogger(InjectionPoint injectionPoint){
    return LoggerFactory.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
}

Supondo que você declarou o qualificador:

@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface LogbackLogger {
}

Em seguida, em um feijão com capacidade de passivação, injete da seguinte forma:

@Inject
@LogbackLogger
private Logger logger;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top