I started working again on a project I started a few years ago (code available here: http://code.google.com/p/mipnp/). It's a UPnP mediaserver that can stream media to an xbox 360.
For the SOAP part in UPnP I used Apache CXF. With CXF version 2.4.8 everything works like it should. But whenever I try to update to CXF version 2.4.9 (or newer) I get the following exception:
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)
This is what the SOAP request looks like:
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>
I'm guessing it has something to do with the 'DeviceID' parameter not being in the 'u' namespace. But I can't seem to find a fix or workaround.
This is how i'm creating the web service:
/*
* 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;
}
}
(You can find the complete code here)
And this is how the wsdl looks like:
<?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>
I tried adding the following line, because I read somewhere that the security measures went up since CXF version 2.4.9:
@EndpointProperty(key="soap.no.validate.parts", value="true")
But that doesn't make a difference.
THe issue is that the wsdl has:
<soap:operation soapAction="" style="document"/>
but the request is sending:
SOAPACTION: "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1#IsAuthorized"
There are a couple options:
1) You could update the WSDL to include that string as the soapAction and regenerate all the code and such.
2) You could write a CXF interceptor that removes the soapAction from the request headers (or sets it to "" like the wsdl states)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With