Figure 4‑1 illustrates the client/server relationship between a Jolt program and the Jolt Server.
Table 4‑1 describes the client-side requests and Jolt Server-side actions in a simple example program.
Figure 4‑2 illustrates the relationship between the instantiated objects of the Jolt Class Library classes.
•
|
Contains-a relationship—at the class level an object can contain other objects. For example, a JoltTransaction stores (or contains) a JoltSession object.
|
•
|
Is-a relationship—the is-a relationship usually occurs at the class instance or sub-object level and denotes that the object is an instance of a particular object.
|
•
|
Uses-a relationship—an object can use another object without containing it. For example, a JoltSession can use the JoltSessionAttributes object to obtain the host and port information.
|
2.
|
The sattr.checkAuthenticationLevel() allows the application to determine the level of security required to log on to the server.
|
The add*() methods can throw
IllegalAccessError or
NoSuchFieldError exceptions.
Listing 4‑1 shows an example of a simple application for the transfer of funds using the Jolt classes.
Before running the ToUpper.java example, you need to define the
TOUPPER service through the Metadata Repository Editor.
The ToUpper.java Java code fragment in
Listing 4‑2 illustrates how Jolt works with a service with a buffer type of STRING. The example shows a Jolt client using a STRING buffer to pass data to a server. The Oracle Tuxedo server would take the buffer, convert the string to all uppercase letters, and pass the string back to the client. The following example assumes that a session object was already instantiated.
The following tryOnFml examples illustrate the use of the FML buffer type. The examples show a Jolt client using FML buffers to pass data to a server. The server takes the buffer, creates a new FML buffer to store the data, and passes that buffer back to the Jolt client. The examples consist of the following components.
The tryOnFml.java Java code fragment in
Listing 4‑4 illustrates how Jolt works with a service whose buffer type is FML. In this example, it is assumed that a session object was already instantiated.
The BULKPKG package contains the
PASSFML service, which is used with the
tryOnFml.java and
tryOnFml.c code. Before running the
tryOnFml.java example, you need to modify the
PASSFML service through the Metadata Repository Editor (see
Define TOUPPER in the Repository Editor for an example).
Listing 4‑6 illustrates the server side code for using the FML buffer type. The PASSFML service reads in an input FML buffer and outputs a FML buffer.
* tryOnFml.c
*
* Copyright (c) 1997 Oracle Systems, Inc. All rights reserved
*
* Contains the PASSFML Oracle Tuxedo server.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <malloc.h>
#include <math.h>
#include <string.h>
#include <fml.h>
#include <fml32.h>
#include <Usysflds.h>
#include <atmi.h>
#include <userlog.h>
#include "tryOnFml.f16.h"
/*
* PASSFML service reads in a input fml buffer and outputs a fml buffer.
*/
void
PASSFML( TPSVCINFO *rqst )
{
FLDLEN len;
FBFR *svcinfo = (FBFR *) rqst->data;
char inputString[256];
long inputInt;
float inputFloat;
FBFR *fml_ptr;
int rt;
if (Fget(svcinfo, INPUTSTRING, 0, inputString, &len) < 0) {
(void)userlog("Fget of INPUTSTRING failed %s",
Fstrerror(Ferror));
tpreturn(TPFAIL, 0, rqst->data, 0L, 0);
}
if (Fget(svcinfo, INPUTINT, 0, (char *) &inputInt, &len) < 0) {
(void)userlog("Fget of INPUTINT failed %s",Fstrerror(Ferror));
tpreturn(TPFAIL, 0, rqst->data, 0L, 0);
}
if (Fget(svcinfo, INPUTFLOAT, 0, (char *) &inputFloat, &len) < 0) {
(void)userlog("Fget of INPUTFLOAT failed %s",
Fstrerror(Ferror));
tpreturn(TPFAIL, 0, rqst->data, 0L, 0);
}
/* We could just pass the FML buffer back as is, put lets */
/* store it into another FML buffer and pass it back. */
if ((fml_ptr = (FBFR *)tpalloc("FML",NULL,rqst->len))==(FBFR *)NULL) {
(void)userlog("tpalloc failed in PASSFML %s",
tpstrerror(tperrno));
tpreturn(TPFAIL, 0, rqst->data, 0L, 0);
}
if(Fadd(fml_ptr, OUTPUTSTRING, inputString, (FLDLEN)0) == -1) {
userlog("Fadd failed with error: %s", Fstrerror(Ferror));
tpfree((char *)fml_ptr);
tpreturn(TPFAIL, 0, NULL, 0L, 0);
}
if(Fadd(fml_ptr, OUTPUTINT, (char *)&inputInt, (FLDLEN)0) == -1) {
userlog("Fadd failed with error: %s", Fstrerror(Ferror));
tpfree((char *)fml_ptr);
tpreturn(TPFAIL, 0, NULL, 0L, 0);
}
if(Fadd(fml_ptr, OUTPUTFLOAT, (char *)&inputFloat, (FLDLEN)0) == -1) {
userlog("Fadd failed with error: %d\n", Fstrerror(Ferror));
tpfree((char *)fml_ptr);
tpreturn(TPFAIL, 0, NULL, 0L, 0);
}
tpreturn(TPSUCCESS, 0, (char *)fml_ptr, 0L, 0);
}
/* Copyright 1997 Oracle Systems, Inc. All Rights Reserved */
/*
* This code fragment illustrates how Jolt works with a service whose buffer
* type is VIEW.
*/
import bea.jolt.*;
class ...
{
...
public void simpview ()
{
JoltRemoteService ViewSvc;
String outString;
int outInt;
float outFloat;
// Create a Jolt Service for the Oracle Tuxedo service "SIMPVIEW"
ViewSvc = new JoltRemoteService("SIMPVIEW",session);
// Set the input parameters required for SIMPVIEW
ViewSvc.setString("inString", "John");
ViewSvc.setInt("inInt", 10);
ViewSvc.setFloat("inFloat", (float)10.0);
// Call the service. No transaction required, so pass
// a "null" parameter
ViewSvc.call(null);
// Process the results
outString = ViewSvc.getStringDef("outString", null);
outInt = ViewSvc.getIntDef("outInt", -1);
outFloat = ViewSvc.getFloatDef("outFloat", (float)-1.0);
// And display them...
System.out.print("outString=" + outString + ",");
System.out.print("outInt=" + outInt + ",");
System.out.println("outFloat=" + outFloat);
}
}
In Listing 4‑9, the input and output buffers are VIEW. The code accepts the VIEW buffer data as input and outputs the same data as VIEW.
/*
* SIMPVIEW.c
*
* Copyright (c) 1997 Oracle Systems, Inc. All rights reserved
*
* Contains the SIMPVIEW Oracle Tuxedo server.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <malloc.h>
#include <math.h>
#include <string.h>
#include <fml.h>
#include <fml32.h>
#include <Usysflds.h>
#include <atmi.h>
#include <userlog.h>
#include "simpview.h"
/*
* Contents of simpview.h.
*
*struct SimpView {
*
* char inString[32];
* long inInt;
* float inFloat;
* char outString[32];
* long outInt;
* float outFloat;
*};
*/
/*
* service reads in a input view buffer and outputs a view buffer.
*/
void
SIMPVIEW( TPSVCINFO *rqst )
{
/*
* get the structure (VIEWSVC) from the TPSVCINFO structure
*/
struct SimpView *svcinfo = (struct SimpView *) rqst->data;
/*
* print the input params to the UserLog. Note there is
* no error checking here. Normally a SERVER would perform
* some validation of input and return TPFAIL if the input
* is not correct.
*/
(void)userlog("SIMPVIEW: InString=%s,InInt=%d,InFloat=%f",
svcinfo->inString, svcinfo->inInt, svcinfo->inFloat);
/*
* Populate the output fields and send them back to the caller
*/
strcpy (svcinfo->outString, "Return from SIMPVIEW");
svcinfo->outInt = 100;
svcinfo->outFloat = (float) 100.00;
/*
* If there was an error, return TPFAIL
* tpreturn(TPFAIL, ErrorCode, (char *)svcinfo, sizeof (*svcinfo), 0);
*/
tpreturn(TPSUCCESS, 0, (char *)svcinfo, sizeof (*svcinfo), 0);
}
The XML buffer type enables Oracle Tuxedo applications to use XML documents for exchanging data within and between applications. Oracle Tuxedo applications can send and receive XML
buffers, and route those buffers to the appropriate servers. All logic for dealing with XML
documents, including parsing, resides in the application.
To specify the bea.jolt.mbencoding or bea.jolt.mbencodingmap, jolti18n.jar must be included in the
CLASSPATH. If
jolti18n.jar is not included in the
CLASSPATH, the encoding name is set to “ISO-8859-1” and no encoding name is done between Java and Tuxedo even if these properties are specified in the Java command line.
“Threads of Control” describes the issues arising from using threads with different Java implementations and is followed by an example of the use of threads in a Jolt program.
You can use threads in Jolt to get asynchronous behavior that is analogous to the tpacall() function in Oracle Tuxedo. With this capability, you do not need an asynchronous service request function. You can get this functionality because Jolt is thread-safe. For example, the Jolt client application can start one thread that sends a request to an Oracle Tuxedo service function and then immediately start another thread that sends another request to an Oracle Tuxedo service function. So even though the Jolt
tpacall() is synchronous, the application is asynchronous because the two threads are running at the same time.
Listing 4‑11 illustrates the use of two threads in a Jolt application.
•
|
Unsolicited Event Notifications—these are notifications that a Jolt client receives as a result of an Oracle Tuxedo client or service issuing a broadcast using either a tpbroadcast() or a directly targeted message via a tpnotify() ATMI call.
|
•
|
Brokered Event Notifications—these notifications are received by a Jolt client through the Oracle Tuxedo Event Broker. The notifications are only received when the Jolt client subscribes to an event and any Oracle Tuxedo client or server issues a system-posted event or tppost() call.
|
•
|
JoltSession—the JoltSession class includes an onReply() method for receiving notifications and notification messages.
|
•
|
JoltReply—the JoltReply class gives the client application access to any messages received with an event or notification.
|
•
|
JoltMessage—the JoltMessage class provides get() methods for obtaining information about the notification or event.
|
•
|
JoltUserEvent—the JoltUserEvent class supports subscription to both unsolicited and event notification types.
|
The client application must provide a single handler (by overriding the onReply() method) per session that will be invoked for all notifications received by that client for that session. The single handler call-back function is used for both unsolicited and event notification types. It is up to the (user-supplied) handler routine to determine what event caused the handler invocation and to take appropriate action. If the user does not override the session handler, then notification messages are silently discarded by the default handler.
Note:
|
Subscribing to single event notification is not the recommended method for enabling unsolicited notification. If you want unsolicited notification, the application should explicitly subscribe to unsolicited notifications (as described in the JoltUserEvent class). The next section is about unsubscribing from notifications.
|
The “Asynchronous Notification” listing shows how to use the Jolt Class Library for receiving notifications and includes the use of the
JoltSession,
JoltReply,
JoltMessage and
JoltUserEvent classes.
class EventSession extends JoltSession
{
public EventSession(
JoltSessionAttributes attr, String user,
String role, String upass, String apass )
{
super(attr, user, role, upass, apass);
}
/**
* Override the default unsolicited message handler.
* @param reply a place holder for the unsolicited message
* @see bea.jolt.JoltReply
*/
public void
onReply( JoltReply reply )
{
// Print out the STRING buffer type message which contains
// only one field; the field name must be "STRING". If the
// message uses CARRAY buffer type, the field name must be
// "CARRAY". Otherwise, the field names must conform to the
// elements in FML or VIEW.
JoltMessage msg = (JoltMessage) reply.getMessage();
System.out.println(msg.getStringDef("STRING", "No Msg"));
}
public static void main( Strings args[] )
{
JoltUserEvent unsolEvent;
JoltUserEvent helloEvent;
EventSession session;
...
The Jolt Class Library contains the clear() method, which allows you to remove existing attributes from an object and, in effect, provides for the reuse of the object. The
“Jolt Object Reuse (reuseSample.java)” listing illustrates how to use the
clear() method to clear parameter values and how to reuse the JoltRemoteService parameter values; you do not have to destroy the service to reuse it. Instead, the
svc.clear(); statement is used to discard the existing input parameters before reusing the
addString() method.
/* Check what authentication level has been set. */
switch (attr.checkAuthenticationLevel())
{
case JoltSessionAttributes.NOAUTH:
break;
case JoltSessionAttributes.APPASSWORD:
applpasswd = “secret8”;
break;
case JoltSessionAttributes.USRPASSWORD:
username = “myName”;
userpasswd = “BEA#1”;
applpasswd = “secret8”;
break;
}
/* Logon now without any idle timeout (0). */
/* The network connection is retained until logoff. */
attr.setInt(attr.IDLETIMEOUT, 0);
s_session = new JoltSession(attr, username, userrole,
userpasswd, applpasswd);
}
public static void main( String args[] )
{
String host;
short port;
JoltRemoteService svc;
if (args.length != 2)
{
System.err.println(“Usage: reuseSample host port”);
System.exit(1);
}
/* Get the host name and port number for initialization. */
host = args[0];
port = (short)Integer.parseInt(args[1]);
/* Get the object reference to the DELREC service. This
* service has no output parameters, but has only one input
* parameter.
*/
svc = new JoltRemoteService(“DELREC”, s_session);
try
{
/* Set input parameter REPNAME. */
svc.addString(“REPNAME”, “Record1”);
svc.call(null);
/* Change the input parameter before reusing it */
svc.setString(“REPNAME”, “Record2”);
svc.call(null);
/* Simply discard all input parameters */
svc.clear();
svc.addString(“REPNAME”, “Record3”);
svc.call(null);
}
catch (ApplicationException e)
{
System.err.println(“Service DELREC failed: “+
e.getMessage()+” “+ svc.getStringDef(“MESSAGE”, null));
}
/* Logoff now and get rid of the object. */
s_session.endSession();
}
}
The following listing, “Extending Jolt Remote Service (extendSample.java),” illustrates one way to subclass the JoltRemoteService class. In this case, a TransferService class is created by subclassing the JoltRemoteService class. The TransferService class extends the JoltRemoteService class, adding a Transfer feature that makes use of the Oracle Tuxedo BANKAPP funds TRANSFER service.
Listing 4‑14 uses the
extends keyword from the Java language. The
extends keyword is used in Java to subclass a base (parent) class. The following code shows one of many ways to extend from JoltRemoteService.
/* Set the input parameters */
this.setIntItem(“ACCOUNT_ID”, 0, fromAcctNum);
this.setIntItem(“ACCOUNT_ID”, 1, toAcctNum);
this.setString(“SAMOUNT”, amount );
try
{
/* Invoke the transfer service. */
this.call(null);
/* Get the output parameters */
fromBal = this.getStringItemDef(“SBALANCE”, 0, null);
if (fromBal == null)
return “No balance from Account “ +
fromAcctNum;
toBal = this.getStringItemDef(“SBALANCE”, 1, null);
if (toBal == null)
return “No balance from Account “ + toAcctNum;
return null;
}
catch (ApplicationException e)
{
/* The transaction failed, return the reason */
return this.getStringDef(“STATLIN”, “Unknown reason”);
}
}
}
class extendSample
{
public static void main( String args[] )
{
JoltSession s_session;
String
host;
short port;
TransferService xfer;
String failure;
if (args.length != 2)
{
System.err.println(“Usage: reuseSample host port”);
System.exit(1);
}
/* Get the host name and port number for initialization. */
host = args[0];
port = (short)Integer.parseInt(args[1]);
/* Prepare to connect to the Tuxedo domain. */
JoltSessionAttributes attr = new JoltSessionAttributes();
attr.setString(attr.APPADDRESS,”//”+ host+”:” + port);
String username = null;
String userrole = “sw-developer”;
String applpasswd = null;
String userpasswd = null;
/* Check what authentication level has been set. */
switch (attr.checkAuthenticationLevel())
{
case JoltSessionAttributes.NOAUTH:
break;
case JoltSessionAttributes.APPASSWORD:
applpasswd = “secret8”;
break;
case JoltSessionAttributes.USRPASSWORD:
username = “myName”;
userpasswd = “BEA#1”;
applpasswd = “secret8”;
break;
}
/* Logon now without any idle timeout (0). */
/* The network connection is retained until logoff. */
attr.setInt(attr.IDLETIMEOUT, 0);
s_session = new JoltSession(attr, username, userrole,
userpasswd, applpasswd);
/*
* TransferService extends from JoltRemoteService and uses the
* standard Oracle Tuxedo BankApp TRANSFER service. We invoke this
* service twice with different parameters. Note, we assume
* that “s_session” is initialized somewhere before.
*/
xfer = new TransferService(s_session);
if ((failure = xfer.doxfer(10000, 10001, “500.00”)) != null)
System.err.println(“Tranasaction failed: “ + failure);
else
{
System.out.println(“Transaction is done.”);
System.out.println(“From Acct Balance: “+xfer.fromBal);
System.out.println(“ To Acct Balance: “+xfer.toBal);
}
if ((failure = xfer.doxfer(51334, 40343, “$123.25”)) != null)
System.err.println(“Tranasaction failed: “ + failure);
else
{
System.out.println(“Transaction is done.”);
System.out.println(“From Acct Balance: “+xfer.fromBal);
System.out.println(“ To Acct Balance: “+xfer.toBal);
}
}
}
•
|
KEYSTORE—file path for client private key and X.509 certificate
|
•
|
TRUSTSTORE—trust store file path for trusted X.509 certificates
|
Note:
|
Starting with JDK release 8u31, the SSLv3 protocol is deactivated and is not available by default. If SSLv3 is required, the protocol can be reactivated by removing " SSLv3" from the j dk.tls.disabledAlgorithms property in the <JRE_HOME>/lib/security/java.security file, or by dynamically setting this Security property to " true" before JSSE is initialized.
|
Listing 4‑15 shows a Jolt client code example that makes it possible to use SSL when communicating with
JSL/
JSH.