Mvc – Is it possible to add Service layer in MVC pattern

controllerdesign-patternsjavafxmvc

I'm working on javaFX project using Hibernate and H2 database,I'm trying follow the concept of MVC design pattern ,so I have created 3 packages :

  1. models :contains POJO classes

    2.1 views.fxml:contains fxml files

    2.2. views.controllers :contains the controllers classes of fxml files

3
. dao:contains classes which they interact with database.

At now every thing is well ,but when i followed a tutoriel ,i found that he added Service layer ,this one has a role to create objects and send them to DAO layer ,i created this example ,but i'm confused if it is true or i'm out the concepts ,this is my example :

Model :

@Entity
@javax.persistence.Table(name = "ENTREPRENEUR")
public class Entrepreneur implements Serializable {

    private String Id;
    private final StringProperty lastName = new SimpleStringProperty();
    private final StringProperty firstName = new SimpleStringProperty();
    private final StringProperty email = new SimpleStringProperty();
    private final StringProperty password = new SimpleStringProperty();
    private final StringProperty category = new SimpleStringProperty();
    public Date signDate;
    public byte[] picture;

    public Set<Corporation> corporations;

    public Entrepreneur() {
        corporations = new HashSet<>();
    }

    @OneToMany(mappedBy = "entrepreneur")
    public Set<Corporation> getCorporations() {
        return corporations;
    }

    public void setCorporations(Set<Corporation> corporations) {
        this.corporations = corporations;
    }

    @Column(name = "CATEGORY")
    private String getCategory() {
        return category.get();
    }

    public void setCategory(String value) {
        category.set(value);
    }

    private StringProperty categoryProperty() {
        return category;
    }

    @Column(name = "PICTURE")
    public byte[] getPicture() {
        return picture;
    }

    public void setPicture(byte[] picture) {
        this.picture = picture;
    }

    @Column(name = "SIGN_UP_DATE")
    public Date getSignDate() {
        return signDate;
    }

    public final void setSignDate(Date signDate) {
        this.signDate = signDate;
    }

    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    @Column(name = "ID", updatable = false, nullable = false)
    public String getId() {
        return Id;
    }

    public void setId(String Id) {
        this.Id = Id;
    }

    @Column(name = "EMAIL")
    public String getEmail() {
        return email.get();
    }

    public final void setEmail(String value) {
        email.set(value);
    }

    public StringProperty emailProperty() {
        return email;
    }

    @Column(name = "PASSWORD")
    public String getPassword() {
        return password.get();
    }

    public final void setPassword(String value) {
        password.set(value);
    }

    public StringProperty passwordProperty() {
        return password;
    }

    @Column(name = "FIRST_NAME")
    public String getFirstName() {
        return firstName.get();
    }

    public final void setFirstName(String value) {

        firstName.set(value);
    }

    public StringProperty firstNameProperty() {
        return firstName;
    }

    @Column(name = "LAST_NAME")
    public String getLastName() {
        return lastName.get();
    }

    public final void setLastName(String value) {
        lastName.set(value);
    }

    public StringProperty lastNameProperty() {
        return lastName;
    }

    public void addCompany(Corporation company) {
        if (!corporations.contains(company)) {
            corporations.add(company);
        }
    }

Controller :

  @FXML
    private void createAccount() throws IOException {
        String lastNameValue = lastNameField.getText();
        String firstNameValue = firstNameField.getText();
        String categoryValue = this.category.getValue();
        String emailValue = emailField.getText();
        String passwordValue = Security.encrypt(passwordField.getText());
        new EntrepreneurServiceImp().create(lastNameValue, firstNameValue, categoryValue, emailValue, passwordValue);
    }

Service :

public class EntrepreneurServiceImp implements EntrepreneurService {

    @Override
    public void create(String lastName, String firstName, String category, String email, String password) {

        //Create and fill an object
        Entrepreneur entrepreneur = new Entrepreneur();
        entrepreneur.setLastName(lastName);
        entrepreneur.setFirstName(firstName);
        entrepreneur.setCategory(category);
        entrepreneur.setEmail(email);
        entrepreneur.setPassword(password);
        entrepreneur.setSignDate(Date.valueOf(LocalDate.now()));

        //Send object to DAO layer
        new EntrepreneurDao().save(entrepreneur);

    }

}

DAO:

public class EntrepreneurDao extends DAO<Entrepreneur> {

    @Override
    public boolean save(Entrepreneur entrepreneur) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        session.save(entrepreneur);
        session.getTransaction().commit();
        return true;
    }
}

Priviously ,i create and fill the object in controller layer and call the DAO method from the controller ,but now i added Service layer which has a role only with objects ,Is my implementation true or no ?

Best Answer

Your implementation is right, but there is something you could improve.

If you want to introduce S (= service layer) in MVC, then this is one (usual) way you could do it:

Before: M <--> C <--> V

After: M <--> S <--> C <--> V

The controller uses the service class to do business logic. All the business logic is handled by the service class and is therefore at a centralized place.

The thing you are missing is a Service factory. I would introduce a Service factory that is responsible for intantiating specific Service realizations. In your C (controller) classes, you would want to instantiate the service objects using the service factory. The Service object would then itself instantiate all the DAOs. You then delegate all the CRUD operations to the service class and let it handle.

The advantage of this is that you can then swap the service factory which you pass to your controller classes at a centralized place to completely change the behaviour.