Resolving cyclic references in jaxb - java

I'm dealing with some cyclic references while implementing my project's web service layer. I'm using jaxb (latest version, 2.2.7) and even I had a look to some tips as here and here I can't get it working. That's a basic SSCCE about my problem:
/*
* The service interface
*/
#WebService
public interface IMyWS {
#WebMethod
public List<Class1> cyclicTest();
}
/*
* Interface implementation
*/
#WebService(endpointInterface = "com.mycompany.ws.interfaces.IMyWS")
public class MyWS implements IMyWS {
#XmlRootElement
public static class Class1 {
#XmlTransient
private Class2 class2;
public Class1() {
}
public Class1(Class2 refClass) {
class2 = refClass;
}
public Class2 getClass2() {
return class2;
}
public void setClass2(Class2 class2) {
this.class2 = class2;
}
#Override
public String toString() {
return this.getClass().getSimpleName();
}
}
#XmlRootElement
public static class Class2 {
private Class1 class1;
public Class2() {
}
public Class1 getClass1() {
return class1;
}
public void setClass1(Class1 class1) {
this.class1 = class1;
}
#Override
public String toString() {
return this.getClass().getSimpleName();
}
}
#Override
public List<Class1> cyclicTest() {
//I create an instance of each class, having them a cyclic reference to the other instance
Class2 class2 = new Class2();
Class1 class1 = new Class1(class2);
class2.setClass1(class1);
return Arrays.asList(class1);
}
}
And the exception I'm actually dealing with when calling cyclicTest():
Caused by: javax.xml.bind.MarshalException
- with linked exception:
[com.sun.istack.SAXException2: Se ha detectado un ciclo en el gráfico de objeto. Esto provocará un XML con profundidad infinita: Class1 -> Class2 -> Class1]
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:326)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:178)
at org.apache.cxf.jaxb.JAXBEncoderDecoder.writeObject(JAXBEncoderDecoder.java:537)
at org.apache.cxf.jaxb.JAXBEncoderDecoder.marshall(JAXBEncoderDecoder.java:233)
... 50 more
Caused by: com.sun.istack.SAXException2: Se ha detectado un ciclo en el gráfico de objeto. Esto provocará un XML con profundidad infinita: Class1 -> Class2 -> Class1
at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:249)
at com.sun.xml.bind.v2.runtime.XMLSerializer.pushObject(XMLSerializer.java:537)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:631)
at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:158)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:361)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696)
at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:158)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:361)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696)
at com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:69)
at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:172)
at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:159)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:361)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:696)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:156)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:131)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeBody(ElementBeanInfoImpl.java:333)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:340)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:76)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:494)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:323)
... 53 more
I think I have the proper annotations set. What am I actually missing?

Using #XmlID and #XmlIDREF should solve your problem.
Here's what I did:
I added a String field to Class 1 to be used as an id, and annotated it with #XmlID.
Then, I annotated the setClass1() method with #XmlIDREF. My test is in the main method below.
/*
* Interface implementation
*/
#WebService(endpointInterface = "com.mycompany.ws.interfaces.IMyWS")
public class MyWS implements IMyWS {
#XmlRootElement
public static class Class1 {
#XmlID
private String id;
private Class2 class2;
public Class1() {
this.id = UUID.randomUUID().toString();
}
public Class1(Class2 refClass) {
this();
class2 = refClass;
}
public Class2 getClass2() {
return class2;
}
public void setClass2(Class2 class2) {
this.class2 = class2;
}
#Override
public String toString() {
return this.getClass().getSimpleName();
}
}
#XmlRootElement
public static class Class2 {
private Class1 class1;
public Class2() {
}
public Class1 getClass1() {
return class1;
}
#XmlIDREF
public void setClass1(Class1 class1) {
this.class1 = class1;
}
#Override
public String toString() {
return this.getClass().getSimpleName();
}
}
#Override
public List<Class1> cyclicTest() {
//I create an instance of each class, having them a cyclic reference to the other instance
Class2 class2 = new Class2();
Class1 class1 = new Class1(class2);
class2.setClass1(class1);
return Arrays.asList(class1);
}
public static void main(String[] args) throws JAXBException {
JAXBContext ctx = JAXBContext.newInstance(Class1.class);
Marshaller m = ctx.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
List<Class1> class1s = new MyWS().cyclicTest();
for (Class1 c1 : class1s){
m.marshal(c1, System.out);
}
}
}
Output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<class1>
<id>e9e53e73-9a96-4c7c-b919-3ed3d7aa4c5e</id>
<class2>
<class1>e9e53e73-9a96-4c7c-b919-3ed3d7aa4c5e</class1>
</class2>
</class1>

