Connecting from a J2SE Client

Any Java application can access server-side J2EE components simply by setting a few JNDI properties, creating an InitialContext , and looking them up in the global JNDI namespace.

Implementing the Client

The following example client finds and invokes a remote EJB:

Client invoking an EJB

 package com.apress.oc4j.ac.client; import java.rmi.RemoteException; import javax.ejb.CreateException; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.security.auth.login.LoginException; import com.apress.oc4j.ac.ejb.HelloWorld; import com.apress.oc4j.ac.ejb.HelloWorldHome; public class SimpleClient {     private SimpleClient() {     }     private void run() throws NamingException, RemoteException, CreateException, LoginException {          Context ctx = new InitialContext();          HelloWorldHome home = (HelloWorldHome) ctx.lookup("HelloWorldEJB");          HelloWorld bean = home.create();          // call the EJB method          System.out.println(bean.getGreeting());     }     public static void main(String[] args) throws Exception {         new SimpleClient().run();     } } 

Configuring JNDI

Notice that the InitialContext constructor in the example is called with no parameters. In this case (as with many clients ), you'll create a jndi.properties file to avoid hard-coding those values. This jndi.properties file looks like this:

 java.naming.factory.initial=com.evermind.server.rmi.RMIInitialContextFactory java.naming.provider.url=ormi://myserver.acme.com/oracle 
Note 

See Chapter 5 for a more detailed discussion of JNDI.

Authenticating Through JNDI

In OC4J you'll always need to authenticate to access JNDI and other components. Thus, you need to modify the client to authenticate itself to the server before accessing the EJB.

By far, the easiest way to authenticate is by setting two additional properties in the jndi.properties file, like this:

 java.naming.security.principal=someUsername java.naming.security.credentials=somePassword 

Another option is to dynamically set these JNDI properties based on user input or other processing, instead of using a jndi.properties file, as shown here:

 Properties props = new Properties(); props.setProperty("java.naming.factory.initial",                            "com.evermind.server.rmi.RMIInitialContextFactory"); props.setProperty("java.naming.provider.url ","ormi://myserver.acme.com/oracle"); props.setProperty("java.naming.security.principal", getUsername()); props.setProperty("java.naming.security.credentials", getPassword()); Context ctx = new InitialContext(props); 

This second option is usually appropriate for interactive user interfaces.

Authenticating Through JAAS

For greater portability, it's possible for a J2SE application client to authenticate through JAAS by passing in a lot of security- related system properties, creating a LoginContext , passing it a CallbackHandler , and logging in to a JAAS LoginModule . However, it usually makes a lot more sense to just use a J2EE application client, which provides much cleaner and more transparent JAAS integration, as shown in the following code sample.

JAAS Login from a J2SE client

 package com.apress.oc4j.ac.j2seclient; import java.io.IOException; import java.rmi.RemoteException; import javax.ejb.CreateException; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import com.apress.oc4j.ac.ejb.HelloWorld; import com.apress.oc4j.ac.ejb.HelloWorldHome; public class SimpleClient {     private static final String USERNAME = "janm";     private static final String PASSWORD = "h881SDF!fo";     private SimpleClient() {     }     private void run() throws NamingException, RemoteException, CreateException, LoginException {          // get login context  LoginContext loginContext = new LoginContext(USERNAME,   new SimpleCallbackHandler());  try {              // get naming context              Context ctx = new InitialContext();              // login  loginContext.login();  // get the bean              HelloWorldHome home = (HelloWorldHome) ctx.lookup("HelloWorldEJB");              HelloWorld bean = home.create();             // call the EJB method             System.out.println(bean.getGreeting());         } finally {             // logout  loginContext.logout();  }     }     public static void main(String[] args) throws Exception {         new SimpleClient().run();     } } 

Building the Client

Once you have all the code, you'll need to create a build script that will compile all source codes and package the client. You'll create a simple Ant build script for this, as shown here:

 <project name="sample" basedir="." default="dist">     <!-- configure the basic directory properties -->     <property name="dir.java.src" value="src/java"/>     <property name="dir.java.build" value="build"/>     <property name="dir.conf.src" value="src/conf"/>     <property name="dir.lib" value="lib"/>     <property name="dir.dist" value="dist"/>     <path id="project.classpath">         <fileset dir="${dir.lib}">             <include name="*.jar"/>         </fileset>     </path>     <!-- Create needed directories -->     <target name="init">         <mkdir dir="${dir.dist}"/>         <mkdir dir="${dir.java.build}"/>     </target>     <target name="compile-client" depends="init">         <javac srcdir="${dir.java.src}" destdir="${dir.java.build}" debug="on"             debuglevel="lines,vars,source">             <classpath refid="project.classpath"/>             <exclude name="**/Test*.java"/>             <exclude name="**/AllTests.java"/>         </javac>     </target>     <target name="dist" depends="compile-client">         <jar destfile="${dir.dist}/ac.jar">             <fileset dir="${dir.java.build}"><include name="**/*.class"/></fileset>             <fileset dir="${dir.conf.src}"><include name="*/**"/></fileset>         </jar>     </target> </project> 

The script is quite simple. It merely compiles the sources from the src/java directory and creates a JAR file in the dist directory. It also adds the jndi.properties file to the generated JAR file. You can now use the JAR file to run the client.

Running the Client

Typically, you'll package the client code, the EJB interfaces you're using, and the jndi.properties file in a client JAR. Then, assuming OC4J is running and the EJB has been successfully deployed, you can run the client like this:

 java -cp oc4jclient.jar:ac.jar com.apress.oc4j.ac.j2seclient.SimpleClient 
Caution 

In its manifest file ( META-INF/MANIFEST.MF ), oc4jclient.jar has classpath entries that refer to other J2EE libraries. If you're copying this JAR out of your OC4J installation, make sure to include all of the other JARs your code requires, such as ejb.jar .

Depending on your environment, it may make more sense to leave the jndi.properties file out of the JAR and include its parent directory on the classpath. This allows you to easily update server and authentication settings without repackaging the client JAR.



Oracle Application Server 10g. J2EE Deployment and Administration
Oracle Application Server 10g: J2EE Deployment and Administration
ISBN: 1590592352
EAN: 2147483647
Year: 2004
Pages: 150

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net