REQUIREMENT client.activex |
Type | NEW |
Priority | MEDIUM |
Status | DEPRECATED |
Topic | XmlBlaster provides access from C# and VisualBasic with ActiveX. |
Des cription |
OverviewWith the free ActiveX bridge from SUN (Java JDK 1.5) we can export the Java client library into an ActiveX control (Windows only). With this control easy access to xmlBlaster is possible from C# or Visual Basic .net
With this control you can access xmlBlaster from C#
or VisualBasic which calls a client side java bean
which again connects to the xmlBlaster server.
All invocations are done with Micheles xml scripting
client, see
client.script requirement
and
ActiveX bridge howto
by calling
Alternatively you can use the methods like LimitationsIt seems to work only with the ActiveX bridge from JDK 1.5 or higher. JDK 1.4.2 failed on my Windows XP. Probably we need to create a ActiveX VisualBasic 6.0 proxy control which delegates the calls from VisualBasic .net for JDK 1.4.2
If you compile the dll bridge with xmlBlaster/build.xml
you need a MS Visual C++ installed otherwise the IDL compiler
It was tested for example with Microsoft .net Framework 1.1.4322 on Windows XP Professional 2002 Service Pack 1. Installation
First you need to create a dll and register it, theses steps are described
in the above mentioned howto. We have added these steps into a new build -DJRE_HOME=C:\PROGRA~1\Java\j2re1.5.0 activex Please adjust the JRE_HOME setting to point to your Java runtime installation. Now you find all generated files under C:\PROGRA~1\Java\j2re1.5.0\activex and the control is registered in the registry under regedit -> HKEY_CLASSES_ROOT -> CLSID -> D824B185-AE3C-11D6-ABF5-00B0D07B8581 -> XmlScriptAccess Bean Control Demonstration clientsA functional C# demo client and a VisualBasic .net client you find in directory xmlBlaster\demo\activex Here are the steps to use the demonstration clients from Visual Studio: Visual Studio: -> Solution Explorer -> References -> (right mouse): Add Reference -> COM -> XmlScriptAccess Task bar: Java Icon: -> Open Console Don't forget to start the server first: java -jar lib\xmlBlaster.jar API usageThe Java bean XmlScriptAccess exports all needed functionality to activeX aware languages. All native data types are directly available from C#/VisualBasic, xmlBlaster specific java objects returned by XmlScriptAccess methods are automatically available in C#/VisualBasic, so you simply use the returned objects as you would in java. Here is an example of the subscribe method declaration in Java (XmlSriptAccess bean) public SubscribeReturnQos subscribe(String xmlKey, String xmlQos) throws XmlBlasterException In Visual Basic you use the returned java object like Try ... Dim subscribeReturnQos As Object subscribeReturnQos = xmlBlaster.subscribe("<key oid='HelloWorld3'/>", "<qos/>") ' Access examples: ' subscribeReturnQos.getSubcriptionId() ' subscribeReturnQos.getStateInfo() ' ... ... Catch e As SystemException Console.WriteLine("Exception:" & e.ToString()) You just lookup all methods of the returned java object in the Javadoc API and call the methods as you would do in Java Callback usageAs events into ActiveX can't have a return value and can't throw
an exception back to us we handle it here as a callback, for example
Visual Basic needs to call
The 'msg' received in the callback method is of type Accessing byte[] with ActiveX bridgePrivate Sub XmlScriptAccess_update(ByVal msg As Object) _ Handles xmlBlaster.XmlScriptAccessSource_Event_update Try ' Access the raw content bytes (by Robert Dupuy) ... Dim len As Int32 = msg.getContent().length Dim str As String Dim contentSBytes As SByte() contentSBytes = msg.getContent() Dim contentBytes As Byte() = New Byte(contentSBytes.Length) Buffer.BlockCopy(contentSBytes, 0, contentBytes, 0, contentSBytes.Length) str = System.Text.Encoding.ASCII.GetString(contentBytes) MsgBox("Success, message arrived:" & str) ... If the ActiveX bridge has problems to convert Java byte[] as described in bug_id=4887461 you can use the Base64 workaround: We offer in the callback a method msg.getContentBase64() if you need to transfer binary data. If your content contains only strings (for example a xml string) you can use the convenience method msg.getContentStr(). Here is an example for the callback method update(), str and decoded contain the same result: Private Sub XmlScriptAccess_update(ByVal msg As Object) _ Handles xmlBlaster.XmlScriptAccessSource_Event_update Try Dim str As String Dim len As Int32 Dim encoded As String Dim decoded As Byte() str = msg.getContentStr() len = msg.getContentLength() encoded = msg.getContentBase64() decoded = Convert.FromBase64String(encoded) ... |
Example Csharp |
C# example// HelloWorld.cs using System; namespace demo { class XmlBlasterCSharp { [STAThread] static void Main(string[] args) { // See registry: // regedit -> HKEY_CLASSES_ROOT // -> CLSID // -> D824B185-AE3C-11D6-ABF5-00B0D07B8581 // -> XmlScriptAccess Bean Control // org.xmlBlaster.client.activex.XmlScriptAccess XmlScriptAccess.XmlScriptAccessClass xmlBlaster; xmlBlaster = new XmlScriptAccess.XmlScriptAccessClass(); string[] argArr = { "-protocol", "SOCKET" }; xmlBlaster.initArgs(argArr); string request = "<xmlBlaster>" + " <connect/>" + " <wait delay='1000' />" + " <publish>" + " <key oid='test'><airport name='london' /></key>" + " <content>This is a simple script test</content>" + " <qos/>" + " </publish>" + "</xmlBlaster>"; string response = xmlBlaster.sendRequest(request); Console.WriteLine("Got response from xmlBlaster: " + response); } } } Tim Heilig posted how to retrieve the MsgUnit from callback calls in the update() method While I don't have time to update the examples on the website, I figured I'd send a code snippet to the list of a working C# client with the activex bridge. this code should reside in a try/catch so you can appropriately set the update return if problems occur, I just included the success case. public void update(object o) { string key; string content; string qos; object k; object q; Type eventType = o.GetType(); k = eventType.InvokeMember("getKey", System.Reflection.BindingFlags.InvokeMethod, null, o, null); q = eventType.InvokeMember("getQos", System.Reflection.BindingFlags.InvokeMethod, null, o,null); content = (string)eventType.InvokeMember("getContentStr", System.Reflection.BindingFlags.InvokeMethod, null, o, null); eventType = k.GetType(); key = (string)eventType.InvokeMember("toXml", System.Reflection.BindingFlags.InvokeMethod, null, k, null); eventType = q.GetType(); qos = (string)eventType.InvokeMember("toXml", System.Reflection.BindingFlags.InvokeMethod, null, k, null); MemoryStream memoryStream = new MemoryStream(new UTF8Encoding().GetBytes(content)); XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8); XmlDocument keyDoc = new XmlDocument(); keyDoc.LoadXml(key); xmlBlaster.setUpdateReturn(" |
Example VisualBasic |
VisualBasic.net example' Simple HelloWorld example how to access xmlBlaster ' We connect to xmlBlaster and query the free memory of the server ' @author Marcel Ruff Module HelloWorld Sub Main() Dim request, response As String Dim xmlBlaster As XmlScriptAccess.XmlScriptAccessClass xmlBlaster = New XmlScriptAccess.XmlScriptAccessClass ' Configure using the SOCKET protocol Dim argArr(1) As String argArr(0) = "-protocol" argArr(1) = "SOCKET" xmlBlaster.initArgs(argArr) ' Connect to the server response = xmlBlaster.sendRequest("<xmlBlaster><connect/></xmlBlaster>") ' Query the free memory request = "<xmlBlaster><get><key oid='__cmd:?freeMem'/></get></xmlBlaster>" response = xmlBlaster.sendRequest(request) Console.WriteLine("Got response:" & response) ' Leave the server response = xmlBlaster.sendRequest("<xmlBlaster><disconnect/></xmlBlaster>") End Sub End Module |
Example VisualBasic |
VisualBasic.net example with asynchronous callbacks'------------------------------------------------------------------------------ ' XmlBlaster access with asynchronous callbacks from Visual Basic .net ' Calls are routed over ActiveX encapsulating a Java client bean which ' connects to xmlBlaster ' @file xmlBlaster/demo/activex/VisualBasic3.vb ' @author Marcel Ruff, xmlBlaster@marcelruff.info (2004-03-17) ' @see http://www.xmlBlaster.org/xmlBlaster/doc/requirements/client.activex.html ' @see org.xmlBlaster.client.activex.XmlScriptAccess '------------------------------------------------------------------------------ Imports System Module HelloWorld3 Private WithEvents xmlBlaster As XmlScriptAccess.XmlScriptAccessClass Dim ascii As System.Text.ASCIIEncoding = New System.Text.ASCIIEncoding Sub Main() Call HelloWorld3() End Sub '--------------------------------------------------------------------------- ' This method is called asynchronously from java delivering a message. ' As events from java into ActiveX can't deliver a return value ' or an exception back we need to call either ' setUpdateReturn() -> passes a return value to the server ' or ' setUpdateException() -> throws an XmlBlasterException ' If you forget this the update thread of the java bean will block forever ' @param msg See ' http://www.xmlblaster.org/xmlBlaster/doc/client-api/org/xmlBlaster/client/activex/UpdateEvent.html '--------------------------------------------------------------------------- Private Sub XmlScriptAccess_update(ByVal msg As Object) _ Handles xmlBlaster.XmlScriptAccessSource_Event_update Try Dim age As String age = msg.getQos().getClientProperty("myAge").getStringValue() Console.WriteLine("SUCCESS: Update arrived: " & msg.getCbSessionId() & _ ", oid=" & msg.getKey().getOid() & _ ", content=" & msg.getContentStr() & _ ", myAge=" & age) xmlBlaster.setUpdateReturn("<qos><state id='OK'/></qos>") Catch e As SystemException Console.WriteLine("Exception in update:" & e.ToString()) xmlBlaster.setUpdateException("user.update.internalError", e.ToString()) End Try End Sub '--------------------------------------------------------------------------- ' Connect to xmlBlaster and try all possible methods '--------------------------------------------------------------------------- Sub HelloWorld3() Dim key, qos As String xmlBlaster = New XmlScriptAccess.XmlScriptAccessClass Dim prop As Object = xmlBlaster.createPropertiesInstance() prop.setProperty("protocol", "SOCKET") prop.setProperty("trace", "false") xmlBlaster.initialize(prop) Try ' Connect to the server qos = "<qos>" & _ " <securityService type='htpasswd' version='1.0'>" & _ " <![CDATA[" & _ " <user>HelloWorld3</user>" & _ " <passwd>secret</passwd>" & _ " ]]>" & _ " </securityService>" & _ "</qos>" Dim connectReturnQos As Object connectReturnQos = xmlBlaster.connect(qos) Console.WriteLine("Connected to xmlBlaster, sessionId=" & _ connectReturnQos.getSecretSessionId()) ' Publish a message key = "<key oid='HelloWorld3' contentMime='text/xml'>" & _ " <org.xmlBlaster><demo/></org.xmlBlaster>" & _ "</key>" Dim content As Byte() = ascii.GetBytes("Hi") qos = "<qos>" & _ "<clientProperty name='myAge' type='int'>18</clientProperty>" & _ "</qos>" Dim publishReturnQos As Object publishReturnQos = xmlBlaster.publishBlob(key, content, qos) Console.WriteLine("Published message id=" & _ publishReturnQos.getRcvTimestamp().toXml("", True)) ' Get synchronous the above message Dim getMsgArr As Object() getMsgArr = xmlBlaster.get("<key oid='HelloWorld3'/>", "<qos/>") Dim msg As Object For Each msg In getMsgArr Console.WriteLine("Get returned:" & msg.toXml()) Next ' Subscribe Dim subscribeReturnQos As Object subscribeReturnQos = xmlBlaster.subscribe("<key oid='HelloWorld3'/>", "<qos/>") Console.WriteLine("Got subscribe response:" & _ subscribeReturnQos.getSubscriptionId()) ' Give control to the main loop to receive the update event System.Windows.Forms.Application.DoEvents() ' Publish again, message arrives asynchronously in ' Sub XmlScriptAccess_update() (see above) publishReturnQos = xmlBlaster.publishStr(key, "Ho", qos) Console.WriteLine("Got publish response:" & publishReturnQos.toXml()) ' Give control to the main loop to receive the update event System.Windows.Forms.Application.DoEvents() ' UnSubscribe Dim k As String = "<key oid='" & subscribeReturnQos.getSubscriptionId() & "'/>" xmlBlaster.unSubscribe(k, "<qos/>") ' Destroy the topic "HelloWorld3" xmlBlaster.erase("<key oid='HelloWorld3'/>", "<qos/>") ' Leave the server, cleanup resources xmlBlaster.disconnect("<qos/>") ' Pass control to eventLoop ... MsgBox("Click me to finish ...") Catch e As SystemException Console.WriteLine("Exception:" & e.ToString()) End Try End Sub End Module |
Example VisualBasic |
VisualBasic 6 exampleNote: The synchronous invocations like '--------------------------------------------------------------------------- ' This method is called asynchronously from java delivering a message. ' As events from java into ActiveX can't deliver a return value ' or an exception back we need to call either ' setUpdateReturn() -> passes a return value to the server ' or ' setUpdateException() -> throws an XmlBlasterException ' If you forget this the update thread of the java bean will block forever '--------------------------------------------------------------------------- Public Sub XmlScriptAccess_update(ByVal msg As Object) On Error GoTo UpdateErrorHandler Dim age As String age = msg.getQos().getClientProperty("myAge").getStringValue() log ("SUCCESS: Update arrived: " & msg.getCbSessionId() & _ ", oid=" & msg.getKey().getOid() & _ ", content=" & msg.getContentStr() & _ ", myAge=" & age) MsgBox ("Success, message arrived:" & Str) xmlBlaster.setUpdateReturn ("<qos><state id='OK'/></qos>") Exit Sub UpdateErrorHandler: log (Err.Number & ": " & Err.Description) xmlBlaster.setUpdateException "user.update.internalError", Err.Description Exit Sub End Sub '--------------------------------------------------------------------------- ' Connect to xmlBlaster and try all possible methods '--------------------------------------------------------------------------- Private Sub xmlBlasterDemo() On Error GoTo ErrorHandler Set xmlBlaster = CreateObject("XmlScriptAccess.Bean") Set prop = xmlBlaster.createPropertiesInstance() Rem CallByName(prop, "setProperty", vbLet, "protocol","SOCKET") Rem prop.setProperty("protocol", "SOCKET") Rem prop.setProperty("trace", "false") xmlBlaster.Initialize (prop) Dim argArr(3) As String argArr(0) = "-protocol" argArr(1) = "SOCKET" argArr(2) = "-trace" argArr(3) = "false" xmlBlaster.initArgs (argArr) ' Connect to the server qos = "<qos>" & _ " <securityService type='htpasswd' version='1.0'>" & _ " <user>HelloWorld3</user>" & _ " <passwd>secret</passwd>" & _ " </securityService>" & _ "</qos>" Dim connectReturnQos As Object Set connectReturnQos = xmlBlaster.Connect(qos) sessionId = connectReturnQos.getSecretSessionId() log ("Connected to xmlBlaster, sessionId=" & sessionId) ' Publish a message Key = "<key oid='HelloWorld3' contentMime='text/xml'>" & _ " <org.xmlBlaster><demo/></org.xmlBlaster>" & _ "</key>" contentStr = "Hi" qos = "<qos>" & _ "<clientProperty name='myAge' type='int'>18</clientProperty>" & _ "</qos>" Set publishReturnQos = xmlBlaster.publishStr(Key, contentStr, qos) log ("Published message id=" & publishReturnQos.getRcvTimestamp().toXml("", True)) ' Get synchronous the above message getMsgArr = xmlBlaster.get("<key oid='HelloWorld3'/>", "<qos/>") For Each msg In getMsgArr log ("Get returned:" & msg.toXml()) Next ' Subscribe Set subscribeReturnQos = xmlBlaster.subscribe("<key oid='HelloWorld3'/>", "<qos/>") log ("Got subscribe response:" & subscribeReturnQos.getSubscriptionId()) Call loopEvents ' Publish again, message arrives asynchronously in ' Sub XmlScriptAccess_update() (see above) Set publishReturnQos = xmlBlaster.publishStr(Key, "Ho", qos) log ("Got publish response:" & publishReturnQos.toXml()) Call loopEvents ' UnSubscribe k = "<key oid='" & subscribeReturnQos.getSubscriptionId() & "'/>" unSubscribeReturnQos = xmlBlaster.unSubscribe(k, "<qos/>") ' Destroy the topic "HelloWorld3" eraseReturnQos = xmlBlaster.erase("<key oid='HelloWorld3'/>", "<qos/>") Call loopEvents xmlBlaster.disconnect ("<qos/>") Set xmlBlaster = Nothing Rem MsgBox ("Hit a key to continue ...") Exit Sub ErrorHandler: log (Err.Number & ": " & Err.Description) MsgBox ("Error, giving up: " & Err.Description) Exit Sub End Sub Private Sub loopEvents() ' Give control to the main loop to receive the update event 'System.Windows.Forms.Application.DoEvents() MsgBox ("Hit a key to continue ...") End Sub ' Log into the GUI text area Private Sub log(text) Logger.text = Logger.text & vbCrLf & text End Sub ' GUI button to start the demo Private Sub Start_Click() Call xmlBlasterDemo End Sub |
Configure |
Set JRE_HOME to point to your java runtime environment, for example
NOTE: Configuration parameters are specified on command line (-someValue 17) or in the
xmlBlaster.properties file (someValue=17). See requirement "util.property" for details. |
Todo |
|
See REQ | interface |
See REQ | client.script |
See API | org.xmlBlaster.client.activex.XmlScriptAccess |
See | Sun ActiveX bridge guide |
See | http://forum.java.sun.com/forum.jsp?forum=40 |
See | VisualBasic 6 hints |
See | Bean implementation |
See | http://www.xmlblaster.org/xmlBlaster/demo/activex |
This page is generated from the requirement XML file xmlBlaster/doc/requirements/client.activex.xml