You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by John Hite <jh...@appsecinc.com> on 2009/11/13 19:34:00 UTC

WSDL to Java and SOAP 1.2

Hi,

I am trying to write a client using cxf-2.2 for a SOAP 1.2 service. The wsdl has soap 1.2 binding configuration like this

<wsdl:binding name="WSHttpBinding_IProxyService" type="tns:IProxyService">
    <wsp:PolicyReference URI="#WSHttpBinding_IProxyService_policy" />
    <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="GetOneMessage">
      <soap12:operation soapAction="Services.Messaging/ISubscribe/GetOneMessage" style="document" />
      <wsdl:input name="GetOneMessageRequest">
        <soap12:body use="literal" />
      </wsdl:input>
      <wsdl:output name="GetOneMessageResponse">
        <soap12:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
</wsdl:binding>

I am using wsdl2java to generate the client interface and client beans, then I use JaxWsProxyFactoryBean to construct the actual client.

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(IProxyService.class);
factory.setAddress("http://localhost:8080/myservice");
IProxyService client = (IProxyService) factory.create();

The soap messages generated are SOAP 1.1 messages, not SOAP 1.2. In order to get SOAP 1.2 messages, I have to add the following line:

factory.setBindingId("http://schemas.xmlsoap.org/wsdl/soap12/");

Why does my client not know that it needs to use SOAP 1.2 unless I specify that binding id?

Thanks,
John

RE: WSDL to Java and SOAP 1.2

Posted by John Hite <jh...@appsecinc.com>.
Thanks for all the help.

The NullPointerException and the wsdl operation input/output problems are the same thing, so I only filed one bug.

https://issues.apache.org/jira/browse/CXF-2546

Thanks for clearing up my confusion about the catalog feature. We'll have to write a utility to generate the wsdl's from the .NET service, since .NET doesn't seem to provide a nice way of generating the wsdl.

I'll try calling setServiceName/setEndpointName methods on the factory.

Thanks again,
John

-----Original Message-----
From: Daniel Kulp [mailto:dkulp@apache.org] 
Sent: Tuesday, November 17, 2009 2:21 PM
To: users@cxf.apache.org
Cc: John Hite
Subject: Re: WSDL to Java and SOAP 1.2

On Tue November 17 2009 11:05:58 am John Hite wrote:
> Hi Dan,
> 
> I upgraded to cxf 2.2.4 and tried calling factory.setWsdlLocation(...).
>  That did make it use SOAP 1.2 and it also applied the policy. I assumed
>  that the ws-* information would be somehow preserved in the generated java
>  code, so I didn't think to provide the wsdl.

The SOAP 1.2 thing SHOULD have been via a @SOAPBinding annotation on the 
generated code.   I'm not sure why that isn't working.   That may have been a 
bug.


> On another note, I've had a lot of problems trying to make CXF work with
>  the wsdl my .NET 3.0 service provides. I have yet to be able to use the
>  wsdl without modifying it by hand.
> 
> The first problem I had was generating the bindings using wsdl2java. I use
>  .net's svcutil to pull the wsdl out of my service contract. This generates
>  a wsdl and several xsd files. The wsdl has a schema section that looks
>  like this:
> 
> <xsd:schema targetNamespace=" Services/Imports">
>       <xsd:import namespace=" Services" />
> 	<xsd:import namespace="Services.Interface" />
>       <xsd:import namespace="Services.Messaging" />
>       <xsd:import
>  namespace="http://schemas.microsoft.com/2003/10/Serialization/" />
>  <xsd:import
>  namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
>  <xsd:import namespace="http://schemas.datacontract.org/2004/07/System" />
>  </xsd:schema>

That SERIOUSLY looks like a bug in .NET.   If it's importing them, they should 
have schemaLocations defined OR the schemas should be inline in the wsdl.  


> Notice there is no schemaLocation attribute, so wsdl2java failed. I thought
>  I could solve this with a catalog file, so I created a catalog file like
>  so:

