javadesign-patternsreflectiontype-conversiondynamictype

Initialize a POJO dynamically from another method


Let's say I have these set of POJO class that implement an interface but there are no common attributes here.

public interface MainIfc {}

class Ifc1 implements MainIfc {
    private String a1;
    public String getA1() {
        return a1;
    }
    public void setA1(String a1) {
        this.a1 = a1;
    }
}

class Ifc2 implements MainIfc {
    private String x1;
    private String x2;
    public String getX1() {
        return x1;
    }
    public void setX1(String x1) {
        this.x1 = x1;
    }
    public String getX2() {
        return x2;
    }
    public void setX2(String x2) {
        this.x2 = x2;
    }
}

And in conjunction with these POJO classes I have a couple of methods which I can use to retrieve the type of POJO being returned based on another value and the actual POJO with values.

public class GetIfc {
    public Class getIfcType(int code) {
        if (code==1)
            return Ifc1.class;
        else
            return Ifc2.class;
    }
    public MainIfc getIfc(int code) {
        if (code==1) {
            Ifc1 thisIfc = new Ifc1();
            thisIfc.setA1("Ifc1");
            return thisIfc;
        } else {
            Ifc2 thisIfc = new Ifc2();
            thisIfc.setX1("Ifc2");
            thisIfc.setX2("Ifc2");
            return thisIfc;
        }
    }
}

Is there a way using which I can read the concrete POJO safely in my code and use the getters/setters? I have gone through quite a few questions which provide answers based on Reflection but that isn't working for me. The getters/setters aren't visible and when I call .getClass() on the returned Object I see it is the MainIfc interface.

The design problem I am trying to solve pertains to a REST API automation framework that I am trying to design. Basically I have a ClientResponse parser which will send back the POJO I am looking for. But I don't want the folks writing the test cases to worry about the type of POJO that is returned. So I was thinking I could return the type and the instantiated POJO so I get the values but I am troubled over how to achieve this dynamically.


Solution

  • Do consumers of MainIfc actually need the POJOs, or just the data inside of them?

    It might be cleaner design if MainIfc declares a method or two that exposes the data that its consumers will need. Your POJOs can then implement the methods that the MainIfc interface declares. Or you can build a wrapper class for each POJO that conforms it to the interface, if you want to keep the concerns of implementing your interface separate from your POJOs.

    Ideally an interface should expose a few methods that can be used to interact with any class which implements it and no one should need to know about the underlying POJOs/implementation.

    public interface MainIfc {
      public Hash getAttributes();
      public setAttributes(Hash attributes);
    }
    
    class Ifc1 implements MainIfc {
      private String a1;
      public String getA1() {
        return a1;
      }
      public void setA1(String a1) {
        this.a1 = a1;
      }
      public Hash getAttributes() {
        // return a hash with data that MainIfc consumer will need from this POJO
      }
      public setAttributes(Hash attributes) {
        // copy hash attributes to corresponding POJO fields
      }
    }
    
    class Ifc2 implements MainIfc {
      private String x1;
      private String x2;
      public String getX1() {
        return x1;
      }
      public void setX1(String x1) {
        this.x1 = x1;
      }
      public String getX2() {
        return x2;
      }
      public void setX2(String x2) {
        this.x2 = x2;
      }
      public Hash getAttributes() {
        // return a hash with data that MainIfc consumer will need from this POJO
      }
      public setAttributes(Hash attributes) {
        // copy hash attributes to corresponding POJO fields
      }
    }