服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

jboss技术支持文档

1、下载例子源程序

  所有例子的源代码可以直接从 www.jboss.org进行下载。下载完后放在一个目录下。下载网址:http://www.jboss.org/docs/manual/files/documentation-example.zip

  1.1 建立 bean

  此节主要是建立一个简单的ejb,可以查看代码,这个“interest”例子,是一个简单无状态的会话ejb。它的目的是根据说明的利息率,来对借的所有钱计算利息。实际上在整个包代码中只有一行功能。

  1.2 回顾ejbs

  在我们查看代码之前,我们先对ejb进行复习一下。在ejb最小类型,也必须有三个类:remote interface, home interface和bean实现类。

  remote interface是会把ejb中方法提供给外边世界,让外边的代码来进行调用,在这个例子中类名称是org.jboss.interest.interrest。

  home interface是管理remote interface类的类。包括建立、删除等操作。在这个例子中类名称是org.jboss.interest.interresthome。

  bean实现类提供home interface和remote interface所有方法的实现。在这个例子中类名称是org.jboss.interest.interrestbean。

  当然一个bean可能还包括其他类,甚至其他包。但是必须有此三个类,其他类是在此三个类之上建立的。所有类被打包进一个jar文件,此文件是用一个目录结构来反映出包的层次关系。在此例子中所有类都打包在org.jboss.interest包中,所以他们需要在目录org/jboss/interest/下。

  在包含所有类的jar文件建立之前,必须有一个meta-inf目录。此目录存放了部署描述符(通常叫“ejb-jar.xml”),和可选的其他xml文件。这些文件告诉服务器关于应用明确服务信息。对于jboss 来讲,文件名必须叫“jboss.xml”。

  创建jar文件后部署到jboss server上。在客户端你需要一个jndi.properties文件,此文件告诉你的客户端程序从哪里初始化查找jndi 命名服务。从这个服务,客户端将查找到interest bean,并且返回bean的home interface。home interface用来得到bean的一个remote interface。它可以用远程接口来访问bean提供的商业方法。

  1.3 ejb类

  我们需要三个类:remote interface, home interface 和bean实现类。remote interface远程接口类,文件名interest.java。代码如下:

package org.jboss.docs.interest;
import javax.ejb.ejbobject;
import java.rmi.remoteexception;
/**
this interface defines the `remote' interface for the `interest' ejb. its
single method is the only method exposed to the outside world. the class
interestbean implements the method.
*/
public interface interest extends ejbobject
{
/** calulates the compound interest on the sum `principle', with interest rate per period `rate' over `periods' time periods. this method also prints a message to standard output; this is picked up by the ejb server and logged. in this way we can demonstrate that the method is actually being executed on the server, rather than the client. */

public double calculatecompoundinterest(double principle, double rate, double periods) throws remoteexception;

}

  远程接口只有一个商业方法calculatecompoundinterest。home interface 文件名interesthome.java。代码如下:

package org.jboss.docs.interest;
import java.io.serializable;
import java.rmi.remoteexception;
import javax.ejb.createexception;
import javax.ejb.ejbhome;

/**
this interface defines the 'home' interface for the 'interest' ejb.
*/
public interface interesthome extends ejbhome
{
/** creates an instance of the `interestbean' class on the server, and returns a remote reference to an interest interface on the client. */
interest create() throws remoteexception, createexception;
}

  最后我们给出bean实现类,文件名称:interestbean.java。代码如下:

package org.jboss.docs.interest;
import java.rmi.remoteexception;
import javax.ejb.sessionbean;
import javax.ejb.sessioncontext;

/**
this class contains the implementation for the 'calculatecompoundinterest' method exposed by this bean. it includes empty method bodies for the methods prescribe by the sessionbean interface; these don't need to do anything in this simple example. */public class interestbean implements sessionbean
{
/** calulates the compound interest on the sum `principle', with interest rate per period `rate' over `periods' time periods. this method also prints a message to standard output; this is picked up by the ejb server and logged. in this way we can demonstrate that the method is actually being executed on the server, rather than the client. */
public double calculatecompoundinterest(double principle, double rate, double periods)
{
system.out.println("someone called `calculatecompoundinterest!'");
return principle * math.pow(1+rate, periods) - principle;
}
/** empty method body */
public void ejbcreate() {}
/** every ejbcreate() method always needs a corresponding ejbpostcreate() method with exactly the same parameter types. */
public void ejbpostcreate() {}
/** empty method body */
public void ejbremove() {} /** empty method body */
public void ejbactivate() {} /** empty method body */
public void ejbpassivate() {} /** empty method body */
public void setsessioncontext(sessioncontext sc) {}

}

  注意大部分方法是空的。因为这些方法在sessionbean接口中说明,所以必须在interestbean中存在,但在这个简单例子中,不需要具体内容。

  2、部署描述符

  当你编辑完类文件后,我们来看部署描述符。此文件告诉ejb server是哪个类应该被唤醒bean、home interface 和remote interface。如果一个包中有不止一个bean,它指明ejb同另外bean如何相和。在这
个简单例子中只有一个ejb,所以我们不用关心这方面问题。

  大部分商业ejb server都提供图形化部署工具,来构造部署描述符,jboss没有xml编辑器,但是它能够简单手工构造部署描述符。下面是interest bean部署描述符:

<?xml version="1.0" encoding="utf-8"?>
<ejb-jar>
<description>jboss interest sample application</description>
<display-name>interest ejb</display-name>
<enterprise-beans>
<session>
<ejb-name>interest</ejb-name>
<home>org.jboss.docs.interest.interesthome</home>
<remote>org.jboss.docs.interest.interest</remote>
<ejb-class>org.jboss.docs.interest.interestbean</ejb-class>
<session-type>stateless</session-type>
<transaction-type>bean</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>

  部署描述符文件必须命名为“ejb-jar.xml”,并且必须放在目录meta-inf下。一个大家容易犯的错误是目录名字,有的写成“meta_inf”, “meta~inf”或“meta-inf”所有这些都不能正常的工作。

  我们在server上部署一个应用程序,而不是一个ejb。在这个例子中我们的应用程序只有一个ejb。在部署描述符中<ejb-name>interest</ejb-name>表明ejb的名称。jboss缺省是把bean的home interface作为jndi命名空间放在<ejb-name>中,除非你修改缺省值。实际上客户端应用程序不是必须使用这个名字的。开发者不用为jndi命名空间指明一个不同的名字而费心。然而一个由完整应用程序的产品包含多个beans,通常用一个和开发者说明不同的名字。所以会发现“[application name]/[bean name]”等,关于这部分我们以后介绍。

  尽管部署描述符格式的文件ejb-jar.xml对所有ejb server都是共有的。你可以从sun得到一个正确定义的dtd, 但是没有为一个特殊ejb server指明每个必须要求。也没有说明如何从ejb-name影射到部署的jndi名字,例如“[application name]/[bean name]”。通过jboss提供一个缺省行为,来进行工作。这些工作来自于ejb-jar.xml。在高级配置的案例中,你必须定义jboss说明行为, 此行为用jboss.xml部署描述符。在高级配置中我们会谈到jboss.xml描述符的详细信息的。

  这里我们仅配置jboss.xml描述符的jndi名字来用来访问interest ejb home inrterface。通过缺省的jndi名字用来访问ejb home inrterface, 需要同ejb-jar.xml的ejb-name相同。对于这个简单的例子,interest bean通过jndi初始化上下文(作为“interest”)来定位。 我们想用“interest/interest”使home interface 可以使用,所以我们必须用jboss.xml描述符来说明。在jboss.xml中,重新覆盖缺省的jndi命名。为了重新编写缺省的行为,我们用ejb-jar.xml中的ejb-name元素值作为bean home接口的jndi命名,必须说明jndi命名,来写jboss.xml描述符如下:

<?xml version="1.0" encoding="utf-8"?>
<jboss>
<enterprise-beans>
<session>
<ejb-name>interest</ejb-name>
<jndi-name>interest/interest</jndi-name>
</session>
</enterprise-beans>
</jboss>

  这个文件说明调用的interest bean被绑定在interest/interest的jndi名称下。我们建立的标准ejb-jar.xml部署描述符同jboss说明jboss.xml共同设置interest ejb home接口的jndi名称为“interest/interest”。我们现在有了ejb类,这些类是建立ejb 文件包必须的文件。


  3、打包和部署bean

  jar包是建立一个jar文件,该文件包含ejb类文件和部署描述符。在下载的例子可能和你设置环
