Hi Jeff - will try to investigate early next week, Cheers, Sergey On 16/02/12 02:37, Jeff Wang wrote:
Scenario: User "owns" contacts via an unidirectional @ManyToOne JPA mapping on Contact. Contact subclasses from a @MappedSuperclass called UserResource.What I would like to do: an Interface called ISubResourceService<T extends UserResource> that has a CXF annotation of: public interface ISubResourceService<T extends UserResource> { @GET @Produces("application/json") List<T> getAll(@PathParam("userId") Long userId) throws DataNotFoundException; } and an Interface called IContactService extends ISubResourceService<Contact> with contact specific annotations (such as a class level @Path("/contact")) but no other (relevant to this discussion) annotations or mappings. finally, in the ideal world, the implementation: public abstract class AbstractSubResourceService<T extends UserResource> implements ISubResourceService<T> { @Override public List<T> getAll(Long userId) throws DataNotFoundException { <code deleted for brevity> } } and of course: (ideally, no code other than the @Service for Spring to pick it up need to go here) @Service public class ContactServiceImpl extends AbstractSubResourceService<Contact> implements IContactService { } The problem with the above implementation is that I get the "No message body writer has been found for response class ArrayList" error, which essentially is the problem when returning generic collections, probably because of type erasure. The following also return message body writer issues: 2) have AbstractSubResourceService return a Response, using entity(new GenericEntity(List<T>){}), (we'll call this implementation 2, the base is implementation 1) 3) have ContactService implement a getAll with the return signature List<Contact> whose only code is "return super.getAll(userId);" (implementation 3) 4) have IContactService do an @Override getAll with a return value of List<Contact> (interface 2, same results vs all 3 implementations) 5) have IContactService copy getAll's declaration (with all CXF annotations) with a return value of List<Contact> (interface 3, same results vs all 3 implementations) 6) interface 3, remove the declaration of getAll in ISubResourceService (call this interface 4), implementation (1 or 2) AND 3 (see below for 2 without 3) The following generates a no matching method WebApplicationException: 7) interface 4, implementation 1 or 2 (without 3) The following works: 8) interface 4, implementation 3. Based upon the above results: 1) GenericEntity is pointless if you are returning a generic collection. (implementation 2 never worked, in any form) 2) having a sub interface "override" a super interface does not work on an annotation basis (interface 2 and 3 does not work) possibly due to retention when compiling? 3) I'm not quite sure why #7 returned no matching method. Is there an annotation retention issue that causes CXF not to "see" that the getAll in AbstractSubResourceService has applicable annotations in IContactService? (never mind that it's truly horrendous coding style.) So anyways, I've got code that works, but isn't particularly ideal. If anyone can shed light on how they've done similar work, or suggestions, I'd be happy to try them out. Sergey, could you shed some light on results 2 and 3? thanks Jeff
