【问题标题】:How to enhance classes properly at build time using Maven? OpenJPA如何使用 Maven 在构建时正确增强类? OpenJPA
【发布时间】:2021-06-02 21:57:42
【问题描述】:

我正在尝试增强(实体)类,所以我不会得到这个异常:

Exception in thread "main" <openjpa-3.1.2-r66d2a72 nonfatal user error> org.apache.op
enjpa.persistence.ArgumentException: Attempt to cast instance "entities.EntityPerson@
6dba847b" to PersistenceCapable failed.  Ensure that it has been enhanced.
FailedObject: entities.EntityPerson@6dba847b
    at org.apache.openjpa.kernel.BrokerImpl.assertPersistenceCapable(BrokerImpl.java:486
3)
    at org.apache.openjpa.kernel.BrokerImpl.persistInternal(BrokerImpl.java:2762)
    at org.apache.openjpa.kernel.BrokerImpl.persist(BrokerImpl.java:2707)
    at org.apache.openjpa.kernel.BrokerImpl.persist(BrokerImpl.java:2690)
    at org.apache.openjpa.kernel.BrokerImpl.persist(BrokerImpl.java:2592)
    at org.apache.openjpa.kernel.DelegatingBroker.persist(DelegatingBroker.java:1197)
    at org.apache.openjpa.persistence.EntityManagerImpl.persist(EntityManagerImpl.java:8
37)
    at openjpa.Test/main.Main.main(Main.java:23)

说我试图坚持的实例不是增强的

