简体   繁体   English

使用 Java RMI 传递复合对象

[英]Passing composite objects using java RMI

I need to send a medication plan for the client using RMI.我需要使用 RMI 为客户发送药物计划。 The server and client are in separate projects, both have these classes defined (entities and the remote interface):服务器和客户端在不同的项目中,都定义了这些类(实体和远程接口):

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;
}

The code above works fine, but i need to have a list of medications in the Plan like this:上面的代码工作正常,但我需要在Plan有一个药物清单,如下所示:

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

If i run with this Plan class, i get this exception:如果我用这个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)

After this I added SecutiryManager to System i get error:在此之后,我将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)

So, it works fine without List<Medication> in the Plan .因此,它在Plan没有List<Medication>情况下工作正常。 Doesn't RMI like composite objects? RMI 不喜欢复合对象吗? Should i define a new remote method for getting the list of medications separately?我应该定义一个新的远程方法来分别获取药物列表吗?

The problem appears to be the runtime type of your List .问题似乎是您的List的运行时类型。 The class is not available from the client end, so RMI is trying to download the code from the remote codebase.该类在客户端不可用,因此 RMI 试图从远程代码库下载代码。 This has quite reasonably been disabled.这已相当合理地被禁用。

The easiest fix would be to use a well known implementation for List .最简单的解决方法是使用众所周知的List实现。 Copy the list either where it is set in Plan or in a custom writeObject method.复制在Plan中设置的列表或自定义writeObject方法中的列表。

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

Or或者

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

It looks like you List is a lazy loading implementation, so this will force it to be entirely loaded.看起来你List是一个延迟加载实现,所以这将强制它完全加载。 You might be able to simply use eager loading.您也许可以简单地使用预先加载。

Ideally, don't use RMI including the Java Serialization part.理想情况下,不要使用包含 Java 序列化部分的 RMI。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM