Веб
сервисам и их клиентам может понадобиться доступ к обработке SOAP сообщения, для этого создаются SOAP
перехватчики (SOAP
message handler). SOAP
handler
вызываются автоматически, для входного (Outbound Message) сообщения,
которое приходит к нам и выходного (Inbound Message) сообщения, уходящего от
нас. JAX-WS handler делятся на два типа обработчиков: SOAP handler и logical
handler.
Различие в том что, SOAP handler имеет больше возможностей,
а именно имеет доступ к SOAP сообщению полностью, к заголовкам(Headers) и телу(Body), а logical handler только к телу(Body). Для того что бы написать обработчики вам нужно
реализовать интерфейсы для SOAP
handler - javax.xml.ws.handler.soap.SOAPHandler,
а для logical handler - javax.xml.ws.handler.LogicalHandler. У этих
интерфейсов есть три одинаковых метода, которые реализуются в
перехватчиках и ведут себя одинаково, рассмотрим их подробно. Первый метод
который вам нужно реализовать это public boolean handleMessage(“Context”
context), тип “Context” принимает значение или LogicalMessageContext
или SOAPMessageContext, в зависимости от реализации интерфейса. Здесь нужно
сказать про цепочку вызовов (handler-chain), у вас может быть множество
перехватчиков (handler), которые
выполняются друг за другом. Тип Boolean который возвращает метод handleMessage, говорит что нужно делать дальше, если true - после завершения метода,
переходим к вызову следующего перехватчика, а точнее метода handleMessage
следующего обработчика. Если вы передаете false, то прерывается всякая последующая обработка и выполнение
операции веб сервиса. Представте себе такую ситуацию, что вы проверяете права
доступа, и если нет у пользователя прав на вызов операции web сервиса то вы прерываете вызов, вернув
параметр false, все просто. Если происходит любая исключительная
ситуация, то опять же прерывается обработка цепочки вызовов и выполняется
второй метод public boolean
handleFault(Context context), в
зависимсти от того что вы вернете в методе обработчика зависит поведение всего
вызова операции. Если вы вернете true
после
обработки ошибки, то будет продолжена цепочка вызовов и выполнение перейдет следующему обработчику в цепочке. Если передатите false, то
клиенту который вызвал операцию web
сервиса
вернется ошибка и прекратится вся последующая обработка вызовов. Следующий
метод это public void close(), этим методом завершается работа обработчика,
если вы открывали какие-нибудь ресурсы то в этом месте нужно их закрыть и
освободить. Обработчики могут регистрироваться как на клиенте, так и
на web сервисе. Есть
у обработчиков последовательность выполнения, сначала выполняются все Logical Handlers, затем Message
Handlers на клиенте, потом пройдя по
транспортному протоколу, в нашем случае HTTP опять
выполняются Message
Handlers на web сервисе, потом Logical Handlers и только
после этого вызывается операция web
сервиса.
Ответ web сервиса проходит тот же путь, в той же
последовательности через все
обработчики, смотрите рисунок.

Давайте
напишем пример: два обработчика Logical Handler, по одному для клиента и для web сервиса. И два обработчика Message Handler, опять же один пусть будет на стороне клиента, один на стороне web сервиса.
Потом я вам покажу как подключить обработчики клиенту и web сервису, использовать будем пример из прошлой статьи.
Обрабочик SOAPHandlerClient.java:
package org.lopanov;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import
javax.xml.ws.handler.MessageContext;
import
javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import java.util.Set;
public class SOAPHandlerClient implements
SOAPHandler<SOAPMessageContext> {
@Override
public Set<QName> getHeaders() {
return null;
}
@Override
public boolean handleMessage(SOAPMessageContext context) {
Boolean b = (Boolean)
context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (b) {
System.out.printf("%s","Исходящее сообщение
SOAPHandlerClient");
} else {
System.out.printf("%s","Входящее сообщение
SOAPHandlerClient");
}
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
return false;
}
@Override
public void close(MessageContext context) { }
}
Обрабочик LogicalHandlerClient.java:
package org.lopanov;
import
javax.xml.ws.handler.LogicalHandler;
import
javax.xml.ws.handler.LogicalMessageContext;
import
javax.xml.ws.handler.MessageContext;
public class LogicalHandlerClient
implements LogicalHandler<LogicalMessageContext> {
@Override
public boolean handleMessage(LogicalMessageContext context) {
Boolean b = (Boolean)
context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (b) {
System.out.printf("%s",
"Исходящее сообщение LogicalHandlerClient");
} else {
System.out.printf("%s", "Входящее сообщение
LogicalHandlerClient");
}
return true;
}
@Override
public boolean handleFault(LogicalMessageContext context) {
return false;
}
@Override
public void close(MessageContext context) {
}
}
Обрабочик SOAPHandlerWebService.java:
package org.lopanov;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import
javax.xml.ws.handler.MessageContext;
import
javax.xml.ws.handler.soap.SOAPHandler;
import
javax.xml.ws.handler.soap.SOAPMessageContext;
import java.util.Set;
public class SOAPHandlerWebService
implements SOAPHandler<SOAPMessageContext> {
@Override
public Set<QName> getHeaders() {
return null;
}
@Override
public boolean handleMessage(SOAPMessageContext context) {
Boolean b = (Boolean)
context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (b) {
System.out.printf("%s", "Исходящее сообщение
SOAPHandlerWebService");
} else {
System.out.printf("%s", "Входящее сообщение
SOAPHandlerWebService");
}
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
return false;
}
@Override
public void close(MessageContext context) { }
}
Обрабочик LogicalHandlerWebService.java:
package org.lopanov;
import javax.xml.ws.handler.LogicalHandler;
import
javax.xml.ws.handler.LogicalMessageContext;
import
javax.xml.ws.handler.MessageContext;
public class LogicalHandlerWebService
implements LogicalHandler<LogicalMessageContext> {
@Override
public boolean handleMessage(LogicalMessageContext context) {
Boolean b = (Boolean)
context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (b) {
System.out.printf("%s", "Исходящее сообщение
LogicalHandlerWebService");
} else {
System.out.printf("%s", "Входящее сообщение
LogicalHandlerWebService");
}
return true;
}
@Override
public boolean handleFault(LogicalMessageContext context) {
return false;
}
@Override
public void close(MessageContext context) { }
}
Два обработчика
SOAPHandlerClient.java и LogicalHandlerClient.java зарегистрируем на клиенте. Для этого мы должны реализовать интерфейс HandlerResolver и в его методе public List<Handler> getHandlerChain(PortInfo
portInfo), добавить в цепочку обработчиков два наших класса. На клиенте после создания сервиса
добавить класс реализующий наш
интерфейс, перед вызовом любых операций web сервиса. Смотрим пример:
package org.lopanov;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.handler.Handler;
import
javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.PortInfo;
import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
public class Main1 {
private static final QName SERVICE_NAME = new
QName("http://lopanov.org/", "HelloWorldService");
private static final QName PORT_NAME = new
QName("http://lopanov.org/", "HelloWorldPort");
public static void main(String args[]) throws Exception {
Service service = Service.create(new
URL("http://169.254.201.140:7001/hello-ws/HelloWorldService?WSDL"),
SERVICE_NAME);
service.setHandlerResolver(//устанавливае цепочку вызовов
new HandlerResolver() {
@Override
public List<Handler>
getHandlerChain(PortInfo portInfo) {
List<Handler>
list = new ArrayList<Handler>();
Handler handler = new SOAPHandlerClient();
list.add(handler);
Handler handler1 = new LogicalHandlerClient();
list.add(handler1);
return list;
}
}
);
Hello hw = service.getPort(PORT_NAME, Hello.class);
System.out.println(hw.sayHello("World"));
System.exit(0);
}
}
Получили
вывод лога:
Исходящее сообщение LogicalHandlerClient
Исходящее сообщение SOAPHandlerClient
---[HTTP request -
http://169.254.201.140:7001/hello-ws/HelloWorldService]---
….
<?xml version='1.0'
encoding='UTF-8'?>
<S:Envelope
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header/>
<S:Body>
<ns0:sayHelloResponse
xmlns:ns0="http://lopanov.org/">
<return>Hello,
World!</return>
</ns0:sayHelloResponse>
</S:Body>
</S:Envelope>
Входящее сообщение SOAPHandlerClient
Входящее сообщение LogicalHandlerClient
Hello, World!
Подключим
обработчики на стороне web
сервиса, делается это посредством аннотации @HandlerChain(),
передав в атрибуте file
имя файла где описаны обработчики. Файл
представляет собой xml
документ с пространством имен xmlns="http://java.sun.com/xml/ns/javaee",
для начало опишем MyHandlers.xml:
<?xml version="1.0"
encoding="UTF-8" standalone="yes"?>
<handler-chains
xmlns="http://java.sun.com/xml/ns/javaee">
<handler-chain>
<handler>
<handler-name>SOAPHandlerWebService</handler-name>
<handler-class>org.lopanov.SOAPHandlerWebService</handler-class>
указываем подключаемы обработчик
</handler>
</handler-chain>
<handler-chain>
<handler>
<handler-name>LogicalHandlerWebService</handler-name>
<handler-class>org.lopanov.LogicalHandlerWebService</handler-class>
указываем подключаемы обработчик
</handler>
</handler-chain>
</handler-chains>
Добавим
аннотацию в наш web
сервис:
package org.lopanov;
import weblogic.jws.Policies;
import weblogic.jws.Policy;
import javax.jws.HandlerChain;
import javax.jws.WebService;
@WebService( endpointInterface =
"org.lopanov.Hello")
@Policies( { @Policy(uri =
"policy:Mtom.xml",attachToWsdl = true,direction =
Policy.Direction.both) } )
@HandlerChain(file
= "../../MyHandlers.xml")
public class HelloWorld implements Hello {
public String sayHello(String name){
String result = String.format("Hello, %s!", name);
System.out.println(result);
return result;
}
….
}
На выходе
у сервера Weblogic получим такой лог:
Исходящее
сообщение LogicalHandlerWebService
Исходящее
сообщение SOAPHandlerWebService
Hello, World!
Входящее
сообщение SOAPHandlerWebService
Входящее
сообщение LogicalHandlerWebService
Давайте я
вам раскажу как можно получить доступ к телу сообщения в LogicalHandler,
это
делается двумя способами посредством доступа к xml содержимому тела или посредством доступа к
объекту JAXB. И так в методе handleMessage()
передается нам LogicalMessageContext context, посредством его мы можем получить доступ к
свойсвам контекста с помощью метода get(). Вызов context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)
в примере нам возвращал переменую которая подсказывала исходящее
или входящее пришло к нам сообщение. Полный перечень свойств вы можете
посмотреть в документации перейдя по ссылке http://docs.oracle.com/javaee/6/api/javax/xml/ws/handler/MessageContext.html. Продолжим, посредством вызова метода context.getMessage()
мы можем получить доступ к LogicalMessage message. У объекта LogicalMessage есть метод getPayload(), если его вызвать без параметров, то он возвращает нам
объект класса javax.xml.transform.Source, который дает возможность работать с
телом сообщения как с xml документом, читать его и писать в него.
Расмотрим пример:
package org.lopanov;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.activation.DataHandler;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.ws.LogicalMessage;
import javax.xml.ws.ProtocolException;
import
javax.xml.ws.handler.LogicalHandler;
import javax.xml.ws.handler.LogicalMessageContext;
import
javax.xml.ws.handler.MessageContext;
import java.util.List;
import java.util.Map;
public class LogicalHandlerClient
implements LogicalHandler<LogicalMessageContext> {
@Override
public boolean handleMessage(LogicalMessageContext context) {
Boolean b = (Boolean)
context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (b) {
System.out.printf("%s", "Исходящее сообщение
LogicalHandlerClient\n");
System.out.println("Response code
" + context.get(MessageContext.HTTP_RESPONSE_CODE));
try {
LogicalMessage message =
context.getMessage();//получили сообщение
Source source =
message.getPayload();//получили источник
Transformer xFormer =
TransformerFactory.newInstance().newTransformer();
xFormer.setOutputProperty("omit-xml-declaration",
"yes");
DOMResult result = new
DOMResult();
xFormer.transform(source, result);//преобразовали источник к DOM
объекту, можно работать как с xml документом
Node node = result.getNode();
NodeList nodes =
node.getChildNodes();
for (int i = 0; i <
nodes.getLength(); i++) {
Node current =
nodes.item(i);
System.out.printf("\n-=%s=-\n",
current.getLocalName().toString());
if
("sayHello".equals(current.getLocalName())) {//нашли тег
current.getFirstChild().setTextContent("XXX1");
//установили значение тега
}
}
source = new DOMSource(node);
message.setPayload(source);//нужно вернуть изменненный нами объект обратно впоток передачи
} catch (Exception ex) {
throw new
ProtocolException(ex);
}
} else {
System.out.printf("%s", "Входящее сообщение
LogicalHandlerClient");
}
return true;
}
@Override
public boolean handleFault(LogicalMessageContext context) {
return false;
}
@Override
public void close(MessageContext context) { }
}
Был такой
лог, до вызова нашего перехвачика LogicalHandlerClient:
<?xml version='1.0'
encoding='UTF-8'?>
<S:Envelope
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header/>
<S:Body>
<ns0:sayHello
xmlns:ns0="http://lopanov.org/">
<arg0>World</arg0>
</ns0:sayHello>
</S:Body></S:Envelope>
Получили такой лог после вызова нашего перехвачика LogicalHandlerClient:
<?xml version='1.0'
encoding='UTF-8'?>
<S:Envelope
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header/>
<S:Body>
<ns0:sayHello
xmlns:ns0="http://lopanov.org/">
<arg0>XXX1</arg0>
</ns0:sayHello>
</S:Body></S:Envelope>
Можно
заменить любой тег или добавить новый, делать с телом xml документа что угодно. Перейдем к работе с JAXB объектом, для него нужно сделать еще одну
дополнительную вещь, создать ObjectFactory.java, делается это путем вызова команды:
C:\jboss-4.2.0.GA\vit\hello-ws\target>wsimport.exe
HelloWorldService.xml -s src
parsing WSDL...
Generating code...
Compiling code...
На выходе
мы получаем набор классов и фабрику
которая поможет нам создать наш JAXBContext.
HelloWorldService.xml – это wsdl документ который вы можете получить
перейдя на свой развернутый web
сервис, я его получил по адресу http://169.254.201.140:7001/hello-ws/HelloWorldService?WSDL.
wsimport.exe - это утилита входит в поставку jdk, генерирует классы по wsdl
документу, src каталог куда будут сгенерированы наши классы,
он должен существовать перед запуском утилиты, иначе будет ошибка генерации.
Привожу полный список классов которые были сгерерированы:
package-info.java
ObjectFactory.java
Person.java
SayHello.java
SayHelloResponse.java
SayHi.java
SayHiResponse.java
GetBinary.java
GetBinaryResponse.java
Hello.java
HelloWorldService.java
Их я
перекинул к себе в проект, кроме помеченных красным цветом, т. к. эти классы я
писал вручную. Продолжим, посредством вызова
метода context.getMessage()
мы можем получить доступ к LogicalMessage message. У объекта LogicalMessage есть метод getPayload(), если его вызвать с параметром ObjectFactory.class, то он возвращает нам объекты класса JAXBElement,
которые дают возможность работать с телом сообщения как с объектом JAXB, читать его свойства и писать в его свойства, работать будем с JAXB объектом SayHello. Расмотрим пример:
package org.lopanov;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.activation.DataHandler;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.ws.LogicalMessage;
import javax.xml.ws.ProtocolException;
import
javax.xml.ws.handler.LogicalHandler;
import
javax.xml.ws.handler.LogicalMessageContext;
import javax.xml.ws.handler.MessageContext;
import java.util.List;
import java.util.Map;
public class LogicalHandlerClient
implements LogicalHandler<LogicalMessageContext> {
@Override
public boolean handleMessage(LogicalMessageContext context) {
Boolean b = (Boolean)
context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (b) {
System.out.printf("%s", "Исходящее сообщение LogicalHandlerClient\n");
try {
LogicalMessage message =
context.getMessage();//получаем сообщение
JAXBContext jaxbContext =
JAXBContext.newInstance(org.lopanov.ObjectFactory.class);//создаем контекст с нашей фабрикой
Object payload =
message.getPayload(jaxbContext);
Object value = payload;
if (payload instanceof
JAXBElement) { //проверяем вернули нам
JAXBElement
value =
((JAXBElement<?>)payload).getValue();
}
if (value instanceof
SayHello) {//Наш JAXB объект?
SayHello req =
(SayHello)value;// получаем его
req.setArg0("Hello JAXB!");//производим измениния
message.setPayload(payload, jaxbContext);// Сохраняем наши измения и
отправляем запрос дальше в web сервис.
}
} catch(JAXBException e) {
e.printStackTrace();
}
} else {
System.out.printf("%s", "Входящее сообщение LogicalHandlerClient");
}
return true;
}
@Override
public boolean handleFault(LogicalMessageContext context) {
return false;
}
@Override
public void close(MessageContext context) {
}
}
Был такой
лог, до вызова нашего перехвачика LogicalHandlerClient:
<?xml version='1.0'
encoding='UTF-8'?>
<S:Envelope
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header/>
<S:Body>
<ns0:sayHello
xmlns:ns0="http://lopanov.org/">
<arg0>World</arg0>
</ns0:sayHello>
</S:Body></S:Envelope>
Получили такой лог после вызова нашего перехвачика LogicalHandlerClient:
<?xml version='1.0'
encoding='UTF-8'?>
<S:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header/>
<S:Body>
<ns0:sayHello
xmlns:ns0="http://lopanov.org/">
<arg0>Hello JAXB!</arg0>
</ns0:sayHello>
</S:Body></S:Envelope>
Приведу
наш JAXB объект и фабрику классов:
package org.lopanov;
import
javax.xml.bind.annotation.XmlAccessType;
import
javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "sayHello",
propOrder = {
"arg0"
})
public class SayHello {
protected String arg0;
public String getArg0() {
return arg0;
}
public void setArg0(String value) {
this.arg0 = value;
}
}
package org.lopanov;
import javax.xml.bind.JAXBElement;
import
javax.xml.bind.annotation.XmlElementDecl;
import
javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;
@XmlRegistry
public class ObjectFactory {
private final static QName _GetBinary_QNAME = new
QName("http://lopanov.org/", "getBinary");
private final static QName _SayHelloResponse_QNAME = new
QName("http://lopanov.org/", "sayHelloResponse");
private final static QName _SayHi_QNAME = new
QName("http://lopanov.org/", "sayHi");
private final static QName _GetBinaryResponse_QNAME = new
QName("http://lopanov.org/", "getBinaryResponse");
private final static QName _SayHello_QNAME = new
QName("http://lopanov.org/", "sayHello");
private final static QName _SayHiResponse_QNAME = new
QName("http://lopanov.org/", "sayHiResponse");
private final static QName _Person_QNAME = new
QName("http://lopanov.org/", "person");
private final static QName _GetBinaryArg0_QNAME = new
QName("", "arg0");
public ObjectFactory() {}
public SayHello createSayHello() {
return new SayHello();
}
public SayHiResponse createSayHiResponse() {
return new SayHiResponse();
}
public Person createPerson() {
return new Person();
}
public GetBinary createGetBinary() {
return new GetBinary();
}
public SayHelloResponse createSayHelloResponse() {
return new SayHelloResponse();
}
public SayHi createSayHi() {
return new SayHi();
}
public GetBinaryResponse createGetBinaryResponse() {
return new GetBinaryResponse();
}
@XmlElementDecl(namespace = "http://lopanov.org/", name =
"getBinary")
public JAXBElement<GetBinary> createGetBinary(GetBinary value) {
return new JAXBElement<GetBinary>(_GetBinary_QNAME,
GetBinary.class, null, value);
}
@XmlElementDecl(namespace = "http://lopanov.org/", name =
"sayHelloResponse")
public JAXBElement<SayHelloResponse> createSayHelloResponse(SayHelloResponse
value) {
return new JAXBElement<SayHelloResponse>(_SayHelloResponse_QNAME,
SayHelloResponse.class, null, value);
}
@XmlElementDecl(namespace = "http://lopanov.org/", name =
"sayHi")
public JAXBElement<SayHi> createSayHi(SayHi value) {
return new JAXBElement<SayHi>(_SayHi_QNAME, SayHi.class, null,
value);
}
@XmlElementDecl(namespace = "http://lopanov.org/", name =
"getBinaryResponse")
public JAXBElement<GetBinaryResponse>
createGetBinaryResponse(GetBinaryResponse value) {
return new
JAXBElement<GetBinaryResponse>(_GetBinaryResponse_QNAME,
GetBinaryResponse.class, null, value);
}
@XmlElementDecl(namespace = "http://lopanov.org/", name =
"sayHello")
public JAXBElement<SayHello> createSayHello(SayHello value) {
return new JAXBElement<SayHello>(_SayHello_QNAME, SayHello.class,
null, value);
}
@XmlElementDecl(namespace = "http://lopanov.org/", name =
"sayHiResponse")
public JAXBElement<SayHiResponse>
createSayHiResponse(SayHiResponse value) {
return new JAXBElement<SayHiResponse>(_SayHiResponse_QNAME,
SayHiResponse.class, null, value);
}
@XmlElementDecl(namespace = "http://lopanov.org/", name =
"person")
public JAXBElement<Person> createPerson(Person value) {
return new JAXBElement<Person>(_Person_QNAME, Person.class, null,
value);
}
@XmlElementDecl(namespace = "", name = "arg0", scope
= GetBinary.class)
public JAXBElement<byte[]> createGetBinaryArg0(byte[] value) {
return new JAXBElement<byte[]>(_GetBinaryArg0_QNAME, byte[].class,
GetBinary.class, ((byte[]) value));
}
}
Перейдем теперь
к обработчику SOAPHandler, он возвращает нам SOAPMessageContext context который дает нам возвожнось вызвав метод context.getMessage(), получить объект SOAPMessage message, а это уже доступ к
технологии SAAJ которая
уже позволяет дотянуться до тела сообщения(Body), до его заголовков (Headers) и к
присоединенным объектам(Attachments)
– объектам MTOM. Если не
вкурсе что за объекты MTOM,
то читайте мои предыдущие статьи. Приведу пример как добавить два тега в
заголовок(Headers):
package org.lopanov;
import javax.xml.namespace.QName;
import javax.xml.soap.*;
import javax.xml.ws.handler.MessageContext;
import
javax.xml.ws.handler.soap.SOAPHandler;
import
javax.xml.ws.handler.soap.SOAPMessageContext;
import java.util.Set;
public class SOAPHandlerClient implements
SOAPHandler<SOAPMessageContext> {
@Override
public Set<QName> getHeaders() {
return null;
}
@Override
public boolean handleMessage(SOAPMessageContext context) {
Boolean b = (Boolean)
context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
SOAPMessage message = context.getMessage();
if (b) {
System.out.printf("%s","Исходящее сообщение SOAPHandlerClient");
try {
SOAPElement element1=
SOAPFactory.newInstance().createElement(new QName("http://lopanov.org/","test"));//создаю 1-й SOAPElement – тег test
element1.addTextNode("Vit");// устанавливаю значение
SOAPElement element2=
SOAPFactory.newInstance().createElement(new
QName("http://lopanov.org/","test"));//создаю 1-й SOAPElement – тег test
element2.addTextNode("Hello");// устанавливаю значение
message.getSOAPPart().getEnvelope().getHeader().addChildElement(element1);//дотягиваюсь посредством технологии
SAAJ до заголовка и устанавливаю 1-й тег
message.getSOAPPart().getEnvelope().getHeader().addChildElement(element2);//устанавливаю 2-й тег
} catch (SOAPException e) {
e.printStackTrace(); //To change body of catch statement use File
| Settings | File Templates.
}
} else {
System.out.printf("%s","Входящее сообщение SOAPHandlerClient");
}
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
return false;
}
@Override
public void close(MessageContext context) { }
}
Был такой
лог, до вызова нашего перехвачика SOAPHandlerClient:
<?xml version='1.0'
encoding='UTF-8'?>
<S:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header/>
<S:Body>
<ns0:sayHello
xmlns:ns0="http://lopanov.org/">
<arg0>World</arg0>
</ns0:sayHello>
</S:Body></S:Envelope>
Получили
такой лог после вызова нашего перехвачика SOAPHandlerClient:
<?xml version='1.0'
encoding='UTF-8'?>
<S:Envelope
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header>
<test xmlns="http://lopanov.org/">Vit</test>
<test
xmlns="http://lopanov.org/">Hello</test>
</env:Header>
<S:Body>
<ns0:sayHello
xmlns:ns0="http://lopanov.org/">
<arg0>World</arg0>
</ns0:sayHello>
</S:Body></S:Envelope>
Вот и все
о перехватчиках.