【问题标题】:Unable to create web service bean with Grails and CXF Plugin无法使用 Grails 和 CXF 插件创建 Web 服务 bean
【发布时间】:2026-02-05 20:00:02
【问题描述】:

我正在尝试使用 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

【问题讨论】:

    标签: web-services grails groovy cxf


    【解决方案1】:

    查看 cxf 插件信息页面我发现了这个:

        Note that any classes being returned or passed as parameters 
        must be annotated with @XmlAccessorType(XmlAccessType.FIELD)
    
        @XmlAccessorType(XmlAccessType.FIELD)
        class Person {
           ....
        }
    

    -----编辑----- 这个让我很困扰,因为它应该很简单。我不知道你是否让它工作,但这是我必须做的:

        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 = {
            }
        }
    

    它会抛出与任何 XmlAccessorType 相同的错误,但 NONE 除外。然后为了获得可用的字段,我必须添加 @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>
    

    【讨论】:

    • 我也遇到过,但似乎没有任何效果。即使添加了注解,也会出现同样的异常。
    • 这个调整对我来说非常有效,谢谢。我有点困惑为什么这是必要的,我搜索的每个论坛条目都简单地说添加 @XmlAccessorType(XmlAccessor.FIELD) 可以解决这个问题。我希望这只是这个版本的 CXF 的一个小故障,但谁知道呢。
    • 这听起来绝对像一个错误。除了FIELD之外,我找不到任何东西......
    最近更新 更多