You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Mordecus <si...@thinkingphones.com> on 2012/01/10 20:39:15 UTC

CXF-java2wsdl-plugin not importing external schema defined in @XmlSchema annotation

I'm using the cxf-java2ws-plugin to generate a WSDL file from JAX-WS
annotated classes. For my data objects; I'm specifying the fact that an
external schema file already exists (by adding an @XmlSchema annotation with
a location attribute to the package-info.java file). When the WSDL file gets
generated; the namespace for the imported schema is declared; but the schema
file itself is never imported. This results in a malformed schema.

My plugin configuration is as follows:

<plugin>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-java2ws-plugin</artifactId>
    <version>2.4.2</version>
    <dependencies>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>2.4.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-simple</artifactId>
            <version>2.4.2</version>
        </dependency>
    </dependencies>

    <executions>
        <execution>
            <id>process-classes</id>
            <phase>process-classes</phase>
            <configuration>
                <className>com.mycorp.hello.HelloWebService</className>
                <genWsdl>true</genWsdl>
                <verbose>true</verbose>
               
<outputFile>${basedir}/src/main/webapp/WEB-INF/wsdl/HelloWebService.wsdl</outputFile>
            </configuration>
            <goals>
                <goal>java2ws</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Here is an example of the package-info.java file:

@javax.xml.bind.annotation.XmlSchema(location="http://localhost:16899/schema/model.xsd",
namespace="urn:ws.mycorp.com:hello:model")
package com.mycorp.hello.model;

Here is the pre-existing schema file:

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:ws.mycorp.com:hello:model"
xmlns:tns="urn:ws.mycorp.com:hello:model" elementFormDefault="qualified">
    <complexType name="MessageObject">
    <sequence>
        <element name="message" nillable="true" type="string"></element>
    </sequence>
    </complexType>
</schema>

Here is the generated schema:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:ns1="urn:ws.mycorp.com:hello:model"
xmlns:tns="http://hello.mycorp.com/" elementFormDefault="unqualified"
targetNamespace="http://hello.mycorp.com/" version="1.0">
<xs:import namespace="urn:ws.mycorp.com:hello:model"/>
<xs:element name="getHelloMessage" type="tns:getHelloMessage"/>
<xs:element name="getHelloMessageResponse"
type="tns:getHelloMessageResponse"/>
<xs:complexType name="getHelloMessage">
    <xs:sequence>
      <xs:element minOccurs="0" name="name" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
<xs:complexType name="getHelloMessageResponse">
    <xs:sequence>
      <xs:element minOccurs="0" name="return" type="ns1:messageObject"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

Note how the "urn:ws.mycorp.com:hello:model" namespace is declared and
imported but is lacking the actual schema location
(http://localhost:16899/schema/model.xsd). As a result, the generated schema
has an error since ns1:messageObject cannot be found.

Obviously, I could manually modify the generated schema; but this becomes a
nuisance since I'd have to do it every time the code is modified... and in a
real world scenario (I put together this simple test case to illustrate the
problem), there might be more than 1 pre-existing schema file.

EDIT:After doing a bit more research on this, I believe the problem is that
JAXB requires a catalog file:

http://jaxb.java.net/guide/Fixing_broken_references_in_schema.html

The catalog file would allow JAXB to resolve the existing namespace
(urn:ws.mycorp.com:hello:model) to an actual location. Unfortunately, the
java2ws cxf tool seems to lack options to customize the JAXB databinding
process:

http://cxf.547215.n5.nabble.com/jira-Resolved-CXF-1693-Allow-custom-Jaxb-databinding-in-java2ws-just-like-in-wsdl2java-td4787407.html

And the documentation from jaxb that indicates how to pass the catalog file
assumes jaxb is getting invoked directly(either via ant/maven or the command
line CLI tool); which isn't the case with java2ws...

--
View this message in context: http://cxf.547215.n5.nabble.com/CXF-java2wsdl-plugin-not-importing-external-schema-defined-in-XmlSchema-annotation-tp5135016p5135016.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: CXF-java2wsdl-plugin not importing external schema defined in @XmlSchema annotation

Posted by Daniel Kulp <dk...@apache.org>.
On Monday, March 12, 2012 05:57:16 AM arikgold wrote:
> Hi Dan,
> 
> Is there any intention to extend java2ws for supporting customized jaxb
> binding
> Specifically specifying catalog file?

Java2WS should already pick up an existing META-INF/jax-ws-catalog.xml file 
since it pretty much uses the same mechanisms as the runtime.   Beyond that, 
patches would be welcome.  :-)

