Java-JNI-COM-ActiveX Bridge.; Lots of jumps-n- hoops 4

Posted by Rajesh Shetty on December 30, 2004

I’m assuming reader will have basic idea of what and how Java-JNI works, if not refer to Sun’s JNI Tutorial section . For Advanced Java-JNI Programming look at this site.

Now this article is not to teach JNI, this one is about my discoveries in regards to mystery of JNI communication with Microsoft native COM/ActiveX components. It is not as straight forward it as it looks like. JNI says I CAN talk to Microsoft DLL component, but it does not say that DLL has to be written in certain way. That way is again guided and defined by JNI standards. This article will explain how to go about building a compatible bridge between any form of DLL and Java application.

Requirement: (Requirements are always simple, seems easy as grabbing a beer from the refrigerator)

My requirement is to communicate with Visual Basic ActiveX component (DLL file) using Java.

Speculation: (We always speculate with lots of options and think one thing or other will get us there easily)

  • There are millions of way achieving this, Use commercial/Open source products (As mentioned on the right hand side of the article table 1)
  • Write your JNI bridge to communicate.

Facts: (When you actual fact bites you, its not pleasant)

  • You have to go thru many of the open source products, test them, make sure it do exactly same, as you expect.( Ah!!! lot of patience)
  • Some of the product you finally pick saying “Yes” this works , then you realize there is a Licensing nightmare, you can not use it freely for production deployment. Sometimes you can use it but it

    will come with good amount of per user/per machine/per processor/ (infinite loop of per thingy). So your clients or customer will decide not to buy because it needs a money to deploy ready made solution. e.g. Look at IBM’s license fee for Bridge2java.
  • If you decide to write your own JNI code, well “flip this”. Java does not understand Visual Basic way of defining methods/functions. So it will not understand Visual Basic Active-X DLL component. Bottom line you simply can not talk to Visual Basic DLL directly using Java.

Solution: (Sooner you figure out the solution, better it is for you)

So you are left with, either use existing open source/commercial product or write your own. In my case after trying few of the products out there decide to go with my own.

Solution Detail

As i mentioned, There is no on the earth you can make Java directly talk to Visual Basic DLL, idea is to write a COM Wrapper in C++ (VC++), which will act as bridge between Java and Visual basic. Basically Java can communicate with C++ Wrapper and C++ Wrapper knows all about Visual basic code.



Java(JNI)–> C ++ wrapper –>VB DLL

How Java Talks to VC++

Java JNI will talk to VC++ wrapper using JNI way of defining and communicating. Refer to this tutorial site about how to communicate with DLL files. Key is to follow the pattern of

Java_<Java Class Name>_<Method Name to Invoke> on your .h and .cpp files. typical

method on .h and .cpp will look like this



JNIEXPORT jobjectArray JNICALL Java_CallService_GetEarthCoOrdinates (JNIEnv *env, jobject object)

How VC++ talks to VB

I will not write in detail about this because ,there are good resources out there and one of them is

codeproject
site, about how to get VC++ talking to VB.

That should give you a good idea about how to achieve, two different worlds (Java and Visual Basic) talking with each other.

What next ?; The difficult part.

Once the basic communication done, then comes the most difficult parts where you need pass parameters back and forth. If parameters are complex, then its more painful. I have listed down few points on how to get things across using different data types.

Situation : Lets look at the complex situation. Java is passing String arrays (String[ ][ ]) and Visual Basic is expecting (Variant array Dim earthParams(10, 10) As Variant).

Java VC++ VB
String[][] SAFEARRAY/VARIANT Variant array

  • You have to pass String Array as jobjectArray to VC++
  • Convert them to SAFEARRAY
  • Convert SAFEARRAY to VARIANT
  • Pass VARIANT to VB via call.

Same thing Other way round when data comes back from VB.

Convert jobjectArray (Java String[ ][ ] array) to VC++ SAFEARRAY/VARAINT (C++ Code)

