1

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

1 回答 1

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>
于 2012-05-02T03:59:23.600 回答