DEVELOPING & DEPLOYING A PACKAGED EJB (WEBLOGIC-7) & ACCESSING IT BY A PACKAGED SERVLET (TOMCAT4.1)
===================================================
by Farihah Noushene ([email protected]), B.E.
(published in DeveloperIQ May-2005)
----------------------------------------------
The concept of 'package' is very important in Enterprise Java. Compiling and Deploying such packaged servlets & EJB, requires careful steps. In this tutorial, the author explains the concepts with a simple and practical example.
There have been a number of tutorials on EJB, Servlet & JSP in the past editions. In all these lessons, using 'package' was resorted to, only when essential, so that the examples will be simple to follow and to execute. For example, it is absolutely essential to use a package for a JSP-Bean. Without a package, the Tomcat server may not locate the bean class at all. Hence, in all the JSP examples, the jspbean file began with package statement.
So far as servlets are concerned, it is not absolutely essential to have a package, though it does help. Even if the servlet makes use of a function bean (also called 'utility bean' or helper-class), it is not essential to provide a package statement.
But, the moment, we adopt the MVC pattern, either our own or the Struts pattern, a servlet, bean and JSP share the functionality, and in such cases, we should provide a package and carefully follow the correct procedure, in compiling and deploying. These have already been explained in the article on Struts (Jan-2005 issue of Developer IQ).
In actual Enterprise world, 'package' concept is very important. The Web Universe has thousands and thousands of applications and to avoid name-clash, it is absolutely essential to carefully give a unique name for our classes, within a unique package. Otherwise, there will be name-collision. Java language provides a built in facility for package.
Marty Hall has provided a very nice note on compiling and deploying Servlets with or without package and beans, along with JSP.
(www.moreservlets.com).
To guarantee the uniqueness of package names, JavaSoft suggests to use the Internet address (of the company developing the program) as a prefix for the package. For example, if a company has registered the address xxxx.com and has a project called account, it can create the package name as com.xxxx.account
Typically, the series of names in a package (for example book.chapter3.example1.greeter) maps to a series of directories in the file system of the machine (book\chapter3\example1\greeter). If we give classpath as c:\myclasses and attempt to run a program that attempts to run a program that has package name book.chapter3.example1.greeter, the Java Virtual Machine (JVM) will look for the program's classes in the directory
c:\myclasses\book\chapter3\example1\greeter; if it doesn't find the classes in this directory it will report a ClassNotFound Exception. The same idea extended to Tomcat, would mean that we create a folder with the same name as that of the package name under the 'classes' folder in Tomcat\webapps\root\web-inf\.
In real life situations, the EJB developer is different from client who uses the EJB. So, the package name of servlet, will be different from that of the EJB. In this tutorial, we will see how to compile the ejb with a particular package name and call that ejb from an ejb caller from a different package name.
-----------------------------------------------------------------------
Our project folder is f:\ejbdemo.
We are using Windows-2000 & WebLogic-7.
If our package name for ejb classes is 'demo1', we create a subfolder 'demo1' under ejbdemo folder. Next we give home, path and classpath. The classpath should be carefully noted. It includes the project folder as well as the subfolder 'demo1'.
------------------
f:>md ejbdemo
f:>cd ejbdemo
f:\ejbdemo>md demo1
f:\ejbdemo\demo1>set JAVA_HOME=g:\jdk1.3
f:\ejbdemo\demo1>set WL_HOME=E:\bea\weblogic700
f:\ejbdemo\demo1>set path=c:\windows\command;g:\jdk1.4\bin;
e:\bea\weblogic700\server\bin
f:\ejbdemo\demo1>set classpath=f:\ejbdemo\demo1;f:\ejbdemo;
g:\tomcat41\tomcat\common\lib\servlet.jar;
e:\bea\weblogic700\server\lib\weblogic.jar;
-----------------------------------------------------------------------
Edit Remote, Home and Bean in the demo1 folder.
//f:\ejbdemo\demo1\sqlRemote.java
package demo1;
import javax.ejb.*;
import java.rmi.*;
import java.util.*;
public interface sqlRemote extends EJBObject
{
public String getresult(String s)
throws RemoteException;
}
-----------------------------------------------------------------------
//f:\\ejbdemo\demo1\sqlHome.java
package demo1;
import javax.ejb.*;
import java.rmi.*;
public interface sqlHome extends EJBHome
{
public sqlRemote create()
throws RemoteException,CreateException;
}
-----------------------------------------------------------------------
//f:\\ejbdemo\demo1\sqlBean.java
package demo1;
import javax.ejb.*;
import java.util.*;
import java.sql.*;
public class sqlBean implements SessionBean
{
public String getresult(String sql)
{
//.....USUAL JDBC CODE
}
public void ejbCreate() {}
public void ejbRemove() {}
public void ejbActivate() {}
public void ejbPassivate() {}
public void setSessionContext
(SessionContext sc){}
}
-----------------------------------------------------------------------
We will be able to compile all the above files, as we have already given the required classpath.
Usually, we create a sub-folder named 'META-INF' in the current folder and edit the two xml files in META-INF folder( ejb-jar.xml & weblogic-ejb-jar.xml). The folder should be META-INF & not 'meta-inf'
But, when we use a package for the EJB classes, we should create META-INF folder in the parent directory. Otherwise, the jar file will not get deployed in WebLogic properly.
----------------------------------------------------------------------
f:\ejbdemo\demo1>cd..
f:\ejbdemo>md META-INF
f:\ejbdemo>cd META-INF
f:\ejbdemo\META-INF>
-----------------------------------------------------------------------
Now edit the weblogic-ejb-jar.xml and ejb-jar.xml in META-INF folder.
-----------------------------------------------------------------------
//f:\ejbdemo\META-INF\ejb-jar.xml
<?xml version="1.0"?>
<!DOCTYPE ejb-jar PUBLIC
"-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN"
"http://java.sun.com/dtd/ejb-jar_1_1.dtd">
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>sqlBean</ejb-name>
<home>demo1.sqlHome</home>
<remote>demo1.sqlRemote</remote>
<ejb-class>demo1.sqlBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container
</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
-----------------------------------------------------------------------
//f:/ejbdemo/demo1/weblogic-ejb-jar.xml
<?xml version="1.0" ?>
<!DOCTYPE weblogic-ejb-jar PUBLIC
'-//BEA Systems, Inc.//DTD WebLogic 5.1.0 EJB//EN'
'http://www.bea.com.servers/wls510/dtd/weblogic-ejb-jar.dtd'>
<weblogic-ejb-jar>
<weblogic-enterprise-bean>
<ejb-name>sqlBean</ejb-name>
<jndi-name>ejbpackJndi</jndi-name>
</weblogic-enterprise-bean>
</weblogic-ejb-jar>
-----------------------------------------------------------------------
We can now , create the jar file by the following command;
f:\ejbdemo>jar cf sqlejbpack.jar
demo1\*.class META-INF\*.xml
Carefully note that we are including all the class files in demo1 folder and all the xml files in META-INF folder by this command.
Another point to be noted is that we are giving the command from the parent-directory i.e. 'ejbdemo'. The differences between this and the usual procedure in earlier lessons may kindly be noted. If we adopt the earlier method i.e. create a subfolder under 'demo1' named 'META-INF' and give command as : demo1>jar cf myjar.jar *.class META-INF\*.xml, the jar will be created and there won't be any problem in ejbc step also but, the jar will not get deployed in the weblogic server. We will get the error message - 'Unable to load a class specified in your ejb-jar.xml: demo1.sqlBean '.This is a crucial point to be noted.
Now we can deploy the jar easily.
f:\ejbdemo>java weblogic.ejbc sqlejbpack.jar sqlejbpack1.jar
After some time, we will get the message 'ejbc successful'
-----------------------------------------------------------------------
Now, we copy the jar file to the WebLogic folder as shown below.
f:\ejbdemo>copy sqlejbpack1.jar
e:\bea\user_projects\mydomain\applications
Start the weblogic server and the jar will be deployed by the server.
Thus, development of the EJB and its deployment in WebLogic server are over.
**********************************************************************
We now develop a client program for the above ejb. As this is being done by a different party, the package name will be different.
(say) ourpack.
f:\ejbdemo>md ourpack
Now edit the ejb caller program and the client in the 'ourpack' folder
-----------------------------------------------------------------------
//f:\ejbdemo\ourpack\ejbcaller.java
package ourpack;
import java.util.*;
import javax.ejb.*;
import javax.rmi.*;
import javax.naming.*;
import java.rmi.*;
import java.io.*;
public class ejbcaller
{
public String callejb(String s)
{
String r;
try
{
System.out.println("Please Wait...");
Properties props =new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
props.put(Context.PROVIDER_URL,
"t3://127.0.0.1:7001");
Context ctx=new InitialContext(props);
System.out.println("CONTEXT READY");
demo1.sqlHome home=
(demo1.sqlHome)ctx.lookup("ejbpackJndi");
System.out.println("HOME LOCATED");
demo1.sqlRemote remote=home.create();
System.out.println("REMOTE READY");
r=remote.getresult(s);
}
catch(Exception e1){ r=""+e1; }
return r;
}
}
-----------------------------------------------------------------------
//f:\ejbdemo\ourpack\callerconsole.java
package ourpack;
class callerconsole
{
public static void main(String args[])
{
ejbcaller caller1=new ejbcaller();
String s=caller1.callejb(args[0]);
System.out.println(s);
}
}
-----------------------------------------------------------------------
To Run:
Compile the ejbcaller and the client.
f:\ejbdemo\ourpack>java demo1.sqlconsole ?select * from table1?
We will get the result correctly.
Next we will test it with the servlet client.
//f:\ejbdemo\ourpack\callerservlet.java
package ourpack;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class callerservlet extends HttpServlet
{
public void doPost(HttpServletRequest req,
HttpServletResponse res)
throws ServletException,IOException
{
res.setContentType("text/html");
PrintWriter out=res.getWriter();
//-----------------------------------------
String s=req.getParameter("text1");
ejbcaller caller1=new ejbcaller();
String r=caller1.callejb(s);
out.println(r);
}
}
-----------------------------------------------------------------------
sqlservlet.htm
<html>
<body>
<form method=post action="/servlet/ourpack.callerservlet">
<input type=text name="text1">
<input type=submit>
</form>
</body>
</html>
----------------------------------------------------------------------
To Run:
H:\cd tomcat41\webapps\root\web-inf\>
edit web.xml
Add the following entry in web.xml file
<servlet>
<servlet-name>sqlservlet</servlet-name>
<servlet-class>ourpack.callerservlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sqlservlet</servlet-name>
<url-pattern>/servlet/ourpack.callerservlet</url-pattern>
</servlet-mapping>
-----------------------------------------------------------------------
Create two folders 'demo1', 'ourpack' in tomcat41\webapps\root\web-inf\classes
copy sqlRemote.class, sqlHome.class, sqlBean.class to h:\tomcat41\webapps\root\web-inf\classes\demo1
compile the caller servlet and copy callerservlet.class, ejbcaller.class to h:\tomcat41\webapps\root\web-inf\classes\ourpack
Next copy sqlservlet.htm to h:\tomcat41\webapps\root
Start the tomcat server with JAVA_HOME=g:\jdk1.4
Open the browser and type URL as http://localhost:8080/sqlservlet.htm
Type the sql in textbox and click ?submit?. The result will be displayed.
_______________________________________________________________________