Merge pull request #33 from christophstrobl/data/jpa/data-jpa

Add data-jpa smoke test.
This commit is contained in:
Sébastien Deleuze
2023-09-22 14:39:15 +02:00
committed by GitHub
9 changed files with 333 additions and 0 deletions

View File

@@ -0,0 +1 @@
Tests if Spring Data JPA with Hibernate, MySQL & HikariCP is working.

View File

@@ -0,0 +1,24 @@
plugins {
id "java"
id "org.springframework.boot"
id "org.springframework.cr.smoke-test"
}
dependencies {
implementation(platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES))
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.crac:crac:$cracVersion")
implementation(project(":cr-listener"))
runtimeOnly("com.mysql:mysql-connector-j")
testImplementation("org.springframework.boot:spring-boot-starter-test")
appTestImplementation(project(":cr-smoke-test-support"))
appTestImplementation("org.awaitility:awaitility:4.2.0")
}
crSmokeTest {
webApplication = false
}

View File

@@ -0,0 +1,10 @@
version: '3.1'
services:
mysql:
image: 'mysql/mysql-server:8.0'
environment:
- 'MYSQL_DATABASE=test'
- 'MYSQL_USER=mysql'
- 'MYSQL_PASSWORD=password'
ports:
- '3306'

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.data.jpa;
import static org.assertj.core.api.Assertions.*;
import java.time.Duration;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.springframework.cr.smoketest.support.assertj.AssertableOutput;
import org.springframework.cr.smoketest.support.junit.ApplicationTest;
@ApplicationTest
public class DataJpaApplicationTests {
@Test
void connectionTest(AssertableOutput output) {
Awaitility.await().atMost(Duration.ofSeconds(10)).untilAsserted(() -> {
assertThat(output).hasLineMatching("Starting DataReader: was (INITIALIZED|STOPPED)");
assertThat(output).hasLineMatching("count \\d+: Author\\{id=\\d, name='.*'}");
});
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.data.jpa;
import java.util.Objects;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
@Entity
public class Author {
@Id
@GeneratedValue
private Integer id;
private String name;
protected Author() {
}
public Author(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Author author = (Author) o;
return Objects.equals(id, author.id) && Objects.equals(name, author.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
@Override
public String toString() {
return "Author{" + "id=" + id + ", name='" + name + '\'' + '}';
}
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.data.jpa;
import org.springframework.data.repository.ListCrudRepository;
public interface AuthorRepository extends ListCrudRepository<Author, Integer> {
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.data.jpa;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableTransactionManagement
public class DataJpaApplication {
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(DataJpaApplication.class, args);
}
}

View File

@@ -0,0 +1,122 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.data.jpa;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.transaction.Transactional;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.SmartLifecycle;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
@Component
@Transactional
@EnableScheduling
class DataReader implements SmartLifecycle {
private final Object lifecycleMonitor = new Object();
private final AtomicInteger counter = new AtomicInteger(0);
private State state = State.INITIALIZED;
private List<Integer> authorIds;
@Autowired
private AuthorRepository authorRepository;
@PersistenceContext
private EntityManager em;
enum State {
INITIALIZED, STARTED, STOPPED
}
@Override
public void start() {
synchronized (lifecycleMonitor) {
switch (state) {
case INITIALIZED, STOPPED -> {
System.out.printf("Starting DataReader: was %s\n", state);
if (ObjectUtils.isEmpty(authorIds)) {
authorIds = insertAuthors().stream().map(Author::getId).collect(Collectors.toList());
}
state = State.STARTED;
}
}
}
}
@Scheduled(fixedDelay = 1000)
public void scheduled() {
if (isRunning()) {
int count = counter.incrementAndGet();
Author author = authorRepository.findById(authorIds.get(count % 3)).orElse(null);
System.out.printf("count %03d: %s\n", count, author);
}
}
@Override
public void stop() {
synchronized (lifecycleMonitor) {
switch (state) {
case INITIALIZED, STARTED -> {
System.out.printf("Stopping DataReader: was %s\n", state);
state = State.STOPPED;
}
}
}
}
@Override
public boolean isRunning() {
return State.STARTED.equals(state);
}
private List<Author> insertAuthors() {
List<Author> authors = authorRepository.saveAll(List.of( //
new Author(null, "Brandon Sanderson"), //
new Author(null, "Brent Weeks"), //
new Author(null, "Peter V. Brett")));
em.flush();
em.getEntityManagerFactory().getCache().evictAll();
Session session = em.unwrap(Session.class);
if (session != null) {
session.clear(); // internal cache clear
}
return authors;
}
}

View File

@@ -0,0 +1,7 @@
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto=create
spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:${MYSQL_PORT_3306:3306}/test
spring.datasource.username=mysql
spring.datasource.password=password
spring.datasource.hikari.allow-pool-suspension=true