SOAP Web Services with JAX-WS
Domain 7 tests contract-first versus code-first SOAP services: how a class becomes a port, which WSDL style the runtime generates, and where handlers and MTOM fit.
Contract and annotations
- @WebService sits on a class (code-first) or on an SEI used with endpointInterface. @WebMethod exposes an operation, @WebMethod(exclude=true) hides one, and @WebParam and @WebResult name message parts.
- If a class-level @WebService has no @WebMethod anywhere, every public method is exposed, which is how getters leak into a WSDL.
- @SOAPBinding defaults to DOCUMENT with LITERAL use, the only WS-I Basic Profile compliant choice; RPC/encoded is not interoperable.
- @Oneway methods must return void and cannot declare checked exceptions. Static, final and non-public methods are never exposed.
Deployment and clients
- A @WebService class in a WAR, or an EJB @Stateless bean annotated @WebService, is published by the container. wsgen generates portable artifacts from a class and wsimport generates them from a WSDL.
- @WebServiceRef injects a port and @WebServiceClient marks generated stub classes.
- Handlers implement SOAPHandler or LogicalHandler and are attached with @HandlerChain.
- @MTOM with @XmlMimeType("application/octet-stream") enables binary attachments outside the SOAP envelope.
Worked example
A service class annotated @WebService at class level unexpectedly publishes getBalance and getCustomerName as operations. Because no method carries @WebMethod, all public methods become operations, so the getters must be marked @WebMethod(exclude=true) or made private before deployment.
Traps
- Expecting a stateful session bean to serve as a JAX-WS endpoint.
- Believing @WebMethod must appear on every operation.
- Forgetting that a code-first WSDL changes whenever signatures change, breaking existing clients.