S
starbuxman
I have a webservice which im accessing from
http://www.codebump.com/services/zipcodelookup.asmx?WSDL
Its pretty simple and I was able to use Axis to generate the stub /data
model classes and then strip out the connection specific stuff in favor
of usings Springs JAXRPC endpoint support.
All seems to be going well except that it needs to be authenticated --
that is, a header called
"AuthenticationHeader" needs to be sent along with a password string.
Or, put another way, how do i use/modify/coerce Springs support into
allowing me to add
<soap:Header>
<t:AuthenticationHeader xmlns:t="http://skats.net/services/">
<SessionID xsi:type="xsd:string">${SOMEHOW OR ANOTHER MY
PASSWORD HAS TO BE HERE}</SessionID>
</t:AuthenticationHeader>
</soap:Header>
to the request?
Thanks again,
Joshua
The major/relevant code is:
///////
-----------------------------------------------------------------------
// CODE
///////
-----------------------------------------------------------------------
import net.skats.services.*;
import org.apache.axis.encoding.ser.BeanDeserializerFactory;
import org.apache.axis.encoding.ser.BeanSerializerFactory;
import org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean;
import javax.xml.namespace.QName;
import javax.xml.rpc.Service;
import javax.xml.rpc.encoding.TypeMapping;
import javax.xml.rpc.encoding.TypeMappingRegistry;
import javax.xml.rpc.handler.HandlerInfo;
import java.util.List;
public class ZipcodePortProxyFactoryBean extends
JaxRpcPortProxyFactoryBean {
protected void postProcessJaxRpcService(Service service) {
QName port = new QName(this.getNamespaceUri(),
this.getPortName());
List list = service.getHandlerRegistry().getHandlerChain(port);
list.add(new HandlerInfo(CustomHandler.class, null, null));
// code for custom handler follows
TypeMappingRegistry registry =
service.getTypeMappingRegistry();
TypeMapping mapping = registry.createTypeMapping();
registerBeanMapping(mapping, GeoPlaceDistance.class,
"GeoPlaceDistance");
registerBeanMapping(mapping, ZipCodeCoordinates.class,
"ZipCodeCoordinates");
registerBeanMapping(mapping, UserPlaceDetail.class,
"UserPlaceDetail");
registerBeanMapping(mapping, ZipCodeDistances.class,
"ZipCodeDistances");
registerBeanMapping(mapping, FilterType.class, "FilterType");
registry.register("http://schemas.xmlsoap.org/soap/encoding/",
mapping);
}
protected void registerBeanMapping(TypeMapping mapping, Class type,
String name) {
QName qName = new QName("urn:ZipcodeService", name);
mapping.register(type, qName,
new BeanSerializerFactory(type, qName),
new BeanDeserializerFactory(type, qName));
}
}
// that code in turn references CustomHandler, which looks like:
package net.skats.services.misc;
import javax.xml.namespace.QName;
import javax.xml.rpc.JAXRPCException;
import javax.xml.rpc.handler.GenericHandler;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.rpc.handler.soap.SOAPMessageContext;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
public class CustomHandler extends GenericHandler {
// hardcoded for testing
static private String PW = "my pw as obtained from the service
hoster's website" ;
public QName[] getHeaders() {
//
return null // return new QName[]{ new
QName("AuthenticationHeader", PW) } ;
}
public boolean handleRequest(MessageContext messageContext) {
SOAPMessageContext smc = (SOAPMessageContext) messageContext;
SOAPMessage msg = smc.getMessage();
/*
<soap:Header>
<t:AuthenticationHeader xmlns:t="http://skats.net/services/">
<SessionID xsi:type="xsd:string">${SOMEHOW OR ANOTHER MY
PASSWORD HAS TO BE HERE}</SessionID>
</t:AuthenticationHeader>
</soap:Header>
*/
try {
SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
SOAPHeader header = envelope.getHeader();
//header.setAttribute("AuthenticationHeader", );
//
header.setAttributeNS("http://skats.net/services/","SessionID" , PW );
} catch (SOAPException e) {
throw new JAXRPCException(e);
}
return true;
}
}
The declaration is:
/// the domain model /client-side generated code is excluded, but
suffice it to say that it's not th eproblem
/// the java use-case
public void testZipcodeSearch() throws Throwable {
IZipCodeService service = (IZipCodeService)
_context.getBean("zipcodeService");
ZipCodeCoordinates coords =
service.GetZipCodeCoordinates("90211");
log(coords.getLatRadians() + " : " + coords.getLonRadians());
}
//// the xml
<bean id="zipcodeService"
class="net.skats.services.misc.ZipcodePortProxyFactoryBean">
<property name="serviceFactoryClass">
<value>org.apache.axis.client.ServiceFactory</value>
</property>
<property name="wsdlDocumentUrl">
<value>http://www.codebump.com/services/zipcodelookup.asmx?WSDL</value>
</property>
<property name="namespaceUri">
<value>http://skats.net/services/</value>
</property>
<property name="serviceName">
<value>ZipCodes</value>
</property>
<property name="portName">
<value>ZipCodesSoap</value>
</property>
<property name="portInterface">
<value>net.skats.services.ZipCodesSoap</value>
</property>
<property name="serviceInterface">
<value>net.skats.services.IZipCodeService</value>
</property>
</bean>
http://www.codebump.com/services/zipcodelookup.asmx?WSDL
Its pretty simple and I was able to use Axis to generate the stub /data
model classes and then strip out the connection specific stuff in favor
of usings Springs JAXRPC endpoint support.
All seems to be going well except that it needs to be authenticated --
that is, a header called
"AuthenticationHeader" needs to be sent along with a password string.
Or, put another way, how do i use/modify/coerce Springs support into
allowing me to add
<soap:Header>
<t:AuthenticationHeader xmlns:t="http://skats.net/services/">
<SessionID xsi:type="xsd:string">${SOMEHOW OR ANOTHER MY
PASSWORD HAS TO BE HERE}</SessionID>
</t:AuthenticationHeader>
</soap:Header>
to the request?
Thanks again,
Joshua
The major/relevant code is:
///////
-----------------------------------------------------------------------
// CODE
///////
-----------------------------------------------------------------------
import net.skats.services.*;
import org.apache.axis.encoding.ser.BeanDeserializerFactory;
import org.apache.axis.encoding.ser.BeanSerializerFactory;
import org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean;
import javax.xml.namespace.QName;
import javax.xml.rpc.Service;
import javax.xml.rpc.encoding.TypeMapping;
import javax.xml.rpc.encoding.TypeMappingRegistry;
import javax.xml.rpc.handler.HandlerInfo;
import java.util.List;
public class ZipcodePortProxyFactoryBean extends
JaxRpcPortProxyFactoryBean {
protected void postProcessJaxRpcService(Service service) {
QName port = new QName(this.getNamespaceUri(),
this.getPortName());
List list = service.getHandlerRegistry().getHandlerChain(port);
list.add(new HandlerInfo(CustomHandler.class, null, null));
// code for custom handler follows
TypeMappingRegistry registry =
service.getTypeMappingRegistry();
TypeMapping mapping = registry.createTypeMapping();
registerBeanMapping(mapping, GeoPlaceDistance.class,
"GeoPlaceDistance");
registerBeanMapping(mapping, ZipCodeCoordinates.class,
"ZipCodeCoordinates");
registerBeanMapping(mapping, UserPlaceDetail.class,
"UserPlaceDetail");
registerBeanMapping(mapping, ZipCodeDistances.class,
"ZipCodeDistances");
registerBeanMapping(mapping, FilterType.class, "FilterType");
registry.register("http://schemas.xmlsoap.org/soap/encoding/",
mapping);
}
protected void registerBeanMapping(TypeMapping mapping, Class type,
String name) {
QName qName = new QName("urn:ZipcodeService", name);
mapping.register(type, qName,
new BeanSerializerFactory(type, qName),
new BeanDeserializerFactory(type, qName));
}
}
// that code in turn references CustomHandler, which looks like:
package net.skats.services.misc;
import javax.xml.namespace.QName;
import javax.xml.rpc.JAXRPCException;
import javax.xml.rpc.handler.GenericHandler;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.rpc.handler.soap.SOAPMessageContext;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
public class CustomHandler extends GenericHandler {
// hardcoded for testing
static private String PW = "my pw as obtained from the service
hoster's website" ;
public QName[] getHeaders() {
//
return null // return new QName[]{ new
QName("AuthenticationHeader", PW) } ;
}
public boolean handleRequest(MessageContext messageContext) {
SOAPMessageContext smc = (SOAPMessageContext) messageContext;
SOAPMessage msg = smc.getMessage();
/*
<soap:Header>
<t:AuthenticationHeader xmlns:t="http://skats.net/services/">
<SessionID xsi:type="xsd:string">${SOMEHOW OR ANOTHER MY
PASSWORD HAS TO BE HERE}</SessionID>
</t:AuthenticationHeader>
</soap:Header>
*/
try {
SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
SOAPHeader header = envelope.getHeader();
//header.setAttribute("AuthenticationHeader", );
//
header.setAttributeNS("http://skats.net/services/","SessionID" , PW );
} catch (SOAPException e) {
throw new JAXRPCException(e);
}
return true;
}
}
The declaration is:
/// the domain model /client-side generated code is excluded, but
suffice it to say that it's not th eproblem
/// the java use-case
public void testZipcodeSearch() throws Throwable {
IZipCodeService service = (IZipCodeService)
_context.getBean("zipcodeService");
ZipCodeCoordinates coords =
service.GetZipCodeCoordinates("90211");
log(coords.getLatRadians() + " : " + coords.getLonRadians());
}
//// the xml
<bean id="zipcodeService"
class="net.skats.services.misc.ZipcodePortProxyFactoryBean">
<property name="serviceFactoryClass">
<value>org.apache.axis.client.ServiceFactory</value>
</property>
<property name="wsdlDocumentUrl">
<value>http://www.codebump.com/services/zipcodelookup.asmx?WSDL</value>
</property>
<property name="namespaceUri">
<value>http://skats.net/services/</value>
</property>
<property name="serviceName">
<value>ZipCodes</value>
</property>
<property name="portName">
<value>ZipCodesSoap</value>
</property>
<property name="portInterface">
<value>net.skats.services.ZipCodesSoap</value>
</property>
<property name="serviceInterface">
<value>net.skats.services.IZipCodeService</value>
</property>
</bean>