BEA Logo BEA WebLogic Server Release 1.1

  Corporate Info  |  News  |  Solutions  |  Products  |  Partners  |  Services  |  Events  |  Download  |  How To Buy

Writing WebLogic Server Java Client Applications

 

Introduction

Java Client Architecture

How Java Clients Communicate with WebLogic Server

RMI Architecture

Network Connections

T3 and T3S Connections

HTTP and HTTPS Connections

IIOP Connections

WebLogic Server Java-to-Java Connections

Connecting to WebLogic Server with JNDI

The JNDI Naming Tree

Looking up Objects with JNDI

Getting the InitialContext

Looking up WebLogic Server Objects

Looking up an Enterprise JavaBean

Using a JDBC Connection Pool in a Client

Accessing WebLogic Server Services

Additional Topics

What Happened to T3Client?

Java Client Best Practices

Tunneling T3 over HTTP

Tuning WebLogic Server Cluster Clients

Introduction

Writing WebLogic Server Client Applications is for developers writing BEA WebLogic Server client-side Java applications. It describes how Java clients log into WebLogic Server and how clients can access WebLogic Server resources.

Java Client Architecture

A WebLogic Server Java client is a program written in Java that forms a network connection with WebLogic Server in order to use applications, components, or services hosted on WebLogic Server. A Java client runs in its own Java Virtual Machine (JVM) and uses standard J2EE (Java 2, Enterprise Edition) technologies to establish a WebLogic Server connection and access middle tier services.

In many ways, writing a WebLogic Server Java client is like writing a server-side class for WebLogic Server-the RMI (Remote Method Invocation) framework that enables J2EE technologies makes Java classes behave essentially the same way, whether you execute them locally in a client's JVM or remotely in the WebLogic Server JVM.

How Java Clients Communicate with WebLogic Server

WebLogic RMI is the core technology that allows Java clients to use WebLogic Server services. RMI (Remote Method Invocation) enables a Java program to define remote objects that can be executed remotely by another Java program. The RMI framework handles the networking details under the covers, transporting client requests to the server and returning execution results to the client.

With RMI, the terms "server" and "client" describe, respectively, the Java application that provides a remote object and the Java application that executes the object remotely. Any Java application can be a server or a client, or both if it publishes remote objects and uses remote objects published by another application. In the majority of WebLogic Server applications, WebLogic Server is the RMI server and a Java client is the RMI client.

The WebLogic Server services most often used from Java clients are built upon RMI. Enterprise JavaBeans (EJB), Java Messaging Services (JMS), and JDBC connection pools (accessed with WebLogic JDBC/RMI), are all enabled by RMI. WebLogic RMI is also tightly integrated with Java Naming and Directory Services (JNDI), which provides the mechanism for publishing remote objects and looking them up from a client.

RMI Architecture

WebLogic RMI, WebLogic EJB, WebLogic JMS, and WebLogic JDBC/RMI each provide a distributed object capability that hides the underlying networking details. In each case, a client application retrieves an object from WebLogic Server and uses it the same way it would use a local class. However, the server only sends the client an abbreviated "stub" class that contains a method for each of the remote object's public methods. It does not send the implementations for these methods, because the implementations are meant to execute on the server.

When an RMI client invokes a method on a stub, the stub transports the request and its arguments across the network to a "skeleton" class on the server. The skeleton class translates the request into a call on the server-side implementation class and then passes any returned value back to the client stub.

If you create your own remote classes using WebLogic RMI, you create stub and skeleton classes by running the WebLogic RMI compiler on your class files. With an Enterprise JavaBean, the WebLogic EJBC compiler creates stubs and skeletons. To use JMS and WebLogic JDBC/RMI, you do not have to create stubs and skeletons because these services supply their own remote classes.

Network Connections

Clients that use RMI services connect with WebLogic Server using TCP/IP over Java sockets. The WebLogic T3 protocol transports requests between client and server over TCP/IP. A client JVM has a single connection to WebLogic Server; all traffic between the client and server is multiplexed in the T3 datastream.

Note: An often-asked question is whether using a single connection instead of multiple connections has any effect on performance. The answer is "no." A single socket does not have a lower capacity than multiple sockets. The network transports packets at the same rate regardless of the number of sockets sending and receiving them. Since the T3 protocol is optimized for WebLogic RMI, WebLogic Server connections are highly efficient.

