tl; dr version: Is there a way to force strict mode for JAX-WS, which rejects an invalid base64 for the base64Binary XSD data type?
Longer version: I have a web service that receives binary data that maps to the base64Binary XSD base64Binary . When testing the service, I found out that JAX-WS is very soft when it comes to parsing Base64 strings. No matter how invalid my input was, I was unable to get JAX-WS to create an error.
I created a small test service and a client that illustrates the problem. It can be copied more or less verbatim:
Service Interface:
@WebService public interface ITest2 { @WebMethod void foo(byte[] bs); }
Service implementation and testing:
@WebService(endpointInterface="foo.bar.ITest2") public class Test2 implements ITest2 { private static final String requestTemplate = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:bar=\"http://bar.foo/\">" + "<soapenv:Header/>" + "<soapenv:Body>" + "<bar:foo>" + "<arg0>%s</arg0>" + "</bar:foo>" + "</soapenv:Body>" + "</soapenv:Envelope>"; private static final String[] testVector = { "////==", "///==", "//==", "/==", "/==/==/==", "<>", "=====", "%%%///%%%==%%" }; private static PrintWriter pw; static { try { pw = new PrintWriter("/tmp/output"); } catch (FileNotFoundException e) { throw new RuntimeException(e); } } public static void main(String[] args) throws Exception { Endpoint e = Endpoint.publish("http://localhost:54321/foo", new Test2()); URL requestUrl = new URL("http://localhost:54321/foo"); for(String testVal : testVector) { pw.println("[client] >" + testVal + "<"); HttpURLConnection urlc = (HttpURLConnection) requestUrl.openConnection(); urlc.setRequestProperty("Content-Type", "text/xml;charset=UTF-8"); urlc.setDoOutput(true); OutputStream out = urlc.getOutputStream(); String request = String.format(requestTemplate, testVal); out.write(request.getBytes()); out.flush(); InputStream in = urlc.getInputStream(); int read = -1; byte[] buf = new byte[1024]; while((read = in.read(buf)) != -1) { System.err.print(new String(buf, 0, read)); } System.err.println(); } pw.flush(); pw.close(); } @Override public void foo(byte[] bs) { String encoded; if(bs == null) { encoded = "<null>"; } else if(bs.length == 0) { encoded = "<empty>"; } else { encoded = new String(Base64.encodeBase64(bs)); } pw.println("[server] >" + encoded + "<"); } }
The result is the following output in / tmp / output (I use Jetty, which writes a lot to the console and doesn't want to worry about it):
[client] >
So this is a complete mess. Sometimes I get null , sometimes an empty string, and sometimes garbage is replaced with other garbage. Also, each request creates an HTTP 200 response, so no one knows that somewhere something went wrong.
I know that you can get JAXB to test this by adding a schema to Unmarshaller . Since JAX-WS uses JAXB internally, I hope that it is possible to enable this for web services as well. Does anyone know if this is possible and how?
I am using the default JAX-WS implementation from Oracle Java 1.6.0_24 on Ubuntu.