WedX - журнал о программировании и компьютерных науках

Невозможно вызвать метод, так как inject имеет значение null

Я создаю веб-приложение и использую java ee 7, развертывая его с помощью плагина maven tomcat, создавая войну. У меня есть сервлеты, ejb, некоторая логика, интеграция jpa и т. д. Я использую шаблон команды для обработки запросов. Мой основной сервлет извлекает параметры и перенаправляет пользователя на следующую страницу в соответствии с командой из скрытого ввода в качестве параметра.

У меня есть форма входа и классы, которые реализуют логику входа. Эти занятия следующие

EDIT (я отредактировал свой код, добавив инъекцию bean-компонентов. Также я создал соответствующие квалификаторы для каждой команды)

Мой код

SigninCommand.java

@SigninCommandQualifier
public class SigninCommand implements Command {

    @Inject
    private UserEJB userEJB;

    public String execute(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String password = request.getParameter("password");
        String email = request.getParameter("email");
        User signinUser = new User(email, password);
        User foundUser = userEJB.findUser(signinUser);
        if (foundUser != null) {
            request.setAttribute("passedAuth", true);
            return PagesManager.getProperty("page.nameGeneration");
        } else {
            request.setAttribute("passedAuth", false);
            return PagesManager.getProperty("page.signin");
        }
    }
}

UserEJB.java

@Stateless
public class UserEJB implements UserEJBRemote{
    @Inject
    private EntityManager em;
    public List<User> findUsers() {
        TypedQuery<User> query = em.createNamedQuery(FIND_ALL, User.class);
        return query.getResultList();
    }

    public User findUser(@NotNull User user) {
        return em.find(User.class, user);
    }

    public
    @NotNull
    User createUser(@NotNull User user) {
        em.persist(user);
        return user;
    }

    public
    @NotNull
    User updateUser(@NotNull User user) {
        return em.merge(user);
    }

    public void deleteUser(@NotNull User user) {
        em.remove(em.merge(user));
    }
}

beans.xml

<beans xmlns="https://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="https://xmlns.jcp.org/xml/ns/javaee https://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       version="1.1" bean-discovery-mode="all">
</beans>

ProjectServlet.java

public class ProjectServlet extends HttpServlet {

    @Inject
    @EmptyCommandQualifier
    private Command command;

    @Inject
    private ActionFactory actionFactory;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        processRequest(request, response);
    }

    private void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        String action = request.getParameter("command");
        try {
            command = actionFactory.defineCommand(action);
        } catch (IllegalArgumentException e) {
            request.setAttribute("msg", action + " " + MessageManager.getProperty("message.wrongaction"));
        }
        String page;
        try {
            page = command.execute(request, response);
        } catch (IOException e) {
            page = PagesManager.getProperty("page.error");
        }
        if (page != null) {
            if (page.equals("not redirecting")) {
                return;
            }
            RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(page);
            dispatcher.forward(request, response);
        } else {
            page = PagesManager.getProperty("page.index");
            request.getSession().setAttribute("nullPage",
                    MessageManager.getProperty("message.nullpage"));
            response.sendRedirect(request.getContextPath() + page);
        }
    }
}

Command.java

public interface Command {
    String execute(HttpServletRequest request, HttpServletResponse response) throws IOException;
}

CommandEnum.java

public enum CommandEnum {

    EMPTY_COMMAND {
        {
            this.command = emptyCommand;
        }
    },
    NAME_GENERATION {
        {
            this.command = nameGenerationCommand;
        }
    },
    NAME_GENERATION_SETTINGS {
        {
            this.command = nameGenerationSettingsCommand;
        }
    },
    SIGNIN {
        {
            this.command = signinCommand;
        }
    };

    Command command;

    @Inject
    EmptyCommand emptyCommand;
    @Inject
    NameGenerationCommand nameGenerationCommand;
    @Inject
    NameGenerationSettingsCommand nameGenerationSettingsCommand;
    @Inject
    SigninCommand signinCommand;

    public Command getCommand() {
        return command;
    }
}

ActionFactory.java

public class ActionFactory {

    @Inject
    @EmptyCommandQualifier
    private Command command;

    @Inject
    private CommandEnum commandEnum;

    public Command defineCommand(String action) throws IllegalArgumentException {
        if (action == null || action.isEmpty()) {
            return command;
        }
        commandEnum = CommandEnum.valueOf(action.toUpperCase());
        command = commandEnum.getCommand();
        return command;
    }

    @Produces
    public static CommandEnum getEmptyCommandEnum()
    {
        return CommandEnum.EMPTY_COMMAND;
    }
}

