![](/img/trans.png)
[英]How to get WSDL operation name from SoapMessage in CXF Request Interceptor
[英]How to transform SoapFault to SoapMessage via Interceptor in CXF?
我通过Spring
和CXF
创建和配置了Web服务。 见下面的豆子:
<?xml version="1.0" encoding="UTF-8"?>
<beans <!-- ommited -->>
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<bean id="internalActService" class="package.InternalActServiceImpl" />
<jaxws:endpoint implementor="#internalActService" address="/InternalActService">
<jaxws:properties>
<entry key="schema-validation-enabled" value="true" />
</jaxws:properties>
<jaxws:outFaultInterceptors>
<bean class="package.InternalActServiceFaultOutInterceptor" />
</jaxws:outFaultInterceptors>
</jaxws:endpoint>
</beans>
您可以看到我在我的Web服务中添加了模式验证。 但是当请求与架构不对应时, CXF
会抛出SoapFault
。 我想发送给客户端SoapMessage
而不是SoapFault
,这就是为什么我添加了outFaultInterceptors
。
我的问题是如何将SoapFaul
转换为SoapMessage
? 我做了很少尝试,但我不知道如何实现outFaultInterceptor
。
可能你忘了设置拦截器阶段及其在拦截器链中的顺序。
尝试这样的事情:
package org.foo.bar;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.interceptor.AttachmentOutInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.interceptor.StaxOutInterceptor;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageContentsList;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import java.util.Arrays;
import java.util.List;
public class InternalActServiceFaultOutInterceptor extends AbstractSoapInterceptor {
public InternalActServiceFaultOutInterceptor() {
super(Phase.PRE_STREAM);
addBefore(Arrays.asList(StaxOutInterceptor.class.getName(), AttachmentOutInterceptor.class.getName()));
}
@Override
public void handleMessage(SoapMessage message) throws Fault {
Exception exception = message.getContent(Exception.class);
if(exception != null) {
message.getExchange().put(Exception.class, null);
for(Class<?> contentFormat : message.getContentFormats()) {
message.setContent(contentFormat, null);
}
message.setContent(List.class, new MessageContentsList(createSoapMessage(RegisterDocumentResponse.class)));
}
}
protected <T> T createSoapMessage(Class<T> messageType) {
// create your message
return null;
}
}
-编辑-
这是一个适合我的单元测试。 能够将POJO发送到输出端有点棘手。 我想如果自己构建DOM会更简单。
package foo.bar;
import java.util.Arrays;
import java.util.List;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.interceptor.Interceptor;
import org.apache.cxf.interceptor.InterceptorChain;
import org.apache.cxf.interceptor.OutgoingChainInterceptor;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageContentsList;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.service.model.BindingMessageInfo;
import org.apache.cxf.service.model.BindingOperationInfo;
import org.apache.cxf.service.model.MessageInfo;
import org.apache.cxf.service.model.OperationInfo;
import org.apache.cxf.service.model.ServiceModelUtil;
import org.apache.cxf.ws.policy.PolicyOutInterceptor;
public class InternalActServiceFaultOutInterceptor extends AbstractSoapInterceptor {
public InternalActServiceFaultOutInterceptor() {
super(Phase.SETUP);
addBefore(Arrays.asList(PolicyOutInterceptor.class.getName()));
}
@Override
public void handleMessage(SoapMessage message) throws Fault {
Exchange exchange = message.getExchange();
resetOrigInterceptorChain(message);
resetFault(exchange);
Message outMessage = createOutMessage(exchange);
InterceptorChain chain = prepareNewInterceptorChain(exchange);
chain.doIntercept(outMessage);
}
private InterceptorChain prepareNewInterceptorChain(Exchange exchange) {
Message message = exchange.getOutMessage();
bind(message);
InterceptorChain chain = OutgoingChainInterceptor.getOutInterceptorChain(exchange);
message.setInterceptorChain(chain);
return chain;
}
private Message createOutMessage(Exchange exchange) {
Endpoint ep = exchange.get(Endpoint.class);
Message outMessage = ep.getBinding().createMessage();
outMessage.setExchange(exchange);
outMessage.setContent(List.class, new MessageContentsList(createSoapMessage()));
exchange.setOutMessage(outMessage);
return outMessage;
}
private void resetFault(Exchange exchange) {
exchange.put(Exception.class, null);
}
private void resetOrigInterceptorChain(SoapMessage message) {
InterceptorChain chain = message.getInterceptorChain();
for(Interceptor<?> interceptor : chain) {
chain.remove(interceptor);
}
chain.reset();
}
private void bind(Message message) {
Exchange exchange = message.getExchange();
BindingOperationInfo bop = unwrap(message.getExchange().getBindingOperationInfo());
message.put(MessageInfo.class, bop.getOperationInfo().getOutput());
message.put(BindingMessageInfo.class, bop.getOutput());
bop = unwrap(ServiceModelUtil.getOperationForWrapperElement(exchange, bop.getName(), false));
exchange.put(BindingOperationInfo.class, bop);
if (bop != null) {
exchange.put(BindingOperationInfo.class, bop);
exchange.put(OperationInfo.class, bop.getOperationInfo());
}
}
private BindingOperationInfo unwrap(BindingOperationInfo bop) {
while(bop.getUnwrappedOperation() != null) {
bop = bop.getUnwrappedOperation();
return bop;
}
return bop;
}
protected Echo createSoapMessage() {
Echo e = new Echo();
e.setValue("Bye World!");
return e;
}
}
package foo.bar;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "EchoType")
public class Echo {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
package foo.bar;
import javax.jws.WebService;
@WebService
public class InternalActServiceImpl {
public Echo echo(Echo val) {
return val;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-http-jetty.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-jaxws.xml" />
<bean id="internalActService" class="foo.bar.InternalActServiceImpl" />
<jaxws:endpoint implementor="#internalActService" address="http://localhost:9080/InternalActService">
<jaxws:properties>
<entry key="schema-validation-enabled" value="true" />
</jaxws:properties>
<jaxws:outFaultInterceptors>
<bean class="foo.bar.InternalActServiceFaultOutInterceptor" />
</jaxws:outFaultInterceptors>
</jaxws:endpoint>
package foo.bar;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class CxfInterceptorTest {
private static final String REQ =
"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:bar=\"http://bar.foo/\">\r\n" +
" <soapenv:Header/>\r\n" +
" <soapenv:Body>\r\n" +
" <bar:echo>\r\n" +
" <arg0>\r\n" +
" <value1>Hello World</value1>\r\n" +
" </arg0>\r\n" +
" </bar:echo>\r\n" +
" </soapenv:Body>\r\n" +
"</soapenv:Envelope>";
@Test
public void validate() throws Exception {
String s = call();
Assert.assertTrue(s.contains("Bye World!"));
}
private String call() throws Exception {
URL url = new URL("http://localhost:9080/InternalActService");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setInstanceFollowRedirects(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "text/xml;charset=UTF-8");
conn.setRequestProperty("SOAPAction", "");
OutputStream os = conn.getOutputStream();
os.write(REQ.getBytes());
os.flush();
os.close();
final int buffSize = 1024;
byte[] buff = new byte[1024];
InputStream is = conn.getInputStream();
StringBuilder builder = new StringBuilder(buffSize);
for(int readBytes = -1; (readBytes = is.read(buff, 0, buffSize)) != -1; ) {
builder.append(new String(buff, 0, readBytes));
}
is.close();
return builder.toString();
}
}
你的拦截器应该实现
org.apache.cxf.interceptor.Interceptor
将调用handleMessage方法的handleFault。 这两个参数都是一个实例
org.apache.cxf.message.Message
你可以打电话来
removeContent()
要么
setContent()
替换消息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.