Dan


> 
> Thanks,
> Arik
> 
> --
> View this message in context:
> http://cxf.547215.n5.nabble.com/CXF-java2wsdl-plugin-not-importing-extern
> al-schema-defined-in-XmlSchema-annotation-tp5135016p5557643.html Sent from
> the cxf-user mailing list archive at Nabble.com.
-- 
Daniel Kulp
dkulp@apache.org - http://dankulp.com/blog
Talend Community Coder - http://coders.talend.com


Re: CXF-java2wsdl-plugin not importing external schema defined in @XmlSchema annotation

Posted by arikgold <go...@gmail.com>.
Hi Dan, 

Is there any intention to extend java2ws for supporting customized jaxb
binding
Specifically specifying catalog file?

Thanks, 
Arik

--
View this message in context: http://cxf.547215.n5.nabble.com/CXF-java2wsdl-plugin-not-importing-external-schema-defined-in-XmlSchema-annotation-tp5135016p5557643.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: CXF-java2wsdl-plugin not importing external schema defined in @XmlSchema annotation

Posted by Daniel Kulp <dk...@apache.org>.

I'm testing a fix for this now.   Basically, when jaxb generates the schemas, 
it more or less creates 'temporary' schemaLocations in the schemas. (like 
schema1.xsd, schema2.xsd, etc...)    Since we inline everything in the wsdl, 
we strip them out.   However, we're stripping out all the locations, not just 
the temporary ones.   I've fixed that.

HOWEVER (and this is important), we have to process the generated schema as we 
don't know if we need to add wrapper elements, we need to get the "types" 
out,etc...   Thus, if "http://localhost:8080/jaxws-example-ws/xsd/example.xsd" 
is not resolvable when you run "mvn install", it will fail.     I was able to 
get around that by adding a catalog in:

src/main/resources/META-INF/jax-ws-catalog.xml

that contains:
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system">
    <rewriteURI 
    uriStartString="http://localhost:8080/jaxws-example-ws/xsd/example.xsd" 
rewritePrefix="file:/tmp/t2/jaxws-example-
ws/src/main/webapp/xsd/example.xsd"/>
</catalog>

to re-write the location to a local file on disk during processing. 

In anycase, tonights snapshots should fix this.


Dan


