【问题标题】:Passing composite objects using java RMI使用 java RMI 传递复合对象
【发布时间】:2020-04-04 19:04:38
【问题描述】:

我需要使用 RMI 为客户发送用药计划。服务器和客户端在不同的项目中,都定义了这些类(实体和远程接口):

public class Plan implements Serializable {
    private Integer id;
    private Date periodStart;
    private Date periodEnd;
    private Integer patientId;
    private Medication medications;
}

public class Medication implements Serializable {
    private Integer id;
    private String name;
    private Integer dosage;
    private Integer intakeInterval;
}

public interface PillService extends Remote {
    public Plan getPlan(int id) throws RemoteException;
}

上面的代码可以正常工作,但我需要在Plan 中有一个药物列表,如下所示:

 public class Plan implements Serializable {
        ...
        private List<Medication> medications;
    }

如果我使用这个 Plan 类运行,我会得到这个异常:

Client exception: java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
    java.lang.ClassNotFoundException: org.hibernate.collection.internal.PersistentBag (no security manager: RMI class loader disabled)

在此之后我将SecutiryManager 添加到System 我得到错误:

java.security.AccessControlException: access denied ("java.net.SocketPermission" "127.0.0.1:1099" "connect,resolve")
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)

因此,在 Plan 中没有 List&lt;Medication&gt; 时它可以正常工作。 RMI 不喜欢复合对象吗?我应该定义一个新的远程方法来单独获取药物列表吗?

【问题讨论】:

  • org.hibernate.collection.internal.PersistentBag需要在客户端可用。

标签: java serialization rmi


【解决方案1】:

问题似乎是您的List 的运行时类型。该类在客户端不可用,因此 RMI 正在尝试从远程代码库下载代码。这已被相当合理地禁用。

最简单的解决方法是对List 使用众所周知的实现。将列表复制到在Plan 或自定义writeObject 方法中设置的位置。

this.medications = new ArrayList<>(medications);

或者

  private void writeObject(
     ObjectOutputStream out
  ) throws IOException {
     this.medications = new ArrayList<>(this.medications);
     out.defaultWriteObject();
  }

看起来你List 是一个延迟加载实现,所以这将强制它被完全加载。您也许可以简单地使用急切加载。

理想情况下,不要使用包含 Java 序列化部分的 RMI。

【讨论】:

  • 我使用stub = (PillService) registry.lookup("PillService");Plan p = stub.getPlan(id); 获得计划,我不知道在哪里实施您的代码。
  • 它不是“试图从代码库下载”。也就是说,在没有安全管理器的情况下,代码库被禁用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多