Groovy初学者指南

Posted booksea

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Groovy初学者指南相关的知识,希望对你有一定的参考价值。

Groovy是一种基于Java平台的动态编程语言,它结合了Python、Ruby和Smalltalk等语言的特性,同时与Java无缝集成。

本文已收录至Github,推荐阅读

在 Groovy/Gradle 构建上使用 JPA 复合键时,Spock 测试失败

【中文标题】在 Groovy/Gradle 构建上使用 JPA 复合键时,Spock 测试失败【英文标题】:Spock test fails when using JPA Composite Key on Groovy/Gradle build 【发布时间】:2017-11-25 20:17:23 【问题描述】:

我开发了一个 Spring Boot WebApplication,它接收带有一些数据的soap请求并将其保存到数据库中。 由于我是 Spring Boot 和 JPA 的初学者,因此我使用了一种常见的 JPA 配置,其中主键是 JPA 管理的 Id。

@Table(
        name="MyEntity",
        uniqueConstraints=@UniqueConstraint(columnNames=["channel", "service"])
)
public class MyEntity 

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    Long id
    String channel
    String service

我开发了一套关于保存、搜索和修改实体的 Spock 测试,一切运行顺利。 具体来说,我有一个 Spring Boot 应用程序冒烟测试,以确保配置正确加载

@ContextConfiguration
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class ApplicationContextSpec extends Specification 

    @Autowired
    WebApplicationContext context

    def "should boot up without errors"() 
        expect: "(web) application context exists"
        context != null
    
 

由于自然键是渠道和服务,我尝试定义一个复合键

@Table(name="MyEntity")
@IdClass(MyEntityPk.class)
public class MyEntity 

    @Id
    String channel
    @Id
    String service

连同主键类(摘录)

public class MyEntityPk implements Serializable 
    String channel
    String service



@ContextConfiguration
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class ApplicationContextSpec extends Specification 

    @Autowired
    WebApplicationContext context

    def "should boot up without errors"() 
        expect: "(web) application context exists"
        context != null
    

此更改后,Spring Boot 应用程序冒烟测试失败

java.lang.IllegalStateException: Failed to load ApplicationContext
...
Caused by: org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
...
Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.

以及所有其他与 jpa 相关的测试。 作为进一步的信息,我选择了 Spring Boot gs-accessing-data-jpa-master 示例并将其适配为使用 gradle 和 spock。然后我修改为使用复合键,Spring Boot 应用程序冒烟测试按预期成功。 在我的 Ws Web 应用程序(使用依赖 spring-boot-starter-web-services)上,有些东西会导致失败。我想指出,唯一的变化是从自动生成的键移动到复合键。 这会导致找不到 EmbeddedServletContainerFactory。您对此事有什么建议吗?

我也在发布 che build 脚本,相当复杂,所以我添加了一些 cmets 来阐明实现

buildscript 
    ext 
        springBootVersion = '1.5.2.RELEASE'
    
    repositories 
        mavenCentral()
    
    dependencies 
        classpath("org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion")
    


apply plugin: 'groovy'
apply plugin: 'org.springframework.boot'

// I am using a mixed environment with some java generated source code
// and mainly groovy classes. This sourceSets definition forces to compile
// everything with groovy compiler so that java classes see groovy classes
sourceSets 
    main 
        groovy 
            srcDirs = ['src/main/groovy', 'src/main/java']
        
        java 
            srcDirs = []
        
    

    test 
        groovy 
            srcDirs = ['src/test/groovy','src/test/java']
        
        java 
            srcDirs = []
        
    


repositories 
    mavenCentral()


