刚重下了最新包, 但是还有问题:

严重: Unable to serialize delta request for sessionid [0F5F859908E8C82B62B85C8399D58818]
java.io.NotSerializableException: com.jdon.container.visitor.ComponentOriginalVisitor
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1156)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
at org.apache.catalina.ha.session.DeltaRequest$AttributeInfo.writeExternal(DeltaRequest.java:374)
at org.apache.catalina.ha.session.DeltaRequest.writeExternal(DeltaRequest.java:272)
...

出错了


我把原来的那个jboss server/default/deploy内的jivejdon.war替换成了现在的jivejdon3.5的war,结果在发帖的时候出错了,能否解释一下。顺便说一下,本来这个帖子是修改上面那个帖子的。但是很意外,刚才发的那个帖子居然没有修改这个权限,好像目前还没人回复那个帖子吧,怎么自己的发的帖子都不能修改了呢?是不是上传了图片的缘故哟?

[该贴被Hqiu于2008-11-21 15:52修改过]

>java.io.NotSerializableException: com.jdon.container.visitor.ComponentOriginalVisitor


应该彻底解决了,你重新下载。

楼上另外一个错误是升级JiveJdon3.5 必须同时升级Jdon框架,好像是缺少jdom.jarz这个包。

》怎么自己的发的帖子都不能修改了呢
一直有这个顽固BUG,还没找到原因,不定期发生,和并发可能有关,正常测试和性能测试都没有,郁闷。

发现jivejdon3.5提供了完整的设计文档,长达73页啊,至今我还没看到其他哪个开源软件有如此详细的设计文档的,对于大四的那些要做BBS毕业设计的人来说这可谓天上掉下来的宝贝。
jivejdon已经完全开放,我似乎看到了它明天的辉煌!

todo.txt
@component 表示没有名称的组件,有该注释的类都将在启动时和jdonframework.xml中定义的component类
一起载入Jdon的微容器中。
@service(name="") 同@component,不同的是有一个名称,供微容器外调用。

Model的CRUD操作可以在Model类中进行
@Key 表示主键
@Form 表示对应的界面
@CRUDservice(ref="accountService", init="initAccount")
或将@CRUD(model=init) @CRUD

banq老师,这要等多久?好着急啊!!呵呵

重新下了一下包, 还是不行, 同样的错误。 好像那个包没有更新哦, dist下jar文件的日期还是11:08 分, 早上的版本。

现在已经更新,可以下载了。

今天JiveJdon3.5又更新一次,主要解决我上面所的顽固BUG,这个BUG是偶尔出现,这种不可捉摸的问题一般都是设计思路引起的,也就是你的设计没有与领域中那个规律共振,所以,难免有不和谐的问题。

我也从并发线程锁等方面考虑,但是发现,其实最好最严格的对象封装设计才是线程最安全的,这个可以从下面理解:

这个顽固问题是每次回帖后,再主题列表中,看最新回复,没有得到更新反应,在JJ中,我设计师用ForumThreadState来封装更新信息的,现在问题就是,也许ForumThreadState没有更新,或者更新的ForumThreadState是另外一个对象。不过,对象不一致性已经通过缓存解决了,因为发表回帖时,首先要缓存中获得父贴,而父贴因为之前用户阅读了,肯定在缓存中,不会立即被更新,所以,新的回帖和父贴就公用一个ForumThread,所以,不存在不一致性,可能很小。

那么为什么ForumThread的ForumThreadState有时没有执行呢?代码中ForumThreadState有几个动作:读取TreeModel(用来维持内存中帖子的树形结构);从数据库SQL查询获得最新帖子然后将这个帖子赋予ForumThreadState的lastPost,问题可能就出在这两处:

