How are Servlet / JSP MVC templates translated to JSF / Facelets (in particular, to the service and controller parts)?

Take a basic example. In a servlet application, I would have the following classes:

  • app.domain.User : domain or POJO model, will contain fields and getters / seters
  • app.service.UserService : contains methods that work with user instances, for example Register(User) . Would call DAO.
  • app.dao.UserDao : will be called by the service, in fact, say, insert the user into the database.
  • app.servlets.RegisterController : the servlet intercepts requests from www.app/registration and calls methods in app.service.UserService. Then it will be redirected to WEB-INF\JSPs\registration.jsp , which will take care of viewing.

All this made sense to me and clearly shared the problems.

I tried to wrap my head around JSF / Facelets thinking. I went through many excellent resources here in SO and other places, but there is no place that solves this simple question - namely, how the image of dao / service / controller / view is translated into JSF.

To continue my example, I created a JSF project in eclipse, transferred my database schema to "entities" , and now Iโ€™m wondering: which package, with which king of classes should I create for user processing Registration? I understand that I need to create xhtml pages for presentation, but where is the controller?

Please do not point me to textbooks. I know many, including @BalusC one - my problem is not to do this work, but to understand the picture. I saw "session" packages containing "managed beans templates", "abstract facade", etc. Etc., But nothing makes as clear as the good old servlet template.

So, among the "entities" created by the database, there is a User.java class that looks like a model to me. The view will be xhtml. Controller?

NB: there are not so many duplicates of the differences between these technologies - I ask for a clear translation of the very clear and intuitive controller template / dao / service in the JSF structure - or a clear statement that there is no such translation.

See also:

+6
source share
3 answers

JSF 2 has two levels of MVC:

  • Model = @ManagedBean , View = Facelets / xhtml, Controller = FacesServlet if you are only looking at jsf
  • Model = Entities + Services, Controller = @ManagedBean , View = xhtml, if you look at your application as a whole.

A typical package layout in a JSF application is the same:

  • com.foo.domain.featurex.service <- model
  • com.foo.domain.featurex.model <- model
  • com.foo.presentation.featurex < com.foo.presentation.featurex
  • xhtml files <- view

Not much difference here, except that your controller is now a FacesServlet (JSF heart) along with your @ManagedBean/@Named , which will be in a class like com.foo.presentation.featurex.Controller/Handler or something in that kind of thing.

An example of a simple registration:

 // we talk about the big picture here, not about how jsf is built // but how your app is built // model package com.foo.domain.registration.entity; @Entity public class User { // fields } package com.foo.domain.registration.service; // also model @Stateless public class RegistrationService { @PersistenceContext EntityManager em; public void register(User u) { em.persist(u); } } package com.foo.presentation // controller @Named @ViewScoped public class RegistrationController { @Inject RegistrationService rs; User current = new User(); public void register() { rs.register(u); } // get set for current user } // view // quite a lot boilerplate omitted // form omitted which displays all the necessary field of your current user // via value="#{registrationContoller.current.name}" <h:commandButton value="submit" type="submit" action="#{registrationController.register}" /> 
+3
source

This is not true. They are conceptually different. MVC uses the MVC model, and jsf uses a handler-based model.

The face of your page is executed using an XHTML file. A handler processes input input, for example, a submit form. Binding exists between form elements and a handler, usually using getters and setters. Therefore, if the user submits the form, the method of your handler is called, and all the data provided is already used for processing (due to the load of the event phases).

So your XHTML file gives you a username and password. The handler method is called. You look at the credentials and return the string, forwarding the user to a new page.

As already mentioned, you cannot compare two technologies. This is like sending an email or sending a written letter. Yes, they transmit information, and yes, it is a messeging relay system. But how this is done is completely different. This is the same paradigm clash when writing jsf, and then moving on to the gate.

+1
source

Here's what I did - Service, played by DAO:

 package app.service; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.PersistenceContext; import javax.persistence.Query; import app.entities.User; @Stateless public class UserService { @PersistenceContext private EntityManager em; public User register(User u) { // TODO : transactions, sql injection // https://stackoverflow.com/q/21640369/281545 em.persist(u); // em.flush(); // not needed return u; } public boolean isUsernameUnique(String username) { Query query = em .createNativeQuery("SELECT r1_check_unique_username(?)"); short i = 0; query.setParameter(++i, username); return (boolean) query.getSingleResult(); } } 

Controller - Form Access

 package app.controllers; import javax.annotation.PostConstruct; import javax.ejb.EJB; import javax.faces.application.FacesMessage; import javax.faces.bean.ManagedBean; import javax.faces.bean.RequestScoped; import javax.faces.bean.ViewScoped; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.validator.Validator; import javax.faces.validator.ValidatorException; import javax.persistence.NoResultException; import app.entities.User; import app.service.UserService; @ManagedBean @ViewScoped public class UserController { // https://stackoverflow.com/a/10691832/281545 private User user; @EJB // do not inject stateful beans (?) // @Inject private UserService service; public User getUser() { return user; } @PostConstruct void init() { // https://stackoverflow.com/questions/3406555/why-use-postconstruct user = new User(); } public String login() { return null; } public String register() { FacesContext context = FacesContext.getCurrentInstance(); user = service.register(user); if (user.getIduser() == 0) { context.addMessage(null, new FacesMessage( FacesMessage.SEVERITY_ERROR, "Registration failed", null)); return null; } context.getExternalContext().getSessionMap().put("user", user); return "/index.xhtml?faces-redirect=true"; } public String logout() { return null; } @ManagedBean @RequestScoped public static class UniqueUsernameValidator implements Validator { @EJB private UserService service; @Override public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException { if (value == null) return; // Let required="true" handle, if any. try { if (!service.isUsernameUnique((String) value)) { throw new ValidatorException(new FacesMessage( FacesMessage.SEVERITY_ERROR, "Username is already in use.", null)); } } catch (Exception e) {} } } 

Pay attention to the packages and I use the service as a DAO. It is not clear on transactions and EJB against CDI, and all this, but it works and trades;

+1
source

All Articles