spring boot 1.4, spock and application.properties - spring-boot

I am trying to write some tests for my Spring Boot 1.4.0 with Spock and my application-test-properties file is not being picked up.
I have this in my gradle:
dependencies {
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.boot:spring-boot-starter-web')
compile 'org.codehaus.groovy:groovy-all:2.4.1'
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('org.spockframework:spock-spring:1.0-groovy-2.4') {
}
Then I have this in
/src/test/groovy/resources:
# JWT Key
jwt.key=MyKy#99
And finally my Spock test:
#SpringBootTest(classes = MyApplication.class, webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT)
#TestPropertySource("application-test.properties")
public class TokenUtilityTest extends Specification {
#Autowired
private TokenUtility tokenUtility
def "test a valid token creation"() {
def userDetails = new User(username: "test", password: "password", accountNonExpired: true, accountNonLocked: true,
);
when:
def token = tokenUtility.buildToken(userDetails)
then:
token != null
}
}
Which is testing this class:
#Component
public class TokenUtility {
private static final Logger LOG = LoggerFactory.getLogger( TokenUtility.class );
#Value("${jwt.key}")
private String jwtKey;
public String buildToken(UserDetails user) {
return Jwts.builder()
.setSubject(user.getUsername())
.signWith(SignatureAlgorithm.HS512, jwtKey)
.compact();
}
public boolean validate(String token) {
try {
Jwts.parser().setSigningKey(jwtKey).parseClaimsJws(token);
return true;
} catch (SignatureException e) {
LOG.error("Invalid JWT found: " + token);
}
return false;
}
}
I originally instantiated the TokenUtility on my test but the application-test.properties was never loaded (I am assuming since jwtKey was null). So I am trying #Autowired my class under test, but now that is null.
It looks like Spring Boot 1.4 changed a lot for testing, so perhaps I am not wiring this up correctly?

There are several things wrong with your test code; first, your dependencies are bad - Spock 1.0 does not support #SpringBootTest annotation so no context will be initialized and no post-processing will be done, hence the null pointer exception: nothing will be autowired.
Support for that annotation was added in Spock 1.1, which is still release-candidate, so you'll have to use that:
dependencies {
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.boot:spring-boot-starter-web')
compile group: 'io.jsonwebtoken', name: 'jjwt', version: '0.6.0'
compile('org.codehaus.groovy:groovy')
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('org.spockframework:spock-core:1.1-groovy-2.4-rc-1')
testCompile('org.spockframework:spock-spring:1.1-groovy-2.4-rc-1')
testCompile group: 'com.h2database', name: 'h2', version: '1.4.192'
}
Then, your path to the application-test.properties is wrong and should be /application-test.properties since it is in the root of the classpath:
#SpringBootTest(classes = DemoApplication.class,
webEnvironment = WebEnvironment.RANDOM_PORT)
#TestPropertySource("/application-test.properties")
public class TokenUtilityTest extends Specification {
#Autowired
TokenUtility tokenUtility
def "test a valid token creation"() {
def userDetails = new User("test", "password", Collections.emptyList());
when:
def token = tokenUtility.buildToken(userDetails)
then:
token != null
}
}

I had the similar problem, but for me, the solution was to change double quotes ".." to single quotes '..' inside the #Value annotation when working with Spock. Please find the example below:
#Value('${jwt.key}')
private String jwtKey;
PS - This is not the exact answer to the question. I am posting this for someone who faces a similar problem like mine and ends up here.

Related

Initialise MySQL Testcontainer using R2DBC and Jooq

