I've a proyect that call various webservices using an external library. This library give me objects like this:
public static class ObjA {
@XmlElement(name = "counter", required = true)
protected BigInteger counter;
@XmlElement(name = "data", required = true)
protected String data;
[...]
}
and this:
public static class ObjB {
@XmlElement(name = "counter", required = true)
protected BigInteger counter;
@XmlElement(name = "data", required = true)
protected String data;
[...]
}
as you can see objA and objB have same properties so, if I have to use both, I've to duplicate code:
public class myClass {
[...]
private ObjA a;
private ObjB b;
[...]
public void myClass() {
[...]
this.a = new ObjectFactory().createObjA();
this.b = new ObjectFactory().createObjB();
[...]
}
public void init() {
this.initA();
this.initB();
}
private void initA() {
this.a.setCounter(BigInteger.ZERO);
this.a.setData = "";
}
private void initB() {
this.b.setCounter(BigInteger.ZERO);
this.b.setData = "";
}
[...]
}
initA and initB are identical, I cannot access the library code so I can't create a common interface, in which way can I avoid duplicated code? I mean, it's possible to have something like this?
private void initObj([ObjA|ObjB] obj) {
obj.setCounter(BigInteger.ZERO);
obj.setData = "";
}
Thank you! Muchas Gracias!
addendum
Please note I have no access to the underlying library, so I can't add modify classes, interfaces, wsdl or xsd in any way. Also in my opinion is not important if I'm using a ws or not, jaxb or other library: you can imagine ObjA and ObjB without annotations, like this:
public static class ObjA {
protected BigInteger counter;
protected String data;
[...]
}
public static class ObjB {
protected BigInteger counter;
protected String data;
[...]
}
and the crux of the matter doesn't change.
I assume that the classes are generated for you using some sort of tool, perhaps the maven cxf-codegen-plugin etc. If this is the case, you need to modify the WSDL and XSD's such that the DTO classes are generated to your satisfaction. If the WSDL was supplied to you, then you will just have to accept the service as is?
You could use reflection if you know that the common methods all have the same name?
so you'd do something like this with raw reflection :
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void initObject(Object o) throws Exception {
if (!(o instanceof ObjA)&&!(o instanceof ObjB)) return;
Method m = o.getClass().getMethod("setCounter",java.math.BigInteger.class);
m.invoke(o,BigInteger.ZERO);
m = o.getClass().getMethod("setData",java.lang.String.class);
m.invoke(o,"");
}
public static void main(final String[] args) throws Exception {
List<Object>objects = new ArrayList<Object>();
//this is like your factory method
Object o = Class.forName("ObjA").newInstance();
initObject(o);
objects.add(o);
o = Class.forName("ObjB").newInstance();
initObject(o);
objects.add(o);
}
}
If you wanted to use a library you could use something like JXPath and see docs here But I think for your purpose raw reflection is probably fine. There's no need for a massively complicated reflection library.