Helidon MP ValidationException при внедрении MongoDB EntityManager

Я начал изучать Helidon MP уже некоторое время, в учебниках и почти в каждом исходном коде, который я читал на основе этой микросервисной структуры, примеры написаны в базе данных H2. До сих пор я не мог найти ни одного примера, основанного на MongoDB. Я уже знаю о платформе JPA, которую eclipselink разработал для MongoDB, и пробовал использовать руководства в примерах JPA / NoSQL. Кроме того, я действительно мог успешно запустить тесты в простом проекте maven, и создание объекта EntityManager с использованием factory напрямую работает нормально. Но включение его в проект Helidon MP и использование CDI для EntityManager, как в инструкциях, вызывает исключение, когда я получаю доступhttp://localhost:8080/person/sahand с участием curlкоманда. Прежде чем я поместил соответствующие коды, я только что обнаружил, что когда Helidon создает EntityManager для доступа к базе данных NoSQL, он должен использоватьorg.eclipse.persistence.eis.EISLogin объект во время его создания org.eclipse.persistence.sessions.DatabaseLoginвызывая в какой-то момент ClassCastException и так далее. Это исключение, которое я получаю:

Caused by: Exception [EclipseLink-7108] (Eclipse Persistence Services - 2.7.7.v20200504-69f2c2b80d): org.eclipse.persistence.exceptions.ValidationException
Exception Description: This operation is not supported for non-relational platforms.
        at org.eclipse.persistence.exceptions.ValidationException.notSupportedForDatasource(ValidationException.java:590)
        at org.eclipse.persistence.internal.sessions.AbstractSession.getLogin(AbstractSession.java:2751)
        at io.helidon.integrations.cdi.eclipselink.CDISEPlatform.initializeExternalTransactionController(CDISEPlatform.java:228)
        at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.preConnectDatasource(DatabaseSessionImpl.java:851)
        at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.login(DatabaseSessionImpl.java:823)
        at org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:258)
        at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:769)

Это менеджер ресурсов для доступа к базе данных:

@Path("/person")
@Dependent
public class PersonResourceManager {
    @PersistenceContext
    private EntityManager em;

    @GET
    @Path("/{name}")
    @Produces("text/plain")
    @Transactional
    public String getResponse(@PathParam("name") String name) {
        Query query = em.createQuery("Select p from PERSON p where p.name LIKE '" + name + "'");
        Person person = (Person) query.getResultList().get(0);
        return String.valueOf(person.getAge()) + "\n";
    }
}

Вот объект, который я пытаюсь прочитать из уже созданной коллекции MongoDB:

@Entity(name = "PERSON")
@NoSql(dataFormat = DataFormatType.MAPPED)
public class Person implements Serializable {
    @Id
    @GeneratedValue
    @Field(name = "_id")
    private String id;

    @Basic
    private String name;

    @Basic
    private int age;

    @Version
    private long version;

    @Deprecated
    protected Person() {}
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getId() {return id;}
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public int getAge() {return age;}
    public void setAge(int age) {this.age = age;}
}

Это зависимости maven, связанные с базой данных, разрешенной в проекте:

<dependency>
    <groupId>javax.transaction</groupId>
    <artifactId>javax.transaction-api</artifactId>
    <version>1.2</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>javax.resource</groupId>
    <artifactId>connector-api</artifactId>
    <version>1.5</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>io.helidon.integrations.cdi</groupId>
    <artifactId>helidon-integrations-cdi-eclipselink</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.helidon.integrations.cdi</groupId>
    <artifactId>helidon-integrations-cdi-jpa</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.helidon.integrations.cdi</groupId>
    <artifactId>helidon-integrations-cdi-jta-weld</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.helidon.integrations.cdi</groupId>
    <artifactId>helidon-integrations-cdi-datasource-hikaricp</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>jakarta.persistence</groupId>
    <artifactId>jakarta.persistence-api</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.12.6</version>
</dependency>
<dependency>
    <groupId>org.eclipse.persistence</groupId>
    <artifactId>eclipselink</artifactId>
    <version>2.7.7</version>
</dependency>
<dependency>
    <groupId>org.eclipse.persistence</groupId>
    <artifactId>org.eclipse.persistence.nosql</artifactId>
    <version>2.7.7</version>
</dependency>

Определение единицы в persistence.xml файл:

    <persistence-unit name="mongodb" transaction-type="RESOURCE_LOCAL">
        <class>sahand.example.helidon.Person</class>
        <properties>
            <property name="eclipselink.target-database" value="org.eclipse.persistence.nosql.adapters.mongo.MongoPlatform"/>
            <property name="eclipselink.nosql.connection-spec" value="org.eclipse.persistence.nosql.adapters.mongo.MongoConnectionSpec"/>
            <property name="eclipselink.nosql.property.mongo.port" value="27017"/>
            <property name="eclipselink.nosql.property.mongo.host" value="localhost"/>
            <property name="eclipselink.nosql.property.mongo.db" value="jpa-nosql-demo"/>
            <property name="eclipselink.logging.level" value="FINEST"/>
        </properties>
    </persistence-unit>

И наконец часть application.yamlчто я думаю правильно. Однако я уверен, что это исключение происходит еще до чтения этой конфигурации.

javax:
  sql:
    DataSource:
      person:
        dataSourceClassName: othatrg.eclipse.persistence.nosql.adapters.mongo.MongoPlatform
        dataSource:
          url: mongodb://localhost:27017
          user: sample_user
          password: "samplePass"

Буду очень признателен, если кто-нибудь сможет мне с этим помочь. Хотя можно создать каждый объект EntityManager по фабрике, мне кажется, что это решение беспорядочно. Либо я использую неправильную зависимость, либо что-то еще, о чем я не знаю. Этой же инструкции я следовал для Helidon и JPA.

1 ответ

Это была ошибка Helidon в том смысле, что подсистема JPA в Helidon вызывала метод, специфичный для реляционной базы данных. Session#getLogin() вместо более явно универсального Session#getDatasourceLogin() метод.

Исправление должно быть доступно в Helidon 2.0.2. Хотя решение этой проблемы не гарантируется, тем не менее, Helidon поступает правильно.

Другие вопросы по тегам