I want to write integration test for my microservice currently using Kotlin, Jooq and R2dbc at repository level.
I want my test to work in R2dbc mode as well, but for some reason getting this exception:
Caused by: org.testcontainers.containers.JdbcDatabaseContainer$NoDriverFoundException: Could not get Driver
at org.testcontainers.containers.JdbcDatabaseContainer.getJdbcDriverInstance(JdbcDatabaseContainer.java:187)
at org.testcontainers.containers.JdbcDatabaseContainer.createConnection(JdbcDatabaseContainer.java:209)
at org.testcontainers.containers.JdbcDatabaseContainer.waitUntilContainerStarted(JdbcDatabaseContainer.java:147)
at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:466)
... 10 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
Probably, I have to point somewhere that I want to use r2dbc only, not jdbc? I've seen the specs but not sure whether I applied TC_INITSCRIPT and TC_IMAGE_TAG correctly.
I don't use Spring Data r2dbc (jooq only), that's why ResourceDatabasePopulator is not an option for me.
My test looks like:
#SpringBootTest(classes = [UserServiceApp::class])
#ActiveProfiles(profiles = ["test"])
#AutoConfigureWebTestClient
class UserServiceAppIT(#Autowired val client: WebTestClient) {
#Nested
inner class Find {
#Test
#DisplayName("Find existing user by id")
fun `existing user credentials returns OK`() {
val expectedUser = getCredentialsUser() //this is a class with expected data
val response = client.get()
.uri("/user/2") //this is my endpoint
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectStatus().isOk
.expectBody(UserCredentialsModel::class.java)
.returnResult()
.responseBody
assertThat(response)
.isNotNull
.isEqualTo(expectedUser)
}
}
Test config in yaml file:
server.port: 8080
spring:
application:
name: User Service Test
r2dbc:
url: r2dbc:tc:mysql:///pharmacy?TC_IMAGE_TAG=8.0.26&TC_INITSCRIPT=classpath/resources/init.sql
password: root
username: root
pool:
initial-size: 1
max-size: 10
max-idle-time: 30m
Dependencies (gradle):
buildscript {
ext {
springDependencyVersion = '1.0.11.RELEASE'
springBootVersion = '2.5.3'
kotlinVersion = '1.5.0'
jooqPluginVersion = '6.0'
springdocVersion = '1.5.10'
r2dbcMySQLVersion = '0.8.2.RELEASE'
r2dbcPoolVersion = '0.8.7.RELEASE'
mockKVersion = '1.12.0'
kotestVersion = '4.4.3'
kotlinJsonVersion = '1.2.1'
kotlinDateVersion = '0.2.1'
testcontainersVersion = '1.16.0'
}
}
It is easy to integrate Jooq with R2dbc.
#Configuration
class JooqConfig {
#Bean
fun dslContext(connectionFactory: ConnectionFactory) =
using(TransactionAwareConnectionFactoryProxy(connectionFactory), SQLDialect.POSTGRES)
}
NOTE: Do not include Jooq starter if you are using Spring 2.7.x. The Jooq autoconfiguration only supports Jdbc.
An example using Jooq.
class PostRepositoryImpl(private val dslContext: DSLContext) : PostRepositoryCustom {
override fun findByKeyword(title: String): Flow<PostSummary> {
val sql = dslContext
.select(
POSTS.ID,
POSTS.TITLE,
field("count(comments.id)", SQLDataType.BIGINT)
)
.from(
POSTS
.leftJoin(COMMENTS.`as`("comments"))
.on(COMMENTS.POST_ID.eq(POSTS.ID))
)
.where(
POSTS.TITLE.like("%$title%")
.and(POSTS.CONTENT.like("%$title%"))
.and(COMMENTS.CONTENT.like("%$title%"))
)
.groupBy(POSTS.ID)
return Flux.from(sql)
.map { r -> PostSummary(r.value1(), r.value2(), r.value3()) }
.asFlow();
}
override suspend fun countByKeyword(title: String): Long {
val sql = dslContext
.select(
DSL.field("count(distinct(posts.id))", SQLDataType.BIGINT)
)
.from(
POSTS
.leftJoin(COMMENTS.`as`("comments"))
.on(COMMENTS.POST_ID.eq(POSTS.ID))
)
.where(
POSTS.TITLE.like("%$title%")
.and(POSTS.CONTENT.like("%$title%"))
.and(COMMENTS.CONTENT.like("%$title%"))
)
return Mono.from(sql).map { it.value1() ?: 0 }.awaitSingle()
}
}
TestContainers database requires a Jdbc driver, add MySQL Jdbc driver with testcontainter into your test scope.
The following is an example using Postgres and Testcontainers.
#OptIn(ExperimentalCoroutinesApi::class)
#Testcontainers
#DataR2dbcTest()
#Import(JooqConfig::class, R2dbcConfig::class)
class PostRepositoriesTest {
companion object {
private val log = LoggerFactory.getLogger(PostRepositoriesTest::class.java)
#Container
val postgreSQLContainer = PostgreSQLContainer("postgres:12")
.withCopyFileToContainer(
MountableFile.forClasspathResource("/init.sql"),
"/docker-entrypoint-initdb.d/init.sql"
)
#JvmStatic
#DynamicPropertySource
fun registerDynamicProperties(registry: DynamicPropertyRegistry) {
registry.add("spring.r2dbc.url") {
"r2dbc:postgresql://${postgreSQLContainer.host}:${postgreSQLContainer.firstMappedPort}/${postgreSQLContainer.databaseName}"
}
registry.add("spring.r2dbc.username") { postgreSQLContainer.username }
registry.add("spring.r2dbc.password") { postgreSQLContainer.password }
}
}
#Autowired
lateinit var postRepository: PostRepository
#Autowired
lateinit var dslContext: DSLContext
#BeforeEach
fun setup() = runTest {
log.info(" clear sample data ...")
val deletedPostsCount = Mono.from(dslContext.deleteFrom(POSTS)).awaitSingle()
log.debug(" deletedPostsCount: $deletedPostsCount")
}
#Test
fun `query sample data`() = runTest {
log.debug(" add new sample data...")
val insertPostSql = dslContext.insertInto(POSTS)
.columns(POSTS.TITLE, POSTS.CONTENT)
.values("jooq test", "content of Jooq test")
.returningResult(POSTS.ID)
val postId = Mono.from(insertPostSql).awaitSingle()
log.debug(" postId: $postId")
val insertCommentSql = dslContext.insertInto(COMMENTS)
.columns(COMMENTS.POST_ID, COMMENTS.CONTENT)
.values(postId.component1(), "test comments")
.values(postId.component1(), "test comments 2")
val insertedCount = Mono.from(insertCommentSql).awaitSingle()
log.info(" insertedCount: $insertedCount")
val querySQL = dslContext
.select(
POSTS.TITLE,
POSTS.CONTENT,
multiset(
select(COMMENTS.CONTENT)
.from(COMMENTS)
.where(COMMENTS.POST_ID.eq(POSTS.ID))
).`as`("comments")
)
.from(POSTS)
.orderBy(POSTS.CREATED_AT)
Flux.from(querySQL).asFlow()
.onEach { log.info("querySQL result: $it") }
.collect()
val posts = postRepository.findByKeyword("test").toList()
posts shouldNotBe null
posts.size shouldBe 1
posts[0].commentsCount shouldBe 2
postRepository.countByKeyword("test") shouldBe 1
}
// other tests
My example project is based Postgres, R2dbc, And Spring Data R2dbc: https://github.com/hantsy/spring-r2dbc-sample/blob/master/jooq-kotlin-co-gradle

NoSuchMethodException QueryDSL with Spring Boot & Spring Data Mongo

I am trying to implement Query DSL on my Spring Boot 2.0.4.RELEASE app that uses Spring Data Mongo 2.0.4.RELEASE & Gradle 4.10.
I am using Spring Tool Suite for running it locally.
Did the following steps which I found from multiple sources including Spring data documentation:
created gradle/querydsl.gradle which has below content to generate Q classes
apply plugin: "com.ewerk.gradle.plugins.querydsl"
sourceSets {
main {
java {
srcDir "$buildDir/generated/source/apt/main"
}
}
}
querydsl {
springDataMongo = true
querydslSourcesDir = "$buildDir/generated/source/apt/main"
}
dependencies {
compile "com.querydsl:querydsl-mongodb:4.1.4"
compileOnly "com.querydsl:querydsl-apt:4.1.4"
}
sourceSets.main.java.srcDirs = ['src/main/java']
Calling above gradle file from main build.gradle as shown below
buildscript {
ext { springBootVersion = "2.0.4.RELEASE" }
repositories { mavenCentral() }
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
classpath "gradle.plugin.com.ewerk.gradle.plugins:querydsl-plugin:1.0.9"
}
}
plugins {
id "java"
id "eclipse"
id "org.springframework.boot" version "2.0.4.RELEASE"
id "io.spring.dependency-management" version "1.0.6.RELEASE"
}
sourceCompatibility = 1.8
repositories { mavenCentral() }
dependencies {
...
compile("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")
compile("org.springframework.boot:spring-boot-starter-data-mongodb:${springBootVersion}")
...
}
apply from: 'gradle/querydsl.gradle'
/* Added this because Eclipse was not able to find generated classes */
sourceSets.main.java.srcDirs = ['build/generated/source/apt/main','src/main/java']
compileJava.dependsOn processResources
processResources.dependsOn cleanResources
After this updated the Repository annotated interface as below. Note: I also use Fragment Repository FragmentOrderRepository for some custom queries.
public interface OrderRepository<D extends OrderDAO>
extends EntityRepository<D>, PagingAndSortingRepository<D, String>, FragmentOrderRepository<D>, QuerydslPredicateExecutor<D> {}
Then in controller created a GET mapping as shown here
#RestController
public class OrderController {
#GetMapping(value="/orders/dsl", produces = { "application/json" })
public ResponseEntity<List> getOrdersDSL(#QuerydslPredicate(root = OrderDAO.class) Predicate predicate, Pageable pageable, #RequestParam final MultiValueMap<String, String> parameters) {
return (ResponseEntity<List>) orderService.getTools().getRepository().findAll(predicate, pageable);
}
}
Then in my runner class I added EnableSpringDataWebSupport annotation
#SpringBootApplication
#EnableSpringDataWebSupport
public class SampleApp {
public static void main(String[] args) {
SpringApplication.run(SampleApp.class, args);
}
}
With this my app starts up without any errors but when I try hitting the path http://localhost:5057/orders/dsl?email=test#test.com
I get a NoSuchMethodException with message No primary or default constructor found for interface com.querydsl.core.types.Predicate.
Can anyone please help with some pointers to solve this issue?
It seems that parameters are not getting resolved to a type.
---- UPDATE 09/19/19 ----
While debugging I found that a class HandlerMethodArgumentResolverComposite which finds ArgumentResolver for given MethodParameter from a List of argumentResolvers(of type HandlerMethodArgumentResolver). This list does not contain QuerydslPredicateArgumentResolver. Hence it is not able to resolve the arguments.
This means QuerydslWebConfiguration which adds above resolver for Predicate type is not getting called, which in turn indicates that some AutoConfiguration is not happening.
Probably I am missing some annotation here.
Found the mistake I was doing, was missing EnableWebMvc annotation on my Configuration annotated class.
Details are in this documentation.

Circular view path [error] while json output expected in springboot

newbie to Springboot with gradle, I am creating a restful service which queries the db2 database and returns the result in json.
The desired output
{
resource: {
results: [
{
currencyCode: "JPY",
conversionRateToUSD: "0.010286580",
conversionRateFromUSD: "97.214040040",
startDate: "2011-01-01",
endDate: "2011-01-29"
}
]
}
}
The api i am trying to build is http://localhost:8080/apis/exchange-rates/referenceDate=2015-01-01&currencyCode=JPY
I have created the below controller class
#RestController
#Slf4j
#RequestMapping("/apis")
public class IndividualExchangeRateController {
#Autowired
private IndividualExchangeRateService individualExchangeRateService;
public IndividualExchangeRateController(IndividualExchangeRateService individualExchangeRateService) {
this.individualExchangeRateService = individualExchangeRateService;
}
#RequestMapping(value = "/exchange-rates", method = RequestMethod.GET)
#ResponseStatus(HttpStatus.OK)
public #ResponseBody IndividualResource getIndividual(#RequestParam("referenceDate") #DateTimeFormat(pattern = "YYYY-MM-DD")Date referenceDate,
#RequestParam(value = "currencyCode", required = false) String currencyCode){
try {
System.out.println("Inside Controller");
return individualExchangeRateService.getIndividualExchangeRate(referenceDate, currencyCode);
}
catch (HttpClientErrorException e){
throw new InvalidRequestException(e.getMessage());
}
}
}
I am getting the below error when i call the api
javax.servlet.ServletException: Circular view path [error]: would dispatch back to the current handler URL [/error] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
Can anybody help out on this ?
As the output is json i do not have thymeleaf dependencies on my application
Below is the gradle build file
plugins {
id 'org.springframework.boot' version '2.1.7.RELEASE'
id 'java'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.abc.service'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
maven { url "http://artifactory.abcinc.dev/artifactory/maven-repos" }
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
compileOnly 'org.projectlombok:lombok:1.18.8'
annotationProcessor 'org.projectlombok:lombok:1.18.8'
runtime 'com.ibm.db2.jcc:db2jcc4:4.19.49'
compile group: 'org.springframework', name: 'spring-jdbc', version: '5.1.9.RELEASE'
compile group: 'com.zaxxer', name: 'HikariCP', version: '3.3.1'
compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.9.9'
}
public class IndividualExchangeRate {
private String currencyCode;
private double conversionRateFromUSD;
private double conversionRateToUSD;
}
public class IndividualResource {
private List<IndividualExchangeRate> individualExchangeRates;
}
All the classes are annotated with lombok.
Spring Boot uses a default Whitelabel error page in case server error.So there might be some code snippets which is breaking your appliaction flow.
Add server.error.whitelabel.enabled=false in your application.properties file .
OR add the following code snippets :
#Controller
public class AppErrorController implements ErrorController{
private static final String PATH = "/error";
#RequestMapping(value = PATH)
public String error() {
return "Error handling";
}
#Override
public String getErrorPath() {
return PATH;
}
}

