Хобрук: Ваш путь к мастерству в программировании

Невозможно @Inject @ManagedBean в другой @ManagedBean

Хорошо, вот мой сеансовый компонент. Я всегда могу получить currentUser из любого сервлета или фильтра. Проблема не в этом. Проблема в fileList и currentFile. Я тестировал простые int и Strings, и это тот же эффект. Если я установлю значение из моего компонента с областью видимости, я смогу получить данные из другого класса.

@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!");
        }
    }

Вот пример.

Мой взгляд с областью действия bean. Вот так он украшен.

 @ManagedBean
 @ViewScoped
 public class ViewLines implements Serializable {

    @Inject
    private UserSessionBean userSessionBean; 

Теперь код.

    userSessionBean.setCurrentFile(file);
    System.out.println("UserSessionBean : " + userSessionBean.getCurrentFile().getName());

Я прекрасно вижу текущее имя файла. На самом деле это печатается из метода действия jsf. Таким образом, очевидно, что currentFile устанавливается.

Теперь, если я сделаю это.

@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 отображается нормально, но я не вижу файл. Это просто пусто. То же самое происходит со строками, целыми числами и т. д.

Спасибо за любую помощь, которую вы можете предоставить по этому вопросу.

ИНФОРМАЦИЯ: UserSessionBean: строка 3B--8531268875812004316.csv (значение, напечатанное из bean-компонента с областью видимости)

ИНФОРМАЦИЯ: файл filter tester.csv (значение печатается при запуске фильтра).

**РЕДАКТИРОВАТЬ**

Это сработало.

 FacesContext context = FacesContext.getCurrentInstance();
    userSessionBean = (UserSessionBean) context.getApplication().evaluateExpressionGet(context, "#{userSessionBean}", UserSessionBean.class);

Я поместил это в конструктор ViewScoped, и все было в порядке. Теперь, почему инъекция не делает то, что я думал? Сначала я подумал, может быть, потому, что я использовал управляемые компоненты JSF вместо новых компонентов CDI. Но я изменил бины на новый стиль (с именем), и эффект был тот же.

Позволяет ли инъекция только получить доступ к компонентам, но не изменять их атрибуты?

14.03.2011

  • Каково функциональное требование? Вы понимаете, что Filter работает до JSF? 14.03.2011
  • да. Я в основном хочу удалить файл в прослушивателе сеанса. Это тоже не работает. Файл никогда не находится в сеансовом компоненте. Я как бы использовал фильтр в качестве метода тестирования. Я также хочу применить токен к пользовательскому сеансу, чтобы при попадании в сервлет объект пользовательского сеанса должен был определить эту строку для загрузки файла. Просто дополнительная безопасность. Это не обязательно. Я хотел бы сохранить еще несколько вещей в сеансовом компоненте. На данный момент я просто не могу ничего хранить и иметь доступ к данным за пределами этого одного bean-компонента с областью просмотра. 15.03.2011
  • Слушатель сеанса должен быть правильным инструментом. Если файла нет, то вы просто обращаетесь не к тому bean-компоненту или переопределяете bean-компонент и/или список файлов где-то еще. Запустите отладчик. 15.03.2011
  • Привет, Балус. Получение сеансового компонента в компоненте области просмотра с использованием контекста лиц работало отлично. Компонент показал обновленные значения в фильтре и сервлете, а также sessionListener..! Что здесь происходит? 15.03.2011

Ответы:


1

Вы смешиваете JSF и CDI. Ваш UserSessionBean — это JSF @ManagedBean, но вы используете CDI @Inject для его внедрения в другой bean-компонент. CDI не использует повторно управляемый JSF, вместо этого создает совершенно новый. Используйте одно или другое, а не оба. Правильная аннотация для внедрения bean-компонента, управляемого JSF: @ManagedProperty .

Заменять

@Inject
private UserSessionBean userSessionBean; 

by

@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 {}

Additional advantage is that you can just @Inject it inside a regular servlet or filter without the need to manually grab it as request/session/application attribute.

Moreover, JSF bean management annotations are deprecated since JSF 2.3. See also Backing beans (@ManagedBean) or CDI Beans (@Named)?

15.03.2011
  • Маша Данки! ;-) 14.11.2017

  • 2

    Моя лучшая догадка о том, почему это происходит, заключается в том, что файл переменной устанавливается в области представления, а затем передается по ссылке в bean-компонент с областью действия сеанса. Возможно, это происходит из-за того, что когда bean-компонент области представления уничтожается, он все еще имеет ссылку на эту переменную, но не удосуживается проверить, есть ли какие-либо другие ссылки на нее в области сеанса, где она должна быть сохранена. Следовательно, когда он уничтожается, в этом случае он удаляется как из представления, так и из области сеанса.

    Не могли бы вы попробовать вызвать setCurrentFile с объектом, созданным с помощью «нового»? Это может подтвердить или опровергнуть мою гипотезу.

    В противном случае моим лучшим советом было бы взломать отладчик и посмотреть, где именно изменяется getCurrentFile.

    14.03.2011
  • Да, я тоже пытался использовать новый. Забыл это указать. userSessionBean.setCurrentFile (новый файл (file.getAbsolutePath())); То же самое. 14.03.2011
  • Хорошо, как только я нажимаю кнопку для загрузки, фильтр срабатывает. Это когда файловый объект переходит в . Единственное, что устанавливает это значение, — это конструктор сессионного компонента. Я отладил его, и этот конструктор не запускается. Я не знаю, что здесь происходит. 14.03.2011
  • Это головная боль... другие вещи, которые я бы попробовал: 1) Изменение конструктора, чтобы установить значение на что-то сумасшедшее, чтобы убедиться, что пустая строка не является совпадением. 2) вызов setCurrentFile с объектом File, который абсолютно не ссылается на файл; составить какой-то сумасшедший путь. 3) Установите часы для этой переменной в отладчике, чтобы увидеть, можете ли вы заставить ее сломаться в точке, где она сбрасывается. 4) Я заметил, что у currentUser есть аннотация Inject. Это тоже фасоль? Возможно, попробуйте обернуть fileList и currentFile в этот класс, так как currentUser, похоже, не затронут этим странным поведением. 14.03.2011
  • Хорошо, я возился с этим еще немного. Я установил текущий файловый объект в другой файл вместо . Когда я печатаю имя файла из bean-компонента с областью видимости, оно отображается правильно. Если я распечатаю его из фильтра, он покажет файл, установленный в конструкторе. Это действительно странно. Как будто есть два сеансовых компонента. Я неправильно понимаю, что делает инъекция? Это должно дать мне только текущий экземпляр этого компонента. Обновлен исходный пост. Кстати: currentUser является объектом JPA. 15.03.2011
  • Хм, я на самом деле не использовал аннотацию для инъекций, поэтому я не могу много говорить об этом. Но я только что заметил, что вы используете его в сочетании с bean-компонентом с областью видимости, поэтому, возможно, также попробуйте: 1) временно изменить ViewLines на SessionScope, чтобы увидеть, не является ли ViewScope проблемой. 2) Доступ к сеансовому компоненту напрямую, без инъекции. Мой опыт работы с JSF основан исключительно на поддержании существующей базы кода, и с тех пор, как я начал, я обнаружил, что парень до меня делал некоторые сомнительные вещи, но я мог бы дать вам фрагмент кода для прямого доступа к SessionBean, если вы нужно это. 15.03.2011
  • Обновил пост. Получение сеансового компонента с использованием контекста лиц в компоненте ViewScoped работало отлично. Я не знаю, что происходит. 15.03.2011
  • Новые материалы

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

    Внедрите OAuth в свои веб-приложения для повышения безопасности
    OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

    Как свинг-трейдеры могут использовать ИИ для больших выигрышей
    По мере того как все больше и больше профессиональных трейдеров и активных розничных трейдеров узнают о возможностях, которые предоставляет искусственный интеллект и машинное обучение для улучшения..

    Как построить любой стол
    Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...

    Обзор: Машинное обучение: классификация
    Только что закончил третий курс курса 4 часть специализации по машинному обучению . Как и второй курс, он был посвящен низкоуровневой работе алгоритмов машинного обучения. Что касается..

    Разработка расширений Qlik Sense с qExt
    Использование современных инструментов веб-разработки для разработки крутых расширений Вы когда-нибудь хотели кнопку для установки переменной в приложении Qlik Sense? Когда-нибудь просили..