CDI в многоуровневой архитектуре. Как внедрить объект сервиса с помощью аннотаций CDI?

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

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

Перед началом работы я прочитал несколько глав из книги Core JavaServer Faces (3rd Edition) Дэвида Гири и Кей С. Хорстманна. В этой книге авторы настоятельно рекомендуют использовать аннотацию @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, не важно.

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

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

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


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

5
задан Bill the Lizard 28 November 2011 в 11:45
поделиться