Ручная отправка SOAP запросов в Java
Не так давно была опубликована заметка, по созданию SOAP Java SE клиента. В этой заметке будет описан пример создания SOAP запроса “ручками”, без использования сторонних библиотек.
Для создания тела xml запроса, используем класс StringBuilder. Использование StringBuilder/StringBuffer вместо работы с классом String при частом добавлении строк позволяет избежать создания множества экземпляров класса String в памяти.
String body = sb.toString(); byte[] buffer = new byte[body.length()]; try { buffer = sb.toString().getBytes("UTF-8"); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); }
В этом участке кода создается один объект типа String, содержащий в себе тело запроса, далее мы его конвертируем в массив байтов с кодировкой UTF-8. В большинстве случаев параметр кодировки не требуется, т.е. можно просто вызвать
sb.toString().getBytes()
Далее просто создается соединение и открывается. Здесь надо обратить внимание, что url должен содержать путь, без расширения *.wsdl, в отличии от работы с той же библиотекой KSOAP
URL u = new URL("http://url_to_web_service_without_wsdl_exstension"); URLConnection uc = u.openConnection(); HttpURLConnection connection = (HttpURLConnection) uc;
Теперь самое важное – работа с заголовком запроса. Первые 2 строки отвечают за basic authentication(базовую аутентификацию). Для этого пару user:password Надо закодировать в Base64. Далее мы устанавливаем длину тела запроса, тип запроса: application/soap+xml;charset=UTF-8 и название вызываемого веб метода. В нашем случае это Registration. в wsdl его можно посмотреть по имени soapAction=”…”
String authorization =org.kobjects.base64.Base64.encode("user:password".getBytes()); connection.setRequestProperty("Authorization", "Basic "+authorization); connection.setDoOutput(true); connection.setDoInput(true); connection.setRequestProperty("Content-Length", String.valueOf(buffer.length)); connection.setRequestMethod("GET"); connection.setRequestProperty("Content-type", "application/soap+xml;charset=UTF-8"); String soapAction = "http://NAMESPACE#NAME_SERVICE:Registration"; connection.setRequestProperty("SOAPAction", soapAction);
По окончании формирования заголовков, мы открываем выходной поток, куда записываем наше тело запроса:
try(OutputStream out = connection.getOutputStream()){ out.write(buffer); }
По окончании записи проверяем ответ от сервера, он должен быть равен HttpURLConnection.HTTP_OK. Далее все очень просто – берем входной поток от веб сервиса, читаем ответ и парсим, используя возможности пакета javax.xml.parsers.
Полный листинг запроса:
StringBuilder sb = new StringBuilder(); sb.append("<soap:Envelope "); sb.append("xmlns:soap="); sb.append("\"http://www.w3.org/2003/05/soap-envelope\""); sb.append(" xmlns:ser="); sb.append("\"http://NAMESPACE\">\n"); sb.append("<soap:Header/>\n"); sb.append("<soap:Body>\n"); sb.append("<ser:Registration>\r\n"); sb.append("<ser:Organisation>Organization</ser:Organisation>\r\n"); sb.append("<ser:FullName>FIO</ser:FullName>\r\n"); sb.append("<ser:PhoneNumber>111-11-11</ser:PhoneNumber>\r\n"); sb.append("<ser:JobTitle>Scientist</ser:JobTitle>\r\n"); sb.append("<ser:Email>developer@it-notepad.com</ser:Email>\r\n"); sb.append("<ser:InternalPhoneNumber>111</ser:InternalPhoneNumber>\r\n"); sb.append("<ser:MobileNumber>8-111-111-11-11</ser:MobileNumber>\r\n"); sb.append("<ser:UserID>LLL</ser:UserID>\r\n"); sb.append("<ser:ErrorText>Text</ser:ErrorText>\r\n"); sb.append("</ser:Registration>\r\n"); sb.append("</soap:Body>\r\n"); sb.append("</soap:Envelope>"); String body = sb.toString(); byte[] buffer = new byte[body.length()]; try { buffer = sb.toString().getBytes("UTF-8"); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } try{ URL u = new URL("http://url_to_web_service_without_wsdl_exstension"); URLConnection uc = u.openConnection(); HttpURLConnection connection = (HttpURLConnection) uc; String authorization =org.kobjects.base64.Base64.encode("user:password".getBytes()); connection.setRequestProperty("Authorization", "Basic "+authorization); connection.setDoOutput(true); connection.setDoInput(true); connection.setRequestProperty("Content-Length", String.valueOf(buffer.length)); connection.setRequestMethod("GET"); connection.setRequestProperty("Content-type", "application/soap+xml;charset=UTF-8"); String soapAction = "http://NAMESPACE#NAME_SERVICE:Registration"; connection.setRequestProperty("SOAPAction", soapAction); try(OutputStream out = connection.getOutputStream()){ out.write(buffer); } if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { try(InputStreamReader is = new InputStreamReader(connection.getInputStream(),"UTF-8")){ try(BufferedReader rd = new BufferedReader(is)){ StringBuilder strBuildReturn = new StringBuilder(); String line; while ((line = rd.readLine()) != null){ System.out.println(line); strBuildReturn.append(line); } connection.disconnect(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = null; try{ builder = factory.newDocumentBuilder(); try(StringReader strRead = new StringReader(strBuilderReplace.toString())){ InputSource ins = new InputSource(strRead); Document doc = builder.parse(ins); doc.getDocumentElement().normalize(); NodeList nList = doc.getElementsByTagName("RegistrationResponse"); for (int temp = 0; temp < nList.getLength(); temp++) { Node nNode = nList.item(temp); System.out.println("Element :" + nNode.getNodeName()); if (nNode.getNodeType() == Node.ELEMENT_NODE) { Element eElement = (Element) nNode; String userId = eElement.getElementsByTagName("UserID").item(0).getTextContent(); boolean status = Boolean.valueOf(eElement.getElementsByTagName("return").item(0).getTextContent()); ResponseAuth1C responseObj = new ResponseAuth1C(userId, status); } } } } catch (ParserConfigurationException|SAXException e) { e.printStackTrace(); } } } } else { try(InputStreamReader eis = new InputStreamReader(connection.getErrorStream())){ errorHandler(eis); } }catch (IOException e) { System.err.println(e); } return null;