Невозможно @Ввести @ManagedBean в другой @ManagedBean
Хорошо, вот мой сессионный компонент. Я всегда могу получить currentUser из любого сервлета или фильтра. Это не проблема Проблема в fileList и currentFile. Я проверил с простыми int и Strings и с тем же эффектом. Если я установлю значение из моего bean-объекта области видимости, я смогу получить данные из другого класса.
@ManagedBean(name = "userSessionBean")
@SessionScoped
public class UserSessionBean implements Serializable, HttpSessionBindingListener {
final Logger logger = LoggerFactory.getLogger(UserSessionBean.class);
@Inject
private User currentUser;
@EJB
UserService userService;
private List<File> fileList;
private File currentFile;
public UserSessionBean() {
fileList = new ArrayList<File>();
currentFile = new File("");
}
@PostConstruct
public void onLoad() {
Principal principal = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
String email = principal.getName();
if (email != null) {
currentUser = userService.findUserbyEmail(email);
} else {
logger.error("Couldn't find user information from login!");
}
}
Вот пример.
На мой взгляд прицельная фасоль. Вот как это оформлено.
@ManagedBean
@ViewScoped
public class ViewLines implements Serializable {
@Inject
private UserSessionBean userSessionBean;
Теперь код.
userSessionBean.setCurrentFile(file);
System.out.println("UserSessionBean : " + userSessionBean.getCurrentFile().getName());
Я прекрасно вижу текущее имя файла. Это на самом деле печатается из метода действия JSF. Очевидно, что текущий файл установлен.
Теперь, если я сделаю это.
@WebFilter(value = "/Download")
public class FileFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpSession session = ((HttpServletRequest) request).getSession(false);
UserSessionBean userSessionBean = (UserSessionBean) session.getAttribute("userSessionBean");
System.out.println(userSessionBean.getCurrentUser().getUserId()); //works
System.out.println("File filter" + userSessionBean.getCurrentFile().getName()); //doesn't work
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
currentUser показывает нормально, но я не вижу файл. Это просто пусто. То же самое происходит со строками, int и т. Д.
Спасибо за любую помощь, которую вы можете оказать в этом.
ИНФОРМАЦИЯ: UserSessionBean: строка 3B -8531268875812004316.csv (значение выводится из видового объекта bean)
ИНФОРМАЦИЯ: Фильтр файлов tester.csv (значение выводится при запуске фильтра.)
**РЕДАКТИРОВАТЬ**
Это сработало.
FacesContext context = FacesContext.getCurrentInstance();
userSessionBean = (UserSessionBean) context.getApplication().evaluateExpressionGet(context, "#{userSessionBean}", UserSessionBean.class);
Я положил это в конструктор ViewScoped и все было хорошо. Теперь, почему инъекция не делает то, что я думал? Сначала я подумал, может быть, потому что я использовал управляемые компоненты JSF вместо новых компонентов CDI. Но я изменил бобы на новый стиль (с именованным), и это был тот же эффект.
Позволяет ли инъекция только получать доступ к bean-компонентам, но не изменять их атрибуты?
2 ответа
Вы смешиваете JSF и CDI. Ваш UserSessionBean
это JSF @ManagedBean
Тем не менее, вы используете CDI @Inject
ввести его в другой боб. CDI не использует JSF, управляемый JSF, а создает совершенно новый. Используйте один или другой, а не оба. Правильная аннотация для внедрения JSF-управляемого компонента: @ManagedProperty
,
замещать
@Inject
private UserSessionBean userSessionBean;
от
@ManagedProperty(value="#{userSessionBean}")
private UserSessionBean userSessionBean;
и убедитесь, что у вас нет import javax.enterprise.context
в любом месте вашего кода (который представляет собой пакет аннотаций CDI).
Также можно перенести все аннотации управления компонентами JSF в аннотации управления компонентами CDI.
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
@Named
@SessionScoped
public class UserSessionBean implements Serializable {}
import javax.inject.Named;
import javax.faces.view.ViewScoped;
@Named
@ViewScoped
public class ViewLines implements Serializable {}
Дополнительным преимуществом является то, что вы можете просто @Inject
он внутри обычного сервлета или фильтра без необходимости вручную захватывать его как атрибут запроса / сеанса / приложения.
Более того, аннотации управления компонентами JSF не поддерживаются, начиная с JSF 2.3. См. Также Бэк-бины (@ManagedBean) или CDI-бины (@Named)?
Моя лучшая догадка о том, почему это происходит, заключается в том, что файл переменной устанавливается в области видимости, а затем передается по ссылке в bean-объект области действия. Возможно, это происходит потому, что, когда компонент области видимости уничтожен, у него все еще есть ссылка на эту переменную, но он не заботится о том, чтобы найти какие-либо другие ссылки на него в области действия сеанса, где он должен быть сохранен. Следовательно, когда он уничтожается, он удаляется из области просмотра и сеанса в этом случае.
Не могли бы вы попробовать вызвать setCurrentFile с объектом, созданным с помощью 'new'? Это может доказать или опровергнуть мою гипотезу.
В противном случае, мой лучший совет - взломать отладчик и посмотреть, где именно изменяется getCurrentFile.