No.  The catalog is to map from one location to another.  In this case, there 
isn't a location so nothing to map.
 
> Now that I was able to generate the bindings, I tried creating my service
>  and calling factory.setWsdlLocation(...). This caused an error
.....
> In the WSDL, my portType was named "IProxyService" and my service
>  definition was named "ProxyService". CXF doesn't seem to like this for
>  some reason. I had to change my service definition name to
>  "IProxyServiceService" to get passed this.

You need to call the setServiceName/setEndpointName  methods on the factory to 
names in the wsdl.   The interface that you use only represents (and thus has 
annotations for) the portType, not the service/port.   Thus, you need to 
specify those.    That said, you could consider using the generated Service 
object that probably has a getIProxyService method that would do most of the 
work for you.


> Next I got a strange NullPointerException.

Can you send the stack trace.  That definitely shouldn't have occurred.  
Please log a JIRA (and a test case would be great)

> I debugged through the CXF code
>  till I found the problem. My wsdl uses ws-addressing. The wsdl operations
>  looked like this
> 
> <wsdl:operation name="GetStatus">
>       <wsdl:input wsam:Action="Services/IProxyService/GetStatus"
>  message="tns:IProxyService_GetStatus_InputMessage" /> <wsdl:output
>  wsam:Action="Services/IProxyService/GetStatusResponse"
>  message="tns:IProxyService_GetStatus_OutputMessage" /> </wsdl:operation>
> 
> The wsam namespace was set to
>  http://www.w3.org/2007/05/addressing/metadata, which CXF did not
>  recognize, so it couldn't figure out what the Action should be. I changed
>  it to http://www.w3.org/2006/05/addressing/wsdl and then everything
>  worked.

Hmm...  we're only checking based on that namespace in the policies, not the 
attributes on the wsdl input/output.   That would be a bug.    Could you log 
that as well?

Thanks!
Dan


> 
> This has been incredibly frustrating. Am I just doing this all wrong or do
>  other people have similar problems?
> 
> Any help is greatly appreciated.
> 
> Thanks,
> John
> 
> -----Original Message-----
> From: Daniel Kulp [mailto:dkulp@apache.org]
> Sent: Monday, November 16, 2009 9:55 AM
> To: users@cxf.apache.org
> Cc: John Hite
> Subject: Re: WSDL to Java and SOAP 1.2
> 
> 
> What happens if you call factory.setWsdlLocation(....) with the location of
> the wsdl?   Does that then make it send soap 1.2 properly?    (Also, try
>  with 2.2.4)
> 
> Doing that may actually be important.   I notice your binding has a policy
> reference in it.   Without the wsdl location set, the policy would not be
> applied.  Without seeing the policy, I'm not sure how important that is.
> 
> Dan
> 
> On Fri November 13 2009 1:34:00 pm John Hite wrote:
> > Hi,
> >
> > I am trying to write a client using cxf-2.2 for a SOAP 1.2 service. The
> >  wsdl has soap 1.2 binding configuration like this
> >
> > <wsdl:binding name="WSHttpBinding_IProxyService"
> > type="tns:IProxyService"> <wsp:PolicyReference
> > URI="#WSHttpBinding_IProxyService_policy" /> <soap12:binding
> > transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation
> > name="GetOneMessage">
> >       <soap12:operation
> >  soapAction="Services.Messaging/ISubscribe/GetOneMessage"
> > style="document" /> <wsdl:input name="GetOneMessageRequest">
> >         <soap12:body use="literal" />
> >       </wsdl:input>
> >       <wsdl:output name="GetOneMessageResponse">
> >         <soap12:body use="literal" />
> >       </wsdl:output>
> >     </wsdl:operation>
> > </wsdl:binding>
> >
> > I am using wsdl2java to generate the client interface and client beans,
> >  then I use JaxWsProxyFactoryBean to construct the actual client.
> >
> > JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
> > factory.setServiceClass(IProxyService.class);
> > factory.setAddress("http://localhost:8080/myservice");
> > IProxyService client = (IProxyService) factory.create();
> >
> > The soap messages generated are SOAP 1.1 messages, not SOAP 1.2. In order
> >  to get SOAP 1.2 messages, I have to add the following line:
> >
> > factory.setBindingId("http://schemas.xmlsoap.org/wsdl/soap12/");
> >
> > Why does my client not know that it needs to use SOAP 1.2 unless I
> > specify that binding id?
> >
> > Thanks,
> > John
> 