VARIANT loadJavaArrayToCPPSafeArray(jobjectArray stringArray, JNIEnv * env)

{

//Define SAFEARRAY

SAFEARRAY *psa;

VARIANT var1;

SAFEARRAYBOUND rgsabound[2]; //This means 2 Dimensional

SAFEARRAY

rgsabound[0].cElements = 10; // 10 rows

rgsabound[0].lLbound = 0;

rgsabound[1].cElements = 10; //10 columns

rgsabound[1].lLbound = 0;

psa=SafeArrayCreate(VT_VARIANT, 2, rgsabound); //Finally Create

2D SAFEARRAY

//Now get First Dimension Array Length for String [][] array

passed

jint length1Dim = (env)->GetArrayLength(stringArray);

long aiIndex[2];

for (aiIndex[0] = 0; aiIndex[0] < length1Dim; aiIndex[0]++)

{

jobjectArray oneDimArray= (jobjectArray)env->GetObjectArrayElement(stringArray, aiIndex[0]);

//Get Second Dimension

of the String[][] array passed.

jint length2dim = (env)->GetArrayLength(oneDimArray);

jstring oneDim;

const char* szStr;

for(aiIndex[1]=0;aiIndex[1]<length2dim;aiIndex[1]++)

{

oneDim= (jstring)env->GetObjectArrayElement(oneDimArray,

aiIndex[1]);

szStr = env->GetStringUTFChars( oneDim, 0 );

VARIANT var;

_bstr_t str2 = szStr; //Get Sting value from array to BSTR of

C++

var.vt = VT_BSTR;

var.bstrVal = str2;

//Now Populate SAFEARRAY with Data.

HRESULT hrs = SafeArrayPutElement(psa,aiIndex,&var);

//Following is to Check

whether SafeArrayPutElement is successful or not. just for

Debug

if(hrs == S_OK)

cout<< “S_OK”;

else if(hrs == DISP_E_BADINDEX)

cout<< “DISP_E_BADINDEX”;

else if(hrs == E_INVALIDARG)

cout<< “E_INVALIDARG”;

else if(hrs == E_OUTOFMEMORY)

cout<< “E_OUTOFMEMORY”;

//Have to release

Created String.

env->ReleaseStringUTFChars( oneDim, szStr );

}

}

//Finally Create Variant

from SAFEARRAY.

VariantInit(&var1);

var1.vt=VT_ARRAY VT_VARIANT;

var1.parray = psa;

//Return Variant

Representing Two-Dimensional Java ’s String Array String[][]

return var1;

}

Printing 2D BSTR SAFEARRAY Contents

void printSafeArrayContents(SAFEARRAY psa*)

