使用Java RMI传递复合对象

我需要使用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)

因此,在List<Medication>中没有Plan的情况下也可以正常工作。 RMI不喜欢复合对象吗?我是否应该定义一种新的远程方法来分别获取药物清单?

zhufy2009 回答:使用Java RMI传递复合对象

问题似乎是您的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似乎是一个延迟加载的实现,因此将强制其完全加载。您也许可以简单地使用紧急加载。

理想情况下,请勿使用RMI(包括Java序列化部分)。

本文链接:https://www.f2er.com/2941511.html

大家都在问