В документации не очень хорошо описано как создать динамический клиент с помощью Jax-WS. Для этого используется Dispatcher API.
Прежде всего надо добавить необходимую зависимость в проект.
...... com.sun.xml.ws jaxws-rt 2.2.3 ... java.net http://download.java.net/maven/2/
Исходный код клиента - DynamicClient.java
package org.etf.soap;
import java.util.Map;
import javax.xml.soap.SOAPException;
import javax.xml.ws.soap.SOAPBinding;
import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
/**
*
* @author Illya.Yalovyy
*/
public final class DynamicClient {
private final String namespace;
private final Service service;
private final Dispatch dispatch;
private final MessageFactory messageFactory;
public DynamicClient(String namespace, String serviceLocation,
String serviceName, String servicePort) throws SOAPException {
messageFactory = MessageFactory.newInstance();
this.namespace = namespace;
final QName serviceQName = new QName(namespace, serviceName);
final QName servicePortQName = new QName(namespace, servicePort);
service = Service.create(serviceQName);
service.addPort(servicePortQName, SOAPBinding.SOAP11HTTP_BINDING,
serviceLocation);
dispatch = service.createDispatch(servicePortQName, SOAPMessage.class,
Service.Mode.MESSAGE);
}
public SOAPMessage invoke(WebOperation operation, Object... args) throws SOAPException {
Validate.isTrue(args.length <= operation.getArgumentNames().length, "Too many arguments.");
if (operation.getSoapActionUri() == null) {
dispatch.getRequestContext().put(Dispatch.SOAPACTION_USE_PROPERTY, Boolean.FALSE);
dispatch.getRequestContext().put(Dispatch.SOAPACTION_URI_PROPERTY, "");
} else {
dispatch.getRequestContext().put(Dispatch.SOAPACTION_USE_PROPERTY, Boolean.TRUE);
dispatch.getRequestContext().put(Dispatch.SOAPACTION_URI_PROPERTY, operation.getSoapActionUri());
}
SOAPMessage message = messageFactory.createMessage();
SOAPPart soapPart = message.getSOAPPart();
SOAPEnvelope envelope = soapPart.getEnvelope();
SOAPBody body = envelope.getBody();
SOAPBodyElement operationElement = body.addBodyElement(new QName(namespace,
operation.getOperation(), StringUtils.defaultIfBlank(operation.getPrefix(), "")));
for (int i = 0; i < args.length; i++) {
SOAPElement argElement = operationElement.addChildElement(
new QName(operation.getArgumentNames()[i]));
argElement.setValue(String.valueOf(args[i]));
}
return dispatch.invoke(message);
}
public static final class Builder {
private String namespace, serviceLocation, serviceName, servicePort;
public Builder setNamespace(String namespace) {
this.namespace = namespace;
return this;
}
public Builder setServiceLocation(String serviceLocation) {
this.serviceLocation = serviceLocation;
return this;
}
public Builder setServiceName(String serviceName) {
this.serviceName = serviceName;
return this;
}
public Builder setServicePort(String servicePort) {
this.servicePort = servicePort;
return this;
}
public DynamicClient build() throws SOAPException {
Validate.notNull(namespace, "Namespace is required.");
Validate.notNull(serviceLocation, "Service location is required.");
Validate.notNull(serviceName, "Service name is required.");
Validate.notNull(servicePort, "Service port is required.");
return new DynamicClient(namespace, serviceLocation, serviceName, servicePort);
}
}
}
Вспомогательный класс для описания вызываемого метода - WebOperation.java
package org.etf.soap;
import java.util.ArrayList;
import java.util.Arrays;
import org.apache.commons.lang.Validate;
/**
*
* @author Illya.Yalovyy
*/
public class WebOperation {
private final String soapActionUri, operation, prefix;
private final String[] argumentNames;
public WebOperation(String soapActionUri, String operation, String prefix, String[] argumentNames) {
this.soapActionUri = soapActionUri;
this.operation = operation;
this.prefix = prefix;
this.argumentNames = argumentNames;
}
public String[] getArgumentNames() {
return argumentNames;
}
public String getOperation() {
return operation;
}
public String getPrefix() {
return prefix;
}
public String getSoapActionUri() {
return soapActionUri;
}
public static final class Builder {
private String soapActionUri, operation, prefix;
private ArrayList argumentNames = new ArrayList();
public Builder setArgumentNames(String... argumentNames) {
this.argumentNames.clear();
this.argumentNames.addAll(Arrays.asList(argumentNames));
return this;
}
public Builder setOperation(String operation) {
this.operation = operation;
return this;
}
public Builder setPrefix(String prefix) {
this.prefix = prefix;
return this;
}
public Builder setSoapActionUri(String soapActionUri) {
this.soapActionUri = soapActionUri;
return this;
}
public Builder addArgumentName(String name) {
this.argumentNames.add(name);
return this;
}
public WebOperation build() {
Validate.notNull(operation, "Operation name is required");
return new WebOperation(soapActionUri, operation, prefix,
argumentNames.toArray(new String[argumentNames.size()]));
}
}
}
Вспомогательный класс для печати результата на экран - XmlHelper.java
package org.etf.util;
import java.io.StringWriter;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Node;
/**
*
* @author Illya.Yalovyy
*/
public final class XmlHelper {
public static final String INDENTAMOUNT = "{http://xml.apache.org/xslt}indent-amount";
private XmlHelper() {}
public static void dumpNode(Node node) {
try {
final StringWriter writer = new StringWriter();
final Source source = new DOMSource(node);
final Result result = new StreamResult(writer);
Transformer t = TransformerFactory.newInstance().newTransformer();
t.setOutputProperty(OutputKeys.METHOD, "xml");
t.setOutputProperty(OutputKeys.INDENT, "yes");
t.setOutputProperty(OutputKeys.STANDALONE, "yes");
t.setOutputProperty(INDENTAMOUNT,"2");
t.transform(source, result);
System.out.println(writer.toString());
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
Пример использовани динамического клиента:
final DynamicClient mathertelClient = new DynamicClient.Builder()
.setNamespace("http://www.mathertel.de/CalcFactors/")
.setServiceLocation("http://www.mathertel.de/AJAXEngine/S02_AJAXCoreSamples/CalcService.asmx")
.setServiceName("CalcService")
.setServicePort("CalcServiceSoap")
.build();
final WebOperation addIntegerWebOperation = new WebOperation.Builder()
.setSoapActionUri("http://www.mathertel.de/CalcFactors/AddInteger")
.setOperation("AddInteger")
.addArgumentName("number1")
.addArgumentName("number2")
.build();
SOAPMessage response;
response = mathertelClient.invoke(addIntegerWebOperation, 3, 4);
XmlHelper.dumpNode(response.getSOAPBody());
response = mathertelClient.invoke(addIntegerWebOperation, 21, 43);
XmlHelper.dumpNode(response.getSOAPBody());
Полные исходные коды проекта:
https://svn.kenai.com/svn/mce~mce

0 comments:
Post a Comment