Проблема

Когда я нажимаю кнопку входа на странице входа, я ловлю следующее исключение:

java.lang.NullPointerException: Cannot invoke "factory.ActionFactory.defineCommand(String)" because "this.actionFacto
ry" is null
        at servlet.ProjectServlet.processRequest(ProjectServlet.java:39)
        at servlet.ProjectServlet.doPost(ProjectServlet.java:33)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
        at java.base/java.lang.Thread.run(Thread.java:832)
        at org.apache.coyote.http11.AbstractHttp11Proces
sor.process(AbstractHttp11Processor.java:1041)
        at org.apache.coyote.AbstractProtocol$AbstractCo
nnectionHandler.process(AbstractProtocol.java:603)
        at org.apache.tomcat.util.net.JIoEndpoint$Socket
Processor.run(JIoEndpoint.java:310)
        at java.base/java.util.concurrent.ThreadPoolExec
utor.runWorker(ThreadPoolExecutor.java:1130)
        at java.base/java.util.concurrent.ThreadPoolExec
utor$Worker.run(ThreadPoolExecutor.java:630)
        at java.base/java.lang.Thread.run(Thread.java:83
2)

actionFactory имеет значение null, и я не знаю, почему.

Что я пробовал

  1. Добавление аннотации @Stateless к SigninCommand
  2. Добавление файла bean.xml в папку WEB-INF (до того, как он был помещен в META-INF)
  3. Очистить кеш IDEA
  4. Прикрепить аннотацию @Named к классу UserEJB

Но я все еще получаю NPE.

Помогите, пожалуйста.


  • Вам нужно добавить UserEjb в команду другим способом. Inject не будет работать, если объект не создан контейнером. Возможно, вы можете добавить его с помощью getCommand(userEjb). ... Это тоже не сработает. Вы создаете ActionFactory также по новому. Возможно, вам следует подумать о том, чтобы сделать каждую команду Bean-компонентом и получать их с помощью команд @Inject Instance‹Command›. 17.03.2021
  • @aschoerk, спасибо за ответ, я отредактировал свой код выше, добавив инъекцию в классы, чтобы избежать создания экземпляров new, и добавил квалификаторы для определения типа созданного экземпляра интерфейса, но теперь я получаю NPE of actionFactory 17.03.2021
  • Странно, поэтому @Inject в сервлет не работает. Что-нибудь вводится в сервлет? Вы создаете только один архив (война) или несколько (ухо)? Какой контейнер вы используете? 17.03.2021
  • @aschoerk, я создаю войну с помощью кота 17.03.2021
  • Сам по себе Tomcat не является контейнером, который обрабатывает CDI. Вы работаете в соответствии с tomcat.apache.org/tomcat-9.0-doc/cdi? .html? Или вы включаете WELD-Standalone? кстати @Stateless тоже не будет работать. Для этого вам нужен EJB-контейнер. 17.03.2021
  • @aschoerk, спасибо, я не упомянул, что контейнер сервлета только для tomcat :) Я перешел на Wildfly, и теперь у меня есть ошибки из JPA, которых не было в случае с tomcat. Ценю вашу помощь 18.03.2021

Ответы:


1

Проблема заключалась в том, что помимо использования новых для CDI-бинов, tomcat использовался как контейнер без каких-либо дополнений типа Weld-Standalone. Поэтому ни Ejb-аннотации, такие как @Ejb, @Standalone,..., ни CDI-аннотации, такие как @Inject, не имели никакого эффекта во время развертывания файла войны. Разумным решением для этого является переход от чистого контейнера сервлетов к контейнеру микропрофилей, например wildfly, kumuluzee...

19.03.2021

2

Обычно это вызвано некоторым возникновением экземпляра new где-то в вашей иерархии вызовов. Убедитесь, что ни один экземпляр вашего класса SigninCommand не создается new. Поскольку у нас нет вашего основного кода сервлета, я приношу свои извинения за то, что это всего лишь предположение, поскольку я не могу оставить комментарий с просьбой включить ваш код сервлета. Ваше здоровье.

16.03.2021
  • Спасибо, я включил код сервлета для публикации. Да, у меня есть перечисление, которое создает экземпляр SigninCommand, код тоже работает. Что я должен делать? Должен ли я ввести SigninCommand? 17.03.2021
  • Должен ли я преобразовать выполнение метода в статический и вызывать его без создания экземпляра? 17.03.2021
  • Новые материалы

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..


    Для любых предложений по сайту: [email protected]