Come iniettare una classe non serializzabile (come java.util.ResourceBundle) con saldatura
-
25-09-2019 - |
Domanda
Voglio creare un produttore che consente di iniettare un java.util.ResourceBundle in ogni classe al fine di ottenere localizzata stringhe facilmente. I miei sguardi ResourceBundle-Producer come questo:
public class ResourceBundleProducer {
@Inject
public Locale locale;
@Inject
public FacesContext facesContext;
@Produces
public ResourceBundle getResourceBundle() {
return ResourceBundle.getBundle("/messages", locale )
}
}
L'iniezione di opere Locale e FacesContext (ha preso i produttori corrispondenti dalla Sorgente Seam 3 Alpha). Ma, purtroppo, non è ResourceBundle Serializable e, pertanto, non può essere prodotto in questo modo. Sto ottenendo il seguente errore da saldare quando si cerca di accedere a una pagina JSF-che richiede un fagiolo che usa il mio 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
Ci sono modi per ottenere il mio ResourceBundleResolver al lavoro? O ci sono altri meccanismi per ottenere una funzionalità simile? Grazie in anticipo!
Modifica
Va bene, ti ha trascorso alcuni dei miei punti difficilmente guadagnati;) Sarà anche accettare una buona soluzione per questo problema!
ho avuto un altro esempio in cui la creazione di un produttore non funziona: un FlashProducer. Un FacesContext-Flash, inoltre, non può essere prodotto perché Flash non è serializzabile.
Soluzione
Bene, prima di tutto ResourceBundle non è Serializable . Vedere qui . E il messaggio è chiaro
non può produrre non serializzabili istanze per l'iniezione in non transitorio campi di fagioli passivazione
fagioli passivazione ??? I Think web.PersonHome è o uno Stateful Session Bean o un fagiolo @ConversationScoped. Ho ragione ??? Se così si dovrebbe contrassegnare la proprietà fascio come transitoria
private transient @Inject ResourceBundle bundle;
Altri suggerimenti
Come per il filo commenti nella risposta accettata di Arthur. Ho seguito questo blog così come questo di effettuare un esperimento passivazione / attivazione. L'esperimento ha dimostrato MrD commento che la proprietà transitoria sarà NULL al momento dell'attivazione. Quindi, a che fare con proprietà dei membri non serializzabili di un fagiolo in grado di passivazione (vale a dire, sessionscoped, conversationscoped e session bean stateful), suggerisco la seguente soluzione:
private ResourceBundle bundle;
@PostConstruct
@PostActivate
public void getResourceBundle() {
bundle = ResourceBundle.getBundle("/messages", locale );
}
Questa soluzione fa in modo che i membri di proprietà non serializzabili vengono reinizializzati ogni volta che entra nello stato READY.
Un ultimo problema all'indirizzo
Un ultimo problema da affrontare è l'iniezione di un Logger SLF4J che era non serializzabile prima slf4j 1.5.3, e cito :
Come di SLF4J versione 1.5.3, casi logger sopravvivono serializzazione. Così, la serializzazione della classe host non richiede alcuna speciale azione, anche quando logger sono dichiarati come variabili di istanza.
In questo modo fino a quando il dipendenza slf4j è 1.5.3 o poi si può tranquillamente iniettare un Logger SLF4J come segue:
@Produces
@LogbackLogger
public Logger produceLogger(InjectionPoint injectionPoint){
return LoggerFactory.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
}
Supponendo che si dichiarato il qualificatore:
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface LogbackLogger {
}
Poi in un bean passivazione-capace, iniezione come segue:
@Inject
@LogbackLogger
private Logger logger;