CDI в многоуровневой архитектуре. Как внедрить сервисный объект, используя аннотации CDI? - PullRequest
5 голосов
/ 22 ноября 2011

Я занимаюсь разработкой приложения, которое состоит из трех слоев:

  1. Уровень доступа к базе данных (JPA + Hibernate в качестве провайдера)
  2. Уровень бизнес-логики
  3. Уровень представления (JSF 2.0)

Прежде чем начать, я прочитал несколько глав из книги Core JavaServer Faces (3-е издание) Дэвида Гири и Кея С. Хорстманна. В этой книге авторы настоятельно рекомендуют использовать аннотацию @Named вместо @ManagedBean. Хорошо, я думал, что могу попробовать.

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

Я также читал о новой аннотации, а именно @Inject. Я думал, что может быть очень удобно просто внедрить один слой в другой, основываясь только на интерфейсах. Но я боюсь, что я что-то неправильно понял, поэтому я пришел к вам со своей проблемой.

Позвольте мне представить некоторые части моего кода:

CredentialsBean.java

@Named("userCredentials")
public class CredentialsBean {
    @Inject
    AccountService accountService;

    private String login;
    private String password;

    public String verify()
    {
        if (accountService.verifyCredentials(login, password))
            return "success";
        else
            return "failure";
    }
    // getters and setters
}

AccountService.java

public interface AccountService {
    public Boolean verifyCredentials(String login, String password);
}

AccountServiceImpl.java:

public class AccountServiceImpl implements AccountService {
    @Inject
    AccountDAO dao;

    @Override
    public Boolean verifyCredentials(String login, String password) {
        // some logic
    }
}

AccountDAO.java

public interface AccountDAO {
    public Account getAccount(String login);
}

AccountDAOImpl.java

public class AccountDAOImpl implements AccountDAO {
    @PersistenceContext(unitName = "MyApp")
    protected EntityManager em;

    public EntityManager getEntityManager() {
        return em;
    }

    @Override
    public Account getAccount(String login) {
        // some data processing
    }
}

Этот последний класс работает с некоторым классом Java с аннотацией @Entity, не имеет значения.

У меня такое ощущение, что с моим решением что-то не так.

Основная ошибка заключается в том, что даже если я предоставлю некоторые данные в форму, созданную с помощью тега <h:form>, <h:inputText>, при отладке метода verify() я вижу, что login и password равны null что-то здесь не так, но я понятия не имею, что.

У меня также есть проблемы, если я хорошо понимаю @Inject. Могу ли я использовать его так, как описано выше, для объединения слоев с помощью интерфейсов?


Ok. Я нашел причину, по которой я получаю пустые значения в полях логина и пароля, но пока не знаю решения. Это происходит потому, что во время выполнения каким-то волшебным образом создается несколько (как минимум два) экземпляров CredentialsBean. Проверено в отладчике Eclipse. Первый получает свои поля, установленные правильно, а второй нет, и значения этого второго отправляются на сервисный уровень. Мне интересно, если это не вопрос объема. Разве я не должен помещать @SessionScoped в CredentialsBean?

Ответы [ 2 ]

2 голосов
/ 05 марта 2013

Я считаю, что проблема в вашем классе CredintialsBean. Вы не указали область действия для компонента, поэтому он использует область по умолчанию (см. Что такое область по умолчанию для именованного компонента CDI? для получения дополнительной информации).

Если вы добавите что-то вроде @RequestScoped в ваш класс, это должно работать. Убедитесь, что вы используете javax.enterprise.context.RequestScoped, а не версию javax.faces.

1 голос
/ 23 ноября 2011

Ваше понимание @Inject верно, именно для этого оно и существует. Скорее всего, ваши точки внедрения равны нулю, потому что у вас нет архива бина (вам нужен файл с именем beans.xml в WEB-INF или META-INF, если это jar, он может быть пустым). Это обычная причина, по которой в ваших точках впрыскивания есть ноль.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...