大鸟的学习乐园
路漫漫其修远兮,吾将上下而求索
posts - 26,comments - 27,trackbacks - 0
利用JBOSS+MyEclipse完成一个简单的EJB示例

目标:
1、编写一个简单的无状态会话Bean,传入一个字符串参数,返回字符串Hello +
字符串参数。
2、通过JSP页面上输入一个字符串,提交到Servlet,并调用EJB,最后在一个页面上输出处
理后的字符串。
工具:
JBOSS 4.2GA + Eclipse 3.2.2 +MyEclipse 5.5GA + JDK 1.6

首先需要搭建好各种环境,这一步比较简单,就不再赘述。唯一需要注意的是在启动JBOSS
服务器时可能会出现一些问题。如端口号被占用而导致服务器无法启动。如果出现这个问题
可以在%JBOSS%/server/default/deploy/jboss-web.deployer/目录下找到server.xml文件
,修改<Connector port="8080" address="${jboss.bind.address}"
         maxThreads="250" maxHttpHeaderSize="8192"
         emptySessionPath="true" protocol="HTTP/1.1"
         enableLookups="false" redirectPort="8443" acceptCount="100"
         connectionTimeout="20000" disableUploadTimeout="true" />
中的port属性,然后再重新启动服务器。默认端口是8080。

JBOSS自带了TOMCAT
5.X,当然也可以使用另外的Web服务器,不过后面的程序会稍微有些改动。
环境搭建完成后就需要编写EJB代码。一个EJB至少需要3个类,即Home接口、远程接口、实
现类。新建一个EJB Project,项目名为:MyFirstEJB.
-----------------------------------------------------------------------------------------
1、创建Home接口---HelloHome.java
package com;

public interface HelloHome extends javax.ejb.EJBHome {
    public Hello create() throws javax.ejb.CreateException,
            java.rmi.RemoteException;
}
-----------------------------------------------------------------------------------------
2、创建远程接口---Hello.java
package com;

public interface Hello extends javax.ejb.EJBObject {
       public String sayHello(String message) throws java.rmi.RemoteException;

}
-----------------------------------------------------------------------------------------
3、创建实现类---HelloBean.java
package com;

import java.rmi.RemoteException;

import javax.ejb.CreateException;
import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;

public class HelloBean implements SessionBean {

    private SessionContext context;

    public HelloBean() {

    }

    public String sayHello(String message) {
        if (message == null)
            message = "";
        message = "i am xiongxiong.Hello " + message + "!";
        return message;
    }

    public void ejbActivate() throws EJBException, RemoteException {
   

    }

    public void ejbPassivate() throws EJBException, RemoteException {

    }

    public void ejbRemove() throws EJBException, RemoteException {

    }

    public void setSessionContext(SessionContext newContext)
            throws EJBException {
        context = newContext;
    }

    public void ejbCreate() throws CreateException {

    }

    public void replaceWithRealBusinessMethod() throws EJBException {

    }

}

-----------------------------------------------------------------------------------------
其中方法sayHello就是我们需要实现的业务。
类建好之后,接下来就需要配置相关的xml文件。在该项目下的META-INF里新建两个xml文件
ejb-jar.xml和jboss.xml。具体配置如下:
-----------------------------------------------------------------------------------------
ejb-jar.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd">
<ejb-jar>
       <description>
              <![CDATA[No Description.]]>
       </description>
       <display-name>Generated by XDoclet</display-name>
       <enterprise-beans>
              <session>
                     <description>
                            <![CDATA[Description for Hello]]>
                     </description>
                     <display-name>Name for Hello</display-name>
                     <ejb-name>Hello</ejb-name>
                     <home>com.HelloHome</home>
                     <remote>com.Hello</remote>
                     <ejb-class>com.HelloBean</ejb-class>
                     <session-type>Stateless</session-type>
                     <transaction-type>Container</transaction-type>
              </session>
       </enterprise-beans>
       <assembly-descriptor>
       </assembly-descriptor>
</ejb-jar>

-----------------------------------------------------------------------------------------
jboss.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 2.4//EN" "http://www.jboss.org/j2ee/dtd/jboss_2_4.dtd">
<jboss>
   <enterprise-beans>
      <session>
         <ejb-name>Hello</ejb-name>
         <jndi-name>ejb/Hello</jndi-name>
      </session>
   </enterprise-beans>
   <resource-managers>
   </resource-managers>
</jboss>
-----------------------------------------------------------------------------------------
使用XDoclet来自动生成这些文件还是很方便的,只是同时会生成一些多余的类和代码,需
要手动去删除他们。

到这里一个简单的无状态会话Bean就完成了,下面就是将他们部署到Jboss下面。可以将项
目打包成jar文件,然后放在
%JBOSS%/server/default/deploy/目录下,这样就算部署完成。还可以使用MyEclipse来帮
你进行部署。如果控制台上出现:
01:59:48,640 INFO [EjbModule] Deploying Hello
01:59:48,703 INFO [ProxyFactory] Bound EJB Home 'Hello' to jndi 'ejb/Hello'
01:59:48,703 INFO [EJBDeployer] Deployed:
file:/%jboss%/server/default/deploy/MyFirstEJB.jar/
就表示部署成功。下面我们就可以编写客户端程序来调用该EJB。

新建一个Web项目,项目名为testEJB,里面包含两个jsp文件和一个servlet。
-----------------------------------------------------------------------------------------
EJBServlet.java

package com;

import java.io.IOException;

