我们需要使用其他团队开发的Web服务。使用JAX-WS生成Web服务。我们使用wsimport生成客户端存根。
问题是我需要将以下信息作为标题与肥皂体一起传递。
<soapenv:Header>
<ns1:HeaderData xmlns:wsse="http:///wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:ns1="http:///esb/data_type/HeaderData/v1">
<ChannelIdentifier>ABC</ChannelIdentifier>
</ns1:HeaderData>
</soapenv:Header>
<execution>
<id>wsimport-profile</id>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<wsdlDirectory>src/main/resources/wsdl/GPP</wsdlDirectory>
<wsdlFiles>
<wsdlFile>LoadProfileService.wsdl</wsdlFile>
</wsdlFiles>
<packageName>com.soapbinding.service</packageName>
<extension>true</extension>
<protocol>Xsoap1.2</protocol>
<xadditionalHeaders>true</xadditionalHeaders>
</configuration>
</execution>
我尝试使用JAX-WS。它几乎相同,修改标题以添加用户凭据:
public class LoadProfileSOAPHandler implements SOAPHandler<SOAPMessageContext> {
@Log
private Logger LOGGER;
private String username;
/**
* Handles SOAP message. If SOAP header does not already exist, then method will created new SOAP header. The
* username is added to the header as the credentials to authenticate user. If no user credentials is
* specified every call to web service will fail.
*
* @param context SOAP message context to get SOAP message from
* @return true
*/
@Override
public boolean handleMessage(SOAPMessageContext context) {
try {
String uri = "http:/SCL/CommonTypes";
String prefix = "q2";
SOAPMessage message = context.getMessage();
SOAPHeader header = message.getSOAPHeader();
SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
if (header == null) {
header = envelope.addHeader();
}
QName qNameFndtHeader = new QName(uri,prefix, "FndtHeader");
SOAPHeaderElement fndtHeader = header.addHeaderElement(qNameFndtHeader);
QName qNamecredentials = new QName(prefix, "credentials");
QName qNameuser = new QName(prefix, "UserID");
SOAPHeaderElement userHeader = header.addHeaderElement(qNameuser);
userHeader.addTextNode(this.username);
fndtHeader.addChildElement(qNameFndtHeader);
fndtHeader.addChildElement(qNamecredentials);
fndtHeader.addChildElement(userHeader );
message.saveChanges();
//TODO: remove this writer when the testing is finished
StringWriter writer = new StringWriter();
message.writeTo(new StringOutputStream(writer));
LOGGER.debug("SOAP message: \n" + writer.toString());
} catch (SOAPException e) {
LOGGER.error("Error occurred while adding credentials to SOAP header.", e.getMessage());
} catch (IOException e) {
LOGGER.error("Error occurred while writing message to output stream.", e.getMessage());
}
return true;
}
//TODO: remove this class after testing is finished
private static class StringOutputStream extends OutputStream {
private StringWriter writer;
public StringOutputStream(StringWriter writer) {
this.writer = writer;
}
@Override
public void write(int b) throws IOException {
writer.write(b);
}
}
@Override
public boolean handleFault(SOAPMessageContext context) {
LOGGER.debug("handleFault has been invoked.");
return true;
}
@Override
public void close(MessageContext context) {
LOGGER.debug("close has been invoked.");
}
@Override
public Set<QName> getHeaders() {
LOGGER.debug("getHeaders has been invoked.");
return null;
}
public void setUsername(String username) {
this.username = username;
}
}
@Component("loadProfileHandlerResolver")
/**
* Overrode in order to load custom handlers.
* @see javax.xml.ws.handler.HandlerResolver#getHandlerChain(javax.xml.ws.handler.PortInfo)
*/
public class LoadProfileHandlerResolver implements org.springframework.context.ApplicationContextAware, HandlerResolver {
/*@Autowired
LoadProfileSOAPHandler loadProfileSOAPHandler;
*/
@Override
public void setApplicationContext(ApplicationContext arg0)
throws BeansException {
ListableBeanFactory lb = (ListableBeanFactory) arg0;
System.out.println(Arrays.toString(lb.getBeanDefinitionNames()));
}
public LoadProfileHandlerResolver() {
// TODO Auto-generated constructor stub
System.out.println("");
}
@Override
public List<Handler> getHandlerChain(PortInfo arg0) {
List<Handler> handlerChain = new ArrayList<Handler>();
LoadProfileSOAPHandler loadProfileSOAPHandler =new LoadProfileSOAPHandler();
handlerChain.add(loadProfileSOAPHandler);
return handlerChain;
}
还在应用程序配置文件中添加了依赖性。我在Spring配置中定义了这个处理程序,如上所述
<bean id="loadProfilePortProxy"
class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
<property name="serviceInterface"
value="com.soapbinding.gpppservice.LoadProfileServicePortType" />
<property name="wsdlDocumentUrl" value="classpath:wsdl/GPP/LoadProfileService.wsdl" />
<property name="namespaceUri" value="http://SCL/LoadProfileService" />
<property name="serviceName" value="LoadProfileService" />
<property name="endpointAddress" value="${service.loadCalenderdata}" />
<property name="handlerResolver" ref="loadProfileHandlerResolver"/>
</bean>
我正在解决以下问题:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loadProfilePortProxy' defined in class path resource [application-config.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
由于spring application.xml中的property name="handlerResolver" ref="loadProfileHandlerResolver"
并且还让我知道为什么我的wsimport
没有使用xadditionalHeaders
,因为它没有给我带有soap标头的存根类,这可能会以其他方式解决问题。
<xadditionalHeaders>true</xadditionalHeaders>
答案 0 :(得分:0)
解决了这个问题,我们在春天注入属性ref loadProfileHandlerResolver
时得到一些null...谢谢