我正在为一个相当旧(但遗憾的是无法更改)的接口实现一个web服务。我遇到了一个问题,即调用我的服务的客户端需要SOAP响应中的某个命名空间,而我很难将其更改为匹配。
考虑一个hello world示例,我希望这样:
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:helloResponse xmlns:ns2="http://test/">
<return>Hello Catchwa!</return>
</ns2:helloResponse>
</S:Body>
</S:Envelope>
看起来像这样:
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<customns:helloResponse xmlns:customns="http://test/">
<return>Hello Catchwa!</return>
</customns:helloResponse>
</S:Body>
</S:Envelope>
我发现了一些类似于我在这里尝试做的事情,但我很难正确执行类似的代码。(我想继续使用Metro,而不必更换cxf或axis)
我的返回< code > jaxbcontext 的< code>JAXBContextFactory实现如下所示:
import com.sun.xml.bind.api.JAXBRIContext;
import com.sun.xml.bind.api.TypeReference;
import com.sun.xml.ws.api.model.SEIModel;
import com.sun.xml.ws.developer.JAXBContextFactory;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBException;
import javax.xml.namespace.QName;
public class HelloJaxbContext implements JAXBContextFactory
{
@Override
public JAXBRIContext createJAXBContext(SEIModel seim, List<Class> classesToBind, List<TypeReference> typeReferences) throws JAXBException {
List<Class> classList = new ArrayList<Class>();
classList.addAll(classesToBind);
List<TypeReference> refList = new ArrayList<TypeReference>();
for (TypeReference tr : typeReferences) {
refList.add(new TypeReference(new QName(tr.tagName.getNamespaceURI(), tr.tagName.getLocalPart(), "customns"), tr.type, tr.annotations));
}
return JAXBRIContext.newInstance(classList.toArray(new Class[classList.size()]), refList, null, seim.getTargetNamespace(), false, null);
}
}
web服务的一些测试代码很简单:
import com.sun.xml.ws.developer.UsesJAXBContext;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.WebParam;
@WebService(serviceName = "Hello")
@UsesJAXBContext(value = HelloJaxbContext.class)
public class Hello
{
@WebMethod(operationName = "hello")
public String hello(@WebParam(name = "name") String txt)
{
return "Hello " + txt + "!";
}
}
在使用jaxws-rt 2.2.7(来自Maven)的Tomcat 7.0.32和Glassfish 3.1.2中,上述代码不会影响我的web服务输出(名称空间前缀仍然是“ns2”)。
在参考实现中,我这样做是为了最终让它工作。请参见使用Metro编组JAXB类时忽略schemaLocation
实现您试图实现的目标的推荐/标准方法是使用SOAPMessageHandler。它们类似于java web应用程序过滤器(理论上也可以在这里工作),因为它们用于实现责任链模式。例如,在您的案例中,您可以这样做:
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
public class SOAPBodyHandler implements SOAPHandler<SOAPMessageContext> {
static final String DESIRED_NS_PREFIX = "customns";
static final String DESIRED_NS_URI = "http://test/";
static final String UNWANTED_NS_PREFIX = "ns";
@Override
public Set<QName> getHeaders() {
//do nothing
return null;
}
@Override
public boolean handleMessage(SOAPMessageContext context) {
if ((boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)) { //Check here that the message being intercepted is an outbound message from your service, otherwise ignore.
try {
SOAPEnvelope msg = context.getMessage().getSOAPPart().getEnvelope(); //get the SOAP Message envelope
SOAPBody body = msg.getBody();
body.removeNamespaceDeclaration(UNWANTED_NS_PREFIX);
body.addNamespaceDeclaration(DESIRED_NS_PREFIX, DESIRED_NS_URI);
} catch (SOAPException ex) {
Logger.getLogger(SOAPBodyHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
return true; //indicates to the context to proceed with (normal)message processing
}
@Override
public boolean handleFault(SOAPMessageContext context) {
//do nothing
return null;
}
@Override
public void close(MessageContext context) {
//do nothing
}
}
在服务实现Bean类声明中,添加
@HandlerChain(file = "handler-chain.xml")
上面的注释是对配置文件的引用,它实际上允许处理程序启动。配置文件将如下所示
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<javaee:handler-chain>
<javaee:handler>
<javaee:handler-class>your.handler.FQN.here</javaee:handler-class>
</javaee:handler>
</javaee:handler-chain>
</javaee:handler-chains>
在家试试这个。这个特定的代码还没有经过测试
如果您从旧服务的WSDL开始,并使用wsimport
生成所有各种JAXB注释的请求和响应包装器类,那么在生成的包中您应该会找到一个package-info.java
,例如
@javax.xml.bind.annotation.XmlSchema(namespace = "http://test/")
package com.example.test;
JAXB 为您提供了一种机制,可以在@XmlSchema
注释上建议前缀映射,因此您可以尝试修改包信息.java
以读取
@javax.xml.bind.annotation.XmlSchema(namespace = "http://test/",
xmlns = {
@javax.xml.bind.annotation.XmlNs(prefix = "customns",
namespaceURI="http://test/")
}
)
package com.example.test;
并查看这是否对生成的消息有任何影响。这还有一个优点是纯JAXB规范(即不依赖于特定于RI的自定义上下文工厂)。
如果您需要重新运行 wsimport
,您可以通过将 -npa
选项传递给 xjc
来防止它覆盖修改后的包信息(这告诉它不要生成包信息.java
而是将所有必要的命名空间
设置放在类级注释上)。具体如何执行此操作取决于您运行
wsimport
的方式。
命令行:
wsimport -B-npa ....
蚂蚁:
<wsimport wsdl="..." destdir="..." .... >
<xjcarg value="-npa" />
</wsimport>
专家:
<plugin>
<groupId>org.jvnet.jax-ws-commons</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<xjcArgs>
<xjcArg>-npa</xjcArg>
</xjcArgs>
</configuration>
</execution>
</executions>
</plugin>
问题内容: 目标 我正在为相当老的(但可悲的是不可更改)的接口实现Web服务。我有一个问题,正在调用我的服务的客户端期望SOAP响应中有某个命名空间,而我很难更改它以使其匹配。 考虑一个世界的例子,我想要这样: 看起来像这样: 我在这里找到了与尝试执行的操作类似的操作,但是在使相似的代码正确执行方面遇到困难。(我想坚持使用Metro,而不必更改为cxf或axis) 执行 我的实现返回如下所示: 该
问题内容: 所以我有一个简单的Web服务: 书的类也很简单: 现在,当您在浏览器的测试器中调用此Web服务时,我得到: 是否有可能将返回的 HashMap 对象显示在标记中,例如 我想要返回标签中的值的原因是,从客户端来看,我在网页中使用jQuery AJAX调用此Web服务,而我得到的响应XML只是空标签。我如何从AJAX客户端获得真实的账面价值? 这是我的AJAX网络代码: 我使用简单的Hel
问题内容: 我正在尝试创建一个独立的客户端来使用某些Web服务。我必须将我的用户名和密码添加到SOAP Header。我尝试添加凭据,如下所示: 当我在服务上调用方法时,出现以下异常: 我究竟做错了什么?如何将这些属性添加到SOAP Header? 编辑:我正在使用JDK6中包含的JAX-WS 2.1。我现在正在使用JAX-WS 2.2。我现在得到以下异常: 如何创建此令牌? 问题答案: 不是10
在一个 Java 项目中,我使用 jax-ws 和 wsdl 创建了一个 Web 服务客户端。该请求是有效的 xml,但缺少此特定 SOAP 调用中所需的前缀。目前,我通过手动将xmlns={@javax.xml.bind.annotation.XmlNs(前缀=“gen”,namespaceURI=“http://schemas...”)})添加到package-info.java类来解决此问题
我需要解析jax-ws-rest响应,我尝试了以下两种解析响应的方法。两者都很好。但我需要知道最有效的实施方式。请告诉我你的看法。 < li >使用getEntity对象并获取响应作为输入流。 < li >使用Jackson object mapper read value()-将inputstream转换为java对象。 < li >使用嵌套java类的getters和setters获取响应对象
我现在正在学习jax-ws。我定义了一个Web服务: 用户服务。JAVA UserServiceImpl。JAVA 使用者JAVA 当我在客户端中调用queryUserInfo()时,它会工作;但是当服务器执行该函数时,参数user将为空。 我使用wsimport生成客户机代码。 ...........................................................