pizycki pizycki -4 years ago 209
Java Question

JAXB cannot handle an interface - what am I missing?

I'm getting familiar with web services in Java using Jax-ws (or JAXB, not sure, anyway...).

I've created small project with a single webservice. The WS has the only endpoint called transfer and returns objects inheriting ITransferResult interface.

Web service contract

//Service Endpoint Interface
@WebService
@SOAPBinding(style = Style.RPC)
public interface IBankWebSrv {
@WebMethod
ITransferResult transfer(String accountNumber, double amount);
}


Web service implementation

//Service Implementation
@WebService(endpointInterface = "Contracts.IBankWebSrv")
public class BankWebSrv implements IBankWebSrv {
@Override
public ITransferResult transfer(String accountNumber, double amount) {
ITransferResult result = new TransferResult();
// TODO logic here
result.setSuccessful(true);
return result;
}
}


TransferResult contract

@XmlJavaTypeAdapter(TransferResult.class)
public interface ITransferResult {
boolean isSuccessful();
void setSuccessful(boolean successful);
}


TransferResult implementation

public class TransferResult extends XmlAdapter<TransferResult, ITransferResult>
implements ITransferResult {

@XmlElement
boolean successful;

public boolean isSuccessful() {
return this.successful;
}

public void setSuccessful(boolean successful) {
this.successful = successful;
}

@Override
public TransferResult marshal(ITransferResult v) throws Exception {
return (TransferResult) v;
}

@Override
public ITransferResult unmarshal(TransferResult v) throws Exception {
return (ITransferResult) v;
}
}


When I publish my web service, I get the following error:


Exception in thread "main" javax.xml.ws.WebServiceException: Unable to
create JAXBContext...

Caused by: java.security.PrivilegedActionException:
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1
counts of IllegalAnnotationExceptions ITransferResult is an interface,
and JAXB can't handle interfaces.
this problem is related to the
following location: at ITransferResult


I've looked over SO for the answer and applied to the most repetitive tips, but none of them have worked for me yet.

What am I missing?

Answer Source

It looks like it's not processing the annotations on the TransferResult class as a bindable element. That means you probably need to add @XmlSeeAlso(TransferResult.class) to the interface (ITransferResult). You also need to put @XmlRootElement on the serialization-implementation (TransferResult) so that an actual XML document can be produced, and not just a type that you use in some other document. This is because when the JAX-WS implementation is creating the JAXB context that it uses internally, it only uses the argument and result types that you define on the service interface as arguments to JAXB.newInstance(…); anything not literally listed there (or findable via simple following the types) will be omitted, and it's entirely possible that the type adapters used are not processed for annotations (after all, they don't need to be instances of the interface they're adapting, nor does the type being adapted need to be an interface).

(Yes, a SOAP response is an enclosing document, but the recommended way of using it is to put a single element inside the SOAP Body, and that means you need to know the name of the element. Which means an @XmlRootElement annotation.)


Warning: I'm not 100% sure that this will work. If it doesn't, you'll have to switch to using concrete types (probably straight POJOs) as results. It might not be a particularly palatable thing, but it's at least easy to do…

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download