Thursday, December 30, 2004

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

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


Wednesday, December 22, 2004

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

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.

Monday, December 20, 2004

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

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!!..

Tuesday, December 07, 2004

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

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.