-- 
Daniel Kulp
dkulp@apache.org
http://www.dankulp.com/blog

Re: WSDL to Java and SOAP 1.2

Posted by Daniel Kulp <dk...@apache.org>.
On Tue November 17 2009 11:05:58 am John Hite wrote:
> Hi Dan,
> 
> I upgraded to cxf 2.2.4 and tried calling factory.setWsdlLocation(...).
>  That did make it use SOAP 1.2 and it also applied the policy. I assumed
>  that the ws-* information would be somehow preserved in the generated java
>  code, so I didn't think to provide the wsdl.

The SOAP 1.2 thing SHOULD have been via a @SOAPBinding annotation on the 
generated code.   I'm not sure why that isn't working.   That may have been a 
bug.


> On another note, I've had a lot of problems trying to make CXF work with
>  the wsdl my .NET 3.0 service provides. I have yet to be able to use the
>  wsdl without modifying it by hand.
> 
> The first problem I had was generating the bindings using wsdl2java. I use
>  .net's svcutil to pull the wsdl out of my service contract. This generates
>  a wsdl and several xsd files. The wsdl has a schema section that looks
>  like this:
> 
> <xsd:schema targetNamespace=" Services/Imports">
>       <xsd:import namespace=" Services" />
> 	<xsd:import namespace="Services.Interface" />
>       <xsd:import namespace="Services.Messaging" />
>       <xsd:import
>  namespace="http://schemas.microsoft.com/2003/10/Serialization/" />
>  <xsd:import
>  namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
>  <xsd:import namespace="http://schemas.datacontract.org/2004/07/System" />
>  </xsd:schema>

That SERIOUSLY looks like a bug in .NET.   If it's importing them, they should 
have schemaLocations defined OR the schemas should be inline in the wsdl.  


> Notice there is no schemaLocation attribute, so wsdl2java failed. I thought
>  I could solve this with a catalog file, so I created a catalog file like
>  so:

No.  The catalog is to map from one location to another.  In this case, there 
isn't a location so nothing to map.
 
> Now that I was able to generate the bindings, I tried creating my service
>  and calling factory.setWsdlLocation(...). This caused an error
.....
> In the WSDL, my portType was named "IProxyService" and my service
>  definition was named "ProxyService". CXF doesn't seem to like this for
>  some reason. I had to change my service definition name to
>  "IProxyServiceService" to get passed this.

You need to call the setServiceName/setEndpointName  methods on the factory to 
names in the wsdl.   The interface that you use only represents (and thus has 
annotations for) the portType, not the service/port.   Thus, you need to 
specify those.    That said, you could consider using the generated Service 
object that probably has a getIProxyService method that would do most of the 
work for you.


> Next I got a strange NullPointerException.

Can you send the stack trace.  That definitely shouldn't have occurred.  
Please log a JIRA (and a test case would be great)

> I debugged through the CXF code
>  till I found the problem. My wsdl uses ws-addressing. The wsdl operations
>  looked like this
> 
> <wsdl:operation name="GetStatus">
>       <wsdl:input wsam:Action="Services/IProxyService/GetStatus"
>  message="tns:IProxyService_GetStatus_InputMessage" /> <wsdl:output
>  wsam:Action="Services/IProxyService/GetStatusResponse"
>  message="tns:IProxyService_GetStatus_OutputMessage" /> </wsdl:operation>
> 
> The wsam namespace was set to
>  http://www.w3.org/2007/05/addressing/metadata, which CXF did not
>  recognize, so it couldn't figure out what the Action should be. I changed
>  it to http://www.w3.org/2006/05/addressing/wsdl and then everything
>  worked.