// This task defines a jaxb task that takes xsd schema definition
// and generates java classes used when mapping soap requests
task genJaxb 
    ext.sourcesDir = "$buildDir/generated-sources/jaxb"
    ext.classesDir = "$buildDir/classes/jaxb"
    ext.schema = "src/main/resources/myws.xsd"

    outputs.dir classesDir

    doLast() 
        project.ant 
            taskdef name: "xjc", classname: "com.sun.tools.xjc.XJCTask",
                    classpath: configurations.jaxb.asPath
            mkdir(dir: sourcesDir)
            mkdir(dir: classesDir)

            xjc(destdir: sourcesDir, schema: schema) 
                arg(value: "-wsdl")
                produces(dir: sourcesDir, includes: "**/*.java")
            

            javac(destdir: classesDir, source: 1.6, target: 1.6, debug: true,
                    debugLevel: "lines,vars,source",
                    classpath: configurations.jaxb.asPath) 
                src(path: sourcesDir)
                include(name: "**/*.java")
                include(name: "*.java")
            

            copy(todir: classesDir) 
                fileset(dir: sourcesDir, erroronmissingdir: false) 
                    exclude(name: "**/*.java")
                
            
        
    


configurations 
    jaxb


sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies 
    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    compile("org.springframework.boot:spring-boot-starter-web-services")
    compile('org.springframework.boot:spring-boot-starter-actuator')
    compile("org.codehaus.groovy:groovy-all:2.4.7")
    compile("wsdl4j:wsdl4j:1.6.1")
    compile(files(genJaxb.classesDir).builtBy(genJaxb))
    runtime('com.h2database:h2')
    jaxb("org.glassfish.jaxb:jaxb-xjc:2.2.11")
    testCompile 'org.springframework.boot:spring-boot-starter-test'
    testCompile 'org.spockframework:spock-spring:1.0-groovy-2.4'
    testCompile 'cglib:cglib-nodep:3.2.5'



jar 
    baseName = 'myws'
    version =  '0.7.1'
    excludes = ['**/application.yml']
    from sourceSets.main.output
    // adding jaxb generated file to be included in jar
    from('build/classes/jaxb') 
        include '**'
    


// this defines a uber-jar so that I may launch spring server 
// from command line using java -jar myws-spring-boot.jar
task('execJar', type:Jar, dependsOn: 'jar') 
    baseName = 'myws'
    version =  '0.7.1'
    classifier = 'spring-boot'
    from sourceSets.main.output
    from('build/classes/jaxb') 
        include '**'
    



bootRepackage  
    withJarTask = tasks['execJar']

最后,我要做的就是:

gradlew build

构建 jar 并运行测试,然后

java -jar myws-spring-boot.jar

启动 Spring Boot 服务器

【问题讨论】:

你用的是什么版本的spock和spring?请发布您的 build.gradle 构建相当复杂,我将其添加到我的问题中 请尝试更新到 spock 1.1,并发布您的应用程序配置,可能您的问题出在***.com/questions/21783391/… 【参考方案1】:

烟雾测试无法正常工作,因为从“Long id”字段作为主键移动时,我没有执行所有必需的更改

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
Long id

@Id
String channel
@Id
String service

我忘记删除存储库类中引用“Long id”字段的方法。在按照 Leonard Brünings 的建议迁移到 spring-spock 1.1 后,我收到了更详细的错误消息,指出了正确的方向。

Error creating bean with name 'modelEntryRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property id found for type ModelEntryEntity!

所以我删除了引用(存储库接口中的方法声明)并且冒烟测试成功结束。 顺便说一句,在 build.gradle 中,我必须显式添加 spock 核心,所以我不得不输入 spring-spock 1.0 而不是一行

testCompile 'org.spockframework:spock-core:1.1-groovy-2.4'
testCompile 'org.spockframework:spock-spring:1.1-groovy-2.4'

【讨论】:

以上是关于Groovy初学者指南的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 参考指南 - 从 app.groovy 示例中获取 404

Spock单元测试框架实战指南十 - 注意事项

Linux 中的逻辑卷 LVM 管理完整初学者指南

Grails - 将数据添加到 bootstrap.groovy 时不会打开 localhost

ElasticSearch 初学者指南 [关闭]

致Python初学者:Anaconda入门使用指南