我正在尝试使用Grails和Apache CXF创建一个Web服务,自然使用CXF-Grails插件。我创建了一个名为Test Service的简单服务
package testcxf
class TestService {
static expose = ['cxf']
String echoString(String str) {
return str
}
String reverseString(String str) {
return str.reverse()
}
}
此服务完全按预期工作,测试客户端成功调用了echo和reverse方法。接下来,我创建了一个名为Person
的简单域类package testcxf
class Person {
String name
String city
int age
static constraints = {
}
}
使用一些基本功能修改服务以与域进行交互。
package testcxf
class TestService {
static expose = ['cxf']
String echoString(String str) {
return str
}
String reverseString(String str) {
return str.reverse()
}
void addPerson(Person person) {
person.save()
}
Person getPerson(String name) {
return Person.findByName(name)
}
List<Person> getAllPeople() {
return Person.findAll()
}
}
那时它就崩溃了。当调用grails run-app时,我收到以下异常。应用程序完成了启动,但生成的wsdl不完整,缺少复杂类型Person的所有定义。
| Error 2012-05-01 20:51:03,504 [pool-7-thread-1] ERROR [localhost].[/TestCxf] - StandardWrapper.Throwable
Message: Error creating bean with name 'testServiceBean': Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.apache.cxf.endpoint.Server org.apache.cxf.frontend.ServerFactoryBean.create()] threw exception; nested exception is org.apache.cxf.service.factory.ServiceConstructionException
Line | Method
->> 578 | createApplicationContext in grails.spring.BeanBuilder
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 57 | loadAdditionalConfig in org.grails.cxf.GrailsCXFServlet
| 40 | init . . . . . . . . . . in ''
| 334 | innerRun in java.util.concurrent.FutureTask$Sync
| 166 | run . . . . . . . . . . in java.util.concurrent.FutureTask
| 1110 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 603 | run . . . . . . . . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 722 | run in java.lang.Thread
Caused by BeanDefinitionStoreException: Factory method [public org.apache.cxf.endpoint.Server org.apache.cxf.frontend.ServerFactoryBean.create()] threw exception; nested exception is org.apache.cxf.service.factory.ServiceConstructionException
->> 578 | createApplicationContext in grails.spring.BeanBuilder
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 57 | loadAdditionalConfig in org.grails.cxf.GrailsCXFServlet
| 40 | init . . . . . . . . . . in ''
| 334 | innerRun in java.util.concurrent.FutureTask$Sync
| 166 | run . . . . . . . . . . in java.util.concurrent.FutureTask
| 1110 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 603 | run . . . . . . . . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 722 | run in java.lang.Thread
Caused by ServiceConstructionException: null
->> 341 | initialize in org.apache.cxf.jaxb.JAXBDataBinding
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 86 | initializeDataBindings in org.apache.cxf.service.factory.AbstractServiceFactoryBean
| 442 | buildServiceFromClass . in org.apache.cxf.service.factory.ReflectionServiceFactoryBean
| 505 | initializeServiceModel in ''
| 242 | create . . . . . . . . . in ''
| 101 | createEndpoint in org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory
| 148 | create . . . . . . . . . in org.apache.cxf.frontend.ServerFactoryBean
| 578 | createApplicationContext in grails.spring.BeanBuilder
| 57 | loadAdditionalConfig . . in org.grails.cxf.GrailsCXFServlet
| 40 | init in ''
| 334 | innerRun . . . . . . . . in java.util.concurrent.FutureTask$Sync
| 166 | run in java.util.concurrent.FutureTask
| 1110 | runWorker . . . . . . . in java.util.concurrent.ThreadPoolExecutor
| 603 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 722 | run . . . . . . . . . . in java.lang.Thread
Caused by IllegalAnnotationsException: 5 counts of IllegalAnnotationExceptions
->> 102 | check in com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 472 | getTypeInfoSet in com.sun.xml.bind.v2.runtime.JAXBContextImpl
| 302 | <init> . . . . . . . . . in ''
| 1140 | build in com.sun.xml.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder
| 154 | createContext . . . . . in com.sun.xml.bind.v2.ContextFactory
| 121 | createContext in ''
| 248 | newInstance . . . . . . in javax.xml.bind.ContextFinder
| 235 | newInstance in ''
| 432 | find . . . . . . . . . . in ''
| 637 | newInstance in javax.xml.bind.JAXBContext
| 564 | createContext . . . . . in org.apache.cxf.jaxb.JAXBDataBinding
| 504 | createJAXBContextAndSchemas in ''
| 324 | initialize . . . . . . . in ''
| 86 | initializeDataBindings in org.apache.cxf.service.factory.AbstractServiceFactoryBean
| 442 | buildServiceFromClass . in org.apache.cxf.service.factory.ReflectionServiceFactoryBean
| 505 | initializeServiceModel in ''
| 242 | create . . . . . . . . . in ''
| 101 | createEndpoint in org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory
| 148 | create . . . . . . . . . in org.apache.cxf.frontend.ServerFactoryBean
| 578 | createApplicationContext in grails.spring.BeanBuilder
| 57 | loadAdditionalConfig . . in org.grails.cxf.GrailsCXFServlet
| 40 | init in ''
| 334 | innerRun . . . . . . . . in java.util.concurrent.FutureTask$Sync
| 166 | run in java.util.concurrent.FutureTask
| 1110 | runWorker . . . . . . . in java.util.concurrent.ThreadPoolExecutor
| 603 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 722 | run . . . . . . . . . . in java.lang.Thread
| Error 2012-05-01 20:51:03,570 [pool-7-thread-1] ERROR [localhost].[/TestCxf] - Servlet /TestCxf threw load() exception
Message: 5 counts of IllegalAnnotationExceptions
Line | Method
->> 102 | check in com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 472 | getTypeInfoSet in com.sun.xml.bind.v2.runtime.JAXBContextImpl
| 302 | <init> . . . . . . . . . . in ''
| 1140 | build in com.sun.xml.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder
| 154 | createContext . . . . . . . in com.sun.xml.bind.v2.ContextFactory
| 121 | createContext in ''
| 248 | newInstance . . . . . . . . in javax.xml.bind.ContextFinder
| 235 | newInstance in ''
| 432 | find . . . . . . . . . . . in ''
| 637 | newInstance in javax.xml.bind.JAXBContext
| 564 | createContext . . . . . . . in org.apache.cxf.jaxb.JAXBDataBinding
| 504 | createJAXBContextAndSchemas in ''
| 324 | initialize . . . . . . . . in ''
| 86 | initializeDataBindings in org.apache.cxf.service.factory.AbstractServiceFactoryBean
| 442 | buildServiceFromClass . . . in org.apache.cxf.service.factory.ReflectionServiceFactoryBean
| 505 | initializeServiceModel in ''
| 242 | create . . . . . . . . . . in ''
| 101 | createEndpoint in org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory
| 148 | create . . . . . . . . . . in org.apache.cxf.frontend.ServerFactoryBean
| 578 | createApplicationContext in grails.spring.BeanBuilder
| 57 | loadAdditionalConfig . . . in org.grails.cxf.GrailsCXFServlet
| 40 | init in ''
| 334 | innerRun . . . . . . . . . in java.util.concurrent.FutureTask$Sync
| 166 | run in java.util.concurrent.FutureTask
| 1110 | runWorker . . . . . . . . . in java.util.concurrent.ThreadPoolExecutor
| 603 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 722 | run . . . . . . . . . . . . in java.lang.Thread
答案 0 :(得分:2)
查看cxf插件信息页面,我发现了这个:
Note that any classes being returned or passed as parameters
must be annotated with @XmlAccessorType(XmlAccessType.FIELD)
@XmlAccessorType(XmlAccessType.FIELD)
class Person {
....
}
- - - - - - - - EDIT 这一次困扰了我很多,因为它应该如此简单。我不知道你有没有工作,但这就是我必须要做的事情:
package testcxf
import javax.xml.bind.annotation.*
@XmlRootElement(name="person")
@XmlAccessorType(XmlAccessType.NONE)
@XmlType(propOrder = ["name","city","age"])
class Person {
@XmlElement
String name
@XmlElement
String city
@XmlElement
int age
static constraints = {
}
}
除了NONE之外,它会抛出您使用任何XmlAccessorType接收的相同错误。然后,为了获得可用的字段,我必须添加@XmlElement注释。
现在它运行时没有错误,WSDL包含Person对象的详细信息:
<xs:element name="person" type="tns:person"/>
<xs:complexType name="person">
<xs:sequence>
<xs:element minOccurs="0" name="name" type="xs:string"/>
<xs:element minOccurs="0" name="city" type="xs:string"/>
<xs:element name="age" type="xs:int"/>
</xs:sequence>
</xs:complexType>