【问题标题】:Start JPA EntityManagerFactory in remote server through RMI通过 RMI 在远程服务器中启动 JPA EntityManagerFactory
【发布时间】:2013-06-05 15:10:13
【问题描述】:

我正在尝试完成一个使用 RMI 将工作负载发送到一些远程服务器的原型。工作完成后,远程服务器应该将结果写回数据库。我使用 JPA 和 Hibernate 作为提供者。但是我很难要求远程服务器这样做。

这是要通过 RMI 发送到远程服务器的部分代码

public class UpdateDB implements ServerRun<Boolean>, Serializable {

private static final long serialVersionUID = 2683781993159094346L;

@Override
public Boolean execute() {
    EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory( "abc" );
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    entityManager.getTransaction().begin();
    entityManager.persist( new User( "First user!", new Date() ) );
    entityManager.persist( new User( "Second user", new Date() ) );
    entityManager.getTransaction().commit();
    entityManager.close();

    entityManager.close();
    entityManagerFactory.close();
    return true;
  }
}

这里是上面代码同级的resources/META-INF中的persistence.xml:

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">

<persistence-unit name="abc" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <class>data.persist.User</class>

    <properties>
        <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
        <property name="javax.persistence.jdbc.url" value="jdbc:mysql://192.168.205.103:3306/event_grp" />
        <property name="javax.persistence.jdbc.user" value="username" />
        <property name="javax.persistence.jdbc.password" value="password" />

        <property name="hibernate.show_sql" value="true" />
        <property name="hibernate.hbm2ddl.auto" value="create" />
    </properties>

</persistence-unit>

如果我在服务器上运行 JPA,它就可以工作,而其他任何东西都可以在 RMI 功能方面工作。但是 EntityManagerFactory 不会启动,这是错误:

Exception in thread "main" javax.persistence.PersistenceException: No Persistence provider for EntityManager named abc
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:69)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:47)
    at data.persist.UpdateDB.execute(UpdateDB.java:58)
    at data.persist.UpdateDB.execute(UpdateDB.java:1)
    at engine.ComputeEngine.executeTask(ComputeEngine.java:39)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:303)
    at sun.rmi.transport.Transport$1.run(Transport.java:159)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)
    at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(Unknown Source)
    at sun.rmi.transport.StreamRemoteCall.executeCall(Unknown Source)
    at sun.rmi.server.UnicastRef.invoke(Unknown Source)
    at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unknown Source)
    at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source)
    at com.sun.proxy.$Proxy12.executeTask(Unknown Source)
    at client.JobSubmitter.main(JobSubmitter.java:94)

因此,RMI 似乎无法在 META-INF 中找到或加载 persistence.xml。我也有类似的 log4j 经验,但我通过在代码中定义所有内容而不是使用 log4j.properties 文件来解决问题。

编辑: 要发送到远程服务器的代码包看起来像,这是我放置persistence.xml的唯一地方:

-src/main/java/data/persist/UpdataDB.java
 |
 src/main/resources/META-INF/persistence.xml

根据user1888440的问题,我把安全权限配置放在这里。并且客户端和远程服务器都使用以下权限:

grant {
permission java.security.AllPermission;
};

如何使远程服务器初始化 EntityManagerFactory 以便它可以写回数据库?如果您也能提供一些简单的代码,我将不胜感激。

【问题讨论】:

  • 我看不出这与 RMI 有什么关系。这与您的持久性配置有关。
  • 它可以在本地机器上正常工作。通过 RMI 将其发送到远程服务器时,它不起作用。如果这对您有意义,请重新添加 RMI 标签。

标签: java hibernate jpa rmi distributed


【解决方案1】:

远程服务器需要与客户端相同的资源访问权限。您希望谁真正接触数据库?任何人?如果是这样,这些参与者中的每一个都需要您的 persistence.xml 的副本,以便他们可以创建到数据库的连接。

【讨论】:

  • 感谢您的回复。在打包的 jar 中有一个带有“UpdateDB”类的persistence.xml 的副本。问题是当作业提交者将“UpdateDB”发送到远程服务器时,远程服务器将无法从类加载器中获取persistence.xml,即使它位于“UpdateDB”的类路径中。这很可能是由 RMI 远程类加载器的行为引起的,我不完全理解。
  • 在不了解您的配置的情况下,我无能为力。但您可能需要检查persistence.xml 的权限。通常使用 RMI,您必须根据设置授予特定的授予权限。就像授予代码库“file:/whatever/persistence.xml”{权限java.security.AllPermission; };
  • 请查看已编辑的打包配置以及persistence.xml的放置位置。权限设置为授予客户端和远程服务器的 {permission java.security.AllPermission;}。
  • 看起来像是权限问题,但您可能想试试这里的建议。特别是关于它认为你的 META_INF/persistence.xml 在哪里的部分。 stackoverflow.com/questions/6148730/…
  • 非常感谢您的参考。有趣的部分是我为所有这些设置了所有权限。它行不通。顺便说一句,整个设置工作正常,无需在客户端使用 RMI,这排除了此处错误持久性配置的可能性。所以,它看起来仍然像一个 RMI 问题。我会投票赞成你剪掉有用的参考。但我还没有足够的声望。
猜你喜欢
  • 2018-10-09
  • 2019-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多