Maven build of annotated JAXB 2.2.4-1 Web Service fails with JDK 1.6
Using Maven 3.0.3 to build a web service using JAXB (2.2.4-1) and CXF 2.4.2 fails with the following error:
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.3.2:compile (default-compile) on project cxfmaventest: Compilation failure
/Users/ksuda/Documents/workspace/cxfmaventest/src/main/java/cxfmaventest/CXFMavenTest.java:[18,83] annotation type not applicable to this kind of declaration
The line that fails contains an @XMLElement(required = true)
that by JAXB is allowed to be on a method argument. JDK 1.6 includes a previous version of @XMLElement that is not allowed to be on a method argument. This means it is a pathing issue with it finding the @XMLElement from the JDK's bootclasspath instead of finding it first in the dependencies list before looking in the JDK classes.
The source files build fine in Eclipse, where it seems to put the dependencies before the JDK classes.
I have tried using compilerArguments
and either bootclasspath
or -Xbootclasspath/p:
in the pom.xml to pickup the jaxb-api jar file before the jdk classes, but neither seems to include it with the command line options when I build with mvn -X clean compile
. I also tried to change which maven-compiler-plugin version it used, but from the -X
it didn't change it.
I created a stripped down project to demonstrate the error. You should only need the first two files to replicate. The other files are included as a working sample assuming the build works that exposes a web service using a standalone jetty web service and spring.
CXFMavenText.java:
package cxfmaventest;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlElement;
import org.springframework.stereotype.Service;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;
@WebService(targetNamespace = "http:/cxfmaventest/", name = "CXFMavenTest")
@Service("cxfmaventestws")
public class CXFMavenTest extends SpringBeanAutowiringSupport {
@WebMethod
@WebResult(name = "test")
public String getHelloWorld(@WebParam(mode = WebParam.Mode.IN, name = "mode") @XmlElement(required = true) String mode) throws Exception {
return "Hello World";
}
}
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cxfmaventest</groupId>
<artifactId>cxfmaventest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>cxfmaventest</name>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind开发者_高级运维</groupId>
<artifactId>jaxb-xjc</artifactId>
<version>2.2.4-1</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.4-1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-bundle</artifactId>
<version>2.4.2</version>
</dependency>
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>2.2.5</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>7.4.2.v20110526</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin></artifactId>
<version>2.3.2</version>
<configuration>
<compilerVersion>1.6</compilerVersion>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin></artifactId>
<version>2.8</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
</plugins>
</build>
</project>
applicationContet.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<context:component-scan base-package="cxfmaventest" />
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint id="ws" implementor="#cxfmaventestws" address="/">
<jaxws:features>
<!-- <bean class="org.apache.cxf.feature.LoggingFeature"/> -->
</jaxws:features>
</jaxws:endpoint>
<context:annotation-config />
</beans>
WEB-INF/web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>CXFMavenTest</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
</web-app>
CXFMavenTextStandalone.java:
package cxfmaventest;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;
public class CXFMavenTestStandalone {
public static void main(String[] args) {
try {
String root = ".";
String port = "8080";
for (int x = 0; x < args.length; ++x) {
if (args[x].startsWith("-root=")) {
root = args[x].substring(6);
} else if (args[x].startsWith("-port=")) {
port = args[x].substring(6);
} else {
System.out.println("Arguments:");
System.out.println(" -root=<path> - Set the root path for the webapp files. Defaults to the current directory.");
System.out.println(" -port=<port#> - Set the port number to run the server on. Defaults to port 8080.");
System.exit(1);
}
}
Server server = new Server(Integer.parseInt(port));
WebAppContext context = new WebAppContext();
context.setDescriptor(root + "/WEB-INF/web.xml");
context.setResourceBase(root);
context.setContextPath("/cxfmaventest");
context.setParentLoaderPriority(true);
server.setHandler(context);
server.start();
server.join();
} catch (Throwable ex) {
ex.printStackTrace();
}
}
}
It is a typo. There is an >
at the end of the plugin artifactId. The correct code for prepending the JAXB jar before the classes is (replace the plugin section in the POM.XML in the question with this):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<compilerArgument>-Xbootclasspath/p:${settings.localRepository}/javax/xml/bind/jaxb-api/2.2.3/jaxb-api-2.2.3.jar</compilerArgument>
<compilerVersion>1.6</compilerVersion>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
There is probably a better way to identify the correct jar to prepend the bootclasspath with, but this at least works.
Thanks!
精彩评论