Hmm...  we're only checking based on that namespace in the policies, not the 
attributes on the wsdl input/output.   That would be a bug.    Could you log 
that as well?

Thanks!
Dan


> 
> This has been incredibly frustrating. Am I just doing this all wrong or do
>  other people have similar problems?
> 
> Any help is greatly appreciated.
> 
> Thanks,
> John
> 
> -----Original Message-----
> From: Daniel Kulp [mailto:dkulp@apache.org]
> Sent: Monday, November 16, 2009 9:55 AM
> To: users@cxf.apache.org
> Cc: John Hite
> Subject: Re: WSDL to Java and SOAP 1.2
> 
> 
> What happens if you call factory.setWsdlLocation(....) with the location of
> the wsdl?   Does that then make it send soap 1.2 properly?    (Also, try
>  with 2.2.4)
> 
> Doing that may actually be important.   I notice your binding has a policy
> reference in it.   Without the wsdl location set, the policy would not be
> applied.  Without seeing the policy, I'm not sure how important that is.
> 
> Dan
> 
> On Fri November 13 2009 1:34:00 pm John Hite wrote:
> > Hi,
> >
> > I am trying to write a client using cxf-2.2 for a SOAP 1.2 service. The
> >  wsdl has soap 1.2 binding configuration like this
> >
> > <wsdl:binding name="WSHttpBinding_IProxyService"
> > type="tns:IProxyService"> <wsp:PolicyReference
> > URI="#WSHttpBinding_IProxyService_policy" /> <soap12:binding
> > transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation
> > name="GetOneMessage">
> >       <soap12:operation
> >  soapAction="Services.Messaging/ISubscribe/GetOneMessage"
> > style="document" /> <wsdl:input name="GetOneMessageRequest">
> >         <soap12:body use="literal" />
> >       </wsdl:input>
> >       <wsdl:output name="GetOneMessageResponse">
> >         <soap12:body use="literal" />
> >       </wsdl:output>
> >     </wsdl:operation>
> > </wsdl:binding>
> >
> > I am using wsdl2java to generate the client interface and client beans,
> >  then I use JaxWsProxyFactoryBean to construct the actual client.
> >
> > JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
> > factory.setServiceClass(IProxyService.class);
> > factory.setAddress("http://localhost:8080/myservice");
> > IProxyService client = (IProxyService) factory.create();
> >
> > The soap messages generated are SOAP 1.1 messages, not SOAP 1.2. In order
> >  to get SOAP 1.2 messages, I have to add the following line:
> >
> > factory.setBindingId("http://schemas.xmlsoap.org/wsdl/soap12/");
> >
> > Why does my client not know that it needs to use SOAP 1.2 unless I
> > specify that binding id?
> >
> > Thanks,
> > John
> 

-- 
Daniel Kulp
dkulp@apache.org
http://www.dankulp.com/blog

RE: WSDL to Java and SOAP 1.2

Posted by John Hite <jh...@appsecinc.com>.
Hi Dan,

I upgraded to cxf 2.2.4 and tried calling factory.setWsdlLocation(...). That did make it use SOAP 1.2 and it also applied the policy. I assumed that the ws-* information would be somehow preserved in the generated java code, so I didn't think to provide the wsdl.

On another note, I've had a lot of problems trying to make CXF work with the wsdl my .NET 3.0 service provides. I have yet to be able to use the wsdl without modifying it by hand.

The first problem I had was generating the bindings using wsdl2java. I use .net's svcutil to pull the wsdl out of my service contract. This generates a wsdl and several xsd files. The wsdl has a schema section that looks like this:

<xsd:schema targetNamespace=" Services/Imports">
      <xsd:import namespace=" Services" />
	<xsd:import namespace="Services.Interface" />
      <xsd:import namespace="Services.Messaging" />
      <xsd:import namespace="http://schemas.microsoft.com/2003/10/Serialization/" />
      <xsd:import namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
      <xsd:import namespace="http://schemas.datacontract.org/2004/07/System" />
</xsd:schema>

Notice there is no schemaLocation attribute, so wsdl2java failed. I thought I could solve this with a catalog file, so I created a catalog file like so:

PUBLIC "Services" "Services.xsd"
PUBLIC "Services.Messaging" "Services.Messaging.xsd"
PUBLIC "Services.Interface" "Services.Interface.xsd"
PUBLIC "http://schemas.microsoft.com/2003/10/Serialization/" "schemas.microsoft.com.2003.10.Serialization.xsd"
PUBLIC "http://schemas.microsoft.com/2003/10/Serialization/Arrays" "schemas.microsoft.com.2003.10.Serialization.Arrays.xsd"
PUBLIC "http://schemas.datacontract.org/2004/07/System" "System.xsd"

And I called wsdl2java with the -catalog path/to/catalog.cat. This did not work, since the wsdl didn't validate (and it seems to validate the wsdl regardless of whether I specify the -validate flag). So I modified the wsdl and added the schemaLocation attributes. Now it compiled. I was curious if the catalog file was being used at all, so I tried calling wsdl2java again with the -catalog flag, except this time I provided bad locations for the schema files in the catalog file. The code was successfully generated. It looks like my catalog file isn't being used at all.

Now that I was able to generate the bindings, I tried creating my service and calling factory.setWsdlLocation(...). This caused an error

Nov 17, 2009 10:43:52 AM org.apache.cxf.bus.spring.BusApplicationContext getConfigResources
INFO: No cxf.xml configuration file detected, relying on defaults.
Nov 17, 2009 10:43:53 AM org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromWSDL
INFO: Creating Service {Services}IProxyServiceService from WSDL: file:/G:/ProxyService/trunk/conf/wsdl/Services.wsdl
Exception in thread "main" org.apache.cxf.service.factory.ServiceConstructionException: Could not find definition for service {Services}IProxyServiceService.
	at org.apache.cxf.wsdl11.WSDLServiceFactory.create(WSDLServiceFactory.java:126)
	at 
...

In the WSDL, my portType was named "IProxyService" and my service definition was named "ProxyService". CXF doesn't seem to like this for some reason. I had to change my service definition name to "IProxyServiceService" to get passed this.

Next I got a strange NullPointerException. I debugged through the CXF code till I found the problem. My wsdl uses ws-addressing. The wsdl operations looked like this

<wsdl:operation name="GetStatus">
      <wsdl:input wsam:Action="Services/IProxyService/GetStatus" message="tns:IProxyService_GetStatus_InputMessage" />
      <wsdl:output wsam:Action="Services/IProxyService/GetStatusResponse" message="tns:IProxyService_GetStatus_OutputMessage" />
    </wsdl:operation>

The wsam namespace was set to http://www.w3.org/2007/05/addressing/metadata, which CXF did not recognize, so it couldn't figure out what the Action should be. I changed it to http://www.w3.org/2006/05/addressing/wsdl and then everything worked.

This has been incredibly frustrating. Am I just doing this all wrong or do other people have similar problems?

Any help is greatly appreciated.

Thanks,
John

-----Original Message-----
From: Daniel Kulp [mailto:dkulp@apache.org] 
Sent: Monday, November 16, 2009 9:55 AM
To: users@cxf.apache.org
Cc: John Hite
Subject: Re: WSDL to Java and SOAP 1.2


What happens if you call factory.setWsdlLocation(....) with the location of 
the wsdl?   Does that then make it send soap 1.2 properly?    (Also, try with 
2.2.4)

Doing that may actually be important.   I notice your binding has a policy 
reference in it.   Without the wsdl location set, the policy would not be 
applied.  Without seeing the policy, I'm not sure how important that is.