A client can connect to WebLogic Server using one of five protocols: T3, T3S, HTTP, HTTPS, or IIOP. These protocols are described in the next sections.

T3 and T3S Connections

To use RMI-based WebLogic Services, a Java client connects to WebLogic Server with T3 or T3S, which is T3 wrapped in SSL. A T3 connection is established when the client makes an initial JNDI connection and persists as long as the client JVM continues to make requests on WebLogic Server.

A Java client can also tunnel T3 over HTTP. That is, the client connects to WebLogic Server with HTTP, but proceeds as if it had a T3 connection. It uses JNDI, RMI, EJB, JMS or JDBC and the WebLogic RMI classes wrap the T3 packages in HTTP packets before sending them to Weblogic Server. WebLogic Server recognizes tunneled T3 automatically, unwrapping incoming T3 packages wrapping outgoing T3 packets in HTTP. This makes it possible for a Java client on the other side of a firewall to access a WebLogic Server when only HTTP protocol is accepted through the firewall. The tunneling overhead tunnelling does affect performance, so this option should only be used when a firewall makes it necessary.

HTTP and HTTPS Connections

HTTP connections are usually used by web browsers for web services, such as Servlets, JSP pages, and HTML pages. HTTPS is HTTP wrapped with SSL.

As mentioned in the previous section, Java clients can use HTTP to tunnel the T3 protocol. But a Java client can also get a standard HTTP connection to WebLogic Server by using the JDK java.net.HttpURLConnection class. The Java client must be HTTP-aware.That is, it must understand how to make requests on the HttpURLConnection and how to handle the results returned in the HTTP response.

An HttpURLConnection cannot directly use RMI-based services because they require a T3 connection. But an HttpURLConnection can access Servlets, and Servlets can access RMI-based services or any other service in WebLogic Server. Since an HttpURLConnection requires no WebLogic classes, you can use HTTP and Servlets to create a "thin" Java client-one that could be easily deployed over the Internet.

An interesting article on the Sun Java Developer Connection web site, Java Servlets and Serialization with RMI, describes this application architecture. The author, Scott McPherson, demonstrates how to use proxy classes in an applet to make HTTP requests on Servlets that execute RMI objects on the server. The model essentially replaces RMI stubs with hand-coded stubs that send requests over an HttpURLConnection, and replaces erver-side skeleton classes with Servlets that execute the remote classes on WebLogic Server. This is an especially attractive architecture for applets that use remote objects because it avoids loading WebLogic RMI classes in the browser and is less sensitive to differences in browsers.

The HTTP client architecture is only recommended for Java clients that do not have access to the WebLogic Server classes. WebLogic RMI over a T3 connection is a much more efficient way to use remote objects. It requires less coding than the HTTP model, and uses only standard J2EE technologies. Also, WebLogic RMI support for clustered objects is not available to clients that use the HTTP model.

IIOP Connections

IIOP is the protocol a CORBA client uses to access remote objects on WebLogic Server. IIOP clients may be written in Java, C++, SmallTalk, or other languages with CORBA support. To make J2EE objects, particularly Enterprise JavaBeans, available to CORBA clients, Sun and the Object Management Group have developed, and continue to refine, specifications for mapping the Java and CORBA object models. The CORBA client programming model is very different from the J2EE model, which is the subject of this document. Therefore, the IIOP protocol is not described further in this document. See Using WebLogic RMI over IIOP if you are interested in writing CORBA clients for WebLogic Server.

WebLogic Server Java-to-Java Connections

When a Java client connects to WebLogic Server, the client's JVM (Java Virtual Machine) has a unique ID, which WebLogic Server translates to a unique destination and network connection. WebLogic Server listens for HTTP and T3 connections on one port and HTTPS and T3S connections on another, so a client can have two network connections to a WebLogic Server. The listen port numbers are set in the weblogic.properties file with the weblogic.system.ListenPort and weblogic.system.SSLListenPort properties, which are set to 7001 and 7002 by default. If a client uses a WebLogic Server cluster, a separate network connection is established for each server in the cluster that responds to a client request.

To establish a connection, the client provides a URL in the format protocol://hostname:port, where protocol is HTTP, HTTPS, T3, or T3S, hostname is the DNS name of the computer running WebLogic Server, and port is the port number where WebLogic Server is listening for the connection. The port number must match the protocol-the SSLListenPort for HTTPS or T3S, or the ListenPort for HTTP or T3. For example, to create a T3 connection to a WebLogic Server listening on port 7001 of a computer with the DNS name "bighost", the client supplies this URL:

