Hello,
I'd like to expose some consumer services from xml defined file in
cxf. All such services have corresponding wsdls.
So I thought the best way is to create generic @WebServiceProvider
class and expose services via javax.xml.ws.Endpoint.publish() in loop.
Then I would be able to anwer exchanges for various operations inside
invoke method.
But I saw that exposing a single endpoint in spring config, using such
generic implementor causes problems - in services list I see only a
portType without any operation inside.
And I get failures during recognizing message on soap calls.
Here's my spring config:
<bean id="impl2" class="pl.touk.humantask.ws.JaxWSService">
<property name="services" ref="humanTaskServices"/>
<property name="endpoint" ref="testHtd1"></property>
</bean>
<jaxws:endpoint id="testHtd1"
address="/ClaimsHandlingService/"
implementor="#impl2"
serviceName="ins:ClaimsHandlingService"
endpointName="ins:ClaimsHandlingPort"
publish="true"
wsdlLocation="classpath:ExampleTasks.wsdl"
>
Attached is wsdl (but I think wsdl doesn't really matters, because I
tested it on different ones - including those working on
code-generated services).
Here's my generic implementor class:
package pl.touk.humantask.ws;
import javax.xml.transform.Source;
import javax.xml.ws.Endpoint;
import javax.xml.ws.WebServiceProvider;
import pl.touk.humantask.HumanTaskServices;
@WebServiceProvider
public class JaxWSService {
public Source invoke(Source request) {
System.err.println("invoked " + request + " endpoint " + endpoint);
return request;
}
}
And here's log which I got after soap call:
----------------------------
ID: 2
Address: /x/ClaimsHandlingService29/
Encoding: UTF-8
Content-Type: text/xml;charset=UTF-8
Headers: {content-length=[653], accept-encoding=[gzip,deflate],
host=[localhost:8080], user-agent=[Jakarta Commons-HttpClient/3.1],
SOAPAction=["http://www.insurance.example.com/claims/approve"],
content-type=[text/xml;charset=UTF-8]}
Payload: <soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:cla="http://www.insurance.example.com/claims">
<soapenv:Header/>
<soapenv:Body>
<cla:approve>
<ClaimApprovalRequest>
<cla:cust>
<cla:id>123</cla:id>
<cla:firstname>Edmund</cla:firstname>
<cla:lastname>Zorn</cla:lastname>
</cla:cust>
<cla:amount>1234</cla:amount>
<cla:region>usa</cla:region>
<cla:prio>2</cla:prio>
<cla:activateAt>2009-01-02T12:00:00</cla:activateAt>
</ClaimApprovalRequest>
</cla:approve>
</soapenv:Body>
</soapenv:Envelope>
--------------------------------------
2009-10-08 20:43:37 org.apache.cxf.phase.PhaseInterceptorChain doIntercept
INFO: Interceptor has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: Message part
{http://www.insurance.example.com/claims}approve was not recognized.
(Does it exist in service WSDL?)
at
org.apache.cxf.interceptor.BareInInterceptor.handleMessage(BareInInterceptor.java:133)
at
org.apache.cxf.binding.soap.interceptor.RPCInInterceptor.handleMessage(RPCInInterceptor.java:111)
at
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:236)
at
org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:89)
at
org.apache.cxf.transport.servlet.ServletDestination.invoke(ServletDestination.java:99)
at
org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:357)
at
org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:183)
at
org.apache.cxf.transport.servlet.AbstractCXFServlet.invoke(AbstractCXFServlet.java:163)
at
org.apache.cxf.transport.servlet.AbstractCXFServlet.doPost(AbstractCXFServlet.java:141)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:112)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
at
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at
org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:595)
2009-10-08 20:43:37
org.apache.cxf.interceptor.LoggingOutInterceptor$LoggingCallback
onClose
So is there any fix for it? Or maybe there's more elegant way to
expose dynamic web services in cxf?
Axis2 supports such things, so there needs to be a way in cxf.
Regards,
--
RafaĆ Rusin
http://www.touk.pl
http://top.touk.pl
http://people.apache.org/~rr/
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="ClaimApproval"
targetNamespace="http://www.insurance.example.com/claims"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://www.insurance.example.com/claims"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<xsd:schema elementFormDefault="qualified"
targetNamespace="http://www.insurance.example.com/claims"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://www.insurance.example.com/claims">
<xsd:complexType name="ClaimApprovalData">
<xsd:sequence>
<xsd:element name="cust">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="id" type="xsd:string">
</xsd:element>
<xsd:element name="firstname" type="xsd:string">
</xsd:element>
<xsd:element name="lastname" type="xsd:string">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="amount" type="xsd:double" />
<xsd:element name="region" type="xsd:string" />
<xsd:element name="prio" type="xsd:int" />
<xsd:element name="activateAt" type="xsd:dateTime" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name="ClaimApprovalRequest">
<wsdl:part name="ClaimApprovalRequest"
type="tns:ClaimApprovalData" />
</wsdl:message>
<wsdl:message name="ClaimApprovalResponse">
<wsdl:part name="ClaimApprovalResponse" type="xsd:boolean" />
</wsdl:message>
<wsdl:message name="notifyRequest">
<wsdl:part name="firstname" type="xsd:string" />
<wsdl:part name="lastname" type="xsd:string" />
<wsdl:part name="taskId" type="xsd:string" />
</wsdl:message>
<wsdl:portType name="ClaimsHandlingPT">
<wsdl:operation name="approve">
<wsdl:input message="tns:ClaimApprovalRequest" />
</wsdl:operation>
<wsdl:operation name="escalate">
<wsdl:input message="tns:ClaimApprovalRequest" />
</wsdl:operation>
</wsdl:portType>
<wsdl:portType name="ClaimsHandlingCallbackPT">
<wsdl:operation name="approvalResponse">
<wsdl:input message="tns:ClaimApprovalResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:portType name="ClaimApprovalReminderPT">
<wsdl:operation name="notify">
<wsdl:input message="tns:notifyRequest" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ClaimsHandlingBinding" type="tns:ClaimsHandlingPT">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="approve">
<soap:operation soapAction="http://www.insurance.example.com/claims/approve" />
<wsdl:input>
<soap:body use="literal" namespace="http://www.insurance.example.com/claims" />
</wsdl:input>
</wsdl:operation>
<wsdl:operation name="escalate">
<soap:operation soapAction="http://www.insurance.example.com/claims/escalate" />
<wsdl:input>
<soap:body use="literal" namespace="http://www.insurance.example.com/claims" />
</wsdl:input>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ClaimsHandlingService">
<wsdl:port name="ClaimsHandlingPort" binding="tns:ClaimsHandlingBinding">
<soap:address location="http://localhost:8090"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>