Reputation: 1138
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.
Upvotes: 2
Views: 1142
Reputation: 1130
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.
Upvotes: 1
Reputation: 225
I suppose that you are using JAXB. You can read a list of Objects. See this post: JAXB Unmarshalling: List of objects
Upvotes: 1
Reputation: 2616
Since they don't have a common interface (or parent class?), I guess the way to go is with java reflection.
Create some reflection helper methods by yourself like "init(Class clazz)" and invoke the construtors.
Keep in mind that java reflection is bad practice in most cases, so make sure that there are no other/better methods to accomplish your goal.
Upvotes: 0