首先,通过JProfiler发现“读取TreeModel”很费CPU,每次帖子更新,需要从数据库中重新收集树形结构信息,树形结构反复访问很耗数据库性能,为什么要重新刷新呢,难道不能就只是将最新帖子加入已经存在内存树形结构中,不就更好吗?不必要读取数据库了,内存中ForumThread其实有一份,思考到这里,我也很惭愧我潜意识还是数据库编程,完全忽视内存中ForumThread,总是将缓存或内存中对象看成是数据库的备份,而不是将数据库看成是内存中对象的备份,当我的思路转到后面上来时,就豁然开朗了。

这样,我在ForumThread增加AddNewMessage这样的方法,将当前回帖加入内存中ForumThread的TreeModel中,而不是每次回帖后,从数据库中查询后,再创建新的treeModel,这样,性能快多,也避免因为回帖动作刚刚写完数据库,事务过程有可能没有结束(事务通常较慢),数据库隔离级别是read_commit,再读取可能因为没有commit,不能从数据库读取到最新回帖,新的思路也避免了这种情况的存在。

当我思路回到围绕内存中 ForumThread 对象时,该主题中最新一个帖子也是直接在addNewMessage中通过setLastPost迅速直接完成,不必再到数据库按时间select最新帖子了,这样,ForumThread 中state对象都可以通过 ForumThread 的addNewMessage update 等方法完成,ForumThread 也成为一个标准的胖模型,丰富模型。

看到有人将saveToDB放入领域模型中,这是一种生搬硬套,因为saveToDB涉及服务和SQL,这些很重的单例资源是不能绑在领域模型中的,只有该领域模型做聚合根,对其内部各个子对象的封闭性操作方法才是最好的胖模型行为。

而且,这样的领域模型因为保存在缓存中,每个实例只有一个,在多用户访问同一个实例领域模型情况下,也符合并发计算中所谓安全发布,在多线程下,只有将自己的行为封装在自己对象内部,再通过synchronized等内部锁机制保证这个模型对象内部操作一致性和原子性,否则,你将这些本来属于内部操作的,如forumThread的addNewMessag搬迁到service或外部实现,如果上锁,保证写读的封闭性都是很难做到的。

以上,从一个顽固BUG修正,谈到围绕对象编程和围绕数据库编程两个思路导致的问题,以及领域胖模型 和并发线程安全,这些都是统一的,当你思路重点在对象上,你才会关注领域模型的质量,才会关注并发线程安全。

当然,有可能这个BUG还不能修复,但是至少我自己在修复重前进了一步,走出之前被数据库绕了一圈的弯路。


[该贴被banq于2008-11-22 23:05修改过]

经过上述设计重构,发现问题依然。
前面认为出现这个BUG有两个原因:
1. 回帖更新的ForumThread可能不是浏览时的ForumThread,前面排除这个原因,焦点还是转移到这里。
2. 回帖更新动作很费CPU,或者从数据库中读取最新贴这一过程过于重量,经过前面重构,通过丰富ForumThread行为,增加addNewMessage等方法来直接在内存中更新。

既然第2点已经做得很好,那么就是第一点还是有问题,也就是说回帖更新的ForumThread就不是浏览时的ForumThread。这个情况出现是因为Thread的生命周期掌握不对。

至于在哪里不对,也无法从代码中一一定位,因为生命周期问题不会出现在某个具体代码处,它是整个代码在运行时刻一个总体表现,只有从两个方面来解决这个问题:
1. 断点跟踪回帖更新流程,仔细核对流程中thread的生命周期状态。
2. 重新考虑Thread模型性质:是实体 还是值对象?

这两个方面考虑都得到进展:
在核对回帖流程中,会想到一种可能:thread平时都保存在cache中,但是cache会定时清除,这样thread被cache清除后,下次再访问thread时,必须重新创建一个新的thread对象;而thread又可能被Message引用,这些Message还在缓存中,没有清除,这样这些message中的thread就一直存在,这些thread就和重新创建的thread不是同一个对象,thread不是共享了,变成复制有多份,回帖更新只是其中一个thread。