我已经关注了这个:https://openjpa.apache.org/enhancement-with-maven.html官方openjpa页面并将openjpa-maven-plugin添加到我的pom.xml部分:

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>registry</groupId>
    <artifactId>datalayer</artifactId>
    <version>0.0.1</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.target>11</maven.compiler.target>
        <maven.compiler.source>11</maven.compiler.source>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.sourceEncoding>UTF-8</project.reporting.sourceEncoding>
    </properties>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.openjpa</groupId>
                    <artifactId>openjpa-maven-plugin</artifactId>
                    <version>3.1.2</version>
                    <configuration>
                        <includes>datalayer/dto/*.class</includes>
                        <addDefaultConstructor>true</addDefaultConstructor>
                        <enforcePropertyRestrictions>true</enforcePropertyRestrictions>
                    </configuration>
                    <executions>
                        <execution>
                            <id>enhancer</id>
                            <phase>process-classes</phase>
                            <goals>
                                <goal>enhance</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.apache.openjpa</groupId>
            <artifactId>openjpa</artifactId>
            <version>3.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.derby</groupId>
            <artifactId>derby</artifactId>
            <version>10.15.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.derby</groupId>
            <artifactId>derbytools</artifactId>
            <version>10.15.2.0</version>
        </dependency>
    </dependencies>
</project>

,但我仍然得到那个例外。我正在使用 Eclipse 并内置命令Run As -&gt; Maven install。我还尝试从命令行运行mvn install。然后我只是尝试使用EntityManager 来持久化一些实体。

使用和不使用 openjpa-maven-plugin 运行 mvn install 不会改变任何东西(使用相同的 .class 文件生成相同的 .jar,向控制台输出相同的 maven)

正如答案所说,在使用 Maven 构建时,我需要运行 openjpa:enhance 目标。我实际上没有使用openjpa-maven-plugin,所以我修复了这个问题。 Maven 输出:

[INFO] Error stacktraces are turned on.
[INFO] Scanning for projects...
[INFO] 
[INFO] -------------------------< registry:datalayer >-------------------------
[INFO] Building datalayer 0.0.1
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ datalayer ---
[INFO] Deleting C:\Users\wortigson\Desktop\ISMatrikaBcWorkspace\Openjpa.Test\target
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ datalayer ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ datalayer ---
[WARNING] Can't extract module name from geronimo-jms_1.1_spec-1.1.1.jar: geronimo.jm
s.1.1.spec: Invalid module name: '1' is not a Java identifier
[WARNING] Can't extract module name from geronimo-jta_1.1_spec-1.1.1.jar: geronimo.jt
a.1.1.spec: Invalid module name: '1' is not a Java identifier
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 3 source files to C:\Users\wortigson\Desktop\ISMatrikaBcWorkspace\Op
enjpa.Test\target\classes
[INFO] 
[INFO] --- openjpa-maven-plugin:3.1.2:enhance (default-cli) @ datalayer ---
130  DataLayer  INFO   [main] openjpa.Tool - Enhancer running on type "class entities
.EntityPerson".
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ datalayer ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ datalayer ---
[WARNING] Can't extract module name from geronimo-jms_1.1_spec-1.1.1.jar: geronimo.jm
s.1.1.spec: Invalid module name: '1' is not a Java identifier
[WARNING] Can't extract module name from geronimo-jta_1.1_spec-1.1.1.jar: geronimo.jt
a.1.1.spec: Invalid module name: '1' is not a Java identifier
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 3 source files to C:\Users\wortigson\Desktop\ISMatrikaBcWorkspace\Op
enjpa.Test\target\classes
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ datalay
er ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ datalayer 
---
[WARNING] Can't extract module name from geronimo-jta_1.1_spec-1.1.1.jar: geronimo.jt
a.1.1.spec: Invalid module name: '1' is not a Java identifier
[WARNING] Can't extract module name from geronimo-jms_1.1_spec-1.1.1.jar: geronimo.jm
s.1.1.spec: Invalid module name: '1' is not a Java identifier
[INFO] Changes detected - recompiling the module!
[INFO] 
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ datalayer ---
[INFO] 
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ datalayer ---
[INFO] Building jar: C:\Users\wortigson\Desktop\ISMatrikaBcWorkspace\Openjpa.Test\tar
get\datalayer-0.0.1.jar
[INFO] 
[INFO] --- maven-install-plugin:2.4:install (default-install) @ datalayer ---
[INFO] Installing C:\Users\wortigson\Desktop\ISMatrikaBcWorkspace\Openjpa.Test\target
\datalayer-0.0.1.jar to C:\Users\wortigson\.m2\repository\registry\datalayer\0.0.1\da
talayer-0.0.1.jar
[INFO] Installing C:\Users\wortigson\Desktop\ISMatrikaBcWorkspace\Openjpa.Test\pom.xm
l to C:\Users\wortigson\.m2\repository\registry\datalayer\0.0.1\datalayer-0.0.1.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS

您可以看到我在 EntityPerson 类上运行增强器,这是我测试过的简单 JPA 实体。但是我仍然得到那个例外。 我注意到 maven-compiler-plugin:3.8.1:compile 运行了两次。 openjpa-maven-plugin:3.1.2:enhance 之前和之后 - 这可能是问题吗?

我认为这不是我的情况:How to enhance a class from a separate jar at build time with openJPA?

发现有解决方法Attempt to cast instance to PersistenceCapable failed. Ensure that it's been enhanced 通过在配置中设置一些属性作为接受的答案说,但我不想那样做,因为第一条评论说不推荐它并指向官方 openjpa 页面,我在哪里发现该示例如何在 Maven 构建期间增强类,但正如我所写,它不起作用。

测试主要方法:

public static void main(String[] args)
    {
        HashMap<String, String> jpaProps = new HashMap<String, String>();
        jpaProps.put("javax.persistence.jdbc.url", "jdbc:derby:testDB;create=true");
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("DataLayer", jpaProps);
        EntityManager manager = factory.createEntityManager();
        EntityPerson person = new EntityPerson();
        person.setAge(25);
        person.setName("Andrej Hruska");
        manager.persist(person); // +
    }

EntityPerson 类:

package entities;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class EntityPerson
{
    @Id
    @GeneratedValue
    private long id;
    
    @Column(nullable = false)
    private String name;
    
    private int age;

    public long getId()
    {
        return id;
    }

    public void setId(long id)
    {
        this.id = 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;
    }
}

persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
    xmlns="http://xmlns.jcp.org/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence https://www.oracle.com/webfolder/technetwork/jsc/xml/ns/persistence/persistence_2_2.xsd">
    <persistence-unit name="DataLayer"
        transaction-type="RESOURCE_LOCAL">
        <non-jta-data-source>DataSource</non-jta-data-source>
        <properties>
            <property
                name="javax.persistence.schema-generation.database.action"
                value="create" />
            <property name="javax.persistence.jdbc.driver"
                value="org.apache.derby.jdbc.EmbeddedDriver" />
            <property name="javax.persistence.jdbc.url"
                value="jdbc:derby:db;create=true" />
        </properties>
    </persistence-unit>
</persistence>

项目结构:

重现步骤:

  1. Eclipse 中的克里特岛 Maven 项目
  2. 复制我的 pom.xml(或将依赖项添加到 derby、openjpa 并设置您的 openjpa-maven-plugin、名称和路径)
  3. 复制我的 persistence.xml(或使用一些持久性单元创建您自己的)
  4. 复制我的 EntityPerson 类(或创建简单的 JPA 实体进行测试)
  5. 运行 mvn clean compile openjpa:enhance install(重要部分是 openjpa:enhance)
  6. 尝试像我在 main 方法中所做的那样持久化实体

【问题讨论】:

    标签: java maven openjpa openjpa-maven-plugin byte-code-enhancement


    【解决方案1】:

    一些误解。

    我尝试过只使用 openjpa-maven-plugin 而没有 maven-compiler-plugin,但没有帮助。

    Maven 的 pom.xml 被认为是“项目对象模型”这意味着,对于您的“项目”,它是“建模”构建过程的“对象”。该对象是嵌入在 Maven 中的“父 pom.xml”的子类,它定义了默认构建;因此,如果您删除“maven-compiler-plugin”,您将获得默认的“maven-compiler-plugin”配置。奇怪的是配置很旧,随 Maven 一起提供,你最好包括一个“覆盖”来更新它。

    Eclipse 和 Maven

    Eclpise 和 Maven 一起工作;但是,在您知道它们如何协同工作之前,您将遇到很多问题。

    Eclipse 读取pom.xml 文件并生成一个Eclipse configuration,它应该以相同的方式执行与pom.xml 文件相同的步骤。当您使用 Eclipse 进行编译时,它不会运行 mvn compile,它是基于 Eclipse 配置构建的,它可能比最近编辑的 pom.xml 更旧。因此,在使用 ecplise 时,您应该在每次编辑 pom.xml 后重新阅读您的项目配置。

    如果你想看一个和Eclipse类似的不同IDE;但是,一个调用mvn compile 而不是调用它自己的“应该是相同的,但通常不是”的交互版本,看看NetBeans。 https://netbeans.apache.org/download/nb122/index.html 与 Ecplipse 不同,它不包含用于 Maven 插件(或它自己的嵌入式编译器)的“命令镜像”,它使用 mvn 命令和 javac 编译器并使用配置启动它们以生成大量输出消息,然后读取这些消息以更新它的“IDE 端”。

    我指出这一点的原因是,您可能会按照说明进行操作,如果您是,您可能会在命令行中看到 mvn package 上的正确输出,但在 Eclipse 中却看不到(因为需要从源码刷新eclipse项目pom.xml)

    【讨论】:

    • 我尝试从命令行mvn package,但是输出是相同的 - 相同的 .jar 文件和相同的 .class 文件。我猜想增强目标可能会在流程类步骤中以某种方式被跳过,或者&lt;includes&gt; 路径确实是错误的。
    【解决方案2】:

    您需要告诉 maven 运行增强目标。

    mvn clean compile openjpa:enhance
    

    你应该看到这个输出:

    [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ jpa-example ---
    [INFO] Changes detected - recompiling the module!
    [INFO] Compiling 2 source files to /home/gordon/docs/programming/openjpa/jpa-example/target/classes
    [INFO] 
    [INFO] --- openjpa-maven-plugin:3.1.2:enhance (default-cli) @ jpa-example ---
    [INFO] 
    

    maven 中有一个层次结构。顶部是生命周期,它由作为插件目标实现的阶段组成。包装决定了一个阶段的目标。

    增强目标不是构建或编译的默认目标之一。

    在eclipse中,如果你改变pom.xml你需要右击并选择Maven->Update Project。您可以将 openjpa:enhance 放在 Maven Build 的 eclipse 运行配置的目标字段中。

    【讨论】:

    • 你是救世主!增强目标似乎正在运行,但是我遇到了构建失败:justpaste.it/5ws66。我有 META-INF/persistence.xml 文件,它在我的类路径中。你能展示你的项目结构吗?
    • 我的文件在 src/main/resources/META-INF 中,我的 pom.xml 中有这个 ` src/main/resources`
    • 将该资源添加到 pom.xml 有帮助,但现在我在尝试解析该文件时遇到错误:justpaste.it/7ihlc。你知道有什么问题吗? Eclipse 不会警告该文件中的任何错误。你能描述一下你的 persistence.xml 吗?
    • @Wortig 我认为它是Oracle security change。你需要xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence https://www.oracle.com/webfolder/technetwork/jsc/xml/ns/persistence/persistence_2_2.xsd"
    【解决方案3】:

    将插件定义从&lt;pluginManagement&gt;移动到&lt;plugins&gt;like

    <project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>registry</groupId>
        <artifactId>datalayer</artifactId>
        <version>0.0.1</version>
        <packaging>jar</packaging>
    
        <properties>
            <maven.compiler.target>11</maven.compiler.target>
            <maven.compiler.source>11</maven.compiler.source>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.sourceEncoding>UTF-8</project.reporting.sourceEncoding>
        </properties>
    
        <build>
            <pluginManagement>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-compiler-plugin</artifactId>
                        <version>3.8.1</version>
                    </plugin>
                </plugins>
            </pluginManagement>
            <plugins>
                    <plugin>
                        <groupId>org.apache.openjpa</groupId>
                        <artifactId>openjpa-maven-plugin</artifactId>
                        <version>3.1.2</version>
                        <configuration>
                            <includes>datalayer/dto/*.class</includes>
                            <addDefaultConstructor>true</addDefaultConstructor>
                            <enforcePropertyRestrictions>true</enforcePropertyRestrictions>
                        </configuration>
                        <executions>
                            <execution>
                                <id>enhancer</id>
                                <phase>process-classes</phase>
                                <goals>
                                    <goal>enhance</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
           </plugins>
        </build>
    
        <dependencies>
            <dependency>
                <groupId>org.apache.openjpa</groupId>
                <artifactId>openjpa</artifactId>
                <version>3.1.2</version>
            </dependency>
            <dependency>
                <groupId>org.apache.derby</groupId>
                <artifactId>derby</artifactId>
                <version>10.15.2.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.derby</groupId>
                <artifactId>derbytools</artifactId>
                <version>10.15.2.0</version>
            </dependency>
        </dependencies>
    </project>
    

    PluginManagement 仅用于配置 -- 插件不会自动运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-12
      • 2013-10-04
      • 2012-10-11
      • 2012-01-24
      相关资源
      最近更新 更多