import javax.ejb.CreateException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class EJBServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("gb2312");
        String info = request.getParameter("info");
        InitialContext context = null;
        Hello hello = null;
        try {
            context = new InitialContext();
            HelloHome home = (HelloHome) context.lookup("ejb/Hello");
            hello = home.create();
        } catch (NamingException e) {
            e.printStackTrace();
        } catch (CreateException e) {
            e.printStackTrace();
        }
        info = hello.sayHello(info);
        request.setAttribute("info", info);
        request.getRequestDispatcher("message.jsp").forward(request, response);
    }

}
-----------------------------------------------------------------------------------------
从jsp页面上获得表单中的字符串,然后将这个字符串传递到EJB的会话Bean中进行处理。最
后将返回的字符串显示在另外一个JSP页面上。
-----------------------------------------------------------------------------------------
index.jsp

<%@ page language="java" isELIgnored="false" pageEncoding="gb2312"%>
<html>
<head>
    <title>EJB</title>
</head>
<body>
     <form action="servlet" method="post">
            <input type="text" name="info" />
            <input type="submit" value="提交">
     </form>
</body>
</html>
-----------------------------------------------------------------------------------------
message.jsp

<%@ page language="java" isELIgnored="false" pageEncoding="utf-8"%>
<html>
<head>
    <title>message</title>
</head>
<body>
    <h1>${info }</h1>
</body>
</html>
-----------------------------------------------------------------------------------------
web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
    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/web-app_2_4.xsd">
<servlet>
    <description>This is the description of my J2EE component</description>
    <display-name>This is the display name of my J2EE component</display-name>
    <servlet-name>EJBServlet</servlet-name>
    <servlet-class>com.EJBServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>EJBServlet</servlet-name>
    <url-pattern>/servlet</url-pattern>
</servlet-mapping>

</web-app>
-----------------------------------------------------------------------------------------


如果Web项目和EJB项目在同一服务器中,那么象上面的程序运行是没什么问题的。


如果Web项目和EJB项目不在同一台服务器中,或者同一台服务器中使用的不是JBOSS自带的T
omcat,那么创建
ClientTestEJB.java
-----------------------------------------------------------------------------------------

package com;

import java.rmi.RemoteException;
import java.util.Hashtable;

import javax.ejb.CreateException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.http.HttpServlet;

public class ClientTestEJB extends HttpServlet {

    public static void main(String[] args) {

        String info = "";
        InitialContext context = null;
        Hello hello = null;
        /** *******************添加的代码**************************** */
        Hashtable environment = new Hashtable();

        environment.put(Context.INITIAL_CONTEXT_FACTORY,
                "org.jnp.interfaces.NamingContextFactory");
        environment.put(Context.URL_PKG_PREFIXES,
                "org.jboss.naming:org.jnp.interfaces");
        environment.put(Context.PROVIDER_URL, "jnp://localhost:1099");
        /** ******************************************************** */

        try {
            context = new InitialContext(environment);
            HelloHome home = (HelloHome) context.lookup("ejb/Hello");
            hello = home.create();

            info = hello.sayHello(info);
        } catch (RemoteException e) {
           
            e.printStackTrace();
        } catch (NamingException e) {
       
            e.printStackTrace();
        } catch (CreateException e) {
       
            e.printStackTrace();
        }
        System.out.println(info);

    }

}
-----------------------------------------------------------------------------------------
还需要将%jboss%/client/jbossall-client.jar
和EJB项目的jar包拷贝到web 项目中WEB-INF\lib目录或者CLASSPATH下。

如果不是jsp或servlet调用EJB不会出现下面错误
补充:在jsp或servlet中调用EJB时出现下面错误时:
04:03:33,714 INFO [STDOUT] java.rmi.ServerException: EJBException:; nested
exception is:
javax.ejb.EJBException: Invalid invocation, check your deployment packaging,
method=public abstract test.ejb.TestEJBInterface test.ejb.TestEJBHome.create()
throws javax.ejb.CreateException,java.rmi.RemoteException
解决办法有三种:
1、编辑%jboss%/server/default/conf/jboss-service.xml

<mbean code="org.jboss.naming.NamingService"
      name="jboss:service=Naming"
      xmbean-dd="resource:xmdesc/NamingService-xmbean.xml">
      <!-- The call by value mode. true if all lookups are unmarshalled using
         the caller's TCL, false if in VM lookups return the value by reference.
      -->
      <attribute name="CallByValue">false</attribute>
       ...
</mbean>
将属性CallByValue的值改为true

2、编辑%jboss%/server/default/deploy/ear-deployer.xml

<mbean code="org.jboss.deployment.EARDeployer"
      name="jboss.j2ee:service=EARDeployer">
           <attribute name="Isolated">false</attribute>
         <attribute name="CallByValue">false</attribute>
           <attribute name="EnablelibDirectoryByDefault">true</attribute>
   </mbean>
将属性Isolated和CallByValue的值改为true

3、编辑%jboss%/server/default/deploy/jboss-web.deployer/META-INF/jboss-service.x
ml

<attribute name="Java2ClassLoadingCompliance">false</attribute>
       <attribute name="UseJBossWebLoader">false</attribute>
将属性Java2ClassLoadingCompliance和UseJBossWebLoader的值改为false,这里默认值一
般都是false

一般情况下,使用第二种方式就可以解决该问题。
posted on 2009-09-14 19:41 大鸟 阅读(402) 评论(0)  编辑  收藏 所属分类: WEB

只有注册用户登录后才能发表评论。


网站导航: