无法使用Grails和CXF插件创建Web服务bean

时间:2012-05-02 02:06:11

标签: web-services grails groovy cxf

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

1 个答案:

答案 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>