Регистратор, преобразование из @Inject в производителя

У меня возникли проблемы с реализацией интерфейса входа в систему, как в примере Простое веб-приложение CRUD с JSF 2.1, PrimeFaces 3.5, EJB 3.1, JPA (ORM) / EclipseLink, JAAS, MySQL В списке рассылки TomEE мне сказали, что LoginController.java Я использую попытки внедрить Logger, но внедрение Logger не управляется CDI. Вместо этого мне сказали использовать продюсера. Не зная, что это такое, я поискал в Интернете и нашел этот пример Но я все еще не согласен с этим, поэтому, пожалуйста, объясните, что мне нужно изменить, чтобы реализовать производителя для логгера.

LoginController.java

package controller;

import util.DateUtility;

import java.io.IOException;
import java.io.Serializable;
import java.security.Principal;
import java.util.logging.Level;
import java.util.logging.Logger;


import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * Login Controller class allows only authenticated users to log in to the web
 * application.
 *
 * @author Emre Simtay <[email protected]>
 */
@Named
@SessionScoped

public class LoginController implements Serializable {

    @Inject
    private transient Logger logger;
    private String username;
    private String password;

    /**
     * Creates a new instance of LoginController
     */
    public LoginController() {
        System.out.println("test");
    }

    //  Getters and Setters
    /**
     * @return username
     */
    public String getUsername() {
        return username;
    }

    /**
     *
     * @param username
     */
    public void setUsername(String username) {
        this.username = username;
    }

    /**
     *
     * @return password
     */
    public String getPassword() {
        return password;
    }

    /**
     *
     * @param password
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * Listen for button clicks on the #{loginController.login} action,
     * validates the username and password entered by the user and navigates to
     * the appropriate page.
     *
     * @param actionEvent
     */
    public void login(ActionEvent actionEvent) {
        System.out.println("CONSOLE PRINT TEST");

        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
        try {
            String navigateString = "";
            // Checks if username and password are valid if not throws a ServletException
            request.login(username, password);
            // gets the user principle and navigates to the appropriate page
            Principal principal = request.getUserPrincipal();
            if (request.isUserInRole("Administrator")) {
                navigateString = "/admin/AdminHome.xhtml";
            } else if (request.isUserInRole("Manager")) {
                navigateString = "/manager/ManagerHome.xhtml";
            } else if (request.isUserInRole("User")) {
                navigateString = "/user/UserHome.xhtml";
            }
            try {
                logger.log(Level.INFO, "User ({0}) loging in #" + DateUtility.getCurrentDateTime(), request.getUserPrincipal().getName());
                context.getExternalContext().redirect(request.getContextPath() + navigateString);
            } catch (IOException ex) {
                logger.log(Level.SEVERE, "IOException, Login Controller" + "Username : " + principal.getName(), ex);
                context.addMessage(null, new FacesMessage("Error!", "Exception occured"));
            }
        } catch (ServletException e) {
            logger.log(Level.SEVERE, e.toString());
            context.addMessage(null, new FacesMessage("Error!", "The username or password you provided does not match our records."));
        }
    }

    /**
     * Listen for logout button clicks on the #{loginController.logout} action
     * and navigates to login screen.
     */
    public void logout() {

        HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
        HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
        logger.log(Level.INFO, "User ({0}) loging out #" + DateUtility.getCurrentDateTime(), request.getUserPrincipal().getName());
        if (session != null) {
            session.invalidate();
        }
        FacesContext.getCurrentInstance().getApplication().getNavigationHandler().handleNavigation(FacesContext.getCurrentInstance(), null, "/Login.xhtml?faces-redirect=true");
    }
}

person Germano Massullo    schedule 12.01.2014    source источник


Ответы (2)


Когда вы используете @Inject, CDI пытается создать для вас экземпляр запрошенного типа. Самое простое решение: оно вызывает конструктор по умолчанию и возвращает этот экземпляр.

Проблема с java.util.logging.Logger: у него нет видимого конструктора по умолчанию. Таким образом, вы должны указать CDI, как удовлетворить зависимость, добавив производителя в путь к классам. Хотя использование сварочного регистратора, предложенного @JohnAment, также было бы моим предпочтительным решением, учитывая ваш текущий уровень знаний, вероятно, это будет лучше для вас, если вы начнете с добавления своего собственного производителя.

Итак, рядом с вашим контроллером создайте новый класс (добавьте пакет, импортируйте,... сами)

public class LoggerProducer {
   @Produces
   public Logger getLogger(InjectionPoint p) {
     return Logger.getLogger(p.getClass().getCanonicalName());
   }
}

Это говорит контейнеру CDI: всякий раз, когда вам нужно внедрить java.util.logging.Logger, используйте этот метод, чтобы создать его, взяв полное имя класса, где нужна эта ссылка на регистратор.

Это должно решить вашу проблему. Когда у вас появится идея, подумайте, действительно ли вы хотите/нужно использовать java.util.logging или хотите переключиться на slf4j. В этом случае измените импорт вашего контроллера, удалите LoggerProducer, который вы только что написали, и вместо этого импортируйте jar weld-logger в свое развертывание.

person Jan Galinski    schedule 13.01.2014
comment
Итак, если бы у Logger был общедоступный конструктор по умолчанию, все бы работало? Я могу ошибаться, но это все равно не сработает (нет beans.xml) - person dalvarezmartinez1; 18.09.2014

Они верны, стандартной инъекции регистраторов не существует. Вы можете посмотреть на этот пример из Weld о том, как внедрить их клиентский регистратор. Пожалуйста, не стесняйтесь изменить его, чтобы использовать java.util.logging.

http://grepcode.com/file/repo1.maven.org/maven2/org.jboss.weld/weld-logger/1.0.0-CR1/org/jboss/weld/log/LoggerProducer.java

person John Ament    schedule 12.01.2014
comment
Спасибо, но я предпочитаю изменить существующий bean-компонент LoginController.java, потому что весь пример на веб-сайте SimTay идеально подходит для моих нужд, поэтому я боюсь, что он не будет работать, если я его кардинально изменю. - person Germano Massullo; 12.01.2014
comment
Что заставляет вас думать, что вам нужно изменить контроллер входа в систему? Производитель идет в отдельный класс. - person John Ament; 12.01.2014
comment
Моя полная неопытность в использовании Producer заставляет меня думать, что мне нужно изменить контроллер входа в систему. Знаете ли вы какую-нибудь хорошую веб-страницу, которая объясняет, как ее использовать? Лично я нашел только несколько запутанных объяснений в Интернете. - person Germano Massullo; 12.01.2014
comment
Мне очень помогла документация по сварке производителей: docs.jboss.org/weld/reference/1.0.0/en-US/html/ - person Jan Galinski; 13.01.2014