Quarkus测试失败,因为未找到本机DayOfWeek

时间:2019-09-15 18:04:56

标签: java hibernate quarkus

我创建了一个简单的quarkus(0.21.2版)应用程序,该应用程序将休眠orm与panache一起使用将实体保存到h2数据库中。该实体包括ElementCollection中的DaysOfWeek。我还创建了一些测试来确保CURD能够正常工作。这些测试都可以正常运行,但是当我天真地运行它们时,出现以下异常:

Exception in thread "main" java.lang.RuntimeException: Failed to start quarkus
    at io.quarkus.runner.ApplicationImpl1.doStart(ApplicationImpl1.zig:126)
    at io.quarkus.runtime.Application.start(Application.java:91)
    at io.quarkus.runtime.Application.run(Application.java:204)
    at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:34)
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
    at io.quarkus.hibernate.orm.runtime.boot.FastBootEntityManagerFactoryBuilder.persistenceException(FastBootEntityManagerFactoryBuilder.java:113)
    at io.quarkus.hibernate.orm.runtime.boot.FastBootEntityManagerFactoryBuilder.build(FastBootEntityManagerFactoryBuilder.java:67)
    at io.quarkus.hibernate.orm.runtime.FastBootHibernatePersistenceProvider.createEntityManagerFactory(FastBootHibernatePersistenceProvider.java:54)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
    at io.quarkus.hibernate.orm.runtime.JPAConfig$LazyPersistenceUnit.get(JPAConfig.java:109)
    at io.quarkus.hibernate.orm.runtime.JPAConfig.startAll(JPAConfig.java:57)
    at io.quarkus.hibernate.orm.runtime.HibernateOrmRecorder.startAllPersistenceUnits(HibernateOrmRecorder.java:77)
    at io.quarkus.deployment.steps.HibernateOrmProcessor$startPersistenceUnits19.deploy_0(HibernateOrmProcessor$startPersistenceUnits19.zig:51)
    at io.quarkus.deployment.steps.HibernateOrmProcessor$startPersistenceUnits19.deploy(HibernateOrmProcessor$startPersistenceUnits19.zig:70)
    at io.quarkus.runner.ApplicationImpl1.doStart(ApplicationImpl1.zig:90)
    ... 3 more
Caused by: org.hibernate.MappingException: Could not create DynamicParameterizedType for type: org.hibernate.type.EnumType
    at org.hibernate.mapping.SimpleValue.createParameterImpl(SimpleValue.java:768)
    at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:470)
    at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:455)
    at org.hibernate.mapping.Collection.validate(Collection.java:315)
    at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:347)
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:461)
    at io.quarkus.hibernate.orm.runtime.boot.FastBootEntityManagerFactoryBuilder.build(FastBootEntityManagerFactoryBuilder.java:65)
    ... 12 more
Caused by: org.hibernate.boot.registry.classloading.spi.ClassLoadingException: Unable to load class [java.time.DayOfWeek]
    at io.quarkus.hibernate.orm.runtime.service.FlatClassLoaderService.classForName(FlatClassLoaderService.java:39)
    at org.hibernate.mapping.SimpleValue.createParameterImpl(SimpleValue.java:755)
    ... 18 more
Caused by: java.lang.ClassNotFoundException: java.time.DayOfWeek
    at com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:60)
    at java.lang.Class.forName(DynamicHub.java:1174)
    at io.quarkus.hibernate.orm.runtime.service.FlatClassLoaderService.classForName(FlatClassLoaderService.java:37)
    ... 19 more

我的实体看起来像这样:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.GenericGenerator;

import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.validation.constraints.NotNull;
import java.time.DayOfWeek;
import java.time.LocalTime;
import java.util.*;

import static org.hibernate.annotations.CascadeType.ALL;

@Entity
@JsonIgnoreProperties(ignoreUnknown = true)
public class OpeningTimes extends PanacheEntityBase {
  @Id
  @GeneratedValue(generator = "UUID")
  @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
  private UUID id;

  @NotNull
  private String name;
  private String description;
  private LocalTime timeFrom;
  private LocalTime timeTo;