How to run test Containers with spring boot and spock

I want to use test container with spock on my spring boot application.
these are my dependencies :
dependencies {
compile('org.springframework.boot:spring-boot-starter-data-redis')
compile('org.springframework.boot:spring-boot-starter-web')
compile 'org.testcontainers:spock:1.8.3'
runtime('org.springframework.boot:spring-boot-devtools')
compile 'org.codehaus.groovy:groovy-all:2.4.15'
compileOnly('org.projectlombok:lombok')
compile 'org.testcontainers:testcontainers:1.8.3'
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile "org.spockframework:spock-core:1.1-groovy-2.4-rc-4"
testCompile "org.spockframework:spock-spring:1.1-groovy-2.4-rc-4"
testCompile 'com.github.testcontainers:testcontainers-spock:-SNAPSHOT'
}
I have initialized my test like below :
#SpringBootTest
#Testcontainers
class ProductRedisRepositoryTest extends Specification {
#Autowired
ProductRedisRepository productRedisRepository
#Autowired
TestComponent testComponent
static Consumer<CreateContainerCmd> cmd = { -> e.withPortBindings(new PortBinding(Ports.Binding.bindPort(6379), new ExposedPort(6379)))}
#Shared
public static GenericContainer redis =
new GenericContainer("redis:3.0.2")
//.withExposedPorts(6379)
.withCreateContainerCmdModifier(cmd)
def "check redis repository save and get"(){
given:
Product product = Product.builder()
.brand("brand")
.id("id")
.model("model")
.name( "name")
.build()
when:
productRedisRepository.save(product)
Product persistProduct = productRedisRepository.find("id")
then:
persistProduct.getName() == product.getName()
}
}
But it doesn't initiate redis container when I run test.
What is my mistake. How can I do that.
My springBootVersion = '2.0.4.RELEASE' and I am using Intelij.
This is the log output : LOG
Please remove the static keyword at your #Shared GenericContainer field.
Static fields won't be annotated with #FieldMetadata by the Spock Framework, hence they won't be considered as part of the spec's fields.
Testcontainers-Spock relies on those fields to recognise GenericContainers.
If you need the static modifier though, you can work around the issue like this:
...
public static GenericContainer staticRedis =
new GenericContainer("redis:3.0.2")
//.withExposedPorts(6379)
.withCreateContainerCmdModifier(cmd)
#Shared
public GenericContainer redis = staticRedis
...

