tl; dr версия: есть ли способ принудительно установить строгий режим для JAX-WS, который отклоняет недопустимый base64 для типа данных base64Binary
XSD?
Более длинная версия: у меня есть вебслужба, которая получает двоичные данные, которые сопоставляются с типом XSD base64Binary
.При тестировании сервиса я обнаружил, что JAX-WS очень снисходительно относится к разбору строк Base64.Независимо от того, насколько неверным был мой ввод, я не мог заставить JAX-WS выдавать ошибку.
Я создал небольшой тестовый сервис и клиент, который иллюстрирует проблему.Его можно скопировать более или менее дословно:
Интерфейс службы:
@WebService
public interface ITest2 {
@WebMethod
void foo(byte[] bs);
}
Реализация и тестирование службы:
@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 + "<");
}
}
В результате вы получите следующий вывод в / tmp / output (я использую Jetty, которая довольно часто записывает на консоль и не хотела беспокоиться об этом):
[client] >////==<
[server] ><null><
[client] >///==<
[server] ><null><
[client] >/w==<
[server] >/w==<
[client] >/==<
[server] ><null><
[client] >/==/==/==<
[server] >/////w==<
[client] ><><
[server] ><empty><
[client] >=====<
[server] >/w==<
[client] >%%%///%%%==%%<
[server] >//8=<
Так что это полный беспорядок.Иногда я получаю null
, иногда пустую строку, а иногда мусор заменяется другим мусором.Также каждый запрос генерирует HTTP-ответ 200, так что никто не знает, что где-то что-то пошло не так.
Я знаю, что вы можете заставить JAXB проверить это, добавив схему в Unmarshaller
.Поскольку JAX-WS использует JAXB для внутреннего использования, я надеюсь, что есть возможность включить это и для веб-сервисов.Кто-нибудь знает, возможно ли это и как?
Я использую стандартную реализацию JAX-WS из Oracle Java 1.6.0_24 в Ubuntu.