As you add #XmlTransient on a private property, you should change your XmlAccessType (default to XmlAccessType.PUBLIC_MEMBER) to XmlAccessType.PROPERTY
PUBLIC_MEMBER is the default access type in JAXB. It means that a JAXB implementation will generate bindings for: public fields, annotated fields, properties
code copied from W A :
#WebService(endpointInterface = "com.mycompany.ws.interfaces.IMyWS")
public class MyWS implements IMyWS {
#XmlRootElement
#XmlAccessorType(XmlAccessType.PROPERTY)
public static class Class1 {
private Class2 class2;
public Class1() {
}
public Class1(Class2 refClass) {
class2 = refClass;
}
#XmlTransient
public Class2 getClass2() {
return class2;
}
public void setClass2(Class2 class2) {
this.class2 = class2;
}
#Override
public String toString() {
return this.getClass().getSimpleName();
}
}
#XmlRootElement
public static class Class2 {
private Class1 class1;
public Class2() {
}
public Class1 getClass1() {
return class1;
}
public void setClass1(Class1 class1) {
this.class1 = class1;
}
#Override
public String toString() {
return this.getClass().getSimpleName();
}
}
public List<Class1> cyclicTest() {
//I create an instance of each class, having them a cyclic reference to the other instance
Class2 class2 = new Class2();
Class1 class1 = new Class1(class2);
class2.setClass1(class1);
return Arrays.asList(class1);
}
public static void main(String[] args) throws JAXBException {
JAXBContext ctx = JAXBContext.newInstance(Class1.class);
Marshaller m = ctx.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
List<Class1> class1s = new MyWs().cyclicTest();
for (Class1 c1 : class1s){
m.marshal(c1, System.out);
}
}

Adding to the answer by W Almir, to make generation of unique IDs for objects simpler (no need to add code to constructors), annotate a method that returns the id. For example:
#XmlID
public String getId()
{
return Integer.toString(System.identityHashCode(this));
}
This seems to work not only for converting cyclical graphs of Java objects to XML but also for converting XML to cyclical graphs of Java objects.

Related

Create a generic method with generic signature

i have some redundant code that i would like to remove, my goal would be to create a method of this kind:
private GenericClass myMethod(GenericClass genericClass){
genericClass.getTipe(); //tipe1 or tipe2
genericClass.setValue("foo");
genericClass.setValue2("foo");
//some logic
return genericClass;
}
Where this method can pass two similar classes but which differ in the type of an attribute
public class Class1{
private Tipe1 tipe1;
private String value;
private String value2;
//Constructor,Getter and Setter
}
public class Class2{
private Tipe2 tipe2;
private String value;
private String value2;
//Constructor,Getter and Setter
}
What I would like to do is call the method
someServiceIml.myMethod ("Foo")
passing either an object of type Class1 or Class2 according to my needs, the business logic behind myMethod is practically the same.
This method i wish it was in the same implementation of a certain service, could you give me some solution?
Create a generic abstract type; either a super class or an interface:
public interface GenericClass<T> {
public T getTipe();
public void setValue(String s);
public void setValue2(String s);
}
Have your implementation classes implement it:
public class Class1 implements GenericClass<Tipe1> {
// leave implementation as is
}
public class Class2 implements GenericClass<Tipe2> {
// leave implementation as is
}
And type your method:
private <T> GenericClass<T> myMethod(GenericClass<T> genericClass){
T tipe = genericClass.getTipe();
genericClass.setValue("foo");
genericClass.setValue2("foo");
// some logic
return genericClass;
}
If Tipe1 and Tipe2 share a common type, you can type them too:
public interface GenericClass<T extends SomeTipe> {
public class MyClass {
public static void main(String args[]) {
Class1 c1 = new Class1();
Class2 c2 = new Class2();
GenericClass gc = myMethod(c1);
System.out.println(gc);
}
private static GenericClass myMethod(GenericClass genericClass){
genericClass.getTipe(); //tipe1 or tipe2
genericClass.setValue("foo");
genericClass.setValue2("foo");
//some logic
return genericClass;
}
}
class Class1 extends GenericClass<Tipe1>{
}
class Class2 extends GenericClass<Tipe2>{
}
class Tipe1 {
}
class Tipe2 {
}
class GenericClass<T> implements Tipe<T> {
private String value;
private String value2;
private T t;
public T getTipe() {
return t;
}
void setValue(String s) {
value = s;
}
void setValue2(String s) {
value2 = s;
}
}
interface Tipe<T> {
public T getTipe();
}
or you can cast to parent class like:
GenericClass gc = new Class2();

How to instantiate an interface object?

I have an abstract class and several implementations.
Based on the implementation class, I'd like to execute a method and instantiate the implementation class itself with new constructor.
Of course the following won't work as the class is Abstract, and I cannot change this fact. But how could I pass the "logic" how to create each implementation object to the method prepareList()? Especially regarding design decisions.
abstract class AbstractClass {
int id;
String name;
int age;
//lots of fields
}
class FirstClass extends AbstractClass {
}
class SecondClass extends AbstractClass {
}
class MyService {
void execute(Data data) {
List<FirstClass> list = prepareList(data, FirstClass.class);
//process list
}
List<AbstractClass> prepareList(Data data, Class<? extends AbstractClass> clazz) {
List<AbstractClass> collection = new ArrayList<>();
for (Some value in data.getList()) {
AbstractClass obj = new AbstractClass(); //does of course not work with abstract class
obj.setId();
obj.setName();
obj.setAge();
collection.add(obj);
}
return collection;
}
}
abstract class Fruit { String name; int weight; }
class Apple extends Fruit {}
class Orange extends Fruit {}
class FruitFactory() {
public Fruit create(Data data) {
if ("apple" == data.getFruitName()) return new Apple();
else if ("orange" == data.getFruitName()) return new Orange();
else throw new UnsupportedOperationException();
}
}
class FruitService {
private FruitFactory factory = new FruitFactory();
void execute(Data data) {
List<Fruit> list = prepareList(data);
}
List<Fruit> prepareList(Data data) {
List<Fruit> fruits = new ArrayList<>();
for (Some value : data) {
Fruit fruit = factory.create(data);
// set fields
fruits.add(fruit);
}
return fruits;
}
}
Okay I have a suggestion why don't you do like
public class AbstractClass {
int id;
String name;
int age;
//lots of fields
}
class FirstClass extends AbstractClass{
}
class SecondClass extends AbstractClass{
}
class Data{
}
class Myservice{
void execute(Data data) {
List<FirstClass> list = prepareList(data, new FirstClass());//notice change
//process list
}
List<AbstractClass> prepareList(Data data, AbstractClass abstractClassObj) {
List<AbstractClass> collection = new ArrayList<>();
for (Some value in data.getList()) {
/* AbstractClass obj = new AbstractClass();*/ //does of course not work with abstract class
abstractClassObj.setId();
abstractClassObj.setName();
abstractClassObj.setAge();
collection.add(obj);
}
return collection;
}
}
BY this your object creation and logic will also remain at different places. It will also be helpful if in future you have another class extending abstract class
or you can have some factory and pass factory object to your method or service class and get instance in the method you want.
Sorry In a hurry I missed the loop thing with factory try some thing like
public class AbstractClass {
int id;
String name;
int age;
//lots of fields
}
class FirstClass extends AbstractClass{
}
class SecondClass extends AbstractClass{
}
class Factory{
public AbstractClass getInstance( Class<? extends AbstractClass> clazz){
if(clazz.getSimpleName().equals(FirstClass.class.getSimpleName())){
return new FirstClass();
}else {
return new SecondClass();
}
}
}
class Data{
}
class Myservice{
private final Factory factory;
public Myservice(Factory factory){
this.factory = factory;
}
void execute(Data data) {
List<FirstClass> list = prepareList(data, FirstClass.class);//notice change
//process list
}
List<AbstractClass> prepareList(Data data, Class<? extends AbstractClass> clazz) {
List<AbstractClass> collection = new ArrayList<>();
for (Some value in data.getList()) {
AbstractClass obj = factory.getInstance(clazz);
abstractClassObj.setId();
abstractClassObj.setName();
abstractClassObj.setAge();
collection.add(obj);
}
return collection;
}
}
Obviously you can modify example as per needs you can use enum sort of things. This is just basic example

Java Interface containing an empty Enum

I'm trying to prepare an interface i want to implement for Datamodel-Classes.Therefor i want to use an enum inside the interface so i know i need to implement it later.
Example:
public interface MyModelInterface {
public enum Field;
public Object get(Field field);
public void set(Field field, Object value);
}
The expected implementation:
public class MyModel implements MyModelInterface {
public enum Field {
ID("id"),
Name1("Name1"),
Name2("Name2");
private String field;
private Field(String field) {
this.field = field;
}
}
public Object get(Field field) {
//...
}
public void set(Field field, Object value){
//...
}
public static void main(String[] args) {
MyModel myModel = new MyModel();
System.out.println(myModel.get(MyModel.Field.ID));
System.out.println(myModel.get(MyModel.Field.Name1));
}
}
Since I don't know which fields the model will contain until I implement it.
I did some research and figured that enum can't be extended, so i am aware of that.
is there any way to archive this or any kind of workaround?
i don't want to use String Parameters on the getter/setter Methods to avoid using wrong values.
Thanks in advance for any suggestion.
Update:
So this is what worked for me: Splitting the interface/class in three parts, including an abstract class:
Interface:
public interface MyModelInterface<E extends Enum<E>> {
public Object get(E field);
public void set(E field, Object value);
}
Abstract Class:
public abstract class MyAbstractModel<E extends Enum<E>> implements MyModelInterface<E>{
protected final EnumMap<E, Object> fields;
public MyAbstractModel(Class<E> enumKlazz) {
fields = new EnumMap<>(enumKlazz);
}
#Override
public Object get(E field) {
return fields.get(field);
}
#Override
public void set(E field, Object value) {
this.fields.put(field, value);
}
}
Class(where i actually archive my goal):
public class MyModel extends MyAbstractModel<MyModel.Field> {
public MyModel() {
super(MyModel.Field.class);
}
public enum Field {
ID("ID"),
Name1("NAME1"),
Name2("NAME2"),
Age("AGE"),
;
private final String field;
private Field(String field) {
this.field = field;
}
public String getName() {
return field;
}
}
public static void main(String[] args) {
MyModel myModel = new MyModel();
System.out.println(myModel.get(Field.Name1));
}
}
Interface fields are static and final implicitly.
What you could do is to have an interface method returning Enum<?>, and your classes implementing it.
For instance:
interface Foo {
public Enum<?> getEnum();
}
class Bar implements Foo {
enum Blah {
INSTANCE;
}
public Enum<?> getEnum() {
return Blah.INSTANCE;
}
}
Edit
Not completely sure I understand your question update, but here's a solution that will de-couple returning a specific enum instance from an enum, by means of two interfaces.
The example is self-contained in a Main class.
public class Main {
public static void main(String[] args) {
System.out.println(new Bar().getEnumField().name());
}
static interface IHasEnum {
public Enum<? extends IMyEnum> getEnumField();
}
static interface IMyEnum {
public Enum<? extends IMyEnum> getField();
}
static class Bar implements IHasEnum {
enum Blah implements IMyEnum {
DEFAULT_INSTANCE,
THE_FIELD;
public Enum<? extends IMyEnum> getField() {
return THE_FIELD;
}
}
public Enum<? extends IMyEnum> getEnumField() {
return Blah.DEFAULT_INSTANCE.getField();
}
}
}
Output
THE_FIELD
Note
The trick here is to add a "default" instance to the enum (DEFAULT_INSTANCE), so the getField method is an instance method, hence overriding the one declared in the IMyEnum interface.
Again, not entirely sure this addresses your issue.
What you are describing is an EnumMap<E, T> - which functions like an array, with that same get-
public class MyModelBase<E extends Enum<E>> {
private final Class<E> enumKlazz;
private final EnumMap<E, Object> fields;
public MyModelBase(Class<E> enumKlazz) {
this.enumKlazz = enumKlazz;
fields = new EnumMpa<>(enumKlazz);
}
public Object get(E field) {
return fields.get(field);
}
public void set(E field, Object value) {
fields.put(field, value);
}
}
enum UserField { id, surname, name, age };
MyModelBase<UserField> userModel = new MyModelBase<>(UserField.class);
userModel.set(UserField.surname, "X");
Because of type erasure the enum map needs the class. Above the enum class is also stored as field, as some static Enum methods need the enum class. For iterating, and so on.
Java generics will be the best solution.
Lets assume, you don't know the contents of the Field as mentioned.
Create a generic interface like this:
public interface MyModelInterface<T> {
public T get();
}
Then create a class Field like this:
public class Field {
private String id;
private String name1;
private String name2;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName1() {
return name1;
}
public void setName1(String name1) {
this.name1 = name1;
}
public String getName2() {
return name2;
}
public void setName2(String name2) {
this.name2 = name2;
}
}
and then your model class will look like
public class MyModel implements MyModelInterface<Field> {
#Override
public Field get() {
Field field = new Field();
field.setId("ID");
field.setName1("Name1");
field.setName2("Name2");
return field;
}
public static void main(String[] args) {
MyModel myModel = new MyModel();
System.out.println(myModel.get().getId());
System.out.println(myModel.get().getName1());
System.out.println(myModel.get().getName2());
}
}

Target Unreachable, 'current' returned null - AbstractFactory

I'm trying to access an object inside a managed bean, which implements AbstractMB. Any property accessed by a page has error "Unknown property". When I try to insert it in the database,through a commandButton, PropertyNotFoundException is thrown.
AbstractMB relevant code:
public abstract class AbstractMB<T> implements Serializable {
private Class<T> type;
private AbstractDAO<T> typeDAO;
private T current;
private List<T> elements = new ArrayList();
protected T object = this.getCurrent();
protected List<T> list = this.getElements();
public abstract void save(ActionEvent actionEvent);
public AbstractMB() {}
public AbstractMB(Class<T> type) {
super();
this.type = type;
}
public T getCurrent() {
return current;
}
public void setCurrent(T current) {
this.current = current;
}
}
Full FonteMB class:
#Named
#RequestScoped
public class FonteMB extends AbstractMB<Fonte> {
public FonteMB() {
super(Fonte.class);
}
#Override
public void save(ActionEvent actionEvent) {
if(this.object.getCodigo() == null) {
this.getTypeDAO().add(this.object);
} else {
this.getTypeDAO().edit(this.object);
}
this.object = new Fonte();
this.list = null;
}
}
Class Fonte from the model package implements java.io.Serializable, all getter and setter, hashCode and equals methods. And toString returning the class name ("Fonte").
Also tried to use a converter, but result was the same.
What I'm missing?

Creating abstract generic jaxb class

I have the following simple jaxB class that takes generic type E
#XmlAccessorType(XmlAccessType.FIELD)
#XmlTransient
#XmlRootElement(name = "searchResponseBase")
public abstract class SearchResponseBase<E>{
#XmlElement(type=NameSearchResults.class)
protected E searchResults;
public E getSearchResults()
{
return searchResults;
}
public void setSearchResults(E mSearchResults)
{
this.searchResults = mSearchResults;
}
}
I need to remove the reference to NameSearchResults #XmlElement(type=NameSearchResults.class) to make the base actually generic, but if I do I get the error.
error
[com.sun.istack.internal.SAXException2: class au.test.nameSearch.NameSearchResults nor any of its super class is known to this context.
javax.xml.bind.JAXBException: class au.test.nameSearch.NameSearchResults nor any of its super class is known to this context.]
This is an example of a class that extends it
extended class
#SuppressWarnings("javadoc")
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(propOrder = {
"searchRequest",
"searchResults"
})
#XmlRootElement(name = "searchResponse")
public class SearchResponse extends SearchResponseBase<NameSearchResults> {
#XmlElement(required = true)
protected SearchRequest searchRequest;
public SearchRequest getSearchRequest() {
return searchRequest;
}
public void setSearchRequest(SearchRequest value) {
this.searchRequest = value;
}
}
How do i make the base class actually generic?
preferably i would like my extended class to work in the format SearchResponse<E> extends SearchResponseBase<E> and use it as a generic type too.
if i do as paul suggested i can get teh class to:
#XmlRootElement(name = "searchResponse")
public class SearchResponse<E extends NameSearchResults> extends SearchResponseBase<E> {
#XmlElement(required = true)
protected SearchRequest searchRequest;
protected E searchResults;
public SearchRequest getSearchRequest() {
return searchRequest;
}
public void setSearchRequest(SearchRequest value) {
this.searchRequest = value;
}
#Override
public E getSearchResults() {
return searchResults;
}
#Override
public void setSearchResults(E mSearchResults) {
this.searchResults = mSearchResults;
}
}
is there a way i can push the NameSearchResults out of this <E extends NameSearchResults>?
Thanks to #PaulBellora for the help, the base and extend class will both become abstract then haveing a Name implimentation, like this:
Base
#XmlRootElement(name = "searchResponseBase")
public abstract class SearchResponseBase<E>{
public abstract E getSearchResults();
public abstract void setSearchResults(E mSearchResults);
}
Extended Base
#XmlRootElement(name = "searchResponse")
public abstract class SearchResponse<E> extends SearchResponseBase<E>{
public abstract SearchRequest getSearchRequest();
public abstract void setSearchRequest(SearchRequest value);
}
Name Implimentation
#XmlRootElement(name = "nameSearchResponse")
public class NameSearchResponse extends SearchResponse<NameSearchResults>{
#XmlElement(required = true)
protected SearchRequest searchRequest;
protected NameSearchResults searchResults;
#Override
public NameSearchResults getSearchResults() {
return searchResults;
}
#Override
public void setSearchResults(NameSearchResults mSearchResults) {
this.searchResults = mSearchResults;
}
#Override
public SearchRequest getSearchRequest() {
return searchRequest;
}
#Override
public void setSearchRequest(SearchRequest value) {
this.searchRequest = value;
}
}
I'm unfamiliar with JAXB, but you could try making getSearchResults and setSearchResults abstract methods, and implement them only when E was resolved. For example:
//annotations ommitted
public abstract class SearchResponseBase<E>{
public abstract E getSearchResults();
public abstract void setSearchResults(E mSearchResults);
}
//annotations ommitted
public class SearchResponse extends SearchResponseBase<NameSearchResults> {
#XmlElement(type=NameSearchResults.class)
protected NameSearchResults searchResults;
#Override
public final NameSearchResults getSearchResults() {
return searchResults;
}
#Override
public final void setSearchResults(NameSearchResults mSearchResults) {
this.searchResults = mSearchResults;
}
...
}

Categories