WebserviceClient mit SOAP Handler (SecurityHandler)
Generierung eines Standard Webserviceclients mit JAXWS (WS-Stub Generierung):
"%java_home%\bin\wsimport" -keep http://<Pfad zur WSDL-Beschreibung des XYZ Service>
In den folgenden Beispielklassen müssen die generierten Klassen dann noch statt der XYZ Klassen eingesetzt werden.
Die eigentliche Klasse des "WebserviceClientWithSOAPHandler":
Die Idee hinter dieser Klasse ist es einen XYZService zu instantiieren, der dann auch direkt verwendet werden soll.
Dieser Service erhält aber zusätzlich einen "ClientHandlerResolver" (siehe unten) welcher vor und nach jedem Aufruf der Methoden des eigentlichen Service aufgerufen wird und das Handling von SOAP-Headern übernimmt.
Von diesem Aufruf bekommt der Nutzer des Proxy nichts mit, dies ist für ihn somit transparent.
Zusätzlich wird die erzeugte Service-Instanz hier noch für weitere Verwendung gepuffert, da das Erzeugen dieser manchmal viel Zeit in Anspruch nehmen kann.
public class WebserviceClientWithSOAPHandler {
private static final String SERVICE_NAMESPACE = "urn:xyzservice.soderer.de";
private static String SERVICE_ENDPOINT_URL_CONTEXT = "services/XYZService";
private ClientHandlerResolver clientHandlerResolver = new ClientHandlerResolver();
private String serverMachine_Hostname = null;
private int serverMachine_Port = 0;
private XYZ servicePort = null;
public WebserviceClientWithSOAPHandler(String serverMachine_Hostname, int serverMachine_Port) {
this.serverMachine_Hostname = serverMachine_Hostname;
this.serverMachine_Port = serverMachine_Port;
}
public XYZ getService() throws MalformedURLException {
if (servicePort == null) {
XYZService service = new XYZService(
new URL("http", serverMachine_Hostname, serverMachine_Port, SERVICE_ENDPOINT_URL_CONTEXT),
new QName(SERVICE_NAMESPACE, "XYZService"));
/**
* Resolver for the security handler.
*/
public class ClientHandlerResolver implements HandlerResolver {
/**
* List of handlers.
*/
@SuppressWarnings("rawtypes")
private List<Handler> _handlers;
/**
* Creates a new handler resolver.
*/
@SuppressWarnings("rawtypes")
public ClientHandlerResolver() {
_handlers = new ArrayList<Handler>();
_handlers.add(new SecurityHandler());
}
@SuppressWarnings("rawtypes")
public List<Handler> getHandlerChain(PortInfo portInfo) {
return _handlers;
}
/**
* Gets the security handler.
* @return the handler.
*/
public SecurityHandler getSecurityHandler() {
return (SecurityHandler)_handlers.get(0);
}
}
Die Hilfs-Klasse "SecurityHandler":
Hier passiert die eigentliche Magie. Denn jeder Aufruf einer Methode des Service-Objects kommt hier in der Phase der SOAP-Header-Erstellung vorbei.
Vor und nach dem Aufruf der Service-Methoden kann also beliebiger Code ausgeführt werden.
In diesem Beispiel wird ein AuthenticationToken als SOAP-Header übertragen und ein zurückgegebenes Token dann für den nächsten Aufruf zwischengespeichert.
public class SecurityHandler implements SOAPHandler<SOAPMessageContext> {
/* Name of the header. */
private static final QName QNAME_AUTH =
new QName("urn:api.soderer.de", "Authentication");
/* Name of the AuthenticationToken tag. */
@SuppressWarnings("unused")
private static final QName QNAME_AUTH_TOKEN =
new QName("urn:api.soderer.de", "AuthenticationToken");
/* List of headers this security handler can handle. */
private static final Set<QName> HEADERS;
54055(+93) Besucher