C# to automate Java application with Java Access Bridge - java

I have a Java application that I want to automate for testing. Unfortunately, the app window only registers as a SunAWTFrame, which means none of the controls are exposed to typical window analysis and automation tools.
My search has lead me to C# and utilising Java Access Bridge DLLS in a C# program to automate it.
Has anyone had any experience of this?
Oracle provides JavaAccessBridge (JAB) with some DLLS to help with this as I understand it after reading a few articles around the internet. There are some code examples but I'm really not groking it right now. By breaking it down, I think this is what needs to be achieved:
Import / load / parse the JAB dlls
Map functions in the JAB dll to methods / calls within my program
Have the Java application to automate run (with JAB enabled) and get handle of it to my program
Utilise the JAB functions to control the Java application
I don't know C# as well as I know Java, but that's not going to stop me.
If anyone can provide help, guidance, pointers or anything to get me started, that'd be truly awesome.

As of 2019 we have a great tool AccessBridgeExplorer created and open-sourced by google. It's a really good staring point that contains a WindowsAccessBridgeInterop project which encapsulates almost every JAB API into a class oriented, .NET friendly assembly.
One notable thing, AccessBridge.Initialize() must be called in WPF/WinForm UI thread or in your own messaging pump thread, otherwise some methods like AccessBridge.EnumJvms() will always return false/empty.

