Connecting from a J2EE Application Client

Developing a J2EE application client requires a few extra steps, but results in a much more portable client implementation.

Implementing the Client

The implementation is nearly identical to the J2SE client example, except that you're able to use a local JNDI location, java:comp/env/ejb/HelloWorldEJB , instead of the global HelloWorldEJB . This indirection is important for portability, since some servers may not allow you to bind the EJB to the global HelloWorldEJB location, as shown in the following sample:

 package com.apress.oc4j.ac.j2seclient; import java.io.IOException; import java.rmi.RemoteException; import java.util.Properties; 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 void run() throws NamingException, RemoteException, CreateException, LoginException {          Context ctx = new InitialContext();         // get the bean         HelloWorldHome home = (HelloWorldHome) ctx.lookup("java:comp/env/ejb/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

The jndi.properties file uses a different InitialContextFactory , and doesn't need to include the security properties because you'll typically use JAAS authentication, as shown here:

 java.naming.factory.initial=   com.evermind.server.ApplicationClientInitialContextFactory java.naming.provider.url= ormi://myserver.acme.com/oracle 
Caution 

The value provided for java.naming.provider.url is actually ignored when using a JAAS CallbackHandler .However, some value must be set for this property to avoid errors in the current OC4J release.

Implementing a JAAS CallbackHandler

Since you're relying on JAAS for security, you'll need to implement a CallbackHandler to provide credentials whenever a secure call is made. The following example always authenticates with the same username and password (which may be loaded out of a properties file for portability).

We've chosen to implement the CallbackHandler as an inner class in this example, even though you'll need to move it to a public class in the next example.

JAAS CallbackHandler implementation

 // imports omitted public class SimpleClient {     private static final String USERNAME = "janm";     private static final String PASSWORD = "h881SDF!fo";     class SimpleCallbackHandler implements CallbackHandler {         private Properties securityProperties;         public SimpleCallbackHandler() {             securityProperties = new Properties();             securityProperties.setProperty("Username", USERNAME);             securityProperties.setProperty("Password", PASSWORD);             securityProperties.setProperty("URL", "ormi://localhost/oracle");         }         private void handleNameCallback(NameCallback callback) {             callback.setName(securityProperties.getProperty(callback.getPrompt()));         }         private void handlePasswordCallback(PasswordCallback callback) {             callback.setPassword(securityProperties.getProperty (callback.getPrompt()).toCharArray());         }         private void handleTextInputCallback(TextInputCallback callback) {             callback.setText(securityProperties.getProperty(callback.getPrompt()));         }         public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {             for (int i = 0; i < callbacks.length; i++) {                 Callback callback = callbacks[i];                 if (callback instanceof NameCallback) handleNameCallback((NameCallback)callback);                else if (callback instanceof PasswordCallback)                    handlePasswordCallback((PasswordCallback)callback);                else if (callback instanceof TextInputCallback)                    handleTextInputCallback((TextInputCallback)callback);             }         }     } // rest of the code omitted } 

Of course, in a user interface situation, it might be preferable to ask the user to enter a username and password. Implementation of such an application depends on the user interfacefrom a simple command-line interface, through rich graphical interfaces to special limited interfaces, such as ATMs.

Server-Side Configuration

Next, you need to add an application-client .xml deployment descriptor to the J2EE application EAR. Described in the J2EE specification, this is a standard deployment descriptor that allows you to set up any EJB references or environment entries needed by the client. It also allows you to specify which CallbackHandler should be used for authentication, as shown here:

 <!DOCTYPE application-client       PUBLIC "-//Sun Microsystems, Inc.//DTD J2EE Application Client 1.3//EN"                   "http://java.sun.com/dtd/application-client_1_3.dtd"> <application-client>     <display-name>My Application Client</display-name>     <ejb-ref>         <ejb-ref-name>ejb/HelloWorldEJB</ejb-ref-name>         <ejb-ref-type>Session</ejb-ref-type>         <home>com.apress.oc4j.ac.ejb.HelloWorldHome</home>         <remote>com.apress.oc4j.ac.ejb.HelloWorld</remote>         <ejb-link>HelloWorldEJB</ejb-link>     </ejb-ref>     <callback-handler>com.apress.oc4j.ac.client.SimpleCallbackHandler </callback-handler> </application-client> 
Note 

If your application-client.xml remaps the JNDI locations of resources other than EJBs (for example, data sources, mail sessions, JMS destinations), then you should also create an orion-application-client.xml descriptor to map each resource. This file follows the same straightforward pattern as all other server-specific descriptors. The DTD is available at http://xmlns.oracle.com/ias/dtds/orion-application-client-9_04.dtd .

Your application-client.xml and orion-application-client.xml (if you created one) should be placed inside a JAR along with the code like this:

 META-INF/application-client.xml META-INF/orion-application-client.xml com/apress/oc4j/ac/client/TestClient.class com/apress/oc4j/ac/SimpleCallbackHandler.class 

Include this client JAR in the EAR and add a reference to it in the application.xml descriptor, like this:

 <!DOCTYPE application       PUBLIC "-//Sun Microsystems, Inc.//DTD J2EE Application 1.3//EN"      "http://java.sun.com/dtd/application_1_3.dtd"> <application>     <display-name>My Application</display-name>     <module>         <ejb>acejb.jar</ejb>     </module>     <module>         <java>ac.jar</java>     </module> </application> 

At this point, the application should be redeployed so that the client will be recognized when it connects.

Tip 

OC4J doesn't support the distribution of client code from the server to the client container, so it's not actually necessary to include the client code in the JAR that's placed in the EAR. However, we've done that here because other servers do support that feature, and because it lets you use the same client JAR to invoke the classes directly from the command line.

Running the Client

Once you've assembled the client JAR and redeployed the J2EE application, you can invoke the J2EE client from the command line, as you did with the J2SE client, as shown here:

 java -cp oc4j.jar:ac.jar:jndipropertiesdirectory com.apress.oc4j.ac. SimpleClient 

Note that since you'll require JAAS support, you need to include oc4j.jar on the class- path instead of oc4jclient.jar . Also, in this example, you've included the parent directory of jndi.properties on the classpath instead of placing that file in the JAR.

Caution 

In its manifest file ( META-INF/MANIFEST.MF ), oc4j.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 .



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