build-helper-maven-plugin 导致 AnnotationTypeMismatchException
我正在使用 JAXB 从 java 类生成模式。该模式又由 WSDL 文档引用。例如,我有一个 common-ws-data 项目。 common-ws-data 项目包含一个“FaultMessage”对象;看起来像这样:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "FaultMessage",namespace="urn:ws.mycorp.com:common:faults", propOrder = {"message"})
public class FaultMessage {
@XmlElement(required = true, nillable = true)
protected String message;
/**
* @return the message
*/
public String getMessage() {
return message;
}
/**
* @param message the message to set
*/
public void setMessage(String message) {
this.message = message;
}
这通过 JAXB 生成一个模式;生成的模式如下所示:
<xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" version="1.0" targetNamespace="urn:ws.mycorp.com:common:faults" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="FaultMessage">
<xs:sequence>
<xs:element name="message" type="xs:string" nillable="true"/>
</xs:sequence>
</xs:complexType>
到目前为止一切顺利。但是,我们希望对模式和 WSDL 进行版本控制,并且网络上的各种最佳实践建议建议将版本控制信息嵌入到您的名称空间中。所以...
urn:com.mycorp.ws:common:faults
将变得
urn:com.mycorp.ws:common:faults:1.3.1
显然,这意味着将注释修改为
@XmlType(name = "FaultMessage",namespace="urn:ws.mycorp.com:common:faults:1.3.1", propOrder = {"message"})
但是,由于模式项目可能变得相当大,因此每次版本更改时都必须更新所有域对象上的注释是不切实际的。所以我的想法是以某种方式从 Maven POM 文件中提取版本信息并将该值连接到默认名称空间。
为此,我编写了自己的 Maven 插件,它将创建一个“ProjectConstants”类,该类将各种 Maven 项目属性公开为公共最终字符串字段;即:
public final class ProjectConstants {
public static final String ARTIFACT_ID="common-ws-data";
public static final String GROUP_ID="com.mycorp";
public static final String VERSION="1.3.1";
}
注释现在可以变成:
@XmlType(name = "FaultMessage",namespace="urn:ws.mycorp.com:common:faults:" + ProjectConstants.VERSION, propOrder = {"message"})
如果生成的 ProjectConstants 类放置在与FaultMessage java 文件相同的源路径中(即 src/main/java),则效果很好。
但是,如果我有我的插件在不同的源路径中生成 ProjectConstants 类;例如:/target/ generated/maven;然后通过builder-helper-maven-plugin将生成的源文件夹添加为额外的源文件夹,maven编译过程会因AnnotationTypeMismatchException而崩溃。
这是 builder-helper-maven-plugin 的 Maven 配置。基本上非常标准:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>target/generated/maven</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
这是我们得到的例外:
Problem encountered during annotation processing;
see stacktrace below for more information.
java.lang.annotation.AnnotationTypeMismatchException: Incorrectly typed data found for annotation element public abstract java.lang.String javax.xml.bind.annotation.XmlType.namespace() (Found data of type java.lang.String)
at com.sun.tools.apt.mirror.declaration.AnnotationProxyMaker$ValueVisitor$1.generateException(AnnotationProxyMaker.java:241)
at sun.reflect.annotation.AnnotationInvocationHandler.invoke(AnnotationInvocationHandler.java:56)
at $Proxy3.namespace(Unknown Source)
at com.sun.xml.bind.v2.model.annotation.XmlTypeQuick.namespace(XmlTypeQuick.java:36)
at com.sun.xml.bind.v2.model.impl.TypeInfoImpl.parseTypeName(TypeInfoImpl.java:152)
at com.sun.xml.bind.v2.model.impl.ClassInfoImpl.<init>(ClassInfoImpl.java:169)
at com.sun.xml.bind.v2.model.impl.ModelBuilder.createClassInfo(ModelBuilder.java:339)
at com.sun.xml.bind.v2.model.impl.ModelBuilder.getClassInfo(ModelBuilder.java:239)
at com.sun.xml.bind.v2.model.impl.ModelBuilder.getClassInfo(ModelBuilder.java:209)
at com.sun.xml.bind.v2.model.impl.ModelBuilder.getTypeInfo(ModelBuilder.java:315)
at com.sun.xml.bind.v2.model.impl.ModelBuilder.getTypeInfo(ModelBuilder.java:330)
at com.sun.tools.xjc.api.impl.j2s.JavaCompilerImpl.bind(JavaCompilerImpl.java:90)
at com.sun.tools.jxc.apt.SchemaGenerator$1.process(SchemaGenerator.java:115)
at com.sun.mirror.apt.AnnotationProcessors$CompositeAnnotationProcessor.process(AnnotationProcessors.java:60)
at com.sun.tools.apt.comp.Apt.main(Apt.java:454)
at com.sun.tools.apt.main.JavaCompiler.compile(JavaCompiler.java:258)
at com.sun.tools.apt.main.Main.compile(Main.java:1102)
at com.sun.tools.apt.main.Main.compile(Main.java:964)
at com.sun.tools.apt.Main.processing(Main.java:95)
at com.sun.tools.apt.Main.process(Main.java:85)
at com.sun.tools.apt.Main.process(Main.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.tools.jxc.AptBasedTask$InternalAptAdapter.execute(AptBasedTask.java:97)
at com.sun.tools.jxc.AptBasedTask.compile(AptBasedTask.java:144)
at com.sun.tools.jxc.maven2.SchemaGenAdapter.execute(SchemaGenAdapter.java:111)
at com.sun.tools.jxc.maven2.SchemaGenMojo.execute(SchemaGenMojo.java:161)
at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:490)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:694)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLifecycle(DefaultLifecycleExecutor.java:556)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:535)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:387)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:348)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:180)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:328)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:138)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:362)
at org.apache.maven.cli.compat.CompatibleMain.main(CompatibleMain.java:60)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
[INFO] ----------------------------------- ------------------------------------------------ [错误]致命错误
我怀疑这是某种类加载器问题... @XmlType 注释的 namespace() 属性的类型是 java.lang。细绳;显然“urn:com.mycorp.ws:common:faults”和ProjectConstants.VERSION的串联也是一个字符串;所以原则上它应该有效;如果我将 ProjectConstants 放在 /src/main/java 中,它肯定有效。所以我怀疑发生的事情是 builder-helper-maven-plugin 在读取 /src/main/java 后以某种方式修改类路径;然后触发 AnnotationTypeMismatchException。
关于如何解决这个问题有什么想法吗?
I'm using JAXB to generate a schema from a java class. The schema, in turn, is referenced by a WSDL document. so for instance, I have a common-ws-data project. The common-ws-data project contains a "FaultMessage" object; which looks like this:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "FaultMessage",namespace="urn:ws.mycorp.com:common:faults", propOrder = {"message"})
public class FaultMessage {
@XmlElement(required = true, nillable = true)
protected String message;
/**
* @return the message
*/
public String getMessage() {
return message;
}
/**
* @param message the message to set
*/
public void setMessage(String message) {
this.message = message;
}
this generates a schema through JAXB; and the resulting schema looks like this:
<xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" version="1.0" targetNamespace="urn:ws.mycorp.com:common:faults" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="FaultMessage">
<xs:sequence>
<xs:element name="message" type="xs:string" nillable="true"/>
</xs:sequence>
</xs:complexType>
So far so good. However, we want to version our schemas and WSDLs, and various best practice suggestions around the web suggest embedding the versioning info into your namespace. So...
urn:com.mycorp.ws:common:faults
would become
urn:com.mycorp.ws:common:faults:1.3.1
Obviously, this means modifying the annotation to
@XmlType(name = "FaultMessage",namespace="urn:ws.mycorp.com:common:faults:1.3.1", propOrder = {"message"})
However, since the schema project can get quite large, it's impractical to have to update the annotations on ALL of your domain objects each time your version changes. So the idea I had was to somehow pull version information from the maven POM file and concatenate this value onto the default namespace.
To that end, I wrote my own maven plugin which will create a "ProjectConstants" class which exposes various maven project attributes as public final String fields; i.e.:
public final class ProjectConstants {
public static final String ARTIFACT_ID="common-ws-data";
public static final String GROUP_ID="com.mycorp";
public static final String VERSION="1.3.1";
}
The annotation can now become:
@XmlType(name = "FaultMessage",namespace="urn:ws.mycorp.com:common:faults:" + ProjectConstants.VERSION, propOrder = {"message"})
This works fine if the generated ProjectConstants class is placed in the same source path as the FaultMessage java file (i.e. src/main/java)
However, IF I have my plugin generate the ProjectConstants class in a different source path; for example: /target/generated/maven; and then add the generated source folder as an extra source folder via the builder-helper-maven-plugin, the maven compilation process blows up with an AnnotationTypeMismatchException.
Here is the maven configuration for the builder-helper-maven-plugin. Pretty standard, basically:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>target/generated/maven</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
Here is the exception we get:
Problem encountered during annotation processing;
see stacktrace below for more information.
java.lang.annotation.AnnotationTypeMismatchException: Incorrectly typed data found for annotation element public abstract java.lang.String javax.xml.bind.annotation.XmlType.namespace() (Found data of type java.lang.String)
at com.sun.tools.apt.mirror.declaration.AnnotationProxyMaker$ValueVisitor$1.generateException(AnnotationProxyMaker.java:241)
at sun.reflect.annotation.AnnotationInvocationHandler.invoke(AnnotationInvocationHandler.java:56)
at $Proxy3.namespace(Unknown Source)
at com.sun.xml.bind.v2.model.annotation.XmlTypeQuick.namespace(XmlTypeQuick.java:36)
at com.sun.xml.bind.v2.model.impl.TypeInfoImpl.parseTypeName(TypeInfoImpl.java:152)
at com.sun.xml.bind.v2.model.impl.ClassInfoImpl.<init>(ClassInfoImpl.java:169)
at com.sun.xml.bind.v2.model.impl.ModelBuilder.createClassInfo(ModelBuilder.java:339)
at com.sun.xml.bind.v2.model.impl.ModelBuilder.getClassInfo(ModelBuilder.java:239)
at com.sun.xml.bind.v2.model.impl.ModelBuilder.getClassInfo(ModelBuilder.java:209)
at com.sun.xml.bind.v2.model.impl.ModelBuilder.getTypeInfo(ModelBuilder.java:315)
at com.sun.xml.bind.v2.model.impl.ModelBuilder.getTypeInfo(ModelBuilder.java:330)
at com.sun.tools.xjc.api.impl.j2s.JavaCompilerImpl.bind(JavaCompilerImpl.java:90)
at com.sun.tools.jxc.apt.SchemaGenerator$1.process(SchemaGenerator.java:115)
at com.sun.mirror.apt.AnnotationProcessors$CompositeAnnotationProcessor.process(AnnotationProcessors.java:60)
at com.sun.tools.apt.comp.Apt.main(Apt.java:454)
at com.sun.tools.apt.main.JavaCompiler.compile(JavaCompiler.java:258)
at com.sun.tools.apt.main.Main.compile(Main.java:1102)
at com.sun.tools.apt.main.Main.compile(Main.java:964)
at com.sun.tools.apt.Main.processing(Main.java:95)
at com.sun.tools.apt.Main.process(Main.java:85)
at com.sun.tools.apt.Main.process(Main.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.tools.jxc.AptBasedTask$InternalAptAdapter.execute(AptBasedTask.java:97)
at com.sun.tools.jxc.AptBasedTask.compile(AptBasedTask.java:144)
at com.sun.tools.jxc.maven2.SchemaGenAdapter.execute(SchemaGenAdapter.java:111)
at com.sun.tools.jxc.maven2.SchemaGenMojo.execute(SchemaGenMojo.java:161)
at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:490)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:694)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLifecycle(DefaultLifecycleExecutor.java:556)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:535)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:387)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:348)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:180)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:328)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:138)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:362)
at org.apache.maven.cli.compat.CompatibleMain.main(CompatibleMain.java:60)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
[INFO] ------------------------------------------------------------------------
[ERROR] FATAL ERROR
I suspect it's some kind of class-loader problem... the type of the namespace() attribute of the @XmlType annotation IS java.lang.String; and obviously the concatenation of "urn:com.mycorp.ws:common:faults" and ProjectConstants.VERSION is a string as well; so it should work, in principle; and it definitely works if I put ProjectConstants in /src/main/java. So I suspect what's happening is that builder-helper-maven-plugin is somehow modifying the classpath AFTER /src/main/java has already been read; which then triggers the AnnotationTypeMismatchException.
Any ideas on how to get around this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您使用 com.sun.tools.xjc.maven2:maven-jaxb-plugin 为什么您不调整执行顺序来编译您的接口,然后运行 jaxb 编译器,然后编译您的最终代码。
有一种更简单的方法:只需将您的界面移动到另一个 jar(工件)并让您依赖它。这样编译顺序就会很自然。
玩得开心。
You use com.sun.tools.xjc.maven2:maven-jaxb-plugin why you just don't tweak execution order to make compilation of your interfaces and then run jaxb compiler and then compile you final code.
There's one easier way : just move your interface to another jar (artifact) and make your dependent on it. So that compilation order will be natural.
Have fun.