On Monday, January 16, 2012 12:34:21 PM Mordecus wrote:
> Hi Daniel, I've put together a little test case.
> 
> If you download the zip archive at this link:
> 
> http://dl.dropbox.com/u/24296192/JAXWSExample.zip
> 
> You will find two maven projects inside. The first one, jaxws-example-model,
> contains a simple Java POJO called "Message". The project contains the
> necessary JAXWS annotations to control how the schema for this object gets
> generated; and it specifies the location of an external schema file; like
> so:
> 
> @XmlSchema(namespace="urn:ws.example.com:model",
> location="http://localhost:8080/jaxws-example-ws/xsd/example.xsd")
> package com.example.model;
> import javax.xml.bind.annotation.XmlSchema;
> 
> 
> Note that the POM file of the project has the JAXB plugin so that the schema
> file can be re-generated if required (although that would require removing
> the location attribute from the @XmlSchema annotation again; as JAXB will
> ignore any packages that have that).
> 
> The second project, jaxws-example-ws, is the actual webservice. It has a
> dependency on jaxws-example-data; so you will have to run a mvn install on
> that project first in order for compilation to work. The webservice is
> rigged up in the src/main/resources/spring/appContext.xml file; like so:
> 
> <jaxws:endpoint
> 	  id="exampleWebService"
> 	  implementor="#exampleService"
> 	  implementorClass="com.example.ws.ExampleWebServiceImpl"
> 	  address="/ExampleService"
> 
> 
> I'm also using the cxf-java2ws-plugin in the POM file to generate a static
> WSDL file at /src/main/wsdl/ExampleWebService.wsdl. This WSDL is identical
> to the one generated on the fly by CXF if you start the application; so in
> both cases the behavior is similar.
> 
> If you look at the WSDL; you'll see that the urn:ws.example.com:model schema
> is imported; but no schemaLocation is specified; which results in a
> malformed WSDL.
> 
> 
> 
> I guess I should have also explained what I'm actually trying to do. Our
> company is implementing a full SOA approach; including the use of ESBs and
> WS-BPEL. As we're offering a full fledged API to our customers; we're
> finding that a lot of our webservices re-use the same underlying domain
> objects. We don't want each webservice have it's own embedded schema
> definitions for these domain objects; because, among other things, it causes
> problems when using BPEL. So the idea was to have a foundation of schema's
> describing domain objects (users, accounts, etc, etc) and then having the
> various webservice wsdls reference those.
> 
> With a contract-first approach, this is of course perfectly possible; and
> that's in fact what we're doing right now. But given number of webservice
> operations we're implementing, WSDL first is turning out to be quite
> cumbersome and time-consuming. A Java-first approach would allow us to roll
> out webservices quicker; while retaining full control over the form of the
> generated WSDL by using the JAXWS annotations.
> 
> It's still a less than ideal situation; as you can see - we need to remove
> the location attribute from the XMLSchema annotation to have JAXB generate
> the external schema; then add it back in to avoid having the
> cxf-java2ws-plugin generate the schema when the WSDL is generated; but it's
> workable.
> 
> I suppose the ultimate solution would be something similar to what's
> possible with the wsdl2java plugin and the -nexclude argument that can be
> added into the WSDLOption of the plugin... if we could somehow tell the
> cxf-java2ws-plugin that when it encounters the schema urn:com.example.model,
> it should NOT generate a schema in the WSDL but instead import an external
> schema at http://localhost/jaxws-example-ws/xsd/example.xsd; that would
> really be the perfect solution; i.e something like:
> 
> <plugin>
> 		    <groupId>org.apache.cxf</groupId>
> 		    <artifactId>cxf-java2ws-plugin</artifactId>
> 		    <version>${cxf.version}</version>
> 		    <dependencies>
> 		        <dependency>
> 		            <groupId>org.apache.cxf</groupId>
> 		            <artifactId>cxf-rt-frontend-jaxws</artifactId>
> 		            <version>${cxf.version}</version>
> 		        </dependency>
> 		        <dependency>
> 		            <groupId>org.apache.cxf</groupId>
> 		            <artifactId>cxf-rt-frontend-simple</artifactId>
> 		            <version>${cxf.version}</version>
> 		        </dependency>
> 		    </dependencies>
> 
> 		    <executions>
> 		        <execution>
> 		            <id>process-classes</id>
> 		            <phase>process-classes</phase>
> 		            <configuration>
> 		                
<className>com.example.ws.ExampleWebService</className>
> 		                <genWsdl>true</genWsdl>
> 		                <verbose>true</verbose>
> 
> <outputFile>${basedir}/src/main/wsdl/ExampleWebService.wsdl</outputFile>
>                                 *<extraargs>
>                                       <extraarg>-nexclude</extraarg>
> 
> <extraarg>urn:ws.example.com:model=http://localhost/jaxws-example-ws/xsd/exa
> mple.xsd</extraarg> </extraargs>*
> 		            </configuration>
> 		            <goals>
> 		                <goal>java2ws</goal>
> 		            </goals>
> 		        </execution>
> 		    </executions>
> 		</plugin>
> 
> But I don't know how hard that is to implement....
> 
> --
> View this message in context:
> http://cxf.547215.n5.nabble.com/CXF-java2wsdl-plugin-not-importing-external
> -schema-defined-in-XmlSchema-annotation-tp5135016p5149809.html Sent from the
> cxf-user mailing list archive at Nabble.com.
-- 
Daniel Kulp
dkulp@apache.org - http://dankulp.com/blog
Talend Community Coder - http://coders.talend.com