  @ElementCollection
  @Cascade(value = {ALL})
  private Collection<DayOfWeek> daysOfWeek;

  /**
   * DO NOT USE! ONLY FOR JPA!
   */
  OpeningTimes() {
    super();
    name = "";
  }

  @JsonCreator
  public OpeningTimes(
      @JsonProperty("name") String name,
      @JsonProperty("timeFrom") LocalTime timeFrom,
      @JsonProperty("timeTo") LocalTime timeTo,
      @JsonProperty("daysOfWeek") Collection<DayOfWeek> daysOfWeek) {
    this.name = name;
    this.timeFrom = timeFrom;
    this.timeTo = timeTo;
    this.daysOfWeek = new HashSet<>(daysOfWeek);
  }

  public OpeningTimes(String name, LocalTime from, LocalTime to, DayOfWeek... daysOfWeek) {
    this(name, from, to, new ArrayList<>(Arrays.asList(daysOfWeek)));
  }

  public LocalTime getTimeFrom() {
    return timeFrom;
  }

  public void setTimeFrom(LocalTime timeFrom) {
    this.timeFrom = timeFrom;
  }

  public LocalTime getTimeTo() {
    return timeTo;
  }

  public void setTimeTo(LocalTime timeTo) {
    this.timeTo = timeTo;
  }

  public Collection<DayOfWeek> getDaysOfWeek() {
    return daysOfWeek;
  }

  public void setDaysOfWeek(Set<DayOfWeek> daysOfWeek) {
    this.daysOfWeek = daysOfWeek;
  }

  public UUID getId() {
    return id;
  }

  public void setId(UUID id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getDescription() {
    return description;
  }

  public void setDescription(String description) {
    this.description = description;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof OpeningTimes)) return false;
    OpeningTimes that = (OpeningTimes) o;
    return Objects.equals(getId(), that.getId())
            && Objects.equals(getName(), that.getName())
            && Objects.equals(getDescription(), that.getDescription())
            && Objects.equals(getTimeFrom(), that.getTimeFrom())
            && Objects.equals(getTimeTo(), that.getTimeTo())
            && Objects.equals(getDaysOfWeek(), that.getDaysOfWeek());
  }

  @Override
  public int hashCode() {
    return Objects.hash(
            getId(), getName(), getDescription(), getTimeFrom(), getTimeTo(), getDaysOfWeek());
  }

  @Override
  public String toString() {
    return "OpeningTimes{"
            + "id="
            + id
            + ", name='"
            + name
            + '\''
            + ", description='"
            + description
            + '\''
            + ", timeFrom="
            + timeFrom
            + ", timeTo="
            + timeTo
            + ", daysOfWeek="
            + daysOfWeek
            + '}';
  }

  public void merge(OpeningTimes openingTimes) {
    this.name = openingTimes.name;
    this.description = openingTimes.description;
    this.timeFrom = openingTimes.timeFrom;
    this.timeTo = openingTimes.timeTo;
    this.daysOfWeek = openingTimes.daysOfWeek;
  }
}

这是我的考验:

import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import io.quarkus.test.common.QuarkusTestResource;
import io.quarkus.test.h2.H2DatabaseTestResource;
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.http.ContentType;
import io.restassured.mapper.ObjectMapperType;
import io.restassured.mapper.TypeRef;
import io.restassured.response.Response;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.transaction.Transactional;
import java.time.DayOfWeek;
import java.time.LocalTime;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

@QuarkusTest
@QuarkusTestResource(H2DatabaseTestResource.class)
class OpeningsResourceTest {
  private static final Logger LOG = LoggerFactory.getLogger(OpeningsResourceTest.class);

  @Test
  void testSaveOpening() {
    OpeningTimes opening =
        new OpeningTimes(
            "Test opening", LocalTime.MIN, LocalTime.NOON, DayOfWeek.MONDAY, DayOfWeek.THURSDAY);
    Response response =
        given()
            .when()
            .contentType(ContentType.JSON)
            .body(opening, ObjectMapperType.JACKSON_2)
            .post("/service/events/openings");
    LOG.debug(response.andReturn().body().prettyPrint());
    OpeningTimes responseObject = response.then().statusCode(200).extract().as(OpeningTimes.class);

    // Set the id because its generated on saving
    opening.setId(responseObject.getId());
    assertThat(responseObject, equalTo(opening));
  }

