How do I handle remote exceptions when invoking Gen EJB directly from a hand-written Java client?

Document ID : KB000025535
Last Modified Date : 14/02/2018
Show Technical Document Details

Summary:

Invoking a Gen generated EJB directly from a hand-written Java client requires adding some additional code to handle unexpected problems when processing server logic.

Instructions:

It is important to remember that invoking a Gen generated EJB directly from a hand-written Java client requires adding some additional code to handle unexpected problems encountered when processing server logic. Various problems accessing a database like deadlock, missing or unimplemented table, are examples of such unexpected conditions. The Gen generated client handles these conditions for you automatically. The Gen runtime prepares suitable error message, client logic is interrupted and the error message dialog box is displayed.

Ignoring these exceptions in a hand written situation can be confusing for the end user who may not be aware that certain changes in the database have been rolled back and the transaction was not successfully completed.

A RemoteException class is the common superclass for a number of communication-related exceptions that may occur during the execution of a remote method call. Each method of a remote interface, an interface that extends java.rmi.Remote , must list RemoteException in its throws clause.

The general purpose of this class is to provide an exception-chaining mechanism and allows wrapping messages returned by other classes and their methods. For example, the Gen runtime stores error message returned by the JDBC classes responsible for the execution of the SQL in the generated EJB.

Here are two different example messages returned during processing two different JDBC drivers:

Oracle (deadlock):

ERROR MYSERV @0000000016,0009400214,16 0  [FEDB/0] [BEA][Oracle JDBC Driver][Oracle]ORA-00060: 
deadlock detected while waiting for resource 

MSSQL 2005 (missing table)

ERROR MYSERV@0000000001,0000000021,1 0 [FEDB/0] Table not found in statement
[SELECT MYENTITY01."TEXT0",MYENTITY01."ID" FROM "MYENTITY" MYENTITY01 WHERE MYENTITY01."ID" = ? ]
SQLSTATE: S0002
SQLCODE: -22

You need to extract the error message from the exception object, scan the message to retrieve relevant information and present your own error message to the user. Here is some sample code showing how to invoke the EJB from the Java application and how to retrieve the error message after RemoteException exception is thrown.

package my.pack;
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.rmi.PortableRemoteObject;
 
import m_17642528.MYSERV_Home;
import m_17642528.MYSERV_Remote;
import m_17642528.MyservExport;
import m_17642528.MyservImport;
 
public class InvokeEjb {
 
       private static final String PROVIDER_URL = "jnp://localhost:1099";
       private static final String INITIAL_CONTEXT_FACTORY = "org.jnp.interfaces.NamingContextFactory";
 
       public static void main(String[] args) {
              InvokeEjb invokeEjb = new InvokeEjb();
              try {
                     invokeEjb.start();
              } catch (NamingException e) {
                     e.printStackTrace();
              } catch (RemoteException e) {
                     if (e.getMessage().startsWith("ERROR")) {
                           System.out.println("ERROR MESSAGE: " + e.getMessage());
                     }
              } catch (CreateException e) {
                     e.printStackTrace();
              }
       }
 
       private void start() throws NamingException, RemoteException,
                     CreateException {
              Properties properties = new Properties();
              properties.put(javax.naming.Context.PROVIDER_URL, PROVIDER_URL);
              properties.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY,
                           INITIAL_CONTEXT_FACTORY);
              Context context = new InitialContext(properties);
              MYSERV_Home home = (MYSERV_Home) PortableRemoteObject.narrow(context
                           .lookup("MYSERV"), MYSERV_Home.class);
              MYSERV_Remote remote = home.create();
              MyservImport myservImport = new MyservImport();
              myservImport.getImportMyentity().setId((short) 100);
              myservImport.getImportMyentity().setText("Mary");
              MyservExport myservExport = remote.call(myservImport);
              System.out.println("Returns: "
                           + myservExport.getExportMyentity().getId() + ", "
                           + myservExport.getExportMyentity());
       }
 
}