Re: CXF-java2wsdl-plugin not importing external schema defined in @XmlSchema annotation

Posted by "Avner.Levy" <av...@gmail.com>.
I had the same problem with the location attribute and used javassist tools
for removing the location attribute on the fly from the generated package
when running the xsd generation. This way you don't need to mess with the
source code. Just an idea ;-)

--
View this message in context: http://cxf.547215.n5.nabble.com/CXF-java2wsdl-plugin-not-importing-external-schema-defined-in-XmlSchema-annotation-tp5135016p5709350.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: CXF-java2wsdl-plugin not importing external schema defined in @XmlSchema annotation

Posted by Mordecus <si...@thinkingphones.com>.
Hi Daniel, I've put together a little test case.

If you download the zip archive at this link:

http://dl.dropbox.com/u/24296192/JAXWSExample.zip

You will find two maven projects inside. The first one, jaxws-example-model,
contains a simple Java POJO called "Message". The project contains the
necessary JAXWS annotations to control how the schema for this object gets
generated; and it specifies the location of an external schema file; like
so:

@XmlSchema(namespace="urn:ws.example.com:model",
location="http://localhost:8080/jaxws-example-ws/xsd/example.xsd")
package com.example.model;
import javax.xml.bind.annotation.XmlSchema;


Note that the POM file of the project has the JAXB plugin so that the schema
file can be re-generated if required (although that would require removing
the location attribute from the @XmlSchema annotation again; as JAXB will
ignore any packages that have that).

The second project, jaxws-example-ws, is the actual webservice. It has a
dependency on jaxws-example-data; so you will have to run a mvn install on
that project first in order for compilation to work. The webservice is
rigged up in the src/main/resources/spring/appContext.xml file; like so:

<jaxws:endpoint 
	  id="exampleWebService" 
	  implementor="#exampleService" 
	  implementorClass="com.example.ws.ExampleWebServiceImpl"
	  address="/ExampleService"
	 >

I'm also using the cxf-java2ws-plugin in the POM file to generate a static
WSDL file at /src/main/wsdl/ExampleWebService.wsdl. This WSDL is identical
to the one generated on the fly by CXF if you start the application; so in
both cases the behavior is similar.

If you look at the WSDL; you'll see that the urn:ws.example.com:model schema
is imported; but no schemaLocation is specified; which results in a
malformed WSDL.



I guess I should have also explained what I'm actually trying to do. Our
company is implementing a full SOA approach; including the use of ESBs and
WS-BPEL. As we're offering a full fledged API to our customers; we're
finding that a lot of our webservices re-use the same underlying domain
objects. We don't want each webservice have it's own embedded schema
definitions for these domain objects; because, among other things, it causes
problems when using BPEL. So the idea was to have a foundation of schema's
describing domain objects (users, accounts, etc, etc) and then having the
various webservice wsdls reference those. 

With a contract-first approach, this is of course perfectly possible; and
that's in fact what we're doing right now. But given number of webservice
operations we're implementing, WSDL first is turning out to be quite
cumbersome and time-consuming. A Java-first approach would allow us to roll
out webservices quicker; while retaining full control over the form of the
generated WSDL by using the JAXWS annotations. 

It's still a less than ideal situation; as you can see - we need to remove
the location attribute from the XMLSchema annotation to have JAXB generate
the external schema; then add it back in to avoid having the
cxf-java2ws-plugin generate the schema when the WSDL is generated; but it's
workable. 

I suppose the ultimate solution would be something similar to what's
possible with the wsdl2java plugin and the -nexclude argument that can be
added into the WSDLOption of the plugin... if we could somehow tell the
cxf-java2ws-plugin that when it encounters the schema urn:com.example.model,
it should NOT generate a schema in the WSDL but instead import an external
schema at http://localhost/jaxws-example-ws/xsd/example.xsd; that would
really be the perfect solution; i.e something like:

<plugin>
		    <groupId>org.apache.cxf</groupId>
		    <artifactId>cxf-java2ws-plugin</artifactId>
		    <version>${cxf.version}</version>
		    <dependencies>
		        <dependency>
		            <groupId>org.apache.cxf</groupId>
		            <artifactId>cxf-rt-frontend-jaxws</artifactId>
		            <version>${cxf.version}</version>
		        </dependency>
		        <dependency>
		            <groupId>org.apache.cxf</groupId>
		            <artifactId>cxf-rt-frontend-simple</artifactId>
		            <version>${cxf.version}</version>
		        </dependency>
		    </dependencies>
		
		    <executions>
		        <execution>
		            <id>process-classes</id>
		            <phase>process-classes</phase>
		            <configuration>
		                <className>com.example.ws.ExampleWebService</className>
		                <genWsdl>true</genWsdl>
		                <verbose>true</verbose>
		               
<outputFile>${basedir}/src/main/wsdl/ExampleWebService.wsdl</outputFile>
                                *<extraargs>
                                      <extraarg>-nexclude</extraarg>
                                     
<extraarg>urn:ws.example.com:model=http://localhost/jaxws-example-ws/xsd/example.xsd</extraarg>
                                </extraargs>*
		            </configuration>
		            <goals>
		                <goal>java2ws</goal>
		            </goals>
		        </execution>
		    </executions>
		</plugin>

But I don't know how hard that is to implement....

--
View this message in context: http://cxf.547215.n5.nabble.com/CXF-java2wsdl-plugin-not-importing-external-schema-defined-in-XmlSchema-annotation-tp5135016p5149809.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: CXF-java2wsdl-plugin not importing external schema defined in @XmlSchema annotation

Posted by Mordecus <si...@thinkingphones.com>.
I can probably rig something up over the weekend, Daniel. I'd have to trim
some of the fat as I have a full fledged application I'm trying this in; but
I can probably trim some of the fat and simplify it. Gimme a day or two and
I'll get something to you.

--
View this message in context: http://cxf.547215.n5.nabble.com/CXF-java2wsdl-plugin-not-importing-external-schema-defined-in-XmlSchema-annotation-tp5135016p5143114.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: CXF-java2wsdl-plugin not importing external schema defined in @XmlSchema annotation

Posted by Daniel Kulp <dk...@apache.org>.
On Tuesday, January 10, 2012 11:39:15 AM Mordecus wrote:
> I'm using the cxf-java2ws-plugin to generate a WSDL file from JAX-WS
> annotated classes. For my data objects; I'm specifying the fact that an
> external schema file already exists (by adding an @XmlSchema annotation with
> a location attribute to the package-info.java file). When the WSDL file
> gets generated; the namespace for the imported schema is declared; but the
> schema file itself is never imported. This results in a malformed schema.

Is there any way you could create a small testcase for this?   We may be able 
to look at the @XmlSchema directly ourselves and update the schemas as 
appropriate, but I'd like to see a testcase for this as I've never tried it.

Dan


