Как ввести несериализуемый класс (например, java.util.resourcebundle) с сварным швом
-
25-09-2019 - |
Вопрос
Я хочу создать производителя, который позволяет ввести java.util.resourceBundle в любой класс, чтобы легко получить локализованные строки. Мой ResourceBundle-Producer выглядит так:
public class ResourceBundleProducer {
@Inject
public Locale locale;
@Inject
public FacesContext facesContext;
@Produces
public ResourceBundle getResourceBundle() {
return ResourceBundle.getBundle("/messages", locale )
}
}
Инъекция локаль и Facescontext работает (взял соответствующие производители из шовного альфа-источника). Но, к сожалению, ResourceBundle не является сериализен и поэтому не может быть произведено таким образом. Я получаю следующую ошибку из шва при попытке получить доступ к JSF-странице, которая вызывает боб, который использует мой 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
Есть ли способы получить мой ResourceBundLeresolver для работы? Или есть ли другие механизмы, чтобы получить аналогичную функциональность? Заранее спасибо!
РЕДАКТИРОВАТЬ:
Хорошо, я потратил некоторые из моих едва заработанных очков;) также примет хороший обходной путь для этого вопроса!
У меня еще один пример, где создание производителя не работает: FlashProducer. FaceScontext-Flash также не может быть изготовлена, потому что Flash не является сериализена.
Решение
Ну, прежде всего ресурсыBundle не сериализуется. Отказ Видеть здесь. Отказ И сообщение ясно
не может производить несериализма экземпляры для инъекции в недержательный Поля пассивирующих бобов
Пассивирующие бобы ??? Я думаю web.personhome является либо гостевой сессионной фасолью, либо @conversationCoped Bean. Я прав ??? Если это так, вы должны Отметьте свой собственность вашего пакета в качестве преходящего
private transient @Inject ResourceBundle bundle;
Другие советы
Согласно теме комментариев в принятом ответе Артура. Я последовал за этот блог так же как Вот этот осуществлять эксперимент по пассивации / активации. Эксперимент доказал комментарий MRD, что переходное свойство будет антективным при активации. Таким образом, иметь дело с несериализуемыми свойствами-членами пассивации способного боба (а именно, сеансcoped, разговаривать и заседательную сессию), я предлагаю следующее решение:
private ResourceBundle bundle;
@PostConstruct
@PostActivate
public void getResourceBundle() {
bundle = ResourceBundle.getBundle("/messages", locale );
}
Это решение гарантирует, что члены несериализма имущества повторно ранили каждый раз, когда он входит в состояние готовности.
Окончательная проблема для решения
Окончательная проблема для решения - это инъекция регистратора SLF4J, который был несериализирован до SLF4J 1.5.3, а также я цитирую:
С помощью SLF4J версии 1.5.3, 8 экземпляров выживают сериализацию. Таким образом, сериализация класса Host больше не требует каких-либо специальных действий, даже когда регистраторы объявлены в виде переменных экземпляров.
Таким образом, до тех пор, пока ваша зависимость SLF4J составляет 1,5,3 или позднее, вы можете безопасно ввести регистратор SLF4J следующим образом:
@Produces
@LogbackLogger
public Logger produceLogger(InjectionPoint injectionPoint){
return LoggerFactory.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
}
Предполагая, что вы объявили квалификатор:
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface LogbackLogger {
}
Затем в пассивационном бобовом бобе, введите следующим образом:
@Inject
@LogbackLogger
private Logger logger;