可以或者是在JMS ObjectMessage中保存的对象与发布时相同吗?

时间:2011-07-19 09:42:02

标签: java java-ee thread-safety jms

我认为这是一个愚蠢的问题,但我找不到我在JMS getting started guide或网络上其他地方寻找的答案。 This jGuru post表明以下场景中的线程安全取决于应用程序设计者。

方案

Object视为HttpSession的属性。此对象的类型为ProductQuote

在Java Servlet中,我从请求中获取一些输入并将它们设置为ProductQuote的新实例中的字段,然后使用我的另一个类将相同的ProductQuote实例推送到JMS队列。

在一个单独的线程上,该对象通过容器从队列中弹出,并通过onMessage(Message message)方法传递给implements MessageListener的消息驱动bean(“MDB”)。 MessageListener接口的这种特定实现将改变实例中的字段,然后丢弃该消息,干净地执行。

问题

是否有可能将ProductQuote的实例推送到Servlet中的队列与另一个线程中MDB使用的完全相同的实例?

我假设反向也是可能的(如果不是总是;我试图填补我的知识空白):推送到队列/主题的实例与传递给消费者的实例不同。 / p>

修改的 为了进一步说明,我在给定场景中考虑线程安全性,其中会话中的对象可以在MDB修改/读取的同时进行修改。

原谅这个愚蠢的问题。

4 个答案:

答案 0 :(得分:1)

我认为答案是 - 是的,有可能......(虽然不太可能) 看看JMS规范似乎没有保证,所以它可能取决于您选择的JMS provider。仅仅因为规范说Object必须实现Serializable并不意味着它将被序列化。 但是我会补充一点,如果它与JMS经常用于在应用程序之间执行消息传递的同一个对象,我会感到惊讶,因此该对象必须已被序列化。

答案 1 :(得分:1)

答案在JMS specification中定义,我引用:

  

请注意,ObjectMessage的setObject方法会放置一个副本   消息中的输入对象

鉴于任何JMS提供程序 - 在我的情况下都是BEA Weblogic - 必须坚持这一点,我相信我的原始消息中的线程安全问题是没有根据的:ObjectMessage实例中的对象是复制,因此不存在并发修改的威胁。

修改

我也应该阅读Javadoc

public void setObject(Serializable object)
               throws JMSException
  

设置包含此消息数据的可序列化对象。它是   重要的是要注意ObjectMessage包含的快照   调用setObject()时的对象;随后的修改   该对象对ObjectMessage主体没有任何影响。

答案 2 :(得分:0)

首先,不同的对象可能具有相同的哈希码 其次,我敢打赌,JmsObjectMessage的'内部'是一个对象实例的序列化版本,我想它在反序列化时获得一个新的Object id,并且新的对象实例应该生成与最初序列化的对象。

答案 3 :(得分:0)

很可能,你不会回到同一个对象。它可能与发送的逻辑标识具有相同的逻辑标识,但对其进行更改很可能不会导致原始对象反映该更改。

但是,如果不了解具体对象,就很难完全确定。例如,如果对象是围绕另一个对象的可序列化包装器,并且针对包装器的任何调用会自动刷新包装器对目标对象的引用,那么在所有范围和目的中,您在JMS消息的任一侧都具有相同的对象。

此外,如果您检查java.io.Serializable的JavaDoc,您将看到在序列化/反序列化过程中可以调用的可序列化实现中有许多可选方法。

private void writeObject(java.io.ObjectOutputStream out) throws IOException
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;

这些以正确(或错误)方式实施的方法可能会强化或相信您提供给您问题的任何答案。