CDI in layered architecture. How to add a service object using CDI annotations?

I am developing an application consisting of three layers:

  • Database Access Level (JPA + Hibernate as a Provider)
  • Business logic level
  • Presentation Level (JSF 2.0)

Before I started, I read a few chapters from Core JavaServer Faces (3rd Edition) by David Geary and Kay S. Horstmann. In this book, authors strongly recommend using @Named annotation instead of @ManagedBean . Ok, I thought I could try.

Then I proceeded to create the layers of my application, simply by performing some basic functions - users are logged in.

I also read about a new annotation, namely @Inject . I thought it was very convenient to just paste one layer into another, based only on interfaces. But I'm afraid that I did not understand something, so I came to you with my problem.

Let me introduce some parts of my code:

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

This last class runs on some kind of Java class with annotation @Entity , nevermind.

I have a feeling that something is wrong with my decision.

The basic error is the fact that even if I provided some data to the form created with the <h:form> , <h:inputText> , when debugging the verify() method, I can see that login and password are null >, so here what something is wrong, but I have no idea what.

I also have problems if I understand @Inject well. Can I use it this way, as shown above, to interface layers using interfaces?


Ok I found the reason why I get nulls in the login and password fields, but I don't know the solution yet. This is because at run time in some magical way there are several (at least two) instances of CredentialsBean. Checked in the Eclipse debugger. First, its fields are set correctly, and the second is not, and this second value is sent to the service level. I wonder, not a question of volume. Should I put @SessionScoped in a CredentialsBean?

+4
source share
2 answers

I believe the problem is with your CredintialsBean class. You did not specify a scope for the bean to use the default scope (see What is the default scope for a Named CDI bean? For more information).

If you add something like @RequestScoped to your class, it should work. Make sure you are using javax.enterprise.context.RequestScoped and not the version of javax.faces.

+2
source

Your understanding of @Inject is true exactly what it is. Most likely, your injection points are zero, because you do not have a bean archive (you need a file named beans.xml in WEB-INF or META-INF, if it is a jar, it may be empty). This is a common reason for having zero at your injection points.

+1
source

Source: https://habr.com/ru/post/1382550/


All Articles