{

long arrayIndex[2];

cout<< “=============Printing Out..===========”<<endl;

for(arrayIndex[0] = 0; arrayIndex[0] < 6; arrayIndex[0]++)

{

for(arrayIndex[1] = 0; arrayIndex[1] < 2; arrayIndex[1]++)

{

VARIANT result;

SafeArrayGetElement(psa, arrayIndex, &result);

cout<<result.bstrVal <<endl;

}

cout<< “=========================”<<endl;

}

Generate 2D String array (jobjectArray) from 2D SAFEARRAY, to pass back to Java (Borrowed from

JNISnippets Site and enhanced for SAFEAARRY)

jarray Get2DArrayFromSafeArray(JNIEnv* env, SAFEARRAY *psa)

{

char s[200];

jarray aref;

jobject job;

jclass class1;

jarray row[1];

int rows = 10;

int cols = 10;

int i;

int j;

long biIndex[2];

// Got to build each row

seperately.

for(biIndex[0]=0;biIndex[0]<rows;biIndex[0]++)

{

// get an String object

job = (env)->NewStringUTF(”");

// get String class

class1 = (env)->GetObjectClass(job);

// get the row of String array objects

row[biIndex[0]] = (env)->NewObjectArray(cols,class1,job);

// initialize the elements

for(biIndex[1]=0;biIndex[1]<cols;biIndex[1]++)

{

VARIANT result;

SafeArrayGetElement(psa, biIndex, &result); //Get Variant out of

SAFEARRAY

sprintf(s,”%S”,result.bstrVal); //Get BSTR value from

VARIANTand assign to char c*

job = (env)->NewStringUTF(s);

//Create New string from the value recieved

(env)->SetObjectArrayElement((jobjectArray)row[biIndex[0]],biIndex[1],job);

}

}

//Now once the rows are

constructed with columns in it , now attach it to Master index

row (This is little twisted)

class1 = (env)->GetObjectClass(row[0]);

// get the base array object

aref = (env)->NewObjectArray(rows,class1,0);

// fill in the array

for(i=0;i<rows;i++)

{

(env)->SetObjectArrayElement((jobjectArray)aref,i,row[i]);

}

// return the array

return aref;

}

Conclusion

Its lots of jumps-n-hoops to get this puppy working. I thought i was long done with my VC++/VB and it came back haunting me after 8 years. No complains; its like going back memory lane, opening Visual

Studio for VC++ and VB and sitting coding. Its fun afterall.

Resources






http://msdn.microsoft.com
Microsoft

Developer Network




http://www.codeproject.com
Code Project


http://java.sun.com
Sun’s Java

initiative




http://www.codeguru.com/
Cod Guru




http://www.relevancellc.com/halloway/JavaWin32.html
Java/COM,

Java/Win32 Integration resources




http://jguru.com/faq/view.jsp?EID=448045
JNI FAQ




http://www.geocities.com/Jeff_Louie/safearray.html
Good details

about SAFEARRAY




http://java.sun.com/docs/books/jni/html/jniTOC.html
Online JNI Book

Real FUD on Open source usage, Solution is out there. Do not be misguided by skepticism 7

Posted by Rajesh Shetty on December 23, 2004

I agree with general notion of the subject, Where Open Source software should not be treated as “pick up and go, later forget about it”. There got to be real appreciation in terms of following any Licensing issue, Make sure the licensing terms and conditions and all Attributes are well understood and there is no violation. That is where companies like Apptility LLC (their .com and .net area) helps in, where they are opening up a world for Open Source Governance.

Here is one panicky article, basically says “Every software in the world is dangerous except Microsoft products”. Probably only Didio will agree to it or may be few people more.

Solutions are out there, it is just a matter of adopting it intelligently, Bottom line you save hell lot of money with few right steps initially by embracing Open source platform.

Social Computing: Getting Ahead of the Blog - TechUpdate - ZDNet 2

Posted by Rajesh Shetty on December 21, 2004

A very good old article by

Social Computing: Getting Ahead of the Blog - TechUpdate - ZDNet: “Mike Gotta” about Social computing and its multi-face capability. Its true it goes beyond Blogging/Wiki concept and reaches from all directions to the community, wherever there is a room for social communication. One of my old blogs on this Welcome to longtime; Social movement of this era mentions about Online social network like Linked In.

We have much more to go!!..

HiveMind: Apache’s Service-Configuration Microkernel; Answer to JBoss ’s ? 1

Posted by Rajesh Shetty on December 08, 2004

Well its a chase, Slow but steadily Apache is catching up tp JBoss , on its architecture , and new kid is on the block now. Check Introduction to HiveMind

Very intresting concept, whole Service orchestration/Message Brokering capability can be extended via this framework.

Look at hivemind as replacement for service-message middleware, derive its components and service configuration aspect to create run time/dynamic service, which can integrate legacy-thru-today web service.

Going back to comparison; May it is too early. but

JBoss J2EE Engine + Hibernate = Apache Geronimo + HiveMind + Torque

I’m certainly excited to explore HiveMind and Gerinimo as it matures.