> 
> My plugin configuration is as follows:
> 
> <plugin>
>     <groupId>org.apache.cxf</groupId>
>     <artifactId>cxf-java2ws-plugin</artifactId>
>     <version>2.4.2</version>
>     <dependencies>
>         <dependency>
>             <groupId>org.apache.cxf</groupId>
>             <artifactId>cxf-rt-frontend-jaxws</artifactId>
>             <version>2.4.2</version>
>         </dependency>
>         <dependency>
>             <groupId>org.apache.cxf</groupId>
>             <artifactId>cxf-rt-frontend-simple</artifactId>
>             <version>2.4.2</version>
>         </dependency>
>     </dependencies>
> 
>     <executions>
>         <execution>
>             <id>process-classes</id>
>             <phase>process-classes</phase>
>             <configuration>
>                 <className>com.mycorp.hello.HelloWebService</className>
>                 <genWsdl>true</genWsdl>
>                 <verbose>true</verbose>
> 
> <outputFile>${basedir}/src/main/webapp/WEB-INF/wsdl/HelloWebService.wsdl</ou
> tputFile> </configuration>
>             <goals>
>                 <goal>java2ws</goal>
>             </goals>
>         </execution>
>     </executions>
> </plugin>
> 
> Here is an example of the package-info.java file:
> 
> @javax.xml.bind.annotation.XmlSchema(location="http://localhost:16899/schema
> /model.xsd", namespace="urn:ws.mycorp.com:hello:model")
> package com.mycorp.hello.model;
> 
> Here is the pre-existing schema file:
> 
> <?xml version="1.0" encoding="UTF-8"?>
> <schema xmlns="http://www.w3.org/2001/XMLSchema"
> targetNamespace="urn:ws.mycorp.com:hello:model"
> xmlns:tns="urn:ws.mycorp.com:hello:model" elementFormDefault="qualified">
>     <complexType name="MessageObject">
>     <sequence>
>         <element name="message" nillable="true" type="string"></element>
>     </sequence>
>     </complexType>
> </schema>
> 
> Here is the generated schema:
> 
> <?xml version="1.0" encoding="utf-8"?>
> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
> xmlns:ns1="urn:ws.mycorp.com:hello:model"
> xmlns:tns="http://hello.mycorp.com/" elementFormDefault="unqualified"
> targetNamespace="http://hello.mycorp.com/" version="1.0">
> <xs:import namespace="urn:ws.mycorp.com:hello:model"/>
> <xs:element name="getHelloMessage" type="tns:getHelloMessage"/>
> <xs:element name="getHelloMessageResponse"
> type="tns:getHelloMessageResponse"/>
> <xs:complexType name="getHelloMessage">
>     <xs:sequence>
>       <xs:element minOccurs="0" name="name" type="xs:string"/>
>     </xs:sequence>
>   </xs:complexType>
> <xs:complexType name="getHelloMessageResponse">
>     <xs:sequence>
>       <xs:element minOccurs="0" name="return" type="ns1:messageObject"/>
>     </xs:sequence>
>   </xs:complexType>
> </xs:schema>
> 
> Note how the "urn:ws.mycorp.com:hello:model" namespace is declared and
> imported but is lacking the actual schema location
> (http://localhost:16899/schema/model.xsd). As a result, the generated schema
> has an error since ns1:messageObject cannot be found.
> 
> Obviously, I could manually modify the generated schema; but this becomes a
> nuisance since I'd have to do it every time the code is modified... and in a
> real world scenario (I put together this simple test case to illustrate the
> problem), there might be more than 1 pre-existing schema file.
> 
> EDIT:After doing a bit more research on this, I believe the problem is that
> JAXB requires a catalog file:
> 
> http://jaxb.java.net/guide/Fixing_broken_references_in_schema.html
> 
> The catalog file would allow JAXB to resolve the existing namespace
> (urn:ws.mycorp.com:hello:model) to an actual location. Unfortunately, the
> java2ws cxf tool seems to lack options to customize the JAXB databinding
> process:
> 
> http://cxf.547215.n5.nabble.com/jira-Resolved-CXF-1693-Allow-custom-Jaxb-dat
> abinding-in-java2ws-just-like-in-wsdl2java-td4787407.html
> 
> And the documentation from jaxb that indicates how to pass the catalog file
> assumes jaxb is getting invoked directly(either via ant/maven or the command
> line CLI tool); which isn't the case with java2ws...
> 
> --
> View this message in context:
> http://cxf.547215.n5.nabble.com/CXF-java2wsdl-plugin-not-importing-external
> -schema-defined-in-XmlSchema-annotation-tp5135016p5135016.html Sent from the
> cxf-user mailing list archive at Nabble.com.
-- 
Daniel Kulp
dkulp@apache.org - http://dankulp.com/blog
Talend Community Coder - http://coders.talend.com