Dan


On Fri November 13 2009 1:34:00 pm John Hite wrote:
> Hi,
> 
> I am trying to write a client using cxf-2.2 for a SOAP 1.2 service. The
>  wsdl has soap 1.2 binding configuration like this
> 
> <wsdl:binding name="WSHttpBinding_IProxyService" type="tns:IProxyService">
>     <wsp:PolicyReference URI="#WSHttpBinding_IProxyService_policy" />
>     <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
>     <wsdl:operation name="GetOneMessage">
>       <soap12:operation
>  soapAction="Services.Messaging/ISubscribe/GetOneMessage" style="document"
>  /> <wsdl:input name="GetOneMessageRequest">
>         <soap12:body use="literal" />
>       </wsdl:input>
>       <wsdl:output name="GetOneMessageResponse">
>         <soap12:body use="literal" />
>       </wsdl:output>
>     </wsdl:operation>
> </wsdl:binding>
> 
> I am using wsdl2java to generate the client interface and client beans,
>  then I use JaxWsProxyFactoryBean to construct the actual client.
> 
> JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
> factory.setServiceClass(IProxyService.class);
> factory.setAddress("http://localhost:8080/myservice");
> IProxyService client = (IProxyService) factory.create();
> 
> The soap messages generated are SOAP 1.1 messages, not SOAP 1.2. In order
>  to get SOAP 1.2 messages, I have to add the following line:
> 
> factory.setBindingId("http://schemas.xmlsoap.org/wsdl/soap12/");
> 
> Why does my client not know that it needs to use SOAP 1.2 unless I specify
>  that binding id?
> 
> Thanks,
> John
> 

-- 
Daniel Kulp
dkulp@apache.org
http://www.dankulp.com/blog

Re: WSDL to Java and SOAP 1.2

Posted by Daniel Kulp <dk...@apache.org>.
What happens if you call factory.setWsdlLocation(....) with the location of 
the wsdl?   Does that then make it send soap 1.2 properly?    (Also, try with 
2.2.4)

Doing that may actually be important.   I notice your binding has a policy 
reference in it.   Without the wsdl location set, the policy would not be 
applied.  Without seeing the policy, I'm not sure how important that is.

Dan


On Fri November 13 2009 1:34:00 pm John Hite wrote:
> Hi,
> 
> I am trying to write a client using cxf-2.2 for a SOAP 1.2 service. The
>  wsdl has soap 1.2 binding configuration like this
> 
> <wsdl:binding name="WSHttpBinding_IProxyService" type="tns:IProxyService">
>     <wsp:PolicyReference URI="#WSHttpBinding_IProxyService_policy" />
>     <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
>     <wsdl:operation name="GetOneMessage">
>       <soap12:operation
>  soapAction="Services.Messaging/ISubscribe/GetOneMessage" style="document"
>  /> <wsdl:input name="GetOneMessageRequest">
>         <soap12:body use="literal" />
>       </wsdl:input>
>       <wsdl:output name="GetOneMessageResponse">
>         <soap12:body use="literal" />
>       </wsdl:output>
>     </wsdl:operation>
> </wsdl:binding>
> 
> I am using wsdl2java to generate the client interface and client beans,
>  then I use JaxWsProxyFactoryBean to construct the actual client.
> 
> JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
> factory.setServiceClass(IProxyService.class);
> factory.setAddress("http://localhost:8080/myservice");
> IProxyService client = (IProxyService) factory.create();
> 
> The soap messages generated are SOAP 1.1 messages, not SOAP 1.2. In order
>  to get SOAP 1.2 messages, I have to add the following line:
> 
> factory.setBindingId("http://schemas.xmlsoap.org/wsdl/soap12/");
> 
> Why does my client not know that it needs to use SOAP 1.2 unless I specify
>  that binding id?
> 
> Thanks,
> John
> 

-- 
Daniel Kulp
dkulp@apache.org
http://www.dankulp.com/blog