重新考虑thread的模型性质,它实质是根message,根贴这样实体的代表,thread应该和RootMessage根贴生命周期是一致的。生命周期控制是在Factory中实现的,因此Factory代码中应该加入这两者一致的约束性,之前没有做到,这部分代码要重构。

Thread虽然是实体RootMessage代表,但是它又有值对象Value Object影子,thread一般不变的,只有更新时才会变化,这个变化并不违反DDD中关于值对象不变的约束。

值对象有两种被其他对象使用方式:复制和共享,复制是被推荐的方式,因为值对象是不变的,没有标识,当然可以使用FlyWeight大量复制,每个引用对象人手一份,虽然每个引用对象引用的值对象不是同一个实例,但是他们内容相同,而且在传统的分布式环境中复制很容易传播。
thread因为有实体影子,用户浏览主题列表时,需要查询thread集合,这些使用复制是都可以实现,关键是:用户浏览主题时,他想知道这个主题更新信息,最后回帖是谁等等,如果使用thread的复制,那么所有thread都要通知到,显然不切实际。

所以,thread只能特殊使用共享。一个thread实例被缓存后,可以被这个主题下所有帖子Message共享,当有新帖更新时,更新thread状态,所有帖子对象引用的是同一个thread,他们就都知道,当前这个主题中有更新,如果更新的根贴RootMessage,就用新的根贴替代thread中原来的。

所有重构都集中到thread的工厂中,工厂不但要保证thread和RootMessage是一致的;而且必须保证thread是单例被共享的。


[该贴被banq于2008-11-23 19:34修改过]

恭喜Jdon框架5.5版本和JiveJdon3.5发布...

还有错:

严重: Unable to serialize delta request for sessionid [1A769BB9F333CCEDE4B6EA758
5859A85]
java.io.NotSerializableException: com.jdon.container.pico.PicoContainerWrapper
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1156)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1474)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1392)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
at org.apache.catalina.ha.session.DeltaRequest$AttributeInfo.writeExternal(DeltaRequest.java:374)
at org.apache.catalina.ha.session.DeltaRequest.writeExternal(DeltaRequest.java:272)
at org.apache.catalina.ha.session.DeltaRequest.serialize(DeltaRequest.java:287)

两个解决办法:
1. 升级你的tomcat或其他服务器,tomcat低版本时有这个严格要求。
2.下载最新的jdon框架,打开container.xml,找到下面行:
<component name="httpSessionVisitorFactorySetup"
class="com.jdon.container.visitor.http.HttpSessionVisitorFactorySetup">
<constructor value="40" />
<!-- it is count of the cached instances that saved in a sessionContext instance, -->
<constructor value="true" /> <!-- disable all session cached except SessionConext -->
</component>

将其中true改为false,也就是失效htttpSession作为动态代理实例的缓存这一功能,在HttpSession中只能放用户的数据。

以上是终极方案,如果还有问题,就没有办法了。。。。。

报告:

1. Tomcat 已经是最新版 6.0.18
2. jdon 框架包是今天早上才下的。 container.xml里面没有你所说的那句。 只有
<!-- if not use HttpSession as SessionContext Container, replace this -->
<component name="visitorFactory"
class="com.jdon.container.visitor.http.HttpSessionVisitorFactoryImp" />

>jdon 框架包是今天早上才下的
晕倒,我发贴时才上传最新的。中午以后传的。

不好意思, 没仔细查。

重下了最新的jdon包, 也尝试了把true改成false, 但是还是不幸的看到了java.io.NotSerializableException: com.jdon.container.pico.PicoContainerWrapper 错误。 :(

吐血再改一次,也是原来设计不太好,在放入Session的接口中涉及PicoContainerWrapper 耦合,已经去除,18点左右上传。

你需要做的就是:确认用winrar打开JdonFramework.jar中META-INF的container.xml是否改为false,可以将container.xml先拖到某个文件夹下,修改后,再拖回去即可。

因为设置为false,也就是不再用HttpSession缓存动态代理,我测试发现,最快速度慢了10毫秒,还可以忽略。