Search code examples
javahibernatestruts2daomodel-driven

Multiple different POJOs using ModelDriven in Struts 2


How to use different POJOs like Address and Certificate class object using ModelDriven interface in same Action to perform collection mapping using Hibernate in Struts2?

Here is the code sample:

 package com.acv.in.action;
 import java.util.HashSet;
 import java.util.Set;
 import com.acv.in.bean.Student;
 import com.acv.in.dao.DAO;
 import com.acv.in.dao.DAOImpl;
 import com.opensymphony.xwork2.ActionSupport;
 import com.opensymphony.xwork2.ModelDriven;

 public class UserActionImpl extends ActionSupport implements  ModelDriven<Student>{

private static final long serialVersionUID = 1L;
Set<String> docList= new HashSet<String>();
DAO dao= new DAOImpl();
private Student student= new Student();
 
@Override
public Student getModel() {
    // TODO Auto-generated method stub
    return student;
}

How to return Address and Certificate objects?

public UserActionImpl()
{
    
}

public String add() {
  System.out.println("inside add");
  dao.insert(student);
    return "success";
}

 
public String delete() {
    // TODO Auto-generated method stub
    return "success";
}


public String update() {
    // TODO Auto-generated method stub
    return "success";
}

 
public String getById() {
    // TODO Auto-generated method stub
    return "success";
}


public String getAll() {
    // TODO Auto-generated method stub
    return "success";
}

public Set<String> getDocList() {
    return docList;
}

public void setDocList(Set<String> docList) {
    this.docList = docList;
}

public Student getStudent() {
    return student;
}

public void setStudent(Student student) {
    this.student = student;
}


public DAO getDao() {
    return dao;
}

public void setDao(DAO dao) {
    this.dao = dao;
}

 
}

Solution

  • If you are using ModelDriven and you have multiple beans (in the same action class) that you have to bind to the view. You can aggregate them to the model object.

    public class Student {
      private Address address; 
      private Certificate certificate;
      //getters and setters
    } 
    

    In the JSP you can use address.xxx and certificate.yyy names. What is the best with this approach you map properties of the beans of different types by specifying a prefix name without type checks of the model object.

    If you have multiple action classes you can use their own models like

    public class AddressActionImpl extends ActionSupport implements  ModelDriven<Address>{ }
    
    public class CertificateActionImpl extends ActionSupport implements  ModelDriven<Certificate>{ }
    

    But the problem with this approach if you share the same JSP you shouldn't use them both, because it can't distinguish which class a property belongs to.

    The same thing if you implement ModelDriven<Object> and then return either instances as the model object. The view doesn't know which model is used to bind its properties (unless you explicitly check the instance type). It just assumes the model has a property that is bound to.

    A side note:

    Using models of different types brings unnecessary complexity to the application logic, as well as duplication of code. If you don't have a necessity to use ModelDriven, then better to avoid it. You can use multiple objects of different classes aggregated to the Action class instead of the model class.