  @Test
  void testGetOpening() {
    OpeningTimes testdata = saveTestdata().get(0);
    Response response = given().when().get("/service/events/openings/{id}/", testdata.getId());
    OpeningTimes responseObject = response.then().statusCode(200).extract().as(OpeningTimes.class);
    assertThat(responseObject, equalTo(testdata));
  }

  @Test
  void testDeleteOpening() {
    OpeningTimes testdata = saveTestdata().get(0);
    // Delete
    given()
            .when()
            .delete("/service/events/openings/{id}/", testdata.getId())
            .then()
            .statusCode(204);
    // Check if it is deleted
    given().when().get("/service/events/openings/{id}/", testdata.getId()).then().statusCode(204);
  }

  @Test
  void testChangeOpening() {
    OpeningTimes testdata = saveTestdata().get(0);
    testdata.setDescription("Example description");
    Response response =
            given()
                    .when()
                    .contentType(ContentType.JSON)
                    .body(testdata, ObjectMapperType.JACKSON_2)
                    .put("/service/events/openings/");
    LOG.debug(response.andReturn().body().prettyPrint());
    response.then().statusCode(200).extract().as(OpeningTimes.class);

    OpeningTimes changedOpening =
            given()
                    .when()
                    .get("/service/events/openings/{id}", testdata.getId())
                    .then()
                    .statusCode(200)
                    .extract()
                    .as(OpeningTimes.class);
    assertThat(changedOpening, is(testdata));
  }

  private List<OpeningTimes> saveTestdata() {
    OpeningTimes opening1 =
        new OpeningTimes(
            "Test opening", LocalTime.MIN, LocalTime.NOON, DayOfWeek.MONDAY, DayOfWeek.THURSDAY);
    OpeningTimes opening2 =
        new OpeningTimes("Test opening 2", LocalTime.MIN, LocalTime.NOON, DayOfWeek.FRIDAY);
    opening1 =
            given()
                    .contentType(ContentType.JSON)
                    .body(opening1, ObjectMapperType.JACKSON_2)
                    .post("/service/events/openings")
                    .then()
                    .extract()
                    .as(OpeningTimes.class);
    opening2 =
            given()
                    .contentType(ContentType.JSON)
                    .body(opening2, ObjectMapperType.JACKSON_2)
                    .post("/service/events/openings")
                    .then()
                    .extract()
                    .as(OpeningTimes.class);
    return Arrays.asList(opening1, opening2);
  }

  @Test
  void testGetAll() {
    List<OpeningTimes> testdata = saveTestdata();
    Collection<OpeningTimes> openings =
        given()
            .when()
            .get("/service/events/openings")
            .then()
            .statusCode(200)
            .extract()
            .as(new TypeRef<Collection<OpeningTimes>>() {});

    assertThat(openings, is(testdata));
  }

  @AfterEach
  @Transactional
  void cleanUpDatabase() {
    // Delete all won't work because of the element collection
    OpeningTimes.findAll().stream().forEach(PanacheEntityBase::delete);
  }
}

本机测试:

import io.quarkus.test.junit.SubstrateTest;

@SubstrateTest
public class NativeOpeningsResourceIT extends OpeningsResourceTest {
    // Execute the same tests but in native mode.
}

我不知道为什么找不到java.time.DayOfWeek

1 个答案:

答案 0 :(得分:1)

似乎本地图像工具没有在本地图像中包含java.time.DayOfWeek类。 SubstratVM在封闭环境中工作,只能访问在本机映像编译期间发现的类或专门注册用于反射的类。

您可以按照本节的内容注册java.time.DayOfWeekhttps://quarkus.io/guides/writing-native-applications-tips#registering-for-reflection进行反思。

您可以在Entity类上尝试使用注释,但是我认为您需要将java.time.DayOfWeek类包含在reflection-config.json文件中,因为我不确定注释是否会包含所有使用的类按您的实体或仅按您的实体类。