5
votes

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?

2

2 Answers

4
votes

You may need to change the style to be DOCUMENT instead of RPC in your declaration at @SOAPBinding(style = Style.RPC)

Although this is an old question, I thought I'd answer it as it's common exception people encounter.

The difference between the two styles in high level is as follows

  • Document: The return type and method arguments are clearly explained in a separate XSD with each type in detail - helpful in case of custom data types (Example in your case ITransferResult or java.util.List).

  • RPC: the types are defined in the WSDL itself in simple manner.

1
votes

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…