我开始重新开始几年前开始的项目(代码可在此处获取:http://code.google.com/p/mipnp/)。 它是一个UPnP中介服务器,可以将媒体流式传输到xbox 360。
对于UPnP中的SOAP部分,我使用了Apache CXF。 使用CXF 2.4.8版本,一切都可以正常运行。 但每当我尝试更新到CXF版本2.4.9(或更新版本)时,我都会遇到以下异常:
WARNING: Interceptor for {urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1}MediaReceiverRegistrarService#{urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1}IsAuthorized has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: The given SOAPAction urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1#IsAuthorized does not match an operation.
at org.apache.cxf.binding.soap.interceptor.SoapActionInInterceptor$SoapActionInAttemptTwoInterceptor.handleMessage(SoapActionInInterceptor.java:188)
at org.apache.cxf.binding.soap.interceptor.SoapActionInInterceptor$SoapActionInAttemptTwoInterceptor.handleMessage(SoapActionInInterceptor.java:162)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:207)
at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:209)
at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:191)
at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:114)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:185)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:108)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:755)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:164)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:669)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1336)
at com.googlecode.mipnp.upnp.ServerHeaderFilter.doFilter(ServerHeaderFilter.java:60)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1307)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:453)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:229)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1072)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:382)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1006)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
at org.eclipse.jetty.server.Server.handle(Server.java:365)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:485)
at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:937)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:998)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:856)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:628)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
at java.lang.Thread.run(Thread.java:722)
这就是SOAP请求的样子:
POST /control/x_ms_mediareceiverregistrar HTTP/1.1
User-Agent: Xbox/2.0.16202.0 UPnP/1.0 Xbox/2.0.16202.0
Connection: Keep-alive
Host:192.168.1.11:34331
SOAPACTION: "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1#IsAuthorized"
CONTENT-TYPE: text/xml; charset="utf-8"
Content-Length: 304
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:IsAuthorized xmlns:u="urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1">
<DeviceID></DeviceID>
</u:IsAuthorized>
</s:Body>
</s:Envelope>
我猜这与“DeviceID”参数不在'u'命名空间中有关。 但我似乎找不到修复或解决方法。
这就是我创建网络服务的方式:
/*
* MediaReceiverRegistrar.java
* Created on Jun 30, 2011, 4:00:45 PM
*/
package com.googlecode.mipnp.mediaserver;
import com.googlecode.mipnp.upnp.ServiceImpl;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.ws.Holder;
@WebService(
portName="X_MS_MediaReceiverRegistrar",
targetNamespace="urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1")
public class MediaReceiverRegistrar extends ServiceImpl {
@WebMethod(operationName="IsAuthorized")
public void isAuthorized(
@WebParam(name="DeviceID")
String deviceId,
@WebParam(name="Result", mode=WebParam.Mode.OUT)
Holder<Integer> result) {
result.value = 1;
}
}
(您可以找到完整的代码here)
这就是wsdl的样子:
<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions name="MediaReceiverRegistrarService" targetNamespace="urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<xs:schema elementFormDefault="unqualified" targetNamespace="urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1" version="1.0" xmlns:tns="urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="IsAuthorized" type="tns:IsAuthorized"/>
<xs:element name="IsAuthorizedResponse" type="tns:IsAuthorizedResponse"/>
<xs:element name="IsValidated" type="tns:IsValidated"/>
<xs:element name="IsValidatedResponse" type="tns:IsValidatedResponse"/>
<xs:element name="RegisterDevice" type="tns:RegisterDevice"/>
<xs:element name="RegisterDeviceResponse" type="tns:RegisterDeviceResponse"/>
<xs:element name="getIdAsUrn" type="tns:getIdAsUrn"/>
<xs:element name="getIdAsUrnResponse" type="tns:getIdAsUrnResponse"/>
<xs:element name="getTypeAsUrn" type="tns:getTypeAsUrn"/>
<xs:element name="getTypeAsUrnResponse" type="tns:getTypeAsUrnResponse"/>
<xs:complexType name="getTypeAsUrn">
<xs:sequence/>
</xs:complexType>
<xs:complexType name="getTypeAsUrnResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="IsValidated">
<xs:sequence>
<xs:element minOccurs="0" name="DeviceID" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="IsValidatedResponse">
<xs:sequence>
<xs:element minOccurs="0" name="Result" type="xs:int"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="IsAuthorized">
<xs:sequence>
<xs:element minOccurs="0" name="DeviceID" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="IsAuthorizedResponse">
<xs:sequence>
<xs:element minOccurs="0" name="Result" type="xs:int"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="getIdAsUrn">
<xs:sequence/>
</xs:complexType>
<xs:complexType name="getIdAsUrnResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="RegisterDevice">
<xs:sequence>
<xs:element minOccurs="0" name="RegistrationReqMsg" type="xs:base64Binary"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="RegisterDeviceResponse">
<xs:sequence>
<xs:element minOccurs="0" name="RegistrationRespMsg" type="xs:base64Binary"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="RegisterDeviceResponse">
<wsdl:part element="tns:RegisterDeviceResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getTypeAsUrnResponse">
<wsdl:part element="tns:getTypeAsUrnResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="IsValidatedResponse">
<wsdl:part element="tns:IsValidatedResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getIdAsUrnResponse">
<wsdl:part element="tns:getIdAsUrnResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getIdAsUrn">
<wsdl:part element="tns:getIdAsUrn" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getTypeAsUrn">
<wsdl:part element="tns:getTypeAsUrn" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="RegisterDevice">
<wsdl:part element="tns:RegisterDevice" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="IsValidated">
<wsdl:part element="tns:IsValidated" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="IsAuthorizedResponse">
<wsdl:part element="tns:IsAuthorizedResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="IsAuthorized">
<wsdl:part element="tns:IsAuthorized" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="MediaReceiverRegistrar">
<wsdl:operation name="getTypeAsUrn">
<wsdl:input message="tns:getTypeAsUrn" name="getTypeAsUrn">
</wsdl:input>
<wsdl:output message="tns:getTypeAsUrnResponse" name="getTypeAsUrnResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="IsValidated">
<wsdl:input message="tns:IsValidated" name="IsValidated">
</wsdl:input>
<wsdl:output message="tns:IsValidatedResponse" name="IsValidatedResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="IsAuthorized">
<wsdl:input message="tns:IsAuthorized" name="IsAuthorized">
</wsdl:input>
<wsdl:output message="tns:IsAuthorizedResponse" name="IsAuthorizedResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getIdAsUrn">
<wsdl:input message="tns:getIdAsUrn" name="getIdAsUrn">
</wsdl:input>
<wsdl:output message="tns:getIdAsUrnResponse" name="getIdAsUrnResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="RegisterDevice">
<wsdl:input message="tns:RegisterDevice" name="RegisterDevice">
</wsdl:input>
<wsdl:output message="tns:RegisterDeviceResponse" name="RegisterDeviceResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="MediaReceiverRegistrarServiceSoapBinding" type="tns:MediaReceiverRegistrar">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="getTypeAsUrn">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="getTypeAsUrn">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getTypeAsUrnResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="IsValidated">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="IsValidated">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="IsValidatedResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="IsAuthorized">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="IsAuthorized">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="IsAuthorizedResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getIdAsUrn">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="getIdAsUrn">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getIdAsUrnResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="RegisterDevice">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="RegisterDevice">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="RegisterDeviceResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="MediaReceiverRegistrarService">
<wsdl:port binding="tns:MediaReceiverRegistrarServiceSoapBinding" name="X_MS_MediaReceiverRegistrar">
<soap:address location="http://192.168.1.11:54802/control/x_ms_mediareceiverregistrar"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
我尝试添加以下行,因为我读到了自CXF版本2.4.9以来安全措施上升的地方:
@EndpointProperty(key="soap.no.validate.parts", value="true")
但这没有什么区别。
答案 0 :(得分:9)
问题是wsdl有:
<soap:operation soapAction="" style="document"/>
但请求正在发送:
SOAPACTION: "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1#IsAuthorized"
有几种选择:
1)您可以更新WSDL以将该字符串包含为soapAction并重新生成所有代码等。
2)您可以编写一个CXF拦截器,从请求标头中删除soapAction(或将其设置为&#34;&#34;与wsdl状态一样)
答案 1 :(得分:0)
我有同样的问题长时间agos,我试图添加
@EndpointProperty(key="soap.no.validate.parts", value="true")
但这没有帮助,在我的情况下,我不拥有我正在使用的Web服务,并且该Web服务的响应不遵循WSDL的规则,所以我结束了更改响应和像这样的拦截器:
/ *拦截器类* /
public class MyInterceptor extends AbstractPhaseInterceptor {
private static final Logger logger = Logger.getLogger(MyInterceptor.class);
public MyInterceptor() {
super(Phase.RECEIVE);
}
@Override
public void handleMessage(Message message) throws Fault {
logger.info("TCP-InterceptandoMensaje");
message.put(Message.ENCODING, "UTF-8");
InputStream is = message.getContent(InputStream.class);
if(is!=null){
CachedOutputStream bos = new CachedOutputStream();
try{
IOUtils.copy(is, bos);
String soapMessage = new String(bos.getBytes());
logger.info("-------------------------------------------");
logger.info("TCP-SoapMsgRecibido[" + soapMessage +"]");
logger.info("-------------------------------------------");
bos.flush();
message.setContent(InputStream.class, is);
is.close();
InputStream inputStream = new ByteArrayInputStream(removeBody(soapMessage).getBytes());
message.setContent(InputStream.class, inputStream);
bos.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
private String removeBody(String msg) {
StringBuffer soapMsg = new StringBuffer();
if (msg.contains("Reason")) {
if (msg.contains("TarjetaCreditoConsultaDetalle_Req")) {
soapMsg.append(msg.substring(0, msg.indexOf("<NS1:Body>")));
soapMsg.append("<NS1:Body>");
soapMsg.append("<NS2:TarjetaCreditoConsultaDetalle_Resp xmlns:NS2=\"http://www.bi.com.gt/esb/services/TarjetaCredito\">");
soapMsg.append("<InfoTrx>");
soapMsg.append("<IdTrx>000000000000000000000000</IdTrx>");
soapMsg.append("<Canal>000</Canal>");
soapMsg.append("<PaisOperacion>000</PaisOperacion>");
soapMsg.append("<BancoOperacion>0</BancoOperacion>");
soapMsg.append("<PaisDestino>000</PaisDestino>");
soapMsg.append("<BancoDestino>0</BancoDestino>");
soapMsg.append("<FechaTrx>00000000</FechaTrx>");
soapMsg.append("<HoraTrx>000000</HoraTrx>");
soapMsg.append("<IdCliente/>");
soapMsg.append("<CodOpWeb/>");
soapMsg.append("<CodEmpresa/>");
soapMsg.append("<TotPags>000</TotPags>");
soapMsg.append("<CodRetorno>000</CodRetorno>");
soapMsg.append("</InfoTrx>");
soapMsg.append("<Datos>");
soapMsg.append("<Producto>0</Producto>");
soapMsg.append("<NumProducto>0000000000000000</NumProducto>");
soapMsg.append("<NombreCuenta> </NombreCuenta>");
soapMsg.append("<Moneda>USD</Moneda>");
soapMsg.append("<Estado>00000000</Estado>");
soapMsg.append("<SaldoLocal>0.00</SaldoLocal>");
soapMsg.append("<SaldoDispLocal>0.00</SaldoDispLocal>");
soapMsg.append("<SaldoInter>0.00</SaldoInter>");
soapMsg.append("<SaldoDispInter>0.00</SaldoDispInter>");
soapMsg.append("<DirCorrespond> </DirCorrespond>");
soapMsg.append("<FechaCorte>00000000</FechaCorte>");
soapMsg.append("<FechaProxPago>00000000</FechaProxPago>");
soapMsg.append("<SobreGiroAutLocal>0.00</SobreGiroAutLocal>");
soapMsg.append("<SobreGiroAutInter>0.00</SobreGiroAutInter>");
soapMsg.append("<FecUltCambioEstado>00000000</FecUltCambioEstado>");
soapMsg.append("<FecUltMov>00000000</FecUltMov>");
soapMsg.append("<FecUltAbono>00000000</FecUltAbono>");
soapMsg.append("<PagoMinLocal>0.00</PagoMinLocal>");
soapMsg.append("<PagoContLocal>0.00</PagoContLocal>");
soapMsg.append("<PagoMinInter>0.00</PagoMinInter>");
soapMsg.append("<PagoContInter>0.00</PagoContInter>");
soapMsg.append("<LimiteAutLocal>0.00</LimiteAutLocal>");
soapMsg.append("<LimiteAutInter>0.00</LimiteAutInter>");
soapMsg.append("<Seguros>");
soapMsg.append("<SegTCSalva>1</SegTCSalva>");
soapMsg.append("<SegCobInt/>");
soapMsg.append("<SegVida/>");
soapMsg.append("<SegFourSeason/>");
soapMsg.append("</Seguros>");
soapMsg.append("<MontoTrxLocalDeb>0.00</MontoTrxLocalDeb>");
soapMsg.append("<MontoTrxLocalCred>0.00</MontoTrxLocalCred>");
soapMsg.append("<SaldoMaxVenc>0.00</SaldoMaxVenc>");
soapMsg.append("<MontoExtrafAutLocal>0.00</MontoExtrafAutLocal>");
soapMsg.append("<MontoExtrafAutInter>0.00</MontoExtrafAutInter>");
soapMsg.append("<MontoTrxInterDeb>0.00</MontoTrxInterDeb>");
soapMsg.append("<MontoTrxInterCred>0.00</MontoTrxInterCred>");
soapMsg.append("</Datos>");
soapMsg.append("</NS2:TarjetaCreditoConsultaDetalle_Resp>");
soapMsg.append("</NS1:Body>");
soapMsg.append("</NS1:Envelope>");
} else
soapMsg.append(msg);
} else
soapMsg.append(msg);
logger.info("EditedSoapMsg["+soapMsg+"]");
return soapMsg.toString();
}`
我的spring-config看起来像:
<bean id="tcPaymentServiceInterceptor" class="com.foo.bar.ws.interceptors.TcPaymentServiceInterceptor"/>
<bean id="cxf" class="org.apache.cxf.bus.spring.SpringBus">
<property name="inInterceptors">
<list>
<ref bean="tcPaymentServiceInterceptor"/>
</list>
</property>
</bean>
我希望这可以帮助有同样问题的人。
答案 2 :(得分:0)
我遇到了同样的问题,在http://forum.openkm.com/viewtopic.php?f=6&t=12494
中找到了解决方案Web服务是使用简单的@WebService和@WebParam注释在java中创建的。
从2.5.1到2.6.14,它似乎是Apache CXF库中的一个问题。 Daniel Kulp的第二个解决方案是简单的方法。
在Android的ksoap2(ksoap2-android-assembly-3.5.0-jar-with-dependencies.jar)库中,你可以这样使用:
HttpTransportSE transporte = new HttpTransportSE("http://10.0.2.2:8080/server-ws/actionServerWS?wsdl");
transporte.call("", envelope);
希望这个