t3://bighost:7001

When the client and WebLogic Server execute on the same computer, you can substitute the DNS alias "localhost" for the computer name.

The most efficient connection protocol for a Java client is T3, since it involves neither encryption nor tunnelling. T3S adds overhead when the SSL connection is negotiated (authentication and key exchange) and then additional overhead for encrypting and decrypting all data transferred over the connection. HTTP and HTTPS add overhead for unpacking T3 packets from the HTTP packets, and HTTPS adds SSL overhead.

Connecting to WebLogic Server with JNDI

In a client-server application, the client makes a connection to a server and exchanges requests and results over the connection. The connection acts as a conduit between the client and server, and the application carefully manages the conversation that occurs over the connection. In a J2EE application, the server connection is abstracted out of the application architecture. Instead, J2EE applications operate on local objects that use the server connection transparently to communicate with their server-side counterparts. RMI (Remote Method Invocation) is the technology at the base of this architecture.

JNDI is the complementary technology that clients use to retrieve client-side objects from the application server. Server connections are managed transparently beneath JNDI and RMI by the application server framework. WebLogic Server implements the JNDI 1.2 specification and includes extensions to enable load-balancing and failover for clustered servers.

The JNDI Naming Tree

Application objects are published in a JNDI naming tree, which contains Java objects bound to names. Clients retrieve an object by looking it up by name with the JNDI API. When a lookup succeeds, the object is serialized and transferred to the client.

Any serializable object can be stored in the tree. JNDI objects must be serializable since they are transferred to the client over the network. There are several ways to bind objects in the WebLogic Server JNDI tree. The most common way is to define objects in the weblogic.properties file. WebLogic Server binds the objects in the JNDI tree when it processes properties at startup time. You can also define objects using commands in the WebLogic Console or programmatically with the JNDI API or other APIs that are built upon JNDI.

Several J2EE technologies rely on JNDI for publishing their distributed objects. RMI, which is the other basic enabling technology for distributed applications, binds remote classes in the JNDI tree. When you deploy an Enterprise JavaBean, the bean's home interface is bound in the JNDI tree. JMS binds message Topics, Queues and Factories in the JNDI tree. A JDBC 2.0 DataSource object is a JNDI-accessible factory for getting a connection from a JDBC connection pool.

Looking up Objects with JNDI

Retrieving an object with JNDI is a two-step process. First, the client gets an InitialContext, which connects it with a JNDI provider, specifically the WebLogic Server whose JNDI tree contains the desired object. Second, the client calls lookup() with the name of the desired object. It then casts the returned object to the correct Java type and uses the object in the same way it uses any Java class.

With JNDI, you get an InitialContext from a server by supplying the URL of a server, the name of the factory class that creates the Context, and optional information such as username and password. The InitialContext constructor establishes a network connection and returns a Context object that can be used to look up objects bound in the server's JNDI naming tree.

Getting the InitialContext

The InitialContext contains all of the parameters needed to establish a server connection, including network addresses and the client's identity and security credentials. The connection parameters are stored in a Hashtable and passed to the InitialContext constructor.

Here is an example of getting an InitialContext:

import javax.naming.*;
import java.util.Hashtable;