Spock test fails when using JPA Composite Key on Groovy/Gradle build

I developed a Spring Boot WebApplication that receives a soap request with some data and save it to database.
As I am a kind of beginner on Spring Boot and JPA, I used a commonly found configuration for JPA where the primary key is an Id managed by JPA.
#Table(
name="MyEntity",
uniqueConstraints=#UniqueConstraint(columnNames=["channel", "service"])
)
public class MyEntity {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
Long id
String channel
String service
I developed a set of Spock test about saving, searching and modifying entity and everything runs smoothly.
Specifically I have a Spring Boot application smoke test to be sure that configuration load correctly
#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
}
}
As the natural key is channel and service, I tried to define a composite key
#Table(name="MyEntity")
#IdClass(MyEntityPk.class)
public class MyEntity {
#Id
String channel
#Id
String service
along with the primary key class (excerpt)
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
}
}
After this change, Spring Boot application smoke test fails with
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.
along with all other jpa related tests.
As a further information, I picked Spring Boot gs-accessing-data-jpa-master sample and adapter it to use gradle and spock. Then I modified to use a composite key and Spring Boot application smoke test is successful as expected.
On my Ws Web Application (uses dependency spring-boot-starter-web-services) there is something that causes failure. I would like to point out that the only changes were moving from auto generated key to composite key.
This causes failure to find EmbeddedServletContainerFactory. Do you have any suggestion on the matter ?
I am posting also che build script, quite complex so I added some comments to clarify implementation
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']
}
Eventually, all I have to do is:
gradlew build
to build the jar and run the tests and then
java -jar myws-spring-boot.jar
to launch the spring boot server
Smoke test was not working because I did not perform all required changes when moving from the "Long id" field as primary key
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
Long id
to
#Id
String channel
#Id
String service
I forgot to remove a method in the repository class that was referencing the "Long id" field. After moving to spring-spock 1.1 following Leonard Brünings' suggestion, I got a more detailed error message that pointed me to the right direction.
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!
So I removed the references (method declaration in repository interface) and smoke test ended successfully.
By the way, within build.gradle I had to add spock core explicitly, so instead of one line with reference to spring-spock 1.0 I had to put
testCompile 'org.spockframework:spock-core:1.1-groovy-2.4'
testCompile 'org.spockframework:spock-spring:1.1-groovy-2.4'

Resources