Thursday, December 28, 2006

EJB Lookup

1. When deploying EJB, it has a name(if specified using annotation : @Stateless(name="SessionEJB") or if descriptor: <ejb-name>SessionEJB</ejb-name>.

2. This EJB deployed to OC4J. Now to do a lookup for this EJB, we can use either ApplicationClientInitialContextFactory or RMIInitialContextFactory.

3. In case of RMIInitialContextFactory, no need of application-client.xml and the context lookup will be : new InitialContext.lookup("SessionEJB").

4. In case of ApplicationClientInitialContextFactory, we need application-client.xml. It has to introduce the ejb refrence going to be used in code as:

<application-client 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-client_1_4.xsd" version="1.4" xmlns="http://java.sun.com/xml/ns/j2ee">
<display-name>InterceptorTest-app-client</display-name>
<ejb-ref>
<ejb-ref-name>ejb/SessionEJB</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<remote>myEJB.SessionEJB</remote>
<ejb-link>SessionEJB</ejb-link>
</ejb-ref>
</application-client>

5. Here, ejb-link is used to link to the actual bean. Now, in the client code we use the ejb-ref-name for lookup as:

new InitialContext().lookup("java:comp/env/ejb/SessionEJB");

Sunday, December 24, 2006

MDB deployment in OC4J

1. Create the MDB(normal java class with @MessageDriven annotation). Set the ActivationConfigs.

@MessageDriven(
activationConfig = {
@ActivationConfigProperty(propertyName="connectionFactoryJndiName", propertyValue="jms/TopicConnectionFactory"),
@ActivationConfigProperty(propertyName="destinationName",
propertyValue="jms/demoTopic"),
@ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Topic"),
@ActivationConfigProperty(propertyName="messageSelector", propertyValue="RECIPIENT = 'MDB'") } )

2. Create EJB jar deployment profile(MDBServer.deploy) for the above MDB and deploy it to OC4J server(application name = MDBServer)

3. In same project, create the MDBClient. Inject the resources @Resource(name="jms/demoQueue") and @Resource(name="jms/TopicConnectionFactory"). Use connectionFactory and create connection, then session, message and send the message using producer.

4. In Jdeveloper create jndi.properties file with:

java.naming.factory.initial= oracle.j2ee.naming.ApplicationClientInitialContextFactory
java.naming.provider.url=ormi://localhost:23791/MDBServer
java.naming.security.principal=oc4jadmin
java.naming.security.credentials=welcome

5. Create client Jar deployment profile from Jdeveloper. This creates application-client.xml. Modify application-client.xml and add following lines for the resource reference entries(Make sure to mention the main class file name in descriptor creation)

<application-client 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-client_1_4.xsd" version="1.4" xmlns="http://java.sun.com/xml/ns/j2ee">
<display-name>MDB1-app-client</display-name>
<resource-env-ref>
<resource-env-ref-name>jms/demoTopic</resource-env-ref-name>
<resource-env-ref-type>javax.jms.Topic</resource-env-ref-type>
</resource-env-ref>
<resource-env-ref>
<resource-env-ref-name>jms/TopicConnectionFactory </resource-env-ref-name>
<resource-env-ref-type>javax.jms.TopicConnectionFactory </resource-env-ref-type>
</resource-env-ref>
</application-client>

6. Deploy the deployment profile MDBClient.deploy to MDBClient.jar.

7. From command prompt containing the jar file, set class path and run :

D:\installs\JdevStudio10131\jdev\mywork\MDB\MDB1\deploy>set CLASSPATH =.\;D:\installs\oc4j\j2ee\home\oc4jclient.jar;D:\installs\oc4j\j2ee\home\lib\javax77.jar;

D:\installs\JdevStudio10131\jdev\mywork\MDB\MDB1\deploy>java oracle.oc4j.appclient.AppClientContainer MDBClient.jar

Output from the application server log will contain:

06/12/24 20:26:44 onMessage() - Message[ID:Oc4jJMS.Message.krishnamoorthy.64e0c3
ab:10fb4f6b670:-8000.4]

onMessage method of the MDB just does a system.out.println(message)

Note: Without creating jar of client files and if I directly run using:

D:\installs\JdevStudio10131\jdev\mywork\MDB\MDB1\classes>java -Djava.naming.factory.initial=oracle.j2ee.naming.ApplicationClientInitialContextFactory -Djava.naming.provider.url=ormi://localhost:23791/MDBServer -Djava.naming.security.principal=oc4jadmin -Djava.naming.security.credentials=welcome myJMSClient.TestJMSClient

I get

Exception in thread "main" java.lang.NullPointerException
at myJMSClient.TestJMSClient.main(TestJMSClient.java:22)

So, should a JMS client be run always using AppClientContainer as :

java oracle.oc4j.appclient.AppClientContainer MDBClient.jar

Friday, December 22, 2006

Running EJB Client Standalone

HelloWorld.java

package myEJB;

import javax.ejb.Remote;

@Remote
public interface HelloWorld {
public String sayHello(String name);
}

HelloWorldBean.java

package myEJB;

import javax.ejb.Stateless;

@Stateless
public class HelloWorldBean implements HelloWorld {
private int count;

public String sayHello(String name) {
count++;
System.out.println("sayHello method from Bean ");
return "Hello " + name + " Count : " + count;
}
}

Compile the classes and run in embedded oc4j of jdeveloper. Or create a ejb jar deployment profile and deploy it to standalone oc4j server. Deployment name is the application name in the standalone oc4j. Let us say application is HelloWorldDeploy. Ear file contains jar file and META-INF. Inside META-INF is the application.xml containing the name of ejb module jar file. Jar file contains the interface and bean classes. After deploying, create a test client as follows:

HelloWorldClient.java

package myEJB;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class HelloWorldClient {
public static void main(String [] args) {
try {
final Context context = new InitialContext();
HelloWorld helloWorld = (HelloWorld)context.lookup("java:comp/env/ejb/HelloWorldBean");
// Call any of the Remote methods below to access the EJB
System.out.println(helloWorld.sayHello( "Krishna" ));
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

To invoke ejb method from command line:

D:\work\MyWork\ejb\ejb3>set CLASSPATH=D:\installs\JdevStudio10131\j2ee\home\oc4jclient.jar;.\;

D:\work\MyWork\ejb\ejb3>java -Djava.naming.factory.initial=oracle.j2ee.naming.Ap
plicationClientInitialContextFactory -Djava.naming.provider.url=ormi://localhost
:23791/HelloWorldDeploy -Djava.naming.security.principal=oc4jadmin -Djava.naming
.security.credentials=welcome myEJB.HelloWorldClient

Output is : Hello Krishna Count : 1

Thursday, December 21, 2006

Transaction Isolation Level

Good link for getting a refresh on the isolation level: http://www.oracle.com/technology/oramag/oracle/05-nov/o65asktom.html
Oracle supports READ COMMITTED and SERIALIZABLE. Oracle doesn't allow dirty reads(READ UNCOMMITTED). It allows a third isolation level which is READ ONLY. No insert, update, delete can be done in this mode.

Wednesday, December 20, 2006

RMI tutorial on SUN

1. Start the rmiregistry at the default port 1099. (rmiregistry.exe)

2. Start the Local Http server for delivering class files between server-RMI and RMI-Client.

D:\work\MyWork\rmi\suntutorial>java examples.classServer.ClassFileServer 1185 D:\work\MyWork\rmi\suntutorial

3. Then start the ComputeEngine server using :

D:\work\MyWork\rmi\suntutorial>java -cp .\;compute.jar -Djava.rmi.server.codebase=http://pc-krsethur-in:1185/ -Djava.rmi.server.hostname=pc-krsethur-in -Djava.security.policy=D:\work\MyWork\rmi\suntutorial\server.policy engine.ComputeEngine

4. Remove the client files from the suntutorial folder and place it in a folder named test under this suntutorial so that RMI will get the files using http from the client(thus, the above classpath doesn't include the client classes).

5. server.policy should have the line

grant {
permission java.net.SocketPermission "*:*", "listen,accept,connect";
};

for the binding of remote object to the registry(1099).

6. Now run the client as

D:\work\MyWork\rmi\suntutorial\test>java -cp .\;..\compute.jar; -Djava.rmi.server.codebase=http://pc-krsethur-in:1185/test/ -Djava.security.policy=D:\work\MyWork\rmi\suntutorial\client.policy client.ComputePi pc-krsethur-in 45

Output
3.141592653589793238462643383279502884197169399

7. Client.policy should have similar line above(5)

8. here -Djava.rmi.server.codebase=http://pc-krsethur-in:1185/test/ will be set because during client execution, we call executeTask on the proxy remote object. The remote object running in the RMI runtime will delegate to the task object. Now, the task object is still not present in the RMI runtime and will give class not found exception. To prevent that we set the codebase to http://pc-krsethur-in:1185/test/. Here pc-krsethur-in:1185 will deliver files present under D:\work\MyWork\rmi\suntutorial. However, the task class is present in D:\work\MyWork\rmi\suntutorial\test folder. Hence, we append the test/ in the URL for the codebase. Our local file server will serve the classes from D:\work\MyWork\rmi\suntutorial\test for RMI runtime during client execution. Similarly, when the server was started, during binding of remote object, the interface classes(Compute.class and Task.class) for the RMI runtime was served by -Djava.rmi.server.codebase=http://pc-krsethur-in:1185/.

9. After a single execution of both server and client, the classes(Compute.class and Task.class) for the server execution and the class(Task.class) from client execution will be present in the RMI runtime and hence if the local file server is stopped at this time and the server is aborted and restarted, it will work fine without any error about class not found. Similarly if the client is run now also, the client will work fine, because the Task.class is already loaded in the RMI runtime.

10. Now if we stop the rmiregistry.exe(thus all the classes loaded in RMI runtime are gone) and restart the rmiregistry and then start the server or client(with the local file server stopped), they will fail with class not found exception.