public class myClass {

static Context ctx = null;

boolean myConnect() {

boolean result = false;

Hashtable ht = new Hashtable();
ht.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
ht.put(Context.PROVIDER_URL, "t3://localhost:7001");
ht.put(Context.SECURITY_PRINCIPAL, "username");
ht.put(Context.SECURITY_CREDENTIALS, "password");
try {
ctx = new InitialContext(ht);
result = true;
}
catch (NamingException ne) {
System.out.println("JNDI Exception: ");
ne.printStackTrace();
result = false;
}
return result;
}
. . .

After executing the myConnect() method, the client has a JNDI Context object open on the specified WebLogic Server. If the PROVIDER_URL environment variable contained the address of a WebLogic Server cluster, the load-balancing algorithm selected one WebLogic Server in the cluster to provide the Context.

This example illustrates the most common variables passed in the JNDI Hashtable. The names of the variables, for example Context.INITIAL_CONTEXT_FACTORY, are static Strings defined in javax.naming.Context.

The INITIAL_CONTEXT_FACTORY and PROVIDER_URL variables are required. For WebLogic Server JNDI connections, the INITIAL_CONTEXT_FACTORY variable is always set to "weblogic.jndi.WLInitialContextFactory", which is the name of the WebLogic Server class that creates JNDI Contexts. The PROVIDER_URL is the URL of the target WebLogic Server, including the protocol, usually T3, and the hostname and listen port of the computer running WebLogic Server.

The SECURITY_PRINCIPAL and SECURITY_CREDENTIALS variables usually contain the client's WebLogic Server username and password, which are used to authenticate the client and check permissions for any object the client later looks up with the Context. If you do not set these variables, WebLogic Server defaults to the "guest" user with password "guest".

You can also pass client certificates in the SECURITY_CREDENTIALS variable, in addition to or in place of a password. This Hashtable variable can hold a password, an InputStream opened on a client certificate file, or an array containing a password and one or more InputStreams opened on certificate files. The first certificate in an array is always the client certificate; additional certificates form a certificate chain, each one the certificate of the authority who signed the preceding certificate. The chain allows WebLogic Server to authenticate a certificate as long as it recognizes one of the certificate authorities in the chain.

WebLogic Server does not automatically accept client certificates to authenticate users. If you use the T3S protocol and you configure WebLogic Server to require two-way SSL authentication, the client certificate is used to negotiate an SSL connection and a password is also required to authenticate the WebLogic Server user. Optionally, you can install a CertAuthenticator class in WebLogic Server to map client certificates to WebLogic Server users so that a password is not required. See Mapping a Client Certificate to a WebLogic Server User in "Using WebLogic Realms and Acls" for information about this option.

BEA provides a JNDI enhancement, weblogic.jndi.Environment, which is a wrapper on the JNDI Hashtable. The Environment class provides a method to set each environment variable. See Using WebLogic JNDI for information about using the Environment class.

Next, the client can use the Context to look up resources in WebLogic Server.

Looking up WebLogic Server Objects

The WebLogic Server JNDI naming tree contains:

To look up an object, you call the Context.lookup() method with the name of the object you want and then cast the returned Object to the correct type. JNDI returns whatever is bound in the JNDI naming tree. In many cases, the object is an RMI stub class-a Java class with methods that, when called in the client, use the RMI framework to execute an implementation class on WebLogic Server. Other times, the object retrieved from JNDI is a factory method that creates other objects for the client.

The next sections provide examples of how to access various WebLogic Server facilities in a Java client. The examples include Enterprise JavaBeans, JDBC connection pools, and WebLogic Admin Services. In each case, the example uses a JNDI context to lookup an object and then does something with the object in the Java client. Whatever WebLogic Server services your client uses, the initial steps-getting a JNDI InitialContext and looking up an object-are always the same. Consult the Developers Guides for the services you want to use for the details about each service.

Looking up an Enterprise JavaBean

To use an Enterprise JavaBean named MyBean in a Java client, you use your Context to look up the home interface for the bean:

  MyBeanHome home = (MyBeanHome) ctx.lookup("MyBeanHome");

WebLogic Server serializes the home interface class for MyBean and sends it to the client. For an EJB, the home interface is a stub class containing the home methods your client calls. The RMI framework passes client requests to WebLogic Server for execution and returns the results to the client.

EJB instances are instantiated by executing methods on the bean's home. Here is an excerpt from the examples/intro/EmpQueueReader.java example. This example method, doSal(), looks up an entity bean and calls its setSal() method to change the salary field. The primary key for the entity bean, and new salary amount for the bean, are passed to doSal() in a JMS message:

