2014-10-01 1 views
0

У меня есть куча классов, которые все выглядят одинаково и состоят только из Id и нескольких атрибутов String. Таким образом, я попытался обобщить создание WebServices с помощью Generics:Apache CXF с параметризованными типами

@WebService 
public interface IBasicCRUDService<E extends AbstractEntity, D extends AbstractEntityDTO, ID, DAO extends IGenericDAO<E, ID>>{ 

    public List<D> findAll(BasicFilters filters); 
    public D findById(ID id); 

    @WebMethod(exclude = true) 
    public void setBaseDao(DAO dao); 
} 

Реализация:

public abstract class BasicCRUDService<E extends AbstractEntity, D extends AbstractEntityDTO, ID, DAO extends IGenericDAO<E, ID>> extends AbstractService implements IBasicCRUDService<E, D, ID, DAO> { 

    private IGenericDAO<E, ID> dao; 
    private Class<E> persistentClass; 
    private Class<D> dataTransferClass; 


    public final DAO getDao() { 
     return (DAO) dao; 
    } 


    public void setDao(DAO dao) { 
     this.dao = (IGenericDAO<E, ID>) dao; 
    } 


    @SuppressWarnings("unchecked") 
    public Class<E> getPersistentClass() { 
     if (persistentClass == null) { 
      this.persistentClass = (Class<E>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 
     } 
     return persistentClass; 
    } 

    @SuppressWarnings("unchecked") 
    public Class<D> getDataTransferClass() { 
     if(dataTransferClass == null) { 
      this.dataTransferClass = (Class<D>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1]; 
     } 
     return dataTransferClass; 
    } 


    @Override 
    @Transactional(readOnly=true) 
    @WebMethod(operationName="findAll") 
    public List<D> findAll(BasicFilters filters) { 
     List<E> pList = dao.findAll(filters); 
     List<D> dList = new ArrayList<D>(); 
     for(E e:pList) { 
      dList.add(this.map(e, getDataTransferClass())); 
     } 
     return dList; 
    } 

    @Override 
    @Transactional(readOnly=true) 
    @WebMethod(operationName="findAll") 
    public D findById(ID id) { 
     return this.map(dao.findById(id), getDataTransferClass()); 
    } 

} 

И это было бы конкретную реализацию: @Service ("metodologiaService") общественного класса MetodologiaService распространяется BasicCRUDService реализует IMetodologiaService {

@Override 
    @Autowired 
    @Qualifier("metodologiaDAO") 
    public void setBaseDao(IMetodologiaDAO dao) { 
     super.setDao(dao); 
    } 

} 

@WebService 
public interface IMetodologiaService extends IBasicCRUDService<Metodologia, MetodologiaDTO, Integer, IMetodologiaDAO>{ 
    public List<MetodologiaDTO> findAll(BasicFilters filters); 
    public MetodologiaDTO findById(Integer id); 
} 

Проблема заключается в том, его кажется, что CXF не может правильно отображать атрибуты WebServices. Например, при вызове метода findById, я получаю это:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soap:Body> 
     <soap:Fault> 
     <faultcode>soap:Server</faultcode> 
     <faultstring>com.sun.org.apache.xerces.internal.dom.ElementNSImpl cannot be cast to java.lang.Integer</faultstring> 
     </soap:Fault> 
    </soap:Body> 
</soap:Envelope> 

Однако, если я объявляю методы непосредственно в моем IMetodologiaService, это работает:

@WebService 
public interface IMetodologiaService extends IBasicCRUDService<Metodologia, MetodologiaDTO, Integer, IMetodologiaDAO>{ 
    public List<MetodologiaDTO> findAll(BasicFilters filters); 
    public MetodologiaDTO findById(Integer id); 
} 

Так что, похоже, как-то, простирающиеся интерфейсы не работающих при использовании параметризованных типов. Есть ли способ обойти это?

ответ

0

Вы, вероятно, нужно использовать что-то вроде TypeTools разрешить аргументы типа в этом случае:

public BasicCRUDService() { 
    Class<?>[] typeArgs = TypeResolver.resolveRawArguments(IBasicCRUDService.class, getClass()); 
    persistentClass = typeArgs[0]; 
    dataTransferClass = typeArgs[1]; 
    dao = typeArgs[3]; 
} 
Смежные вопросы