<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>涂0实验室 &#187; jboss</title>
	<atom:link href="http://www.sulong.info/archives/tag/jboss/feed" rel="self" type="application/rss+xml" />
	<link>http://www.sulong.info</link>
	<description>一个程序员的成长之路</description>
	<lastBuildDate>Fri, 27 Aug 2010 01:54:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>王者归来之Seam ?!</title>
		<link>http://www.sulong.info/archives/135</link>
		<comments>http://www.sulong.info/archives/135#comments</comments>
		<pubDate>Thu, 18 Dec 2008 04:58:38 +0000</pubDate>
		<dc:creator>imlsq</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[jboss]]></category>
		<category><![CDATA[seam]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=135</guid>
		<description><![CDATA[王者归来之Seam??!!! 前言： seam :  以前在项目开发的过程中，你需要引入很多框架（比如：hibernate, jsf , 工作流引擎&#8230;.) ,  JBOSS说，你们自己做整合，不专业，我来帮你们做了这个工作吧，我来整合，肯定比你们自己整合要好。于此，JBOSS招兵买马，把hibernate的核心团队，JSF规范制定核心团队，EJB3规范制定核心团队等等，都找来当咨询顾问，共讨整合之事，如此诞生了一个新宝宝,取名为SEAM 使用Seam已经有1个多月的时间了，对Seam有一些简单的了解，谈谈我对Seam的一点感想吧。Seam的目标就是把各种优秀的开源系统，J2EE规范，都通过seam这个框架整合起来，从而简化开发工作，提高开发效率。我想这是seam的目标。 seam亮点： 1  JSF和EJB3.0规范实现与整合是亮点之一。 seam实现了SUN公司JSF规范做了不错的工作，在开发JSF应用时，简化了一些JSF。 Seam框架试图简化JSF的开发比如JSF的异常处理，XML配置，JSF组件的调用等等，在开发的时候让JSF和后端的业务逻辑组件(business service bean)达到紧凑，易用的效果。 2 Seam 很有意思的组件管理 我没有去看seam的源代码，但是从seam的介绍文档里有一些简要的介绍，如果有说得不对的地方，仅为交流。 Seam有2种方式来管理组件，一种为了跟JSF，JSP, servlet 等接口，seam 在web.xml 里添加了一个SeamListener，把JSF所需要的组件实例缓存到ServletContext或者HttpSession中，当请求完成或者Session失效时销毁组件实例. 另一种方式是Seam业务组件，这个组件的生命周期管理，类似EJB3规范里规定的方式,Seam业务组件的生命周期管理是否就是EJB3组件规范的实现，还是有自己的管理方式，这些方面的问题，将在以后再去深入了解。 总之，有了对组件的生命周期管理，您不需要去关心事务，并发，同步等问题。我一直都觉得EJB3的组件生命周期管理，比Spring的实现要舒服很多(Spring的组件生命周期管理，还要实现Spring 的InitializingBean,DisposableBean 这2个类,EJB3的组件就是一个很干净的POJO)。 3 Hibernate，Seam中集成的经典JPA EJB3的JPA规范，作为EJB3的重要组成部分，Seam中对此规范的实现，整合了Hibernate3. 在使用的过程中，好像针对Hibernate3做了一些优化,让您在开发过程中，使用hibernate3更加简单一些了。 EJB2的持久化方案，在过去的几年，被hibernate3之前的版本彻底打败，EJB3开始, 这2家冤家对头，居然走到了一起。在ejb3的JPA规范发布不久，Hibernate就开始支持这一规范, 以前的相互指责，现在变成相互吹捧。 (题外话：其实我在做项目的过程中是很不喜欢hibernate的，不是因为他能提高效率的话，早就抛弃它了。我更喜欢ibatis一些，都是手工写的SQL代码做成映射关系，效率提高很多，可惜他现在对ejb3规范还不支持。虽然开发的时候会多写一点代码，那可是值得的) Seam真的是王者归来，我见未必。让我们跳出SEAM看seam。 不要看seam的介绍文档说得多好听，好比一个人自己说自己多厉害一样，没用，还是要人家去评价才行。 在你使用seam之前，请仔细评估自己的需求，是否需要使用他。 1，你的项目是否需要使用EJB？ SEAM 在文档里有说明，SEAM也可以开发类似struts+spring+hibernate一样的轻量级架构的系统，但是那是胡说八道。我可以负责任的告诉 你，seam是一个很重的架构，他大多数的技术体系都是偏重于EJB，用他开发SSH类似的系统，只会误事误工。 2, JSF是否适合你的项目？ JSF 是SUN公司主推的一种表示层解决方案。可惜生不逢时，用JSF做企业应用，有Flex,Silverlight等技术比他强。 用JSF做WEB网页方向的应用，JSF更是滑稽可笑。也许有人说，JSF跟Seam有什么关系？但是我告诉你,seam核心目标之一就是整合JSF做表 示层开发，是他整合目标的重要组成部分。如果你打算应用seam，那么表示层的开发就一定绕不过JSF这一关。尽管seam说，他不用JSF也可以，但是 不用JSF，用什么！！ 没有其它好的选择了。 3,开发效率低 [...]]]></description>
			<content:encoded><![CDATA[<p>王者归来之Seam??!!!</p>
<p>前言：<br />
seam :  以前在项目开发的过程中，你需要引入很多框架（比如：hibernate, jsf , 工作流引擎&#8230;.) ,  JBOSS说，你们自己做整合，不专业，我来帮你们做了这个工作吧，我来整合，肯定比你们自己整合要好。于此，JBOSS招兵买马，把hibernate的核心团队，JSF规范制定核心团队，EJB3规范制定核心团队等等，都找来当咨询顾问，共讨整合之事，如此诞生了一个新宝宝,取名为SEAM</p>
<p>使用Seam已经有1个多月的时间了，对Seam有一些简单的了解，谈谈我对Seam的一点感想吧。Seam的目标就是把各种优秀的开源系统，J2EE规范，都通过seam这个框架整合起来，从而简化开发工作，提高开发效率。我想这是seam的目标。</p>
<p>seam亮点：</p>
<p>1  JSF和EJB3.0规范实现与整合是亮点之一。</p>
<p>seam实现了SUN公司JSF规范做了不错的工作，在开发JSF应用时，简化了一些JSF。 Seam框架试图简化JSF的开发比如JSF的异常处理，XML配置，JSF组件的调用等等，在开发的时候让JSF和后端的业务逻辑组件(business service bean)达到紧凑，易用的效果。</p>
<p>2 Seam 很有意思的组件管理</p>
<p>我没有去看seam的源代码，但是从seam的介绍文档里有一些简要的介绍，如果有说得不对的地方，仅为交流。<br />
Seam有2种方式来管理组件，一种为了跟JSF，JSP, servlet 等接口，seam 在web.xml 里添加了一个SeamListener，把JSF所需要的组件实例缓存到ServletContext或者HttpSession中，当请求完成或者Session失效时销毁组件实例.</p>
<p>另一种方式是Seam业务组件，这个组件的生命周期管理，类似EJB3规范里规定的方式,Seam业务组件的生命周期管理是否就是EJB3组件规范的实现，还是有自己的管理方式，这些方面的问题，将在以后再去深入了解。<br />
总之，有了对组件的生命周期管理，您不需要去关心事务，并发，同步等问题。我一直都觉得EJB3的组件生命周期管理，比Spring的实现要舒服很多(Spring的组件生命周期管理，还要实现Spring 的InitializingBean,DisposableBean 这2个类,EJB3的组件就是一个很干净的POJO)。</p>
<p>3 Hibernate，Seam中集成的经典JPA</p>
<p>EJB3的JPA规范，作为EJB3的重要组成部分，Seam中对此规范的实现，整合了Hibernate3. 在使用的过程中，好像针对Hibernate3做了一些优化,让您在开发过程中，使用hibernate3更加简单一些了。</p>
<p>EJB2的持久化方案，在过去的几年，被hibernate3之前的版本彻底打败，EJB3开始, 这2家冤家对头，居然走到了一起。在ejb3的JPA规范发布不久，Hibernate就开始支持这一规范, 以前的相互指责，现在变成相互吹捧。</p>
<p>(题外话：其实我在做项目的过程中是很不喜欢hibernate的，不是因为他能提高效率的话，早就抛弃它了。我更喜欢ibatis一些，都是手工写的SQL代码做成映射关系，效率提高很多，可惜他现在对ejb3规范还不支持。虽然开发的时候会多写一点代码，那可是值得的)</p>
<p>Seam真的是王者归来，我见未必。让我们跳出SEAM看seam。</p>
<p>不要看seam的介绍文档说得多好听，好比一个人自己说自己多厉害一样，没用，还是要人家去评价才行。 在你使用seam之前，请仔细评估自己的需求，是否需要使用他。</p>
<p>1，你的项目是否需要使用EJB？</p>
<p>SEAM 在文档里有说明，SEAM也可以开发类似struts+spring+hibernate一样的轻量级架构的系统，但是那是胡说八道。我可以负责任的告诉 你，seam是一个很重的架构，他大多数的技术体系都是偏重于EJB，用他开发SSH类似的系统，只会误事误工。</p>
<p>2, JSF是否适合你的项目？</p>
<p>JSF 是SUN公司主推的一种表示层解决方案。可惜生不逢时，用JSF做企业应用，有Flex,Silverlight等技术比他强。 用JSF做WEB网页方向的应用，JSF更是滑稽可笑。也许有人说，JSF跟Seam有什么关系？但是我告诉你,seam核心目标之一就是整合JSF做表 示层开发，是他整合目标的重要组成部分。如果你打算应用seam，那么表示层的开发就一定绕不过JSF这一关。尽管seam说，他不用JSF也可以，但是 不用JSF，用什么！！ 没有其它好的选择了。</p>
<p>3,开发效率低</p>
<p>呵呵，seam说我的开发效率很高嘛，但那是他自己说的嘛，seam开发环境只能在Jboss里运行才有良好的表现，Jboss在开发,调试,部署还是非常麻烦，和tomcat比效率低很多。</p>
<p>4,学习成本</p>
<p>seam引入了很多相关的其它框架包，假设你有良好的JAVA基础，一个未使用过seam的开发团队，熟悉seam起码也要3周以上的时间，这是我见过的学习成本最高的框架,他整合的框架很多，技术面很广.</p>
<p>5，大型系统的解决方案，seam还是无法提供</p>
<p>一个大型的系统，核心的关键点是：负载均衡，集中缓存处理，并行计算， 分布式存取等， seam面对这些问题，一样显得力不从心，这些问题还是需要架构师自己动手解决。而且seam中有一个web beans的技术(我在想，他使用这个是否考虑到整合JSF才这么做呢！)，给负载均衡, session的处理还不及其它框架灵活。</p>
<p>Seam是否是归来的王者？ 让我们拭目以待！</p>
<p>文章内容只是个人之见，肤浅之处，意在交流。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/135/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>如何让jboss下的消息驱动bean消费远程JMS消息</title>
		<link>http://www.sulong.info/archives/130</link>
		<comments>http://www.sulong.info/archives/130#comments</comments>
		<pubDate>Wed, 10 Dec 2008 11:44:58 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[技巧]]></category>
		<category><![CDATA[程序]]></category>
		<category><![CDATA[jboss]]></category>
		<category><![CDATA[jms]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=130</guid>
		<description><![CDATA[用消息驱动bean来处理本地的JMS消息太容易不过了，但是如何处理远程的消息呢？翻遍了Java EE手册和API也找不到。原来各种应用服务器都有各自的实现。那么如何让jboss下的消息驱动bean消费远程JMS消息呢？把下面的代码复制到一个文件里，并重名为以-service.xml结尾的文件，放到jboss的deploy目录，就可以在本地得到一个从远程获取消息的JMS provider。 &#160; &#160; &#60;mbean code=&#34;org.jboss.jms.jndi.JMSProviderLoader&#34; name=&#34;jboss.mq:service=JMSProviderLoader,name=RemoteJMSProvider,server=remotehost&#34;&#62; &#160; &#160; &#160; &#160; &#60;attribute name=&#34;ProviderName&#34;&#62;RemoteJMSProvider&#60;/attribute&#62; &#160; &#160; &#160; &#160; &#60;attribute name=&#34;ProviderAdapterClass&#34;&#62;org.jboss.jms.jndi.JNDIProviderAdapter&#60;/attribute&#62; &#160; &#160; &#160; &#160; &#60;!-- The connection factory --&#62; &#160; &#160; &#160; &#160; &#60;attribute name=&#34;FactoryRef&#34;&#62;UIL2XAConnectionFactory&#60;/attribute&#62; &#160; &#160; &#160; &#160; &#60;!-- The queue connection factory --&#62; &#160; &#160; &#160; &#160; &#60;attribute name=&#34;QueueFactoryRef&#34;&#62;UIL2XAConnectionFactory&#60;/attribute&#62; &#160; &#160; &#160; &#160; [...]]]></description>
			<content:encoded><![CDATA[<p>用消息驱动bean来处理本地的JMS消息太容易不过了，但是如何处理远程的消息呢？翻遍了Java EE手册和API也找不到。原来各种应用服务器都有各自的实现。那么如何让jboss下的消息驱动bean消费远程JMS消息呢？把下面的代码复制到一个文件里，并重名为以-service.xml结尾的文件，放到jboss的deploy目录，就可以在本地得到一个从远程获取消息的JMS provider。<br/></p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mbean</span> <span style="color: #000066;">code</span>=<span style="color: #ff0000;">&quot;org.jboss.jms.jndi.JMSProviderLoader&quot;</span> </span><br />
<span style="color: #009900;"><span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;jboss.mq:service=JMSProviderLoader,name=RemoteJMSProvider,server=remotehost&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;attribute</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;ProviderName&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>RemoteJMSProvider<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/attribute<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;attribute</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;ProviderAdapterClass&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>org.jboss.jms.jndi.JNDIProviderAdapter<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/attribute<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">&lt;!-- The connection factory --&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;attribute</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;FactoryRef&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>UIL2XAConnectionFactory<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/attribute<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">&lt;!-- The queue connection factory --&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;attribute</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;QueueFactoryRef&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>UIL2XAConnectionFactory<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/attribute<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">&lt;!-- The topic factory --&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;attribute</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;TopicFactoryRef&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>UIL2XAConnectionFactory<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/attribute<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">&lt;!-- Connect to JNDI on the host &quot;the-remote-host-name&quot; port 1099--&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;attribute</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;Properties&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; java.naming.factory.url.pkgs=org.jnp.interfaces<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; java.naming.provider.url=the-remote-host-name:1099<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/attribute<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/mbean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p><br/><br />
注意，你要把上面的 the-remote-host-name 改成你的。部署完成后，确认在jboss的JndiViewer里能不能看到 java:/RemoteJMSProvider 。然后再MDB类上加上：<br/></p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; @MessageDriven<span style="color: #009900;">&#40;</span>activateConfig <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; @ActivationConfigProperty<span style="color: #009900;">&#40;</span>propertyName<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;destinationType&quot;</span>, propertyValue<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;javax.jms.Queue&quot;</span><span style="color: #009900;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; @ActivationConfigProperty<span style="color: #009900;">&#40;</span>propertyName<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;destination&quot;</span>, propertyValue<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;queue/testQueue&quot;</span><span style="color: #009900;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; @ActivationConfigProperty<span style="color: #009900;">&#40;</span>propertyName<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;providerAdapterJNDI&quot;</span>, propertyValue<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;java:/RemoteJMSProvider&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> MDB <span style="color: #000000; font-weight: bold;">implements</span> MessageListener <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></div>
<p><br/><br />
providerAdapterJNDI属性使这个MDB从刚才部署好的JMS provider那里读取消息。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/130/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jboss集群的Barrier mbean是个好东西</title>
		<link>http://www.sulong.info/archives/125</link>
		<comments>http://www.sulong.info/archives/125#comments</comments>
		<pubDate>Tue, 09 Dec 2008 13:38:06 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[技巧]]></category>
		<category><![CDATA[经验]]></category>
		<category><![CDATA[cluster]]></category>
		<category><![CDATA[jboss]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=125</guid>
		<description><![CDATA[在jboss集群时，有一种服务被称为高可用单例服务，意思是指在集群中同时肯定有且只会有一个节点提供这个服务。换句话说这种服务只会在一个节点上启动，并且当这个节点不可用时，集群中会有另一个节点代替它，它是一个具有故障恢复能力的单例服务。要实现这种服务，最简单的方法就是把部署单元，如war, ear, jar，等放到jboss/server/all/deploy-hasingleton/ 目录下。但是放在这个目录下的应用是不能热部署，也不具有farm deploy功能的。还好jboss里有一个很特殊的mbean叫 jboss.ha:service=HASingletonDeployer,type=Barrier，利用它可以很容易的实现高可用单例服务。这个bean很特殊，只有在集群的master节点上它才会被启动，而一旦master节点不再是master，它又会停止。所以一个普通的部署单元，只要依赖上了barrier，就会具有高可用单例服务的能力。下面举一个例子。 现在要实现一个高可用的消息驱动bean，监听远程机器上的消息topic/a。如果只在集群中的一个节点上部署这个MDB，一旦这个节点不可用，消息处理就停止了。为了提高可用性，可以在每个节点上部署这个MDB，但这时同一个消息会被每个MDB收到和处理，这不是我们想要的，因为同一个消息应该只被一个 MDB处理。这个时候只要让这个MDB对barrier依赖，再把它部署在所有节点上，那么就只有主节点上的MDB会运行，并且当主节点完蛋时，其他节点变成主节点时，那个节点上的MDB会自动运行。这样我们就实现了高可用单例消息驱动bean服务。 要让mbean对barrier依赖，只要在它的部署文件里填上一行，例如: &#160; &#160; &#60;server&#62; &#160; &#160; &#160; &#160; &#60;mbean name=&#34;xx&#34; code=&#34;xx.xx.xxx&#34;&#62; &#160; &#160; &#160; &#160; &#160; &#160; &#60;depends&#62;jboss.ha:service=HASingletonDeployer,type=Barrier&#60;/depends&#62; &#160; &#160; &#160; &#160; &#60;/mbean&#62; &#160; &#160; &#60;/server&#62; 对于war,jar,ear，可以在jboss.xml里添加，具体见jboss文档。对于ejb3，加上下面的annotation就好了： @org.jboss.annotation.ejb.Depends&#40;&#34;jboss.ha:service=HASingletonDeployer,type=Barrier&#34;&#41;]]></description>
			<content:encoded><![CDATA[<p>在jboss集群时，有一种服务被称为高可用单例服务，意思是指在集群中同时肯定有且只会有一个节点提供这个服务。换句话说这种服务只会在一个节点上启动，并且当这个节点不可用时，集群中会有另一个节点代替它，它是一个具有故障恢复能力的单例服务。要实现这种服务，最简单的方法就是把部署单元，如war, ear, jar，等放到jboss/server/all/deploy-hasingleton/ 目录下。但是放在这个目录下的应用是不能热部署，也不具有farm deploy功能的。还好jboss里有一个很特殊的mbean叫 jboss.ha:service=HASingletonDeployer,type=Barrier，利用它可以很容易的实现高可用单例服务。这个bean很特殊，只有在集群的master节点上它才会被启动，而一旦master节点不再是master，它又会停止。所以一个普通的部署单元，只要依赖上了barrier，就会具有高可用单例服务的能力。下面举一个例子。<br/></p>
<p>现在要实现一个高可用的消息驱动bean，监听远程机器上的消息topic/a。如果只在集群中的一个节点上部署这个MDB，一旦这个节点不可用，消息处理就停止了。为了提高可用性，可以在每个节点上部署这个MDB，但这时同一个消息会被每个MDB收到和处理，这不是我们想要的，因为同一个消息应该只被一个 MDB处理。这个时候只要让这个MDB对barrier依赖，再把它部署在所有节点上，那么就只有主节点上的MDB会运行，并且当主节点完蛋时，其他节点变成主节点时，那个节点上的MDB会自动运行。这样我们就实现了高可用单例消息驱动bean服务。<br/></p>
<p>要让mbean对barrier依赖，只要在它的部署文件里填上一行，例如:<br/></p>
<div class="codecolorer-container xml default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;server<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mbean</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;xx&quot;</span> <span style="color: #000066;">code</span>=<span style="color: #ff0000;">&quot;xx.xx.xxx&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;depends<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jboss.ha:service=HASingletonDeployer,type=Barrier<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/depends<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/mbean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/server<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>对于war,jar,ear，可以在jboss.xml里添加，具体见jboss文档。对于ejb3，加上下面的annotation就好了：<br/></p>
<div class="codecolorer-container java default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">@org.<span style="color: #006633;">jboss</span>.<span style="color: #006633;">annotation</span>.<span style="color: #006633;">ejb</span>.<span style="color: #006633;">Depends</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;jboss.ha:service=HASingletonDeployer,type=Barrier&quot;</span><span style="color: #009900;">&#41;</span></div></div>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/125/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>jboss下通过本地接口访问ejb3遇到的问题</title>
		<link>http://www.sulong.info/archives/109</link>
		<comments>http://www.sulong.info/archives/109#comments</comments>
		<pubDate>Mon, 08 Sep 2008 10:27:42 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[deploy]]></category>
		<category><![CDATA[ejb]]></category>
		<category><![CDATA[jar]]></category>
		<category><![CDATA[jboss]]></category>
		<category><![CDATA[war]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=109</guid>
		<description><![CDATA[在jboss下，如果包含ejb的jar，和要通过local接口访问ejb的war不被打包成一个ear来部署，会遇到问题。如果你的war中包含了ejb3的local接口的class，那么war在通过jndi取得ejb的引用试图将其转化成接口类型时会抛ClassCastException。而如果war中不包含local接口的class，则会抛class not found的异常。这都是由讨厌的classloader问题导致的。每个放到jboss的deploy目录里的部署单元都有自己的独立的classloader树，这两棵树在jvm的classloader里是平级的。如果war和ejb jar里都包含了某个ejb的local接口的class时，那么同一个类就分别存在于两棵classloader树中。通过jndi取得的引用的类型是ejb jar中的local接口的类型，将其转化成war里的那个local接口类型时就出错了，因为它们不是同一个类。而classloader是不能访问同级的其他的classloader下的类的，所以如果war里不包含接口的class，有会因找不到class而出错。 这种时候就是使用ear的时候，位于同一个ear里ejb jar的classloader是war的classloader的父classloader。这样，只需要部署一份接口类，war也能访问到它，因为子classloader能访问父classloader载入的类。]]></description>
			<content:encoded><![CDATA[<p>在jboss下，如果包含ejb的jar，和要通过local接口访问ejb的war不被打包成一个ear来部署，会遇到问题。如果你的war中包含了ejb3的local接口的class，那么war在通过jndi取得ejb的引用试图将其转化成接口类型时会抛ClassCastException。而如果war中不包含local接口的class，则会抛class not found的异常。这都是由讨厌的classloader问题导致的。每个放到jboss的deploy目录里的部署单元都有自己的独立的classloader树，这两棵树在jvm的classloader里是平级的。如果war和ejb jar里都包含了某个ejb的local接口的class时，那么同一个类就分别存在于两棵classloader树中。通过jndi取得的引用的类型是ejb jar中的local接口的类型，将其转化成war里的那个local接口类型时就出错了，因为它们不是同一个类。而classloader是不能访问同级的其他的classloader下的类的，所以如果war里不包含接口的class，有会因找不到class而出错。</p>
<p>这种时候就是使用ear的时候，位于同一个ear里ejb jar的classloader是war的classloader的父classloader。这样，只需要部署一份接口类，war也能访问到它，因为子classloader能访问父classloader载入的类。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/109/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>理解seam的conversation</title>
		<link>http://www.sulong.info/archives/90</link>
		<comments>http://www.sulong.info/archives/90#comments</comments>
		<pubDate>Sun, 29 Jun 2008 15:23:08 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[程序]]></category>
		<category><![CDATA[jboss]]></category>
		<category><![CDATA[seam]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=90</guid>
		<description><![CDATA[几乎所有对seam进行介绍的文档中都会用大量的篇幅来说明会话(conversation)，因为它是seam的发明，让seam与众不同的一个地方。但是要完全理解和运用conversation并不是容易呀。会话是一种用来存储程序上下文数据的容器，和session类似，只不过它的生存周期和session有很大的差别。 会话分成两类，临时会话和长会话。临时会话会开始于服务器端处理客户端的post请求，结束于下一个页面的生成。也就是说，它存在于post-&#62;redirect-&#62;get 这样一个小周期内。典型的例子是facesmessage组件。这是一个会话内的组件。我们在处理post请求时，写的message，在下个页面生成的时候依然有效。比如，用户提交一个注册表单，表单POST提交后，服务器调用注册方法，在方法结束的时候，调用facesmessage设定信息“注册成功了！”。然后服务器发送一个跳转的response让浏览器转向index页面。在index页面里，我们输出facesmessages里的内容，这时，这个message能够成功的拿到。因为那个facesmessage组件跨越了那一次跳转。之后，如果提交index上的表单的话，又会有一个新的临时会话产生，之前的会话里的内容将不再存在。长会话可以存活得更长。如果在一个短会话内，程序中执行了带有@Begin的方法，或者在page.xml里有配置&#60;begin-conversation/&#62;，那么这个临时会话，就会变成一个长会话。如果服务端在执行方法时遇到标有@End的标注，或者在page.xml里遇到&#60;end-conversation /&#62;，当前的长会话，将会结束；否则，它会一直持续下去。 会话与JPA的entityManager的关系。一个entityManager与hibernate的session相当。JPA里定义的entityManager一级缓存的刷新方式只有两种：Auto和commit。seam发明了第三种方式，Manual。Auto意味着，当执行到select语句时，entityManger会自动执行一下flush()方法，commit会在事务提交时flush()；而Manual则是由你自己来手动控制flush()。每次开始一个会话的时候，seam都会为你开启一个entityManager，这个entityManger会一直打开，直到conversation结束。这是seam的作者Gavin最骄傲的地方了。能让hibernate的session持续在一个会话之内，可以在会话期内的几次服务器与客户端的几次交往中避免LazyInitializationException，最大程度的发挥hibernate延迟载入的能力。其实Gavin最初要把服务端做成这样有状态的，就是因为他认为与orm协作的最佳方式，就是让服务端有状态。 长会话的结束。默认的情况下，当遇到&#60;end-conversation /&#62;或@End时，会话并不会立刻结束，而是会在下个页面生成之后才结束，这是为了避免生成页面时无法取到前一个页面POST时处理的结果。但是有的时候，我们确实需要在POST之后，下个页面生成之前就结束掉。这时需要用@End(beforeRedirect=true),或 &#60;end-conversation before-redirect=&#8221;true&#8221; /&#62;。 会话的维持。我们都知道session是靠一个叫JSESSIONID的cookie或者请里的参数来维持的。类似的会话也是通过这么一个特殊的请求参数来控制的，默认为cid。观查cid的变化，能帮助我们查看conversation的变化。 为什么要发明会话呢？？这得从seam的作者Gavin说起。这个牛人发明了杰出的ORM框架hibernate，但是却发现现在的web开发方式并没有正确的使用它。和 hibernate搭档最多的当属spring了。在结合spring使用hibernate的时候，我们很难把握得好hibernate session的范围，如果太窄，那么在这个范围之外对持久对象的调用很容易产生LazyInitializationException。所以后来OpenSessionInView的方式很流行。但这还是不能完全解决问题。OpenSessionInView把session的范围扩大到了对一个http request的处理过程之中，而不能处理跨页面的情况。如果把hibernate session扩大到 http session范围内，这显然会让session太长，引发其它问题。所以Gavin觉得需要一种能够跨越页面，并且又不会像http session那样太长的Scope，于是conversation就诞生了。在开发中，尤其是以提交表单方式为主的企业开发中，常常需要用几个页面来配合完成一个用例，这几个页面内的数据往往耦合性强，需要被放到同一个上下文中，而这个上下文用conversation来做也是很自然的。对于Gmail这样的应用，conversation没什么意义。 Conversation是个好东西，但是一定要小心的使用。一来它存在着性能问题 ，二来用的太多，不小心控制conversation的开始和结束，就会导致conversation的混乱，那个时候会导致一些奇怪的问题。]]></description>
			<content:encoded><![CDATA[<p>几乎所有对seam进行介绍的文档中都会用大量的篇幅来说明会话(conversation)，因为它是seam的发明，让seam与众不同的一个地方。但是要完全理解和运用conversation并不是容易呀。会话是一种用来存储程序上下文数据的容器，和session类似，只不过它的生存周期和session有很大的差别。<br id="k6p6" /><br />
会话分成两类，临时会话和长会话。临时会话会开始于服务器端处理客户端的post请求，结束于下一个页面的生成。也就是说，它存在于post-&gt;redirect-&gt;get 这样一个小周期内。典型的例子是facesmessage组件。这是一个会话内的组件。我们在处理post请求时，写的message，在下个页面生成的时候依然有效。比如，用户提交一个注册表单，表单POST提交后，服务器调用注册方法，在方法结束的时候，调用facesmessage设定信息“注册成功了！”。然后服务器发送一个跳转的response让浏览器转向index页面。在index页面里，我们输出facesmessages里的内容，这时，这个message能够成功的拿到。因为那个facesmessage组件跨越了那一次跳转。之后，如果提交index上的表单的话，又会有一个新的临时会话产生，之前的会话里的内容将不再存在。长会话可以存活得更长。如果在一个短会话内，程序中执行了带有@Begin的方法，或者在page.xml里有配置&lt;begin-conversation/&gt;，那么这个临时会话，就会变成一个长会话。如果服务端在执行方法时遇到标有@End的标注，或者在page.xml里遇到&lt;end-conversation /&gt;，当前的长会话，将会结束；否则，它会一直持续下去。<br id="yley" /></p>
<p>会话与JPA的entityManager的关系。一个entityManager与hibernate的session相当。JPA里定义的entityManager一级缓存的刷新方式只有两种：Auto和commit。seam发明了第三种方式，Manual。Auto意味着，当执行到select语句时，entityManger会自动执行一下flush()方法，commit会在事务提交时flush()；而Manual则是由你自己来手动控制flush()。每次开始一个会话的时候，seam都会为你开启一个entityManager，这个entityManger会一直打开，直到conversation结束。这是seam的作者Gavin最骄傲的地方了。能让hibernate的session持续在一个会话之内，可以在会话期内的几次服务器与客户端的几次交往中避免LazyInitializationException，最大程度的发挥hibernate延迟载入的能力。其实Gavin最初要把服务端做成这样有状态的，就是因为他认为与orm协作的最佳方式，就是让服务端有状态。<br id="jqks" /><br />
长会话的结束。默认的情况下，当遇到&lt;end-conversation /&gt;或@End时，会话并不会立刻结束，而是会在下个页面生成之后才结束，这是为了避免生成页面时无法取到前一个页面POST时处理的结果。但是有的时候，我们确实需要在POST之后，下个页面生成之前就结束掉。这时需要用@End(beforeRedirect=true),或<br />
&lt;end-conversation before-redirect=&#8221;true&#8221; /&gt;。<br id="xsp4" /><br />
会话的维持。我们都知道session是靠一个叫JSESSIONID的cookie或者请里的参数来维持的。类似的会话也是通过这么一个特殊的请求参数来控制的，默认为cid。观查cid的变化，能帮助我们查看conversation的变化。<br id="wo4q" /><br />
为什么要发明会话呢？？这得从seam的作者Gavin说起。这个牛人发明了杰出的ORM框架hibernate，但是却发现现在的web开发方式并没有正确的使用它。和<br />
hibernate搭档最多的当属spring了。在结合spring使用hibernate的时候，我们很难把握得好hibernate session的范围，如果太窄，那么在这个范围之外对持久对象的调用很容易产生LazyInitializationException。所以后来OpenSessionInView的方式很流行。但这还是不能完全解决问题。OpenSessionInView把session的范围扩大到了对一个http request的处理过程之中，而不能处理跨页面的情况。如果把hibernate session扩大到 http session范围内，这显然会让session太长，引发其它问题。所以Gavin觉得需要一种能够跨越页面，并且又不会像http session那样太长的Scope，于是conversation就诞生了。在开发中，尤其是以提交表单方式为主的企业开发中，常常需要用几个页面来配合完成一个用例，这几个页面内的数据往往耦合性强，需要被放到同一个上下文中，而这个上下文用conversation来做也是很自然的。对于Gmail这样的应用，conversation没什么意义。<br id="i7t8" /><br />
Conversation是个好东西，但是一定要小心的使用。一来它存在着<a id="w8j4" title="性能问题" href="http://www.sulong.info/archives/87">性能问题</a> ，二来用的太多，不小心控制conversation的开始和结束，就会导致conversation的混乱，那个时候会导致一些奇怪的问题。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/90/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>在会话内,EJB的性能优于普通java bean</title>
		<link>http://www.sulong.info/archives/88</link>
		<comments>http://www.sulong.info/archives/88#comments</comments>
		<pubDate>Fri, 27 Jun 2008 15:46:08 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[ejb]]></category>
		<category><![CDATA[jboss]]></category>
		<category><![CDATA[seam]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=88</guid>
		<description><![CDATA[用普通的java bean 做conversation scope内的组件会有这么大的性能问题，那么用ejb会怎么样呢？我今天特意做了一个测试，还是在那台开发机上，还是用那个 supplierSearchAction, 所做的变更，只是把SupplierSearchAction由普通的java bean变成了ejb。我在用ejb，普通conversation scope的java bean, 和page scope的 java bean分别测试了十次，最后的统计结果显示在conversation内ejb的性能还是要高于普通java bean的。conversation pojo 用时 5秒, conversation ejb 用时 3 秒, page pojo 用时 1 秒。在conversation内，ejb比pojo快40%, 而page scope内的pojo比前两者分别快 5 倍和 3倍。虽然还不清楚，为什么在conversation内ejb会比pojo性能要好，但在这一前提下，我们知道，如果非要写conversation内的组件，ejb将是更好的选择。]]></description>
			<content:encoded><![CDATA[<p>用普通的java bean 做conversation scope内的组件会有这么大的性能问题，那么用ejb会怎么样呢？我今天特意做了一个测试，还是在那台开发机上，还是用那个 supplierSearchAction, 所做的变更，只是把SupplierSearchAction由普通的java bean变成了ejb。我在用ejb，普通conversation scope的java bean, 和page scope的 java bean分别测试了十次，最后的统计结果显示在conversation内ejb的性能还是要高于普通java bean的。conversation pojo 用时 5秒, conversation ejb 用时 3 秒, page pojo 用时 1 秒。在conversation内，ejb比pojo快40%, 而page scope内的pojo比前两者分别快 5 倍和 3倍。虽然还不清楚，为什么在conversation内ejb会比pojo性能要好，但在这一前提下，我们知道，<strong>如果非要写conversation内的组件，ejb将是更好的选择</strong>。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/88/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Seam的conversation存在性能问题，要正确使用</title>
		<link>http://www.sulong.info/archives/87</link>
		<comments>http://www.sulong.info/archives/87#comments</comments>
		<pubDate>Tue, 24 Jun 2008 15:34:02 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[jboss]]></category>
		<category><![CDATA[seam]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=87</guid>
		<description><![CDATA[近半年的项目实践让我们注意到了seam2.0.2的conversation的性能问题。测试人员抱怨系统速度慢的时候，我们一开始以为是由于数据库查询导致的性能问题。但是经过各方面排查，我们发现一个不做数据库操作的简单页面，就算是按照前文《优化richfaces，给seam提速》操作后，同样会很慢。于是我们开始怀疑起 seam本身了。一个无意中的试验发现，我把一个以前放在conversation scope内的组件换成 page scope后，速度一下子提高了五六倍。今天通过对日志的分细，证实了我的感觉。 我写了一个timefilter,记下服务器从接到http request到生成后http response后总共花掉了多少时间。被测试的action是一个普通的java bean，共有二十多个property, 里面有一个业务方法。在不改变其它代码，只改变这个java类前的annotation, 把 scope 从conversation改成page后，测试十次，page scope时要比conversation时快5到10倍！这个测试结果确实是非常地让我惊讶！conversation scope的组件到底有什么特殊的呢？ 为了能够观查到seam内部的运作情况，我把org.jboss的log设成debug级别的，现在点一下页面，一个post-&#62;redirect-&#62;get，在使用page scope时会产生 1 万多行日志，而conversation scope时居然会产生 近 3 万条日志！光从这个日志的数目就可以看到 conversation 在背后不只是做了一点点工作呀！再仔细对比两者的日志，会发现，conversation scope里会多出许多处理事件的日志：instantiating Seam component: org.jboss.seam.core.events 。这句日志在conversation时出现了 3630次，而 page scope时只出现了 1464次。conversation的日志里多出了大量如下日志： 2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.core.Events] Processing event:org.jboss.seam.preRemoveVariable.supplierSearchAction.supplierName 2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events 2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] initializing new instance [...]]]></description>
			<content:encoded><![CDATA[<p>近半年的项目实践让我们注意到了seam2.0.2的conversation的性能问题。测试人员抱怨系统速度慢的时候，我们一开始以为是由于数据库查询导致的性能问题。但是经过各方面排查，我们发现一个不做数据库操作的简单页面，就算是按照前文《<a href="http://www.sulong.info/archives/85">优化richfaces，给seam提速</a>》操作后，同样会很慢。于是我们开始怀疑起 seam本身了。一个无意中的试验发现，我把一个以前放在conversation scope内的组件换成 page scope后，速度一下子提高了五六倍。今天通过对日志的分细，证实了我的感觉。<br />
我写了一个timefilter,记下服务器从接到http request到生成后http response后总共花掉了多少时间。被测试的action是一个普通的java bean，共有二十多个property, 里面有一个业务方法。在不改变其它代码，只改变这个java类前的annotation, 把 scope 从conversation改成page后，测试十次，page scope时要比conversation时快5到10倍！这个测试结果确实是非常地让我惊讶！conversation scope的组件到底有什么特殊的呢？</p>
<p>为了能够观查到seam内部的运作情况，我把org.jboss的log设成debug级别的，现在点一下页面，一个post-&gt;redirect-&gt;get，在使用page scope时会产生 1 万多行日志，而conversation scope时居然会产生 近 3 万条日志！光从这个日志的数目就可以看到 conversation 在背后不只是做了一点点工作呀！再仔细对比两者的日志，会发现，conversation scope里会多出许多处理事件的日志：instantiating Seam component: org.jboss.seam.core.events  。这句日志在conversation时出现了 3630次，而 page scope时只出现了 1464次。conversation的日志里多出了大量如下日志：</p>
<p><small><small>2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.core.Events] Processing event:org.jboss.seam.preRemoveVariable.supplierSearchAction.supplierName<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.core.Events] Processing event:org.jboss.seam.postRemoveVariable.supplierSearchAction.supplierName<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.core.Events] Processing event:org.jboss.seam.preRemoveVariable.supplierSearchAction.employee<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.core.Events] Processing event:org.jboss.seam.postRemoveVariable.supplierSearchAction.employee<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.core.Events] Processing event:org.jboss.seam.preRemoveVariable.supplierSearchAction.state<br />
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,593 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,593 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,593 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,593 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,593 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events<br />
2008-06-24 14:23:32,593 DEBUG [org.jboss.seam.core.Events] Processing event:org.jboss.seam.postRemoveVariable.supplierSearchAction.state</small></small></p>
<p>从日志中可以看出seam 处理了大量的<big><big> </big></big><small><small><big><big>org.jboss.seam.preRemoveVariable 和 org.jboss.seam.postRemoveVariable 事件，类似的事件还有 org.jboss.seam.preSetVariable 和 org.jboss.seam.postSetVariable。Seam疯狂地为conversation scope里的组件里的property 都产生了一遍这些事件。更可怕的是，并不是处理一遍，而是会处理很多遍，在我的这个测试的例子中，它处理了47遍！ 这一算，1 action * 30 properties * 2 events * N times * M event listners，不是一个小数目呀，在我这个没有event observer的例子中，N = 47, 会有 1 * 30 * 2 * 47 * 1 = 2847 次操作！通过日志还可以看出 把 supplierSearchAction的所有的properties走一遍事件，要花掉 208ms, 那么 47 次这样的操作，需要 47 * 208 = 9682ms ！ 9秒多的时间，绝对不是一下小数目，改成page scope后快，就快在这里。(208 / 30)  * 47 = 326ms，每个bean的property, 在这个例子中消耗掉了 0.3秒时间，好昂贵呀。幸好我们公司的服务器比较牛，能够把这个差距的绝对值缩到很小，但是，这无疑是一种对CPU的浪费。</big></big></small></small></p>
<p><small><small><big><big><strong>这样看来，conversation是不能乱用的，不能随便把个组件就置成conversation scope的，能把逻辑用page scope, event scope, stateless scope搞定，就尽量不要用conversation。如果有多个页面交互等操作，适合于用conversation的，那也要尽量减少 conversation scope内组件的 properties,  把 conversation 内的组件做成功能明确单一的最好。</strong></big></big></small></small></p>
<p><small><small><big><big></big></big></small></small><small><small><big><big>其实，我的项目中把 supplierSearchAction放在conversation scope里就是不必要的，因为search动作都是在一个页面内完成的，用 page scope就足够了。</big></big></small></small>不仅如此，还把页面上的很多输入框等通过绑定，直接绑定到conversation scope的组件上。以后再用seam的时候，一定要小心使用conversation scope了。也期待着seam的新版本能把conversation scope的组件性能提高！</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/87/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>优化jboss以提高性能</title>
		<link>http://www.sulong.info/archives/84</link>
		<comments>http://www.sulong.info/archives/84#comments</comments>
		<pubDate>Tue, 03 Jun 2008 06:07:34 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[程序]]></category>
		<category><![CDATA[jboss]]></category>

		<guid isPermaLink="false">http://www.sulong.info/?p=84</guid>
		<description><![CDATA[概述 为了优化jboss的性能，对jboss服务器做了如下改动。 设置jvm 参数 安装jboss-native 降低jboss输出日志的等级 起用了jboss内的tomcat对传输数据的压缩功能 使用ehcache做hibernate的二级缓存 下面就以上的各改动做详细说明，为了表述方便&#60;jboss&#62;代表jboss的安装目录： 设置 jvm 参数 编辑&#60;jboss&#62;/bin/run.conf,  在文件的底部找到对参数JAVA_OPTS进行设置的地方。这个参数会最后传到jvm里。其中 -Xms512m 代表jvm最少用 512m内存 -Xmx1024m 代表jvm最多使用 1024m内存 修改这个两参数，给jvm分配适当的内存，一般为服务器的3/4内存量，推荐至少使用4G内存。 另外添加两个参数 -XX:+UseParallelGC -XX:+UseParallelOldGC 这两个让服务并行回收内存空间。修改完成后，大致为 JAVA_OPTS = &#8220;-Xms4096m -Xmx8192m -XX:+UseParallelGC -XX:+UseParallelOldGC -Dsum&#8230;&#8230;. 安装jbossNative jboss的web container使用的 apache tomcat (http://www.apache.org)。 apache tomcat 有一个扩展包，使tomcat可以通过 java native interface 使用 apache portable runtime (APR)，而APR则是大名顶顶的apache httpd 网络服务器的运行时环境。用了这个扩展之后，就使得tomcat可以借助于apache httpd的力量，性能得以提升，尤其是处理静态文件时效率更高。Jboss native，实际上就是tomcat的这个native的扩展，只不过被jboss又添进了一些为了和jboss更好协作而加进去的东西。 要安装jboss native, [...]]]></description>
			<content:encoded><![CDATA[<h1 id="gst60">概述</h1>
<p>为了优化jboss的性能，对jboss服务器做了如下改动。<br id="sr-h0" /></p>
<ol id="k1yr0">
<li id="k1yr1"> 设置jvm 参数<br id="mpms0" /></li>
<li id="k1yr1"> 安装jboss-native</li>
<li id="k1yr2"> 降低jboss输出日志的等级</li>
<li id="k1yr2"> 起用了jboss内的tomcat对传输数据的压缩功能</li>
<li id="k1yr2"> 使用ehcache做hibernate的二级缓存</li>
</ol>
<p>下面就以上的各改动做详细说明，为了表述方便&lt;jboss&gt;代表jboss的安装目录：<br id="mpms1" /></p>
<h1 id="mpms2">设置 jvm 参数</h1>
<p>编辑&lt;jboss&gt;/bin/run.conf,  在文件的底部找到对参数JAVA_OPTS进行设置的地方。这个参数会最后传到jvm里。其中<br id="evo:0" /></p>
<ol id="evo:1">
<li id="evo:2"> -Xms512m 代表jvm最少用 512m内存</li>
<li id="evo:3"> -Xmx1024m 代表jvm最多使用 1024m内存</li>
</ol>
<p>修改这个两参数，给jvm分配适当的内存，一般为服务器的3/4内存量，推荐至少使用4G内存。<br id="ko250" /> 另外添加两个参数 -XX:+UseParallelGC -XX:+UseParallelOldGC 这两个让服务并行回收内存空间。修改完成后，大致为 JAVA_OPTS = &#8220;-Xms4096m -Xmx8192m -XX:+UseParallelGC -XX:+UseParallelOldGC -Dsum&#8230;&#8230;.<br id="w-zw0" /></p>
<h1 id="nf_y0">安装jbossNative</h1>
<p>jboss的web container使用的 apache tomcat (http://www.apache.org)。 apache tomcat 有一个扩展包，使tomcat可以通过 java native interface 使用 apache portable runtime (APR)，而APR则是大名顶顶的apache httpd 网络服务器的运行时环境。用了这个扩展之后，就使得tomcat可以借助于apache httpd的力量，性能得以提升，尤其是处理静态文件时效率更高。Jboss native，实际上就是tomcat的这个native的扩展，只不过被jboss又添进了一些为了和jboss更好协作而加进去的东西。<br id="t11w0" /> 要安装jboss native, 按以下步骤进行<br id="eswo0" /></p>
<ol id="eswo1">
<li id="eswo2"> 请到jboss的网站上下载，地址是 http://www.jboss.org/jbossweb/downloads/jboss-native/?action=a&amp;windowstate=maximized, 依据服务器环境选择合适的版本。 目前我们用的版本是<strong id="fx-00">JBoss Native 2.0.4 Linux x86</strong> 。</li>
<li id="eswo3"> 解压下载后的压缩包到某个目录，比如 jbossNative目录</li>
<li id="eswo3"> 将jbossNative/bin/META-INF/bin/linux2/x86/openssl 复制到&lt;jboss&gt;/bin</li>
<li id="eswo3"> 在&lt;jboss&gt;/bin目录里建一个文件夹，名为 native</li>
<li id="eswo3"> 把jbossNative/bin/META-INF/lib/linux2/x86/ 目录下所有内容复制到上一步建好的&lt;jboss&gt;/bin/native目录下</li>
</ol>
<p><br id="w-zw1" /></p>
<h1 id="w-zw2">降低jboss输出日志的等级</h1>
<p>打开 &lt;jboss&gt;/server/default/conf/jboss-log4j.xml ，这是一个log4j的配置文件。log4j的详细配置说明请参看  http://logging.apache.org/log4j/1.2/index.html  。日志输出的太多，会导致服务器性能降低，所以减少不必要的日志输出。方法大体如下：<br id="b2pr0" /></p>
<ol id="b2pr1">
<li id="b2pr2"> 找到 name=&#8221;org.jboss&#8221; 的category 元素，设置里面的priority元素为 &lt;priority value=&#8221;INFO&#8221; /&gt;</li>
<li id="b2pr2"> 建一个新的category，内容为 &lt;category name=&#8221;javax.faces&#8221;&gt;&lt;priority value=&#8221;INFO&#8221; /&gt;&lt;/category&gt;</li>
</ol>
<p><br id="qxjh0" /> log4j 还能够将不同的日志输入到不同的地方，为了以后维护方便，应该将不同 category的日志输入到不同的文件里。详细方法参看上面的网站里的说明。<br id="idq_0" /> <br id="idq_1" /></p>
<h1 id="idq_2">起用了jboss内的tomcat对传输数据的压缩功能</h1>
<p>合同管理里用了大量的javascript css等，为了减少传输时间，可以起用压缩功能。方法是：<br id="a35u0" /></p>
<ol id="a35u1">
<li id="a35u2"> 打开&lt;jboss&gt;/server/default/deploy/jboss-web.deployer/server.xml</li>
<li id="a35u2"> 找到 protocol=&#8221;HTTP/1.1&#8243;的 Connector元素，添加属性 URIEncoding=&#8221;utf-8&#8243; compression=&#8221;on&#8221; compressionMinSize=&#8221;2048&#8243; noCompressionUserAgents=&#8221;gozilla, traviata&#8221; compressableMimeType=&#8221;text/html,text/xml,text/javascript, text/css, text/plain,application/xhtml+xml,application/x-javascript,application/javascript,text/xhtml&#8221;</li>
</ol>
<p>添加完后类似于：<br id="motl0" /> &lt;Connector port=&#8221;8080&#8243; address=&#8221;${jboss.bind.address}&#8221;   <br id="motl1" /> maxThreads=&#8221;250&#8243; maxHttpHeaderSize=&#8221;8192&#8243;<br id="motl2" /> emptySessionPath=&#8221;true&#8221; protocol=&#8221;HTTP/1.1&#8243;<br id="motl3" /> enableLookups=&#8221;false&#8221; redirectPort=&#8221;8443&#8243; acceptCount=&#8221;100&#8243;<br id="motl4" /> connectionTimeout=&#8221;20000&#8243; disableUploadTimeout=&#8221;true&#8221; URIEncoding=&#8221;utf-8&#8243; compression=&#8221;on&#8221; compressionMinSize=&#8221;2048&#8243; noCompressionUserAgents=&#8221;gozilla, traviata&#8221; compressableMimeType=&#8221;text/html,text/xml,text/javascript, text/css, text/plain,application/xhtml+xml,application/x-javascript,application/javascript,text/xhtml&#8221;/&gt;<br id="izkr1" /> <br id="izkr2" /> <br id="izkr3" /></p>
<h1 id="qp210">使用ehcache做hibernate的二级缓存</h1>
<p>起用二级缓存，可以大大提高hibernate的运行效率。<br id="de:r0" /></p>
<ol id="cj4.0">
<li id="cj4.1"> 到http://ehcache.sourceforge.net/ 网站下载 ehcache-1.4.1.tgz</li>
<li id="cj4.2"> 解压到某个目录，例如ehcache目录</li>
<li id="cj4.2"> 复制 ehcache/ehcache-1.4.1/ehcache-1.4.1.jar, ehcache/ehcache-1.4.1/lib/backport-util-concurrent-3.0.jar和 ehcache/ehcache-1.4.1/lib/jsr107cache-1.0.jar到 &lt;jboss&gt;/server/default/lib目录</li>
</ol>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/84/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>更改jboss默认使用的rmi端口，避免冲突</title>
		<link>http://www.sulong.info/archives/71</link>
		<comments>http://www.sulong.info/archives/71#comments</comments>
		<pubDate>Wed, 27 Feb 2008 06:12:41 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[jboss]]></category>

		<guid isPermaLink="false">http://www.sulong.info/archives/71</guid>
		<description><![CDATA[最近使用jboss的时候常常出现1098端口被占，不能正常起动的错误: 10:28:57,000 WARN  [ServiceController] Problem starting service jboss:service=Naming java.rmi.server.ExportException: Port already in use: 1098; nested exception is: java.net.BindException: Address already in use: JVM_Bind at sun.rmi.transport.tcp.TCPTransport.listen(TCPTransport.java:310) at sun.rmi.transport.tcp.TCPTransport.exportObject(TCPTransport.java:218) 也不知道是哪个程序占用了这个端口。可以通过修改jboss的配置文件，让jboss使用另外一个端口，来修正这个问题。方法如下： 1，打开jboss的jboos-service.xml文件，在我机上位于D:\prog\jboss-4.2.2.GA\server\default\conf 目录。 2，搜索1098，找到 &#60;attribute name=&#8221;RmiPort&#8221;&#62;1098&#60;/attribute&#62;，修改这个端口号为一个一般不会被用到的端口号，比如12345。 再重启jboss应该就OK了。]]></description>
			<content:encoded><![CDATA[<p>最近使用jboss的时候常常出现1098端口被占，不能正常起动的错误:</p>
<p>10:28:57,000 WARN  [ServiceController] Problem starting service jboss:service=Naming<br />
java.rmi.server.ExportException: Port already in use: 1098; nested exception is:<br />
java.net.BindException: Address already in use: JVM_Bind<br />
at sun.rmi.transport.tcp.TCPTransport.listen(TCPTransport.java:310)<br />
at sun.rmi.transport.tcp.TCPTransport.exportObject(TCPTransport.java:218)</p>
<p>也不知道是哪个程序占用了这个端口。可以通过修改jboss的配置文件，让jboss使用另外一个端口，来修正这个问题。方法如下：</p>
<p>1，打开jboss的jboos-service.xml文件，在我机上位于D:\prog\jboss-4.2.2.GA\server\default\conf 目录。</p>
<p>2，搜索1098，找到 &lt;attribute name=&#8221;RmiPort&#8221;&gt;1098&lt;/attribute&gt;，修改这个端口号为一个一般不会被用到的端口号，比如12345。</p>
<p>再重启jboss应该就OK了。</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/71/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jboss指定绑定IP</title>
		<link>http://www.sulong.info/archives/29</link>
		<comments>http://www.sulong.info/archives/29#comments</comments>
		<pubDate>Fri, 02 Nov 2007 05:17:34 +0000</pubDate>
		<dc:creator>sulong</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[jboss]]></category>

		<guid isPermaLink="false">http://sulong.info/archives/29</guid>
		<description><![CDATA[运行jboss时如果不指定绑定IP，它会默认绑定localhost，这样从其他ip地址将无法访问。要解决这个问题，只要在启动时加参数如下： run.sh -b &#60;要绑定的ip&#62;]]></description>
			<content:encoded><![CDATA[<p>运行jboss时如果不指定绑定IP，它会默认绑定localhost，这样从其他ip地址将无法访问。要解决这个问题，只要在启动时加参数如下：</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:500px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">run.sh -b &lt;要绑定的ip&gt;</div></div>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save"><img src="http://www.sulong.info/wp-content/plugins/add-to-any/share_save_171_16.gif" width="171" height="16" alt="Share/Bookmark"/></a> </p>]]></content:encoded>
			<wfw:commentRss>http://www.sulong.info/archives/29/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
