Home > Documentation > 9. サンプル・アプリケーション > 9.6. Geronimo 2.0 でのJNDIの利用方法 |
Java Naming and Directory Interface (JNDI) はApache Geronimoサーバーのコネクション・プールとのインターフェースです。開発者はこのインターフェースを通してEnterprise Java Beans (EJBs)を含むすべてのJavaオブジェクトにアクセスできます。
Apache Geronimo JNDI naming and Java resource connection pools, Part 1: Data source connections. URL: http://www-128.ibm.com/developerworks/opensource/library/os-ag-jndi1の記事は、JNDIを使ってデータソースのコネクション・プールやJava Messaging Services (JMS)、メール・セッションやURLコネクションへアクセスするための豊富なドキュメンテーションを提供してくれます。
上記は良い記事なのですが、Geronimo 1.x向けに書かれたものでありGeronimo 2.0向けとはいえません。
サンプルのJ2EEエンタープライズ・アプリケーションを動かすためには、記事の中では言及されていない、いくつかの追加の構成作業が必要でした。
注記:この情報の確認環境はWindows XP Professional, Version 5.1.2600 Service Pack 2 Build 2600です。
Customer Service J2EEエンタープライズ・アプリケーションを成功裡にデプロイするには、以下の手順に従ってください。アプリケーションは以下からダウンロードできます。
http://www.ibm.com/developerworks/views/download.jsp?contentid=175237&filename=CustomerService-part1.zip&method=http&locale=worldwide
1) j2ee.jarのclasspathへの追加
WebSphere やWebLogicといったアプリケーション・サーバーのlibディレクトリーに存在するj2ee.jar ファイルをclasspathに追加する必要があります。さもないと、antビルド・スクリプトを実行しようとした際に下記のエラーが発生することでしょう。
compile: [javac] Compiling 9 source files to E:\DOWNLOADS\GERONIMO\CustomerService\build\class [javac] E:\DOWNLOADS\GERONIMO\CustomerService\src\com\service\customer\ejb\Customer.java:6: package javax.ejb does not exist [javac] import javax.ejb.EJBObject; [javac] ^
2) Geronimo/Tomcatディストリビューションの利用
Tomcatディストリビューションを使用してください。というのも、現在のJettyディストリビューション(geronimo-jetty6-jee5-2.0-M1)ではGeronimo Server Console | Services | Database Pools | Database ウイザードで "Database Types" ドロップダウン・リスト中にアイテムが何も表示されないからです。
3) データベース・プール (CustomerServicePool)の作成
Tomcatディストリビューションであっても、新しいデータベース・プールを作成する際に問題が起きます。例えば新しいデータベース・プールを作成しようとする際に、データベースのタイプで"Derby embedded"を選択してテストしてみます。この操作は動くのですが、実際は新しいデータベース・プールは作成されません。<GERONIMO_HOME>\var\log\geronimo.logファイルには以下のようなエントリーが出力します。
14:20:19,687 ERROR [DatabasePoolPortlet] Unable to save connection pool javax.enterprise.deploy.spi.exceptions.InvalidModuleException: Not supported at org.apache.geronimo.deployment.plugin.jmx.JMXDeploymentManager.createConfiguration(JMXDeploymentManager.java:297) at org.apache.geronimo.console.databasemanager.wizard.DatabasePoolPortlet.save(DatabasePoolPortlet.java:880) at org.apache.geronimo.console.databasemanager.wizard.DatabasePoolPortlet.processAction(DatabasePoolPortlet.java:341) at org.apache.pluto.core.PortletServlet.dispatch(PortletServlet.java:229) at org.apache.pluto.core.PortletServlet.doPost(PortletServlet.java:163) at javax.servlet.http.HttpServlet.service(HttpServlet.java:713) at javax.servlet.http.HttpServlet.service(HttpServlet.java:806) at org.apache.pluto.core.PortletServlet.service(PortletServlet.java:153) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:683) at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:585) at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:505) at org.apache.pluto.invoker.impl.PortletInvokerImpl.invoke(PortletInvokerImpl.java:120) at org.apache.pluto.invoker.impl.PortletInvokerImpl.action(PortletInvokerImpl.java:68) at org.apache.pluto.PortletContainerImpl.processPortletAction(PortletContainerImpl.java:164) at org.apache.pluto.portalImpl.core.PortletContainerWrapperImpl.processPortletAction(PortletContainerWrapperImpl.java:82) at org.apache.pluto.portalImpl.Servlet.doGet(Servlet.java:227) at org.apache.pluto.portalImpl.Servlet.doPost(Servlet.java:267) at javax.servlet.http.HttpServlet.service(HttpServlet.java:713) at javax.servlet.http.HttpServlet.service(HttpServlet.java:806) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:228) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) at org.apache.geronimo.tomcat.valve.DefaultSubjectValve.invoke(DefaultSubjectValve.java:56) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:525) at org.apache.geronimo.tomcat.GeronimoStandardContext$SystemMethodValve.invoke(GeronimoStandardContext.java:325) at org.apache.geronimo.tomcat.valve.GeronimoBeforeAfterValve.invoke(GeronimoBeforeAfterValve.java:47) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:542) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:212) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:818) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:624) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:445) at java.lang.Thread.run(Thread.java:595)
3.a) デプロイメント・テスト・プランの手動での作成とデプロイ
Geronimoは"Derby embedded"コネクション・プール用のデプロイメント・プランを作成してくれていません。そのため、以下のように自分の手でデプロイメント・プランを作成してデプロイする必要があります。
以下のデプロイメント・プラン・ファイル(CustomerServicePool_test_plan.xml)を作成してください。
<?xml version="1.0" encoding="UTF-8"?> <connector xmlns="http://geronimo.apache.org/xml/ns/j2ee/connector-1.2"> <dep:environment xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.2"> <dep:moduleId> <dep:groupId>console.dbpool</dep:groupId> <dep:artifactId>CustomerServicePool</dep:artifactId> <dep:version>2.0</dep:version> <dep:type>rar</dep:type> </dep:moduleId> <dep:dependencies> <dep:dependency> <dep:groupId>org.apache.derby</dep:groupId> <dep:artifactId>derby</dep:artifactId> <dep:version>10.1.3.1</dep:version> <dep:type>jar</dep:type> </dep:dependency> </dep:dependencies> </dep:environment> <resourceadapter> <outbound-resourceadapter> <connection-definition> <connectionfactory-interface>javax.sql.DataSource</connectionfactory-interface> <connectiondefinition-instance> <name>CustomerServicePool</name> <config-property-setting name="Driver">org.apache.derby.jdbc.EmbeddedDriver</config-property-setting> <config-property-setting name="ConnectionURL">jdbc:derby:CustomerServiceDatabase</config-property-setting> <connectionmanager> <local-transaction/> <single-pool> <max-size>10</max-size> <min-size>0</min-size> <match-one/> </single-pool> </connectionmanager> </connectiondefinition-instance> </connection-definition> </outbound-resourceadapter> </resourceadapter> </connector>
<GERONIMO_HOME>\bin ディレクトリーで以下のコマンドを実行します。
deploy --verbose --user system --password manager deploy D:\appsData\GERONIMO\JNDIApp\CustomerService.ear
3.b) CustomerServicePool用のデプロイメント・バージョンの更新
前述のdeployコマンドを実行したら、さらに別の構成作業を行わなくてはなりません。
Using GERONIMO_BASE: C:\GERONIMO Using GERONIMO_HOME: C:\GERONIMO Using GERONIMO_TMPDIR: C:\GERONIMO\var\temp Using JRE_HOME: C:\Java\Java150_10\jre Error: Unable to distribute CustomerService.ear: Unable to create configuration for deployment org.apache.geronimo.common.DeploymentException: Unable to create configuration for deployment at org.apache.geronimo.deployment.DeploymentContext.createTempConfiguration(DeploymentContext.java:121) at org.apache.geronimo.deployment.DeploymentContext.<init>(DeploymentContext.java:101) at org.apache.geronimo.deployment.DeploymentContext.<init>(DeploymentContext.java:81) at org.apache.geronimo.j2ee.deployment.EARContext.<init>(EARContext.java:65) at org.apache.geronimo.j2ee.deployment.EARConfigBuilder.buildConfiguration(EARConfigBuilder.java:475) at org.apache.geronimo.j2ee.deployment.EARConfigBuilder$$FastClassByCGLIB$$38e56ec6.invoke(<generated>) at net.sf.cglib.reflect.FastMethod.invoke(FastMethod.java:53) at org.apache.geronimo.gbean.runtime.FastMethodInvoker.invoke(FastMethodInvoker.java:38) at org.apache.geronimo.gbean.runtime.GBeanOperation.invoke(GBeanOperation.java:124) at org.apache.geronimo.gbean.runtime.GBeanInstance.invoke(GBeanInstance.java:820) at org.apache.geronimo.gbean.runtime.RawInvoker.invoke(RawInvoker.java:57) at org.apache.geronimo.kernel.basic.RawOperationInvoker.invoke(RawOperationInvoker.java:35) at org.apache.geronimo.kernel.basic.ProxyMethodInterceptor.intercept(ProxyMethodInterceptor.java:96) at org.apache.geronimo.j2ee.deployment.CorbaGBeanNameSource$$EnhancerByCGLIB$$44342279.buildConfiguration(<generated>) at org.apache.geronimo.deployment.Deployer.deploy(Deployer.java:302) at org.apache.geronimo.deployment.Deployer.deploy(Deployer.java:124) at org.apache.geronimo.deployment.Deployer$$FastClassByCGLIB$$734a235d.invoke(<generated>) at net.sf.cglib.reflect.FastMethod.invoke(FastMethod.java:53) at org.apache.geronimo.gbean.runtime.FastMethodInvoker.invoke(FastMethodInvoker.java:38) at org.apache.geronimo.gbean.runtime.GBeanOperation.invoke(GBeanOperation.java:124) at org.apache.geronimo.gbean.runtime.GBeanInstance.invoke(GBeanInstance.java:855) at org.apache.geronimo.kernel.basic.BasicKernel.invoke(BasicKernel.java:239) at org.apache.geronimo.kernel.KernelGBean.invoke(KernelGBean.java:338) at org.apache.geronimo.kernel.KernelGBean$$FastClassByCGLIB$$1cccefc9.invoke(<generated>) at net.sf.cglib.reflect.FastMethod.invoke(FastMethod.java:53) at org.apache.geronimo.gbean.runtime.FastMethodInvoker.invoke(FastMethodInvoker.java:38) at org.apache.geronimo.gbean.runtime.GBeanOperation.invoke(GBeanOperation.java:124) at org.apache.geronimo.gbean.runtime.GBeanInstance.invoke(GBeanInstance.java:855) at org.apache.geronimo.kernel.basic.BasicKernel.invoke(BasicKernel.java:239) at org.apache.geronimo.system.jmx.MBeanGBeanBridge.invoke(MBeanGBeanBridge.java:168) at com.sun.jmx.mbeanserver.DynamicMetaDataImpl.invoke(DynamicMetaDataImpl.java:213) at com.sun.jmx.mbeanserver.MetaDataImpl.invoke(MetaDataImpl.java:220) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:815) at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:784) at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1408) at javax.management.remote.rmi.RMIConnectionImpl.access$100(RMIConnectionImpl.java:81) at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1245) at java.security.AccessController.doPrivileged(Native Method) at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1348) at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:782) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:294) at sun.rmi.transport.Transport$1.run(Transport.java:153) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.Transport.serviceCall(Transport.java:149) at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:466) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:707) at java.lang.Thread.run(Thread.java:595) Caused by: org.apache.geronimo.kernel.config.LifecycleException: load of default/CustomerService/1.0/ear failed at org.apache.geronimo.kernel.config.SimpleConfigurationManager.loadConfiguration(SimpleConfigurationManager.java:322) at org.apache.geronimo.deployment.DeploymentConfigurationManager.loadConfiguration(DeploymentConfigurationManager.java:115) at org.apache.geronimo.kernel.config.SimpleConfigurationManager.loadConfiguration(SimpleConfigurationManager.java:281) at org.apache.geronimo.deployment.DeploymentConfigurationManager.loadConfiguration(DeploymentConfigurationManager.java:111) at org.apache.geronimo.deployment.DeploymentContext.createTempConfiguration(DeploymentContext.java:118) ... 50 more Caused by: org.apache.geronimo.kernel.config.InvalidConfigException: Error starting configuration gbean default/CustomerService/1.0/ear at org.apache.geronimo.kernel.config.SimpleConfigurationManager.load(SimpleConfigurationManager.java:347) at org.apache.geronimo.deployment.DeploymentConfigurationManager.load(DeploymentConfigurationManager.java:119) at org.apache.geronimo.kernel.config.SimpleConfigurationManager.loadConfiguration(SimpleConfigurationManager.java:307) ... 54 more Caused by: org.apache.geronimo.kernel.repository.MissingDependencyException: Unable to resolve dependency console.dbpool/CustomerServicePool/1.0/rar at org.apache.geronimo.kernel.config.ConfigurationResolver.resolve(ConfigurationResolver.java:112) at org.apache.geronimo.kernel.config.Configuration.buildClassPath(Configuration.java:402) at org.apache.geronimo.kernel.config.Configuration.createConfigurationClasssLoader(Configuration.java:324) at org.apache.geronimo.kernel.config.Configuration.<init>(Configuration.java:268) at org.apache.geronimo.kernel.config.SimpleConfigurationManager.load(SimpleConfigurationManager.java:343) ... 56 more
ここに注目してください。
Caused by: org.apache.geronimo.kernel.repository.MissingDependencyException: Unable to resolve dependency console.dbpool/CustomerServicePool/1.0/rar
このメッセージにより、記事の中のファイルが以前の(1.0の)the CustomerServicePool (a Derby embedded database pool)向けに作成されていることがわかります。
3.c) Dependencyのバージョン番号の更新
この事象は、以下のようにCustomerEJB-openejb.xmlファイルのdependenciesセクションの"dep:version"タグを"1.0" から"2.0"へ変更すれば解消できます。
<?xml version="1.0" encoding="UTF-8"?> <openejb-jar xmlns="http://www.openejb.org/xml/ns/openejb-jar-2.1" xmlns:naming="http://geronimo.apache.org/xml/ns/naming-1.1"> <dep:environment xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.1"> <dep:moduleId> <dep:groupId>default</dep:groupId> <dep:artifactId>CustomerEJB</dep:artifactId> <dep:version>1.0</dep:version> <dep:type>jar</dep:type> </dep:moduleId> <dep:dependencies> <dep:dependency> <dep:groupId>console.dbpool</dep:groupId> <dep:artifactId>CustomerServicePool</dep:artifactId> <dep:version>2.0</dep:version> <dep:type>rar</dep:type> </dep:dependency> </dep:dependencies> . . .
(訳者注)
さらに、Apache Derby への接続記述を以下のとおり書き換えてください。
・変更前
<?xml version="1.0" encoding="UTF-8"?> <connector xmlns="http://geronimo.apache.org/xml/ns/j2ee/connector-1.2"> <dep:environment xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.2"> <dep:dependencies> <dep:dependency> <dep:groupId>org.apache.derby</dep:groupId> <dep:artifactId>derby</dep:artifactId> <dep:version>10.1.3.1</dep:version> <dep:type>jar</dep:type> </dep:dependency> </dep:dependencies> </dep:environment> ... 以下、省略 ... </connector>
・変更後
<?xml version="1.0" encoding="UTF-8"?> <connector xmlns="http://geronimo.apache.org/xml/ns/j2ee/connector-1.2"> <dep:environment xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.2"> <dep:dependencies> <dep:dependency> <dep:groupId>org.apache.geronimo.configs</dep:groupId> <dep:artifactId>system-database</dep:artifactId> <dep:type>car</dep:type> </dep:dependency> </dep:dependencies> </dep:environment> ... 以下、省略 ... </connector>
もう一度、<GERONIMO_HOME>\binディレクトリーでコマンド・プロンプトから以下を実行してください。
deploy --verbose --user system --password manager deploy D:\appsData\GERONIMO\JNDIApp\CustomerService.ear
3.d) デプロイメント記述子の更新
application.xmlのデプロイメント記述子をGeronimo 2.0の要件と互換性を保つように変更します。
前述の delpoy コマンドを実行しても、まだ geronimo.log 中に別のエラーが見つかることでしょう。
Deployer operation failed: Could not parse application.xml org.apache.geronimo.common.DeploymentException: Could not parse application.xml at org.apache.geronimo.j2ee.deployment.EARConfigBuilder.getEarPlan(EARConfigBuilder.java:314) at org.apache.geronimo.j2ee.deployment.EARConfigBuilder.getDeploymentPlan(EARConfigBuilder.java:261) at org.apache.geronimo.j2ee.deployment.EARConfigBuilder$$FastClassByCGLIB$$38e56ec6.invoke(<generated>) at net.sf.cglib.reflect.FastMethod.invoke(FastMethod.java:53) at org.apache.geronimo.gbean.runtime.FastMethodInvoker.invoke(FastMethodInvoker.java:38) at org.apache.geronimo.gbean.runtime.GBeanOperation.invoke(GBeanOperation.java:124) at org.apache.geronimo.gbean.runtime.GBeanInstance.invoke(GBeanInstance.java:820) at org.apache.geronimo.gbean.runtime.RawInvoker.invoke(RawInvoker.java:57) at org.apache.geronimo.kernel.basic.RawOperationInvoker.invoke(RawOperationInvoker.java:35) at org.apache.geronimo.kernel.basic.ProxyMethodInterceptor.intercept(ProxyMethodInterceptor.java:96) at org.apache.geronimo.j2ee.deployment.CorbaGBeanNameSource$$EnhancerByCGLIB$$44342279.getDeploymentPlan(<generated>) at org.apache.geronimo.deployment.Deployer.deploy(Deployer.java:232) at org.apache.geronimo.deployment.Deployer.deploy(Deployer.java:124) at org.apache.geronimo.deployment.Deployer$$FastClassByCGLIB$$734a235d.invoke(<generated>) at net.sf.cglib.reflect.FastMethod.invoke(FastMethod.java:53) at org.apache.geronimo.gbean.runtime.FastMethodInvoker.invoke(FastMethodInvoker.java:38) at org.apache.geronimo.gbean.runtime.GBeanOperation.invoke(GBeanOperation.java:124) at org.apache.geronimo.gbean.runtime.GBeanInstance.invoke(GBeanInstance.java:855) at org.apache.geronimo.kernel.basic.BasicKernel.invoke(BasicKernel.java:239) at org.apache.geronimo.deployment.plugin.local.AbstractDeployCommand.doDeploy(AbstractDeployCommand.java:114) at org.apache.geronimo.deployment.plugin.local.DistributeCommand.run(DistributeCommand.java:60) at java.lang.Thread.run(Thread.java:595) Caused by: org.apache.xmlbeans.XmlException: Invalid deployment descriptor: [error: cvc-complex-type.2.4a: Expected element 'module@http://java.sun.co m/xml/ns/j2ee' instead of 'description@http://java.sun.com/xml/ns/j2ee' here in element application@http://java.sun.com/xml/ns/j2ee] Descriptor: <application xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/application_1_4.xsd" version="1.4" xmlns= "http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <display-name>Customer Service utility</display-name> <description>Customer Service utility</description> <module> <web> <web-uri>CustomerService-web.war</web-uri> <context-root>/service</context-root> </web> </module> <module> <ejb>CustomerEJB.jar</ejb> </module> <module> <ejb>ProcessCustomerEJB.jar</ejb> </module> </application> at org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil.validateDD(XmlBeansUtil.java:213) at org.apache.geronimo.j2ee.deployment.EARConfigBuilder.convertToApplicationSchema(EARConfigBuilder.java:420) at org.apache.geronimo.j2ee.deployment.EARConfigBuilder.getEarPlan(EARConfigBuilder.java:312) ... 21 more
application.xmlファイルから"description"と"display-name"タグを除去し、CustomerService.ear 中のapplication.xmlファイルに再度保管してください。
<?xml version="1.0" ?> <application xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/application_1_4.xsd" version="1.4"> <display-name>Customer Service utility</display-name> <module> <web> <web-uri>CustomerService-web.war</web-uri> <context-root>/service</context-root> </web> </module> <module> <ejb>CustomerEJB.jar</ejb> </module> <module> <ejb>ProcessCustomerEJB.jar</ejb> </module> </application>
今度はCustomerService.ear ファイルはうまくデプロイできることでしょう。
deploy --verbose --user system --password manager deploy D:\appsData\GERONIMO\JNDIApp\CustomerService.ear
4) アプリケーションのデプロイとテスト
以下の手順に従い、動いているGeronimo 2.0インスタンスへJ2EEエンタープライズ・アプリケーションを正常にデプロイできました。
1) j2ee.jarのclasspathへの追加
2) Geronimo/Tomcatディストリビューションの利用
3) データベース・プール (CustomerServicePool)の作成
a. デプロイメント・テスト・プランの手動での作成とデプロイ
b. CustomerServicePool用のデプロイメント・バージョンの更新
c. Dependencyのバージョン番号の更新
d. デプロイメント記述子の更新
4) アプリケーションのデプロイとテスト
Bookmark this on Delicious Digg this | Privacy Policy - Copyright © 2003-2009, The Apache Software Foundation, Licensed under ASL 2.0. |