Building on Stackia's great tip to use Google's AccessBridgeExplorer, Here are some tips to get you going:
Download Access Bridge Explorer
Use the WindowsAccessBridgeInterop.dll in your own (WinForms not Console) project (Add> Project Reference> Select the DLL)
Create a new access bridge object
AccessBridge Java = new AccessBridge();
Initialize the Access Bridge object
Java.Initialize();
Call Application.DoEvents() - A hack to wait for Java.Initialize to complete (My simple understanding is Java Access Bridge Uses a hidden window or similar)
Application.DoEvents(); //this waits for Java Bridge to initilize ;)
Get the handle of the Java Window
(plenty of examples online of how to get a Window Handle in C#)
Get Access to the Java Object that represents the window:
Java.Functions.GetAccessibleContextFromHWND(Handle, out int vmid, out JavaObjectHandle javaObjectHandle);
Get AccessibleWindow Object for Window (so you can find its children)
AccessibleWindow win = Java.CreateAccessibleWindow(handle);
Come up with your own way to cycle through the children, and the childrens children until you find the object you are after:
//Similar to:
foreach(var child in win.GetChildren())
JavaObjectHandle? javaObject = Java.Functions.GetAccessibleChildFromContext(node.JvmId, parentJavaObject, child.GetIndexInParent());
//to get the label or title of the object:
child.GetTitle();
To Interact with an object (eg click a button), do similar to the following:
(please note where it says JavaObject - it means the child java object (eg. to click a button you need to get the JavaObject for that button using GetAccessibleChildFromContext as i mentioned above)
//Get Possible Actions
JavaAutomation.Java.Functions.GetAccessibleActions(VMID, JavaObject, out AccessibleActions accessibleActions);
foreach( var action in accessibleActions.actionInfo)
{
Log.Info($"DoAction: {action.name}");
}
AccessibleActionsToDo accessibleActionsToDo = new AccessibleActionsToDo();
accessibleActionsToDo.actions = accessibleActions.actionInfo;
accessibleActionsToDo.actionsCount = accessibleActions.actionsCount;
//Do Actions
JavaAutomation.Java.Functions.DoAccessibleActions(VMID, JavaObject, ref accessibleActionsToDo, out int failure);

Related

Best way to store static data to be bundled with application?

I'm writing an application in java that will facilitate creating wireless sensor networks using off the shelf micro controllers, sensors, and radios. Each sensor and radio will most likely require unique code. I'm planning on creating skeletons for each platform and and then having modular bits of code for each sensor and radio that can be plugged into these skeletons. This will result in a library of static information that will be used to dynamically generate code for these sensors.
I'm not sure what the best way to store and organize this data would be. I started off trying to create classes for each sensor encapsulating its unique properties but using objects for data storage only seems weird. I feel like SQL would be overkill as the data isn't really changing and I would also like to keep everything in version control. Should I just use flat files? XML? Any advice on how to architect this project would be very welcome.
Instead of generating source, I'd go binary. Conceptually, that is.
Why would the source code need to change if a device is plugged in or out? Simply compile binary device driver libraries and link them to the main app.
There is an assembler, so likely there is a linker.
If there is no linker, and you are forced to use a monolithic source file, then at least we can use the concepts of a linker.
Linking Source Code
For inspiration and details I'd look into Operating System Design a little bit, for the concepts of device drivers, and IO devices, and network sockets. I'd use this to take a hard look at the source that would be generated, and what exactly changes if a device is changed, and fix it so that as little as possible, ideally nothing, has to be changed.
The code for the app running on the (presumably embedded) system should be maintained separate from the device drivers, so here is where the abstraction needs to begin. It needs to be refactored to abstract away the particulars of the devices into abstract device classes.
So this is the first step: refactor the generated source to abstract out the particulars of the device drivers so that you have a main
application that calls functions via symbols.
This allows the main app to work regardless of the number and kind of devices available.
Next, I'd look into compiler theory, particularly the concepts of symbol resolution and static/dynamic linking, and stub. Since the generated source is refactored so that there is a main application and a list of device drivers, all that is left is to make the devices available to the application.
Illustration
The application could generate the source code to be assembled by concatenating the source for the main application with the source for the device drivers.
It would provide a stub as well: a small library providing a function to iterate the devices and interrogate their classes.
Your application then becomes so simple that a one-liner on a *NIX prompt could do it. No Java required:
cat program stub drivers/foo drivers/bar > generated-source-or-binary
In it's simplest form, the program would contain a call to an iterate_devices label in stub.
Here's a layout of the source and/or binary image:
// application
main() {
for ( device in list_devices() ) {
switch ( device.class ) {
....
}
}
}
// stub
list_devices() {
for ( device = first; device != null; device += *cur )
yield device;
}
first: // drivers follow
// drivers/foo
dev_foo: .long dev_foo_end - . // size
....
dev_foo_end
// drivers/bar
dev_bar: .long dev_bar_end - .
....
dev_bar_end
Organizing Driver Sources
This shouldn't have to be more complicated than a directory with files.
A simple approach would be to include these in the .jar in a specific package. For instance, having a class provide driver sources like this:
package myapp.drivers;
public class DriverSource {
public static InputStream getDriverSource( String identifier ) {
return this.getClass().getClassLoader().getResourceAsStream(
this.getClass().getPackage().getName().replace('.', '/')
+ '/' + identifier + '.source'
);
}
}
would require the driver sources to be put in myapp/drivers/{identifier}.source. In a standard eclipse project, you'd place the files in src/myapp/drivers/. Using Maven, you'd put them in src/main/resources/myapp/drivers/. You can also put them in another directory, as long as they are copied as resources to the proper package directory.
The above class could also serve as a basis for more complex storage: you could query a remote service and download the source files, or query an SQL database. But resource files will be a decent start.

GWT: Querying and translating proxied UI classes into widgets

This morning I asked this question and received a really great answer for it. I'm now trying to prototype the design and am running into a similar (but not same) issue. Essentially I'm trying to have a 100% configuration-driven GWT UI, where changes to a DB can produce radically different UIs but without any code changes.
My architecture is simple:
I will use a separate tool (or at first, by hand) to produce a .xul (XUL) file and save it to a database; probably a document database like Mongo or something similar
On the server-side, I will write a XulParser that reads the XUL file out of the database and turns it into a ContainerProxy instance
A ContainerProxy is my "proxy" equivalent to a com.google.gwt.user.client.ui.Panel or something similar; it is just a bean/POJO that contains a list of other widget proxies (see code snippet below)
For instance, I might have a XUL file that defines a Button like the one below
This ButtonProxy would be added to a ContainerProxy (along with any other UI widgets in the same container/view/panel)
On the client-side, I'll query for the ContainerProxy somehow (???), and pull it down from the server.
I'll then have a mechanism that translates each of the ContainerProxy's children (the ButtonProxy, etc.) into actual UI widgets.
This way, at first I can put a certain XUL file into the database and the UI might only contain the "Order Now" button on it. But down the road, I might want to use a totally different UI, so I design a different XUL file, update the document in the database, and - voila - the UI changes for all users without any code changes. Please note: I understand this is not a normal way of doing things: I have a special use case where I need such config-driven UIs.
To help clarify the XUL-parsing process:
<button id="order" label="orderNow" clickHandler="org.myapp.OrderButtonHandler" />
after the XulParser reads the above snippet, we get:
ButtonProxy orderButton = new ButtonProxy("order", "OrderNow");
orderButton.addClickHandler(new OrderButtonHandler());
Anyways, my questions:
What do I need to do on the client-side to query for my ContainerProxy? Can anyone provide pseudo-code to help me visualize it?
Once I have the ContainerProxy on the client-side, what UI mechanisms are available for me to translate the proxied classes into actual UI widgets? Is UIBinder available? Again, can someone provide some pseudo-code?
Thanks in advance for any help here!
Here is a bit of a code idea that would do what you wanted. I haven't tested this, but you can get the idea of how it all could work together from it.
String htmlFragment = "<div><button id='action1' type='button>Action 1<button/><div/>";
HTMLPanel container = new HTMLPanel(htmlFragment);
RootLayoutPanel.get().add(container);
Element button1El = container.getElementById("action1");
if(button1El != null){
Button button1 = Button.wrap(button1El);
button1.addClickHandler(new ClickHandler(){
#Override
public void onClick(ClickEvent event) {
// What you want button 1 to do
}
});
}

Automatically generate Java code based on existing fields in a class

Scenario
I'm working with a Java model built from scratch in Eclipse. What's important in this model is that we save our output to MATLAB (.mat) files. I constantly add new features, which require new fields that in turn will have to be exported to the .mat file at every iteration. Upon restarting a crashed simulation, I might have to import the .mat file. To export or import my .mat file I use JMatIO.
For example, if I would add a new field rho_m (a simple double) to my class CModel, I have to add to my Save() method:
mlModel.setField("rho_m", new MLDouble(null, new double[] {rho_m}, 1));
And to my Load() method:
rho_m = ((MLDouble)mlModel.getField("rho_m")).getReal(0);
Note that even though rho_m is a double, it needs to be treated as a double[] in JMatIO. This probably has something to do with MATLAB being orientated towards matrices and matrix operations.
Problem
Instead of doing this manually (prone to errors, annoying to maintain) I would like to automate this procedure. Ideally, I would like my IDE to detect all the fields in CModel and write the code based on the field's name and type. Is there any way to do this in Java/Eclipse?
Ideas so far
I have no formal training in low-level programming languages (yes, Java is low-level to me) and am still relatively new to Java. I do have some experience with MATLAB. In MATLAB I think I could use eval() and fieldnames() in a for loop to do what I mentioned. My last resort is to copy-paste the Java code to MATLAB and from there generate the code using a huge, ugly script. Every time I want to make changes to the model I'd rerun the MATLAB script.
Besides that idea I've found terms like UML, but do not have the background knowledge to figure out if this is what I'm looking for or not.
Any help, even if it's just a small push in the right direction, is greatly appreciated. Let me know if I need to further clarify anything.
Looking at your scenario, you are doing model-driven code generation, that is, you have a model and want to get some code generated according to your current model. Therefore, you need a model-driven code generator.
I lead the ABSE/AtomWeaver project, so I'll outline what you can do to get what you want using AtomWeaver (There are however other solutions like MetaEdit+, XText or Eclipse's own GMT/EMF sub-system).
AtomWeaver is an IDE where you can build a model and generate code from that model. You can change your model as many times you want and hit the "Generate" button to get an updated version of your code. ABSE is the name of the modeling method.
We don't need to go into details, but essentially ABSE follows a "building-block" approach. You create a Template that represents a feature or concept of your model. Then, you can associate a mini-code generator just to that concept. You can then "instantiate" and combine those building blocks to quickly build your models. Variables increase the flexibility of your models.
You can also change your models, or add new features ("blocks") and generate again. The generators are built using the Lua programming language, a very simple language with C-Like syntax.
The best way to understand the ABSE development method and the AtomWeaver IDE is to download the IDE and see the samples or try the tutorials. And yes, you can use AtomWeaver for free.

How to use Java to sent and read a third party javascript variables

I have two javascript files:
http://www.dublinbikes.ie/design/marseille/javascript/gmaps_common.js
http://www.dublinbikes.ie/design/marseille/javascript/gmaps_search_station.js
Which for http://www.dublinbikes.ie/All-Stations/Station-map# website
What I want to do is to simulate the search a station status action that on the left hand side by set variable 'value' a station number and pass it to gmaps_common.js for execute, then read the result from gmaps_search_station.js that executed variable called html from LeftBlock(id) function.
Because I need run whole process automatically several times, so please suggest me could I use Java to do this and how.
Thank you very much for the help.
You should never try to emulate a JavaScript interpreter just to get js variables out of it - just do the same thing the script would do in your language. Java is mighty enough.
The script just gets a list of stations from http://www.dublinbikes.ie/service/carto, and then queries details from http://www.dublinbikes.ie/service/stationdetails/dublin/{number} (example). Java has lots of HTTP and XML libraries, it will be no problem for you to do that, too.

Calling a remote Java program on iSeries from RPG

I'm looking to invoke a Java program from RPG running on Iseries V5r4. The remote program is a web service client (performing a postcode lookup), running in Websphere.
Ideally I'd like to call it direct from RPG? is that possible? or do I have to create a java program to run on the iSeries and use RMI or something to call the remote java program.
We aren't keen on calling the extenral webservice direct as it means opening path from otherside world direct to iSeries.
I'm not an RPG programmer, just looking for something to point our guys in the right direction or anything I need to enable to make the java programs more consumable for the RPG folks.
Thanks,
Scott
Since the program is running on a remote server, you can't call it directly from RPG. Given that it's a web service, I would create a Java program to run on the iSeries and call that Java program from within RPG. Nowaday's, RPG can interface directly with Java. You have to create some D-specs to declare the class and prototype out the method calls. In the following example, assume a Java class exists called ServiceCaller in the package 'tools'. It has a single method called getServiceReply which accepts three character fields and returns an integer.
*Define the Java class locally.
DServiceCaller S O CLASS(*JAVA:'tools.ServiceCaller')
*Class constructor. No parameters.
DnewServiceCaller PR O EXTPROC(*JAVA:
D 'tools.ServiceCaller':
D *CONSTRUCTOR)
D CLASS(*JAVA:'tools.ServiceCaller')
*GetServiceReply.
*public int getServiceReply(byte[] parm1, byte[] parm2, byte[] parm3)
DgetServiceReply PR 10I 0 EXTPROC(*JAVA:
D 'tools.ServiceCaller':
D 'getServiceReply')
D Parm1 400A CONST
D Parm2 400A CONST
D Parm3 400A CONST
Your RPG calc specs will look something like this free-form example:
/free
ServiceCaller = newServiceCaller();
iReply = getServiceReply(ServiceCaller:'Parm1':'Parm2':'Parm3');
/end-free
Inside the java code, within the getServiceReply method, convert those byte arrays to strings like this:
sParm1 = new String(parm1);
sParm2 = new String(parm2);
sParm3 = new String(parm3);
Granted, this is an oversimplified example and your application needs will be slightly different. You will want to add error handling code in case the web service doesn't reply. You may also want to use getters and setters in your class. It all depends on your application needs and the requirements of the remote web service.
Some notes on RPG types to Java types:
RPG Type Java Type
10I 0 int
3I 0 byte
5I 0 short
20I 0 long
N boolean
A byte[]
If you are feeling particularly ambitious, you can call the native Java HTTP classes from within your RPG. But I've found that a custom Java program to act as an in-between that is written specifically to talk to RPG is an easier way to go. Although RPG can talk to Java, it's not as pretty as Java talking to Java.
Additional information on calling Java from RPG can be found in the ILE RPG Programmer's guide. The V5R4 version can be found here: http://publib.boulder.ibm.com/infocenter/iseries/v5r4/topic/books/sc092507.pdf
Since the is a web service, another solution would be to use Scott Klement's HTTP API. It's available on his website at http://www.scottklement.com/httpapi/.
One of the big benefits for me is this is entirely RPG and doesn't use any Java which can be a bit sluggish sometimes. I'm not real familiar with how web services work in Java but it appears that you don't have to form all of the XML and it's done for you. With the HTTP API you would need to do that yourself.
Also Scott Klement has several other useful things on his website. Another site with some neat tools is http://www.think400.dk/downloads.htm.

Categories

Resources