On Fri October 9 2009 5:27:47 am Rafal Rusin wrote:
> Thanks a lot. Implementing Provider interface resolved this problem.
>
> Now I've got 2 minor issues in 2.2.4:
> - method "invoke" shows up in Services List for this portType, but it
> shouldn't (how to deal with it?)
OK. THAT is definitely a bug and should be logged. Internally, we create
an internal "invoke" operation and map everything onto it since we don't do
any real processing of the body for dispatch/provider services. It
shouldn't show up in the list though.
> - operation is not mapped as javax.xml.ws.wsdl.operation property
> inside WebServiceContext, so I need to cast to CXF internal or use
> reflection to actually get it.
This should be set via one of the subclasses of
AbstractInDatabindingInterceptor. For provider based stuff, that would
normally be the DocLiteralInInterceptor. That is where we start looking at
the soap:body and trying to map it to an operation. If you can trace
through there and see if setMessage is ever called or skipped over, that would
be great.
That said, mapping it there is really kind of a waste of processing time. We
really shouldn't bother and instead map it on demand in
org.apache.cxf.jaxws.context.WrappedMessageContext.
Dan
>
> I've got following service's impl (deployed as WAR in Tomcat, endpoint
> spring config is like in previous mail):
>
> package pl.touk.humantask.ws;
> import javax.annotation.Resource;
> import javax.xml.namespace.QName;
> import javax.xml.soap.SOAPMessage;
> import javax.xml.ws.Endpoint;
> import javax.xml.ws.Provider;
> import javax.xml.ws.Service;
> import javax.xml.ws.ServiceMode;
> import javax.xml.ws.WebServiceContext;
> import javax.xml.ws.WebServiceProvider;
> import javax.xml.ws.handler.MessageContext;
>
> @WebServiceProvider
> @ServiceMode(value=Service.Mode.MESSAGE)
> public class JaxWSService implements Provider<SOAPMessage> {
> private WebServiceContext context;
>
> public WebServiceContext getContext() {
> return context;
> }
>
> @Resource
> public void setContext(WebServiceContext context) {
> this.context = context;
> }
>
> public SOAPMessage invoke(SOAPMessage request) {
> try {
> MessageContext c = context.getMessageContext();
> Object operationInfo =
> c.get("org.apache.cxf.service.model.OperationInfo");
> QName operation = (QName)
> operationInfo.getClass().getMethod("getName").invoke(operationInfo);
> QName portType = (QName) c.get("javax.xml.ws.wsdl.interface");
>
> System.err.println("invoked " + request + " endpoint " +
> endpoint + " operation:" + operation + " portType:" + portType);
>
> return null;
> } catch (Exception e) {
> e.printStackTrace();
> return null;
> }
> }
> }
>
>
>
> Those are properties set while executing invoke (note lacking
> javax.xml.ws.wsdl.operation, but existing
> org.apache.cxf.service.model.OperationInfo):
> org.apache.cxf.binding.binding=org.apache.cxf.binding.soap.soapbind...@da7b
> 85 org.apache.cxf.bus=org.apache.cxf.bus.cxfbusi...@1e373de
> javax.xml.ws.wsdl.description=http://localhost:8080/x/ClaimsHandlingService
> /?wsdl
> org.apache.cxf.service.model.BindingOperationInfo=[BindingOperationInfo:
> {http://www.insurance.example.com/claims}approve]
> org.apache.cxf.jaxws.handler.HandlerChainInvoker=org.apache.cxf.jaxws.handl
> er.handlerchaininvo...@1cc2f42
> org.apache.cxf.service.model.OperationInfo=[OperationInfo:
> {http://www.insurance.example.com/claims}approve]
> org.apache.cxf.service.Service=[ServiceImpl
> {http://www.insurance.example.com/claims}ClaimsHandlingService]
> javax.xml.ws.wsdl.service={http://www.insurance.example.com/claims}ClaimsHa
> ndlingService
> javax.xml.ws.wsdl.interface={http://www.insurance.example.com/claims}Claim
> sHandlingPT
> javax.xml.ws.wsdl.port={http://www.insurance.example.com/claims}ClaimsHand
> lingPort
> java.util.concurrent.Executor=org.apache.cxf.workqueue.SynchronousExecutor
> @1f844f7 org.apache.cxf.interceptor.LoggingMessage.ID=1
> org.apache.cxf.endpoint.Endpoint={}
>
> I saw that
> rt/core/src/main/java/org/apache/cxf/transport/ChainInitiationObserver.jav
> a copies some properties, which don't include operation. But it isn't
> staightforwad to fix, because I wasn't able to find OperationInfo
> during runtime. So I suppose operation is available later in
> interceptor chain.
>
> 2009/10/9 Daniel Kulp <[email protected]>:
> > I THINK the provider impl is wrong:
> >> @WebServiceProvider
> >> public class JaxWSService {
> >
> > This should be
> >
> > @WebServiceProvider
> > public class JaxWSService implements Provider<Source> {
> >
> > That MAY be the issue. If it doesn't implement Provider, it may not be
> > treating it as a provider and thus may be the issue. Definitely should
> > provide a better error message though.
> >
> > If the above doesn't fix the issue, can you package it in a war or
> > similar and attach it to a jira as a bug?
> >
> > Thanks!
> > Dan
> >
> > On Thu October 8 2009 5:16:14 pm Rafal Rusin wrote:
> >> 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(BareInInterc
> >>ept or.java:133) at
> >> org.apache.cxf.binding.soap.interceptor.RPCInInterceptor.handleMessage(
> >>RPC InInterceptor.java:111) at
> >> org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptor
> >>Cha in.java:236) at
> >> org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiat
> >>ion Observer.java:89) at
> >> org.apache.cxf.transport.servlet.ServletDestination.invoke(ServletDesti
> >>nat ion.java:99) at
> >> org.apache.cxf.transport.servlet.ServletController.invokeDestination(Se
> >>rvl etController.java:357) at
> >> org.apache.cxf.transport.servlet.ServletController.invoke(ServletContro
> >>lle r.java:183) at
> >> org.apache.cxf.transport.servlet.AbstractCXFServlet.invoke(AbstractCXFS
> >>erv let.java:163) at
> >> org.apache.cxf.transport.servlet.AbstractCXFServlet.doPost(AbstractCXFS
> >>erv let.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(Applic
> >>ati onFilterChain.java:290) at
> >> org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFil
> >>ter Chain.java:206) at
> >> org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFil
> >>ter Internal(OpenEntityManagerInViewFilter.java:112) at
> >> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerReq
> >>ues tFilter.java:76) at
> >> org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Applic
> >>ati onFilterChain.java:235) at
> >> org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFil
> >>ter Chain.java:206) at
> >> org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperVal
> >>ve. java:233) at
> >> org.apache.catalina.core.StandardContextValve.invoke(StandardContextVal
> >>ve. java:175) at
> >> org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.jav
> >>a:1 28) at
> >> org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.jav
> >>a:1 02) at
> >> org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve
> >>.ja va:109) at
> >> org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:
> >>286 ) at
> >> org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:8
> >>44) at
> >> org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process
> >>(Ht tp11Protocol.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,
> >
> > --
> > Daniel Kulp
> > [email protected]
> > http://www.dankulp.com/blog
>
> Regards,
>
--
Daniel Kulp
[email protected]
http://www.dankulp.com/blog