-2

I'm trying to build a maven project, an OSGi bundle, which contains Webservices. I'm using JAX-WS with all the @WebService annotations to specify the webservices I have. To load these Webservices at a client location you are normally using wsgen and wsimport for exporting/importing WSDL files. I plan to use the jaxws-maven-plugin to do so, but here is the problem:

The bundle can act as a server and client at the same time. It can register itself as a client to a parent node of the same bundle (running on a different JVM/host). So this maven project/bundle defines an interface for the webservice and define an implementation class which implements this interface. Both interface and class use the @WebService annotation as usual.

@WebService
public interface Example {
    public void callMe();
}

@WebService
public class ExampleImpl implements Example {
    public void callMe() {};
}

And then somewhere in my code:

Endpoint p = Endpoint.publish(
                 "http://localhost:8080/example",
                 new ExampleImpl());    

The jaxws:wsgen goal reads the annotations and create the output files (.class files, .java files, WSDL files, depending on the configuration...). But how do I use these files during the jaxws:wsimport goal for the same mvn package run? In the same maven project I want to use this webservice, so I need to write something like this:

ExampleImplService service = new ExampleImplService();
Example port = service.getExampleImplPort();
port.callMe();

The jaxws:gen goal is running in the process-classes phase as it needs to read the compiled classes, but jaxws:import must be run in the generate-sources phase to prepare everything for compiling. And now I run in a chicken-egg problem. I need the compiled classes to generate the output files via wsgen, but I need the output files of wsgen for wsimport in the generate-sources phase of maven. My first try was to assign the jaxws:wsgen goal to the generate-sources phase as well but of course its not working as the classes are missing/not compiled yet.

What are my options to solve this problem? Should I run an antrun goal to compile some classes (namely only the classes with the @WebService annotations) prior the generate-sources phase so jaxws:wsgen can use it (in that phase), create the output files which are then used by jaxws:wsimport in the generate-sources phase? Are there other ways to solve this chicken-egg problem? Are there any other "maven ways" for compiling the server and client part of webservices in the same maven project? It should btw. run from a clean mvn clean build, so I don't want/like any solutions like "run mvn package twice to generate the webservices files first and then to compile everything else". In other words: mvn clean package should compile the whole maven project/osgi bundle.

Progman
  • 16,827
  • 6
  • 33
  • 48
  • where you define your plugin you will have to setup two separate executions, one for wsgen and the other wsimport. ...time passes... https://stackoverflow.com/questions/2158175/use-maven-to-trigger-a-wsgen-wsimport-in-a-row-using-wsdllocation – DaShaun Feb 14 '11 at 23:48
  • The solution in the other SO question assume that the "generated stubs" are not needed in the same project. However that is exactly the case in my project, so the stubs must not be generated later than in the `generate-source` phase. – Progman Feb 15 '11 at 08:02

1 Answers1

3

I have managed to solve this problem by moving the jaxsw:wsgen goal to the generate-sources phase. I use the following steps.

  1. First I compile the classes with @WebService annotations via an antrun execution, which use <javac> to compile the classes. I save the resulting .class files in a temporary directory which is deleted after I have created the client stubs.
  2. I create the WSDL file from the compiled .class files with the jaxws:wsgen goal.
  3. From the temporary directory I create the client stubs with the normal jaxws:wsimport goal.
  4. I delete the temporary directory with a second antrun execution.

The resulting pom.xml file looks as follow (only the relevant parts)

<properties>
    <tmpdirectory>${java.io.tmpdir}${file.separator}${user.name}-${project.groupId}-${project.artifactId}</tmpdirectory>
</properties>
...
        <plugin>
            <!-- clean tmp directory at every "mvn clean" -->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-clean-plugin</artifactId>
            <version>2.4.1</version>
            <configuration>
                <filesets>
                    <fileset>
                        <directory>${tmpdirectory}</directory>
                    </fileset>
                </filesets>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.6</version>
            <dependencies>
                  <dependency>
                      <groupId>com.sun</groupId>
                      <artifactId>tools</artifactId>
                      <version>1.6.0</version>
                      <scope>system</scope>
                      <systemPath>${java.home}/../lib/tools.jar</systemPath>
                  </dependency>
            </dependencies>  
            <executions>
                <execution>
                    <!-- compile webservice classes into tmp directory -->
                    <id>mini compile of webservices</id>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>run</goal>
                    </goals>
                    <configuration>
                        <target>
                            <property name="compile_classpath" refid="maven.compile.classpath"/>
                            <mkdir dir="${tmpdirectory}" />
                            <javac includeAntRuntime="false"
                                   classpath="${compile_classpath}"
                                   destdir="${tmpdirectory}">
                                <src path="${project.build.sourceDirectory}" />
                                <include name="org/example/project/*/webservice/*.java" />
                            </javac>
                        </target>
                    </configuration>
                </execution>
                <execution>
                    <!-- delete temporary directory (in case mvn clean is not called) -->
                    <id>clean up tmp dir</id>
                    <phase>process-sources</phase>
                    <goals>
                        <goal>run</goal>
                    </goals>
                    <configuration>
                        <target>
                            <delete dir="${tmpdirectory}" />
                        </target>
                    </configuration>
                </execution>
            </executions>  
        </plugin>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxws-maven-plugin</artifactId>
            <version>1.10</version>
            <executions>
                <execution>
                    <!-- generate WSDL file from the compiled classes in tmp directory -->
                    <id>generate wsdl file</id>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>wsgen</goal>
                    </goals>
                    <configuration>
                        <sei><!-- service endpoint implementation  --></sei>
                        <destDir>${tmpdirectory}</destDir>
                        <genWsdl>true</genWsdl>
                        <resourceDestDir>${tmpdirectory}</resourceDestDir>
                    </configuration>
                </execution>
                <execution>
                    <!-- create client stub files -->
                    <id>create client files from wsdl file</id>
                    <goals>
                        <goal>wsimport</goal>
                    </goals>
                    <configuration>
                        <keep>true</keep>
                        <wsdlDirectory>${tmpdirectory}</wsdlDirectory>
                    </configuration>
                </execution>
            </executions>
        </plugin>
Progman
  • 16,827
  • 6
  • 33
  • 48