[2003-四月-29 04:44:03] 被调试文件:vwDetail.jsp 被调试函数:(开始设置projectID) 调试描述: 取得的projectID为ERPPM200212110000000658310000E8E7FF69
* * Added by daihua 2003-4-29 11:16 * @param strMsg */ public static void logOneLineToFile ( String strLogFile, String strDebugFileName, String strDebugFuncName, String strDebugMsg ){ //如果不需要debug输出的话,直接返回 /*if ( ! debuggingOn ) return; */ java.io.File fd = new java.io.File ( "c://debug" ); if ( !fd.exists() ) { fd.mkdirs(); } //根据当前的日期自动生成debug的文件名,比如:c:/20030506debug.html /*SimpleDateFormat sdfF = new SimpleDateFormat ( "yyyyMMdd" ); String strLogFileName = "c://debug//" + sdfF.format( new Date() ) + "debug.html" ; */ String strLogFileName = "c://debug//" + strLogFile; //还是由程序指定debug的文件名 java.text.SimpleDateFormat bartDateFormat = new java.text.SimpleDateFormat("yyyy-MMMM-dd hh:mm:ss"); java.util.Date date = new java.util.Date(); java.io.FileWriter out = null; try { java.io.File f = new java.io.File ( strLogFileName ); if ( !f.exists() ){ f.createNewFile(); } //out = new RandomAccessFile ( f, "rw" ); out = new java.io.FileWriter ( strLogFileName, true ); //To be ready for append //out.seek( out.length() ); String str1 = "<p style=/"font-size:10.5pt; line-height:15pt/">" + "<font color=/"#999999/">[" + bartDateFormat.format(date) + "] 被调试文件:</font>"; String str2 = "<font color=/"#3333FF/">" + strDebugFileName + "</font>"; String str3 = "<font color=/"#999999/"> 被调试函数:</font><font color=/"#3333FF/">" + strDebugFuncName + "</font>"; String str4 = "<font color=/"#999999/"> 调试描述:</font><br>/r/n"; strDebugMsg = "<font color=red>" + strDebugMsg + "</font></p>/r/n"; strDebugMsg = str1 + str2 + str3 + str4 + strDebugMsg; //out.writeChars( "[" + bartDateFormat.format(date) + "] " + strMsg + "/r/n"); out.write( strDebugMsg ); }catch ( Exception e ) { e.printStackTrace(); } finally{ try{ if ( out != null ) out.close(); }catch ( Exception ex ){ ex.printStackTrace(); } } } public EjbCommon() { } public static void main(String[] args) { EjbCommon ejbCommon1 = new EjbCommon(); } } 编辑完成实体bean 打开EbnEmployee、EbnEmployeeHome、EbnEmployeeBean,首先import一下:import ejbsample.employee.EmployeeModel; 然后开始编辑EbnEmployeeBean,完成EJB设计器里面设计的函数 void setModel(EmployeeModel model)函数: public void setModel(EmployeeModel model) { this.setId ( model.getID() ); this.setName ( model.getName() ); this.setJob ( model.getJob() ); this.setHiredate ( model.getHireDate() ); this.setSal ( model.getSal() ); this.setComm ( model.getComm() ); this.setDeptid ( model.getDeptID() ); } EmployeeModel getModel()函数 public EmployeeModel getModel() { EmployeeModel data = new EmployeeModel(); data.setID( this.getId()); data.setName( this.getName()); data.setJob( this.getJob() ); data.setHireDate( this.getHiredate() ); data.setSal( this.getSal() ); data.setComm( this.getComm() ); data.setDeptID( this.getDeptid() ); return data; } java.lang.String ejbCreate(EmployeeModel model) public java.lang.String ejbCreate(EmployeeModel model) throws CreateException { //说明:这个函数非常重要,每次创建实体bean的时候,都会自动调用ejbCreate,所以如果没有完成这个函数的话,实体bean中将无法赋值 setModel ( model ); return null; } 编辑完成session bean类SbnEmployeeBean.java,如下package ejbsample.employee.session; import javax.ejb.*; import ejbsample.employee.EmployeeModel; import ejbsample.EjbCommon; import java.util.ArrayList; import ejbsample.employee.entity.*; import javax.naming.NamingException; import java.sql.*; import java.rmi.*; public class SbnEmployeeBean implements SessionBean { SessionContext sessionContext; public void ejbCreate() throws CreateException { /**@todo Complete this method*/ } public void ejbRemove() { /**@todo Complete this method*/ } public void ejbActivate() { /**@todo Complete this method*/ } public void ejbPassivate() { /**@todo Complete this method*/ } public void setSessionContext(SessionContext sessionContext) { this.sessionContext = sessionContext; } public EmployeeModel insert(EmployeeModel model) throws CreateException,NamingException,RemoteException{ try { //利用EjbCommon类得到实体bean的home接口 EbnEmployeeHome objHome = (EbnEmployeeHome) EjbCommon.getLocalEJBHome( EjbCommon.E_EMPLOYEE_JNDI ); EbnEmployee objRemote=objHome.create(model); return model; } catch(CreateException e) { throw e; } catch(NamingException e) { throw e; } } public EmployeeModel update(EmployeeModel model) throws FinderException, NamingException, RemoteException { try { //利用EjbCommon类得到实体bean的home接口 EbnEmployeeHome objHome = (EbnEmployeeHome) EjbCommon.getLocalEJBHome(EjbCommon.E_EMPLOYEE_JNDI); EbnEmployee objLocal = objHome.findByPrimaryKey(model.getID()); //调用model的取属性函数,将实体bean更新 //objLocal.setModel(model); //不能这么写。具体为什么,我也不知道。好像没有道理啊 objLocal.setName( model.getName() ); objLocal.setJob( model.getJob() ); objLocal.setHiredate( model.getHireDate() ); objLocal.setSal( model.getSal() ); objLocal.setComm( model.getComm() ); objLocal.setDeptid( model.getDeptID() ); return model; } catch (FinderException e) { throw e; } catch (NamingException e) { throw e; } } public boolean del(String pk) throws RemoveException,FinderException,EJBException,NamingException ,RemoteException { try { //利用EjbCommon类得到实体bean的home接口 EbnEmployeeHome objHome = (EbnEmployeeHome) EjbCommon.getLocalEJBHome( EjbCommon.E_EMPLOYEE_JNDI); EbnEmployee objLocal = objHome.findByPrimaryKey(pk); objLocal.remove(); return true; } catch (RemoveException e) { throw e; } catch (FinderException e) { throw e; } catch (EJBException e) { throw e; } catch (NamingException e) { throw e; } } public EmployeeModel findByPk(String pk) throws FinderException, NamingException, RemoteException { try { //利用EjbCommon类得到实体bean的home接口 EbnEmployeeHome objHome = (EbnEmployeeHome) EjbCommon.getLocalEJBHome(EjbCommon.E_EMPLOYEE_JNDI); EmployeeModel model = new EmployeeModel(); EbnEmployee objLocal = objHome.findByPrimaryKey(pk); model = objLocal.getModel(); return model; } catch (FinderException e) { throw e; } catch (NamingException e) { throw e; } } public boolean delBatch(String[] sid) throws NamingException, SQLException,RemoteException{ String[] sID = null; sID = sid; String sql = "delete FROM tmp_emp WHERE ID='" ; //Note: statmachine is the table name connected with our work String id = new String(); Connection conn = null; Statement st = null; boolean b = false; try { conn = EjbCommon.getConnection(); conn.setAutoCommit(false); st = conn.createStatement(); for(int i = 1;i <= sID.length ;i++ ){ id = sID[i-1]; st.execute(sql + id + "'"); } conn.commit(); b = true; return b; }catch ( NamingException e ){ throw e; }catch(SQLException e){ System.err.print( "delBatch() function error: concerning with database"); try { conn.rollback(); }catch(SQLException sqle){ throw sqle; } throw e; }finally{ try { st.close(); conn.close(); }catch(SQLException e){ throw e; } //return b; //说明:不要在finally里面return,否则,捕捉到的错误不会throw出去!!! } } public java.util.ArrayList queryBySql(String strSql) throws NamingException, SQLException,RemoteException{ ArrayList arrayList = null; EmployeeModel item; Connection conn = null; Statement st = null; ResultSet rs = null; try { conn=EjbCommon.getConnection(); st=conn.createStatement(); rs=st.executeQuery("SELECT * FROM tmp_emp WHERE " + strSql); //Of course, you can change the sql statement according your condition System.out.println("queryBySql函数的sql=" + "SELECT * FROM tmp_emp WHERE " + strSql); arrayList = new ArrayList(); while (rs.next()) { item=new EmployeeModel(); //从数据库里面读取值 item.setID( rs.getString( "ID" )); item.setName( rs.getString( "NAME" )); item.setJob( rs.getString( "JOB" )); item.setHireDate( rs.getDate( "HIREDATE" )); item.setSal( rs.getDouble( "SAL" )); item.setComm( rs.getString( "COMM" )); item.setDeptID( rs.getString( "DEPTID" )); arrayList.add(item); } if ( arrayList.size() <= 0 ){ return null; }else{ return arrayList; } }catch(SQLException e){ System.out.println("queryBySql函数出现了SQL错误:" + e.toString() + ",将返回的ArrayList设置为Null"); throw e; }catch(NamingException e1){ throw e1; } finally{ System.out.println("queryBySql函数进入finally子块,关闭连接"); try { if (rs!=null) rs.close(); }catch(SQLException e){ throw e; } try { if (st!=null) st.close(); }catch(SQLException e){ throw e; } try { if (conn!=null) conn.close(); }catch(SQLException e){ throw e; } //return arrayList; //说明:不要在finally里面return,否则,捕捉到的错误不会throw出去!!! } } } 编制EmployeeAction.java。这个类包装了EJB,是与jsp页面打交道的类。(这个action类,以及前面的model类,是两个主要和jsp页面打交道的类;而action类包装了EJB,model类包装了jsp页面显示元素)新建一个class,命名为EmployeeAction,package定义为ejbsample.employee。内容如下: package ejbsample.employee; /** * Title: (no title) * Description: xxAction类基本上是EJB的包装。 * Copyright: Copyright (c) 2003 * Company: Ebuilds * @author Alex * @version 1.0 */ import ejbsample.SequenceUtil; import ejbsample.EjbCommon; import ejbsample.employee.EmployeeModel; import ejbsample.employee.entity.*; import ejbsample.employee.session.*; import javax.ejb.*; import javax.naming.NamingException; import java.rmi.RemoteException; import java.util.ArrayList; import java.sql.*; public class EmployeeAction { /** * 传入一个model(没有ID这个属性),自动加一个唯一的ID,然后往数据库里面加一条记录 * @param model * @return * @throws NamingException * @throws RemoteException * @throws CreateException */ public EmployeeModel add( EmployeeModel model ) throws NamingException, RemoteException, CreateException { model.setID(SequenceUtil.getUniteCode()); //getUniteCode()的作用是:得到一个唯一的ID号。可以随便怎么写这个函数,比如可以用当前的时间作为ID:getTime();或者用网卡物理地址加上当前时间等等 try { SbnEmployeeHome objHome = (SbnEmployeeHome) EjbCommon. getRemoteEJBHome(EjbCommon. S_EMPLOYEE_JNDI, SbnEmployeeHome.class); SbnEmployee objRemote = objHome.create(); //从上面的两行代码可以看出session bean编码的格式:首先得到home接口;然后调用create()函数得到接口 return objRemote.insert(model); } //关于错误处理:千万不要在catch里面什么都不做,要么把catch到的错误throw出去,要么显示一些信息出来;否则的话,程序将会无法调试! catch (NamingException e) { throw e; } catch (RemoteException e) { throw e; } catch (CreateException e) { throw e; } } /** * 根据传入的主键,删除数据库里面的一条记录。 * @param strPk * @return * @throws NamingException * @throws RemoteException * @throws CreateException */ public boolean delete(String strPk) throws NamingException, RemoteException, CreateException,RemoveException,FinderException { try { SbnEmployeeHome objHome = (SbnEmployeeHome) EjbCommon. getRemoteEJBHome(EjbCommon. S_EMPLOYEE_JNDI, SbnEmployeeHome.class); SbnEmployee objRemote = objHome.create(); boolean b = objRemote.del(strPk); return b; } //关于错误处理:必须这么一个一个地catch错误,然后throw出去! catch (NamingException e) { throw e; } catch (RemoteException e) { throw e; } catch (CreateException e) { throw e; } catch (RemoveException e) { throw e; } catch (FinderException e) { throw e; } } /** * 根据传入的model,更新数据库里面的一条记录 * @param model * @return * @throws NamingException * @throws RemoteException * @throws CreateException */ public EmployeeModel update(EmployeeModel model) throws NamingException, RemoteException, CreateException,FinderException { try { SbnEmployeeHome objHome = (SbnEmployeeHome) EjbCommon. getRemoteEJBHome(EjbCommon. S_EMPLOYEE_JNDI, SbnEmployeeHome.class); SbnEmployee objRemote = objHome.create(); return objRemote.update(model); } catch (NamingException e) { throw e; } catch (RemoteException e) { throw e; } catch (CreateException e) { throw e; } catch (FinderException e) { throw e; } } /** * 根据传入的主键,返回一个model * @param strPk * @return * @throws NamingException * @throws RemoteException * @throws CreateException */ public EmployeeModel findByPk(String strPk) throws NamingException, RemoteException, CreateException,FinderException { try { SbnEmployeeHome objHome = (SbnEmployeeHome) EjbCommon. getRemoteEJBHome(EjbCommon. S_EMPLOYEE_JNDI, SbnEmployeeHome.class); SbnEmployee objRemote = objHome.create(); return objRemote.findByPk(strPk ); } catch (NamingException e) { throw e; } catch (RemoteException e) { throw e; } catch (CreateException e) { throw e; } catch (FinderException e) { throw e; } } /** * 根据传入的sql(注意不是完整的sql语句),得到所有满足条件的model,放到一个ArrayList里面返回 * @param sql * @return * @throws NamingException * @throws RemoteException * @throws CreateException */ public ArrayList queryBySql(String sql) throws NamingException, RemoteException, CreateException,SQLException { try { SbnEmployeeHome objHome = (SbnEmployeeHome) EjbCommon. getRemoteEJBHome(EjbCommon. S_EMPLOYEE_JNDI, SbnEmployeeHome.class); SbnEmployee objRemote = objHome.create(); return objRemote.queryBySql(sql); } catch (NamingException e) { throw e; } catch (RemoteException e) { throw e; } catch (CreateException e) { throw e; } catch (SQLException e) { throw e; } } /** * 根据传入的主键数组,批量删除记录 * @param sId * @return * @throws NamingException * @throws RemoteException * @throws CreateException */ public boolean deleteBatch(String[] sId) throws NamingException, RemoteException, CreateException{ boolean b = false; try { SbnEmployeeHome objHome = (SbnEmployeeHome) EjbCommon. getRemoteEJBHome(EjbCommon. S_EMPLOYEE_JNDI, SbnEmployeeHome.class); SbnEmployee objRemote = objHome.create(); b = objRemote.delBatch(sId); } catch (NamingException e) { throw e; } catch (RemoteException e) { throw e; } catch (CreateException e) { throw e; } finally{ return b; } } public EmployeeAction() { } public static void main(String[] args) { EmployeeAction action = new EmployeeAction(); //以下是调试代码。注意:最好在EJB发布到weblogic之前,将session bean里面的所有方法调试一遍, //确保不会有比较低级的错误。否则,如果到了jsp页面再去调试,无疑是nightmare EmployeeModel data = new EmployeeModel(); //说明:1)要调试的话,只要将“测试xx方法”前面加上/就可以了。 // 2)有时候EJB运行比较慢,JBuilder里面半天没有反应。这是可以在前面的方法里面加一些 // 输出语句,让你知道程序是在正确运行。 //*测试add()方法 for (int i = 0; i < 6; i++) { data.setName("name" + i); data.setJob("job1"); data.setHireDate(java.sql.Date.valueOf( "2003-07-21") ); try { action.add(data); } catch (Exception e) { e.printStackTrace(); } } //**/ /*测试delete()方法 try { action.delete("ID_2003072504CB077B81059114950140"); //这个主键的值是都数据库里面找的。 } catch (Exception e) { e.printStackTrace(); } //*/ /*测试deleteBatch()方法 String[] strSID = { "ID_2003072504CB077B81059116383421", "ID_2003072504CB077B81059116474625", "ID_2003072504CB077B81059116477218" }; try { action.deleteBatch( strSID ); } catch ( Exception e ) { e.printStackTrace(); } //*/ /*测试findByPk()方法 String strPK = "ID_2003072504CB077B81059116477328"; try{ data = action.findByPk( strPK ); System.out.println("找到的name=" + data.getName()); } catch ( Exception e ) { e.printStackTrace(); } //*/ /*测试queryBySql()方法 String strSql = "job1='job1'"; ArrayList alRet = null; try{ alRet = action.queryBySql( strSql ); if ( alRet != null && alRet.size() > 0) { for ( int i = 0; i < alRet.size(); i ++ ){ data = ( EmployeeModel ) alRet.get( i ); System.out.println("找到符合条件的第" + (i+1) + "个记录,name=" + data.getName()); } }else{ System.out.println("没有找到记录"); } } catch ( Exception e ) { e.printStackTrace(); } //*/ /*调试update()函数 String strPK1 = "ID_2003072504CB077B81059118072859"; try{ data = action.findByPk( strPK1 ); System.out.println("找到的旧的name=" + data.getName()); data.setName( "new name" ); action.update( data ); } catch ( Exception e ) { e.printStackTrace(); } //*/ System.out.println("*********Final!"); } } 调试EJB:调试方法是运行EmployeeAction。注意在运行之前,必须启动weblogic,并且保证EJB已经正确发布了。事实上,EJB的发布也要调试很长时间的。调试注意事项: 调试EJB是很麻烦的,而且非常耗费内存。如果内存不是512M以上,就等着痛苦降临吧:)我现在就是这样,简直有砸电脑的欲望。 有时候,所有的步骤都正确,但是总是有一些奇怪的错误。(比如我写这个例子的时候)这时,一般先shutdown weblogic,然后将weblogic目录下的所有临时目录(一般以TMP开头)全部删掉,然后重启一下weblogic。问题往往能够得到解决。不要问为什么,估计bea公司的人也不知道。 在JBuilder中,最好把EJB module的"Always creating JAR when building the project"去掉。免得每次都要重复编译ejb的.jar文件。 有时候编译出来的.jar文件很大(比如1M、2M;一般几十、几百KB是比较正常的),就要看EJB module的属性设置是否正确。主要是content是否包含所有的类,一般应该选择只包含用到的类。 用JBuilder发布的时候,有时候可能会碰到它提示“超过4分钟,时间超时,发布不成功”等等之类的提示。但是事实证明发布却是成功的,如果碰到这种情况,不理它就是了。 FAQ: Q:得到这样的错误javax.naming.NameNotFoundException: Unable to resolve 'SbnEmployee' Resolved: '' Unresolved:'SbnEmployee' ; remaining name 'SbnEmployee' A:没有正确发布EJB。请先启动weblogic,然后在JBuilder中右击ejb module,选择deploy。 Q:调试老通不过A:重启weblogic,然后再试试吧。 Q:我改动了session bean,为什么没有效果?A:修改EJB的任何一个部分,都要重新发布EJB才能生效。这个问题的症结很可能在这里。不过要记住,在JBuilder里面,此时要用Reploy这个选项,不要用Deploy。 Q:我在EJB里面System.out.println了一下,为什么看不到输出?A:EJB的输出在weblogic里面。要注意的是,System.out.println的输出,有时候在JBuilder里面,有时候又在weblogic里面,有时候还可能到java的控制台里面(比如applet的输出,不过这是题外话了)。 Q:我的EJB写的都是正确的啊,为什么老是出现发布的错误?A:试试:打开EJB module的属性,将“discriptors in module”里面的weblogic-ejb-jar.xml删除掉,然后重新发布。问题往往可能会在这里,特别是你用来调试的weblogic的版本变化的时候。说明:这个条目可以放心删除,JBuilder在编译EJB的时候,会自动根据当前的设置加上这个条目。