境不同,所以需要修改examples/build/build.xml的内容。关于各个ant方面的内容,我会在ant文档中介绍给大家。关于如何修改,下面我一步步地来告诉大家。以下是windows平台的。至于unix/lunix平台基本相似,这里就不在叙述了。

  1) 在修改之前,比首先设定jboss_dist环境变量,指定到你安装的jboss的目录。我安装在c:/jboss-3.0.6_tomcat-4.1.18, 所以 jboss_dist设定为c:/jboss-3.0.6_tomcat-4.1.18。

  2) 你是否安装了tomcat或jetty等web服务器。如果你没有安装,建议你安装jboss-3.0.6_tomcat-4.1.18, jboss和tomcat直接结合在一起啦,不需要再单独安装,当然也可以安装jboss-jetty( jboss和jetty直接结合在一起)。取决你喜欢什么web服务器。

  3) 完成上面两步后,我们来讨论修改examples/build/build.xml文件。在原有的文件中的部分代码:

<target name="validate-servlet">
<!-- override with your web server servlet jar location.
the default assumes that jboss_dist points to a
jboss/tomcat bundle distribution
-->
<available property="servlet.jar" value="${env.jboss_dist}/../tomcat/lib/servlet.jar" file="${env.jboss_dist}/../tomcat/lib/servlet.jar"/>
<available property="servlet.jar" value="${env.jboss_dist}/../jetty/lib/javax.servlet.jar" file="${env.jboss_dist}/../jetty/lib/javax.servlet.jar"/>
<available property="servlet.jar" value="${env.jboss_dist}/../catalina/common/lib/servlet.jar" file="${env.jboss_dist}/../catalina/common/lib/servlet.jar"/>
<available property="servlet.jar" value="${env.jboss_dist}/../catalina/common/lib/servlet.jar" file="${env.tomcat_home}/lib/servlet.jar"/>
<property name="servlet.jar" value="could_not_find_servlet_jar"/>
<path id="base.path_22">
<pathelement location="${jboss.dist}/client/ejb.jar"/>
<pathelement location="${jboss.dist}/client/jaas.jar"/>
<pathelement location="${jboss.dist}/client/jbosssx-client.jar"/>
<pathelement location="${jboss.dist}/client/jboss-client.jar"/>
<pathelement location="${jboss.dist}/client/jnp-client.jar"/>
<pathelement location="${servlet.jar}"/>
</path>
<path id="base.path_24">
<pathelement location="${jboss.dist}/client/jboss-j2ee.jar"/>
<pathelement location="${jboss.dist}/client/jaas.jar"/>
<pathelement location="${jboss.dist}/client/jbosssx-client.jar"/>
<pathelement location="${jboss.dist}/client/jboss-client.jar"/>
<pathelement location="${jboss.dist}/client/jnp-client.jar"/>
<pathelement location="${servlet.jar}"/>
</path>
</target>
<target name="validate-jboss" depends="validate-servlet">
<available property="classpath_id" value="base.path_22" file="${jboss.dist}/client/ejb.jar" />
<available property="classpath_id" value="base.path_24" file="${jboss.dist}/client/jboss-j2ee.jar" />
</target>

  由于此代码例子是jboss2.2中的所以对于我们不能适应,在此基础上我们来进行改动。在改动之前,来说明一下为什么改动,让大家清楚改动原因,不是一团雾水。

<available property="servlet.jar" value="${env.jboss_dist}/../tomcat/lib/servlet.jar" file="${env.jboss_dist}/../tomcat/lib/servlet.jar"/>….

  此部分说明你运用的web服务器是什么,根据你使用的web服务器来设置servlet.jar。 由于我使用的是jboss-tomcat.。

<path id="base.path_24"> … </path>说明客户端要的classpath包。

  修改以后的部分文件:

<target name="validate-servlet">
<!-- override with your web server servlet jar location.
the default assumes that jboss_dist points to a
jboss/tomcat bundle distribution
-->
<available property="servlet.jar" value="${env.jboss_dist}/tomcat-4.1.x/common/lib/servlet.jar" file="${env.jboss_dist}/tomcat-4.1.x/common/lib/servlet.jar"/>
<available property="servlet.jar" value="${env.jboss_dist}/../jetty/lib/javax.servlet.jar" file="${env.jboss_dist}/../jetty/lib/javax.servlet.jar"/>
<available property="servlet.jar" value="${env.jboss_dist}/../catalina/common/lib/servlet.jar" file="${env.jboss_dist}/../catalina/common/lib/servlet.jar"/>
<available property="servlet.jar" value="${env.jboss_dist}/../catalina/common/lib/servlet.jar" file="${env.tomcat_home}/lib/servlet.jar"/>
<property name="servlet.jar" value="could_not_find_servlet_jar"/>
<path id="base.path_22">
<pathelement location="${jboss.dist}/client/ejb.jar"/>
<pathelement location="${jboss.dist}/client/jaas.jar"/>
<pathelement location="${jboss.dist}/client/jbosssx-client.jar"/>
<pathelement location="${jboss.dist}/client/jboss-client.jar"/>
<pathelement location="${jboss.dist}/client/jnp-client.jar"/>
<pathelement location="${servlet.jar}"/>
</path>
<path id="base.path_306">
<pathelement location="${jboss.dist}/client/jboss-j2ee.jar"/>
<pathelement location="${jboss.dist}/client/jboss-jaas.jar"/>
<pathelement location="${jboss.dist}/client/jbosssx-client.jar"/>
<pathelement location="${jboss.dist}/client/jboss-client.jar"/>
<pathelement location="${jboss.dist}/client/jnp-client.jar"/>
<pathelement location="${jboss.dist}/client/jbossall-client.jar"/>
<pathelement location="${jboss.dist}/client/log4j.jar"/>
<pathelement location="${servlet.jar}"/>
</path>
</target>
<target name="validate-jboss" depends="validate-servlet">
<available property="classpath_id" value="base.path_22" file="${jboss.dist}/client/ejb.jar" />
<available property="classpath_id" value="base.path_306" file="${jboss.dist}/client/jboss-j2ee.jar" />
</target>

  4)修改完后存盘。然后到exaples/build目录下运行以下命令:

ant intro-interest-jar

  如果成功会提示 : build successful 。

  在编译ejb 类文件,建立ejb-jar文件时,如果有一个java.lang.noclassdeffounderror异常产生,你需要检查你的classpath。修改<path id="base.path_306">中的内容。

  5)完成后你可以查看interest.jar文件中内容:

  jar –tvf interest.jar为了把bean部署到server上,必须拷贝interest.jar文件到jboss_dist/server/default/deploy目录下。服务器自己会发现发生变化的文件,并重新部署它。

  6)当jboss server运行时,通过在examlpes/build目录下运行ant intro-interest-deploy来部署jar。在你部署期间,你会看到在server控制台的一些信息。

  7)如果你发现部署失败的信息,通常是部署描述符ejb-jar.xml文件结构坏了或丢失或在错误的目录下。

  8)如果在server上部署完后,我们来编写一个简单客户端来测试它是否正常工作。
 
  4、 编码和编译客户端

  单独一个ejb是不能用,我们至少需要一个简单客户端来用它的服务。一个ejb可以被其他的ejb,普通的javabean,一个jsp page,一个applet程序或是独立的应用程序调用。在这个例子中。我们编写一个简单的应用程序。这个应用程序将会建立interest类的一个对象。并且执行它的方法。当部署完bean后,server会绑定ejb home 接口到interest/interest的jndi名字下,并输出此home 接口,能通过rmi被调用。客户端代码如下:

package org.jboss.docs.interest;
import javax.naming.initialcontext;
import javax.naming.context;
import javax.rmi.portableremoteobject;
import org.jboss.docs.interest.interest;
import org.jboss.docs.interest.interesthome;
/** this simple application tests the 'interest' enterprise javabean which is
implemented in the package 'org.jboss.docs.interest'. for this to work, the
bean must be deployed on an ejb server.
*/
public class interestclient
{
/** this method does all the work. it creates an instance of the interest ejb on
the ejb server, and calls its `calculatecompoundinterest()' method, then prints
the result of the calculation.

*/
public static void main(string[] args)
{
// enclosing the whole process in a single `try' block is not an ideal way
// to do exception handling, but i don't want to clutter the program up
// with catch blocks
try
{
// get a naming context
initialcontext jndicontext = new initialcontext();
system.out.println("got context");
// get a reference to the interest bean
object ref = jndicontext.lookup("interest/interest");
system.out.println("got reference");
// get a reference from this to the bean's home interface
interesthome home = (interesthome)
portableremoteobject.narrow(ref, interesthome.class);
// create an interest object from the home interface
interest interest = home.create();
// call the calculatecompoundinterest() method to do the calculation
system.out.println("interest on 1000 units, at 10% per period, compounded over 2 periods is:");
system.out.println(interest.calculatecompoundinterest(1000, 0.10, 2));
}
catch(exception e)
{
system.out.println(e.tostring());
}
}
}

  客户端在jndi命名“interest/interest”下查找interesthome接口。如果你提供了一个正确的jboss.xml文件,bean home接口将会绑定到这个名字。否则,jndi的名字是“interest”。为了连接jboss jndi,必须建立一个初始化上下文,该上下文是根据在客户端的classpath路径下jndi.properties来的。这个jndi.property文件我们放在了examples/resources/jndi.properties中。代码如下:

java.naming.factory.initial=org.jnp.interfaces.namingcontextfactory

java.naming.provider.url=localhost:1099

java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces

  指定了initialcontextfactory(初始化上下文工厂),url,和工厂对象的包。在这里url是“localhost”,或运行jboss的主机名(ip),用的缺省端口是1099。为了不同rmi协议互相兼容,通过“narrow”方法来确保“ref”对象能转换为“interesthome”对象。客户端不需要必须和ejb类在同一个包中。所以它必须import ejb claess类。

  为了能运行ant命令。我修改了examples/org/jboss/docs/interest/build.xml文件,原文件的部分内容:

<target name="deploy-ejb-jar" depends="ejb-jar">
<copy file="${build.interest.dir}/interest.jar" todir="${jboss.dist}/deploy" />
</target>
<target name="deploy-ear" depends="ear">
<copy file="${build.interest.dir}/interest.ear" todir="${jboss.dist}/deploy" />
</target>

  修改后为:

<target name="deploy-ejb-jar" depends="ejb-jar">
<copy file="${build.interest.dir}/interest.jar" todir="${jboss.dist}/server/default/deploy" />
</target>
<target name="deploy-ear" depends="ear">
<copy file="${build.interest.dir}/interest.ear" todir="${jboss.dist}/server/default/deploy" />
</target>

  修改完后保存。编译和运行interestclient,通过以下命令:

ant intro-interest-client会出现正确的结果。

  5、补充说明

  各个jar文件:

  1) jboss-j2ee.jar :是标准的javax.ejb.* 包括ejb2.0接口和类。

  2) jboss-jaas.jar :是java鉴定和授权服务安全类。

  3) jbosssx-client.jar :是jbosssx安全扩展客户端类。

  4) jboss-client.jar :是jboss ejb容器代理和stub客户端类。

  5) jnp-client.jar :是jboss jndi提供者客户端类。

  现在隐藏代码,编译和部署ejb, 运行简单客户端进行测试。

  6、 结论

  最后来进行一个总结。

  server:

  为每个ejb(包括有、无状态的session,或实体bean),都需要三个文件: bean实现类, remote接口类,home接口类。这些类和一个或多个部署描述符(ejb-jar.xml, jboss.xml等),这些描述符必须在meta-inf目录下,一起打包进jar文件。为部署这个jar文件,你只需要拷贝到jboss/server/default/deploy/下。

  client:

  1)从jndi服务,查找bean的home 接口;

  2)从home接口,建立一个新的bean或得到一个已经存在bean;

  3)用得到的remote接口来访问服务器上bean实现类中商业方法。

  在客户端查找home 接口之前,客户端必须知道如何从jndi来定位。因此我们提供了一个jndi.properties文件。这个文件和一些jboss/clientx下的jar,必须包含到classpath中,才能使客户端运行。

扫描关注微信公众号