  static void doSal(MapMessage message) 
throws JMSException, RemoteException, NamingException
{
boolean response;

try {
EmpBeanHome home = (EmpBeanHome)
ctx.lookup("EmpBeanHome");
Emp e = home.findByEmpno(message.getInt("empno"));
System.out.println("\n\n\n=== Salary adjustment " +
request ===");
System.out.println("Employee number ..... : " +
message.getInt("empno"));
System.out.println("Employee name ....... : " +
e.getEname());
System.out.println("Current salary ...... : " +
e.getSal());
System.out.println("New salary .......... : " +
message.getFloat("sal"));
System.out.println("===========================");
response = Confirm("Approve this request?");
if (response) {
e.setSal(message.getFloat("sal"));
System.out.println("Salary adjusted.");
}
else
System.out.println("Ignoring request.");
}
catch (FinderException fe) {
System.out.println("EJB FinderException: "
+ fe.getMessage());
}
}

These two lines demonstrate how the (previously opened) context is used to get the bean's home and then look up the entity bean:

EmpBeanHome home = (EmpBeanHome)
ctx.lookup("EmpBeanHome");
Emp e = home.findByEmpno(message.getInt("empno"));

When executed on a WebLogic Server cluster, it is possible for these two lines of code to access two different WebLogic Servers. The first line uses whatever WebLogic Server was selected to provide the JNDI InitialContext. An EJB home is clusterable, which means that the cluster's load-balancing algorithm can select any WebLogic Server that is able to provide the EmpBeanHome Object. The ctx.lookup() call executes on the first WebLogic Server, but the EmpBeanHome Object may be supplied by a different WebLogic Server. If so, a new network connection is created for the second WebLogic Server. All of the bean instances referenced through this object live on the second WebLogic Server, since only the EJB home object is clusterable. When executed against a non-clustered WebLogic Server, of course, both lines execute against the same WebLogic Server using a single connection.

Using a JDBC Connection Pool in a Client

Although a Java client can use a JDBC driver to connect directly to a database, getting a connection from a WebLogic Server JDBC connection pool is a much more efficient use of database resources. A WebLogic Server connection pool maintains a set of open connections to a database server. A client can "reserve" a connection in the pool and use it to execute JDBC statements. When the client closes the connection, it returns to the pool, but remains open, so that other clients can use it. WebLogic Server opens database connections and adds them to the pool when it initializes the pool. Depending on the connection pool configuration, additional connections may be added to the pool when all of the connections are in use, and connections may later be released from the pool to shrink it back to its preferred size. Connections can be tested and refreshed-closed and reopened-if they have gone bad.

A Java client reserves a connection from a connection pool by using JNDI to look up a DataSource. A DataSource is factory for JDBC connections, defined in the JDBC 2.0 specification. The connection pool and DataSource are defined in the weblogic.properties file with properties like these:

weblogic.jdbc.connectionPool.demoPool=\
url=jdbc:cloudscape:demo,\
driver=COM.cloudscape.core.JDBCDriver,\
initialCapacity=1,\
maxCapacity=2,\
capacityIncrement=1,\
props=user=none;password=none;server=none
#
# Add a TXDataSource for the connection pool:
weblogic.jdbc.TXDataSource.demoDataSource=demoPool

The first property defines the connection pool, which is named "demoPool". This property has several arguments to define the JDBC driver WebLogic Server uses to access the database, the database instance to pool uses, the initial and maximum size of the pool, and database username and password. The exact parameters required differ for different databases. The second parameter defines the DataSource, which is named "demoDataSource". This is the string a client looks up with JNDI to access the "demoPool" connection pool. See Using WebLogic JDBC for information about configuring WebLogic Server JDBC connection pools.

Here is an example, from examples/intro/booksPool.java in your WebLogic Server distribution, that shows how a Java client gets a connection from a pool. The entire program is included here to show both JNDI and JDBC in context:

package examples.intro;

import java.sql.*;
import java.util.*;
import javax.naming.*;

public class booksPool {

public static void main(String argv[]) throws Exception {

Context ctx = null;
Hashtable ht = new Hashtable();
java.sql.Connection conn = null;
ht.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
ht.put(Context.PROVIDER_URL,
"t3://localhost:7001");

try {
ctx = new InitialContext(ht);
javax.sql.DataSource ds =
(javax.sql.DataSource) ctx.lookup("demoDataSource");
conn = ds.getConnection();
Statement s = conn.createStatement();

try {
// First, drop the "books" table, in case it
// already exists. If it does not, then this
// statement will get an warning that can be ignored.
System.out.println("Dropping table books.");
s.execute("drop table books");
}
catch ( SQLException se ) {;}


// Now, create the "books" table and insert some data.
System.out.println("Creating table books.");
s.execute("create table books (title varchar(40), " +
"author varchar(40), publisher varchar(40),"+
"isbn varchar(20))");

// Use a PreparedStatement to insert rows in the table.
System.out.println("Loading table.");
PreparedStatement ps = conn.prepareStatement(
"insert into books " +
"(title,author,publisher,isbn) " +
" values (?, ?, ?, ?)");

ps.setString(1, "Java in a Nutshell");
ps.setString(2, "David Flanagan");
ps.setString(3, "O'Reilly");
ps.setString(4, "1-56592-262-X");
ps.execute();

ps.setString(1, "Java Examples in a Nutshell");
// ps.setString(2, "David Flanagan");
// ps.setString(3, "O'Reilly");
ps.setString(4, "1-56592-371-5");
ps.execute();

ps.setString(1, "Design Patterns");
ps.setString(2, "Gamma, Helm, Johnson, Vlissides");
ps.setString(3, "Addison-Wesley");
ps.setString(4, "0-201-63361-2");
ps.execute();

System.out.println("Retrieving rows.");
s.execute("select * from books");

ResultSet rs = s.getResultSet();
while (rs.next()) {
System.out.println(rs.getString("title") + "\n\t" +
rs.getString("author") + "\n\t" +
rs.getString("publisher") + "\n\t" +
rs.getString("isbn"));
}
rs.close();
s.close();
ps.close();
} finally {
try {conn.close();} catch (Exception e) {;}
try {ctx.close();} catch (Exception e) {;}
}
}
}

The following lines look up the DataSource and use it to get a JDBC connection from the pool:

  javax.sql.DataSource ds = 
(javax.sql.DataSource) ctx.lookup("demoDataSource");
conn = ds.getConnection();

The lookup returns the DataSource object, which is a factory. Calling getConnection() on the DataSource object returns a connection from the "demoPool" connection pool.

If you have written JDBC programs, the remainder of this example should be familiar. It uses a JDBC Statement and a PreparedStatement to execute SQL DDL (Data Definition Language) and DML (Data Manipulation Lanaguage) statements, and processes the data returned in a ResultSet.

What you do not see in this example is any reference to a JDBC driver or the database URL passed to DriverManger.getConnection(). When you look up a DataSource, the WebLogic JDBC/RMI JDBC driver operates between the client and WebLogic Server. This multitier JDBC driver wraps the WebLogic JDBC Pool driver with RMI, to pass JDBC calls and results between the client and WebLogic Server. The client executes on stub methods and RMI passes these requests to WebLogic Server. The JDBC calls execute on WebLogic Server and results are serialized and returned to the client.

Accessing WebLogic Server Services

In addition to J2EE technologies such as EJB, JMS, RMI, and JDBC, WebLogic Server offers additional facilities that may be useful in your applications. These facilities are available through an interface named T3ServicesDef.

Warning: In earlier WebLogic Server releases, T3ServicesDef was available to clients through the services() method of their T3Client object. Since using JNDI is preferable to using T3Client, the T3ServicesDef object may now be accessed with a JNDI lookup. Many of the earlier services have been deprecated and replaced with J2EE standard services. Some of the Javadocs for the remaining services still use the T3Client connection method. You should instead use the JNDI method described in this section.

The services you can access through T3ServicesDef include:

To access any of these services, you look up "weblogic.common.T3Services" with JNDI and cast the result to a T3ServicesDef. T3ServicesDef provides factory methods for each of the services that are available. For example, the T3ServicesDef.admin() method is a factory for AdminServicesDef. AdminServicesDef defines methods such as licenses() to retrieve licenses from WebLogic Server, and version() to get the WebLogic Server version number.

Here is an example using T3ServicesDef and AdminServicesDef to display the WebLogic Server version number and licenses:

import weblogic.common.*;
import javax.naming.*;
import java.util.Hashtable;

public class ServerInfo {

static T3ServicesDef t3s;

static Context ctx = null;
public static void main(String argv[]) {

Hashtable env = new Hashtable();
env.put(Context.PROVIDER_URL, "t3://localhost:7001");
env.put(Context.SECURITY_PRINCIPAL, "guest");
env.put(Context.SECURITY_CREDENTIALS, "guest");
env.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
try {
ctx = new InitialContext(env);
t3s = (T3ServicesDef)
ctx.lookup("weblogic.common.T3Services");
ctx.close();
System.out.println(t3s.admin().version());
System.out.println(t3s.admin().licenses());
}

catch (Exception e) {
e.printStackTrace();
}
}
}

The t3s object provides factory methods for all of the services T3ServicesDef provides. The admin() method is the factory method for AdminServicesDef, and version() and licenses() are two methods provided by AdminServicesDef.

The APIs for the services available from T3ServicesDef are accessible from the javadoc page for the weblogic.common.T3ServicesDef interface.

Additional Topics

This section contains additional topics related to WebLogic Server Java client development.

What Happened to T3Client?

In previous WebLogic Server releases, a Java client used the weblogic.common.T3Client class to connect to WebLogic Server. T3Client will be deprecated in the next major WebLogic Server release. You should instead use JNDI (Java Naming and Directory Services) to make WebLogic Server connections. T3 protocol, the BEA protocol for multiplexing client requests over a single connection, is still used between WebLogic Server and its clients. Only the manner of establishing connections has changed.

Using JNDI to connect to WebLogic Server has two advantages over T3Client:

Client applications that use T3Client still work in this release. T3Client may not be supported in future releases, however, so you should modify any T3Client applications you have now to use JNDI, and you should develop all new client applications using JNDI.

Java Client Best Practices

WebLogic Server emphasizes the J2EE (Java 2, Enterprise Edition) application architecture, a multitier architecture with business logic concentrated on WebLogic Server in the middle tier. Clients concentrate on presentation logic and user interface. When the client is a web browser, the user interface is specified with HTML. When the client is a Java program, the user interface must be coded in Java, using standard Java I/O or the JFC/Swing classes.

Sun has created a best practices guide and sample application for J2EE developers. At present (April 2000) the guide is a draft release, but it is already a very thorough and valuable overview of the J2EE application model and design factors. You can download "Designing Enterprise Applications with the Java 2 Platform, Enterprise Edition" from Sun's developer web site, which requires registration.

Concentrating business logic in WebLogic Server makes it easier to deploy and maintain applications. Changes that do not affect presentation or user interface are less likely to affect deployed clients. Modular components, such as Enterprise JavaBeans, can be used by multiple applications and can be modified without having to modify clients.

When you design your application, consider ways of protecting your client from changes in the server-side code. For example, you can create a client-side framework that renders results from the server, much as a browser renders HTML retrieved from a web server. Give your server-side classes the responsibility for presentation logic and write client code that displays data and controls at the server's request.

Consider using WebLogic ZAC (Zero Administration Client) to publish Java clients to users. ZAC makes it easy to install and maintain applications on multiple client computers. You can even call the ZAC API from client programs to have clients perform an automatic self-update when they run. See Using WebLogic ZAC for details.

Tunneling T3 over HTTP

Tunneling allows clients to access a WebLogic Server behind a firewall. When a client must traverse firewalls-where HTTP via port 80 is the only available method of entry-you can tunnel T3 protocol over HTTP. HTTP tunneling can also be used to communicate with WebLogic Server via a proxy, if the proxy has DNS access to the WebLogic Server.

Tunneling slows performance, since each message must be encoded and decoded. You should only use it when the client has no alternative access.

If your WebLogic client is behind a proxy server firewall, you may need to set up a proxy if you are using http, https, or t3s. Configure any of these protocols for proxying by setting values for the two system properties, protocol.proxyHost and protocol.proxyPort. Define these system properties with the -D flag on the java command line. Here are examples of proxying for http, https, and t3s:

  $ java -Dhttp.proxyHost=host -Dhttp.proxyPort=port MyClient

  $ java -Dhttps.proxyHost=host -Dhttps.proxyPort=port MyClient

  $ java -Dssl.proxyHost=host -Dssl.proxyPort=port MyClient

If the proxy server requires authentication, you must provide an implementation of the weblogic.common.ProxyAuthenticator interface. When a proxy server requests authentication, methods in your ProxyAuthenticator implementation class are called to obtain the login name and password for the proxy server. See the examples.security.proxy example for a sample implementation of this interface.

Tuning WebLogic Server Cluster Clients

Execute threads in a Java client handle socket I/O, processing the data exchanged on WebLogic Server connections. A WebLogic Server Java client, by default, creates five execute threads and up to 33%, or two, of these will be socket readers. This is sufficient for a client that connects to a single WebLogic Server, but may not be sufficient to maintain performance for a client that connects with a WebLogic Server cluster.

You can increase the number of execute threads and set the percentage of the threads that are socket readers by setting Java system properties on the client's Java command line:

$ java -Dweblogic.system.executeThreadCount=executeThreads
-Dweblogic.system.percentSocketReaders=percentReaders
myClient

Performance is most influenced by the number of socket reader threads. Raise the number of execute threads and the percentage of socket readers so that the number of socket readers approaches the number of WebLogic Servers in the cluster. For example, to specify ten socket readers and two non-socket reader threads, set the executeThreadCount to 12 and the percentSocketReaders to 83.