Finding Display of an RCP App - reflection

I'm writing a testing Framework which is starting a GUI Application. To be able to test this GUI in the case of an SWT application I need to know it's display. In general, this display is loaded by another classloader, therefore I'm using the method findDisplay(Thread t) of the swt Display class by reflection to accomplish this task. My code looks something like this:
Thread[] threads = new Thread[10];
Thread.enumerate(threads);
Object foundObject = null;
for (Thread t : Arrays.asList(threads)){
foundObject = null;
Class<?> clazz = t.getContextClassLoader().loadClass("org.eclipse.swt.widgets.Display");
final Method method = clazz.getMethod("findDisplay", Thread.class);
foundObject = method.invoke(null, new Object[] {t});
if (foundObject != null) {
System.out.println("yeah, found it!");
break;
}
}
In my opinion this should find every Object of type Display in the current thread group. However I don't get any for the texteditor RCP example although the GUI is starting up perfectly.
Any ideas what is going wrong or how I can debug this in a reasonable way?

I figured out what the main problem was: The ContextClassloader had nothing to do with the classloader who actually loaded the classes.
To resolve my problem I took care of having the classloader which loads the swt display class both in the hierarchy of the RCP program and the hierarchy of my framework. This was possible by using the java extension classloader. (I couldn't use the application classloader since my RCP application doesn't work with it as parent, I haven't figured out yet why) It was then just a matter of adding the swt.jar to the java.ext.dirs property.

If you are using Eclipse RCP then maybe you can use:
PlatformUI.getWorkbench().getDisplay()

Related

Added a method to a class, not seen by debugger, AOS server crashes

I added a new method to the CustVendPaym class called sendersBankCompanyStatementName of type BankCompanyStatementName.
This is the code of said method:
public BankCompanyStatementName sendersBankCompanyStatementName(BankCompanyStatementName _sendersBankCompanyStatementName = sendersBankCompanyStatementName)
{
sendersBankCompanyStatementName = _sendersBankCompanyStatementName;
return sendersBankCompanyStatementName;
}
I added the definition in the classDeclaration method:
BankCompanyStatementName sendersBankCompanyStatementName;
Then in the method vendPaym in the VendOutPaym class, a new instance of VendPaym (which extends CustVendPaym) is created:
vendPaym = new VendPaym();
//A bunch of properties are set then one I created:
vendPaym.sendersBankCompanyStatementName (bankAccountTable.BankCompanyStatementName);
If I break there, I see the assignment with the value I'm expecting working correctly, but then the debugger (watch) never actually shows the new property I added with the value that's supposed to be in it.
Then if I just continue code execution, the AOS server in which I'm developing just crashes :|
Any ideas, am I doing something obviously wrong ?
Thanks.
EDIT: If I rollback my changes (that is deleting the newly added method and removing any references to it) everything works as it was before.
Have you compiled forward the CustVendPaym class?

UIImpersonator.addChild() doesn't dispatch the right events

I am running FlexUnit tests through Ant. The test test1 fails with the message "Timeout Occurred before expected event" but test2 passes. The only difference between the two tests is that one uses UIImpersonator.addChild() whereas the other uses FlexGlobals.topLevelApplication.addElement().
test1 fails even if I listen for "addedToStage" event. Listening for "added" event, however, makes test1 pass.
[Test(async, ui, description="Fails")]
public function test1():void
{
var c:UIComponent = new UIComponent;
Async.proceedOnEvent(this, c, FlexEvent.CREATION_COMPLETE);
UIImpersonator.addChild(c);
}
[Test(async, ui, description="Passes")]
public function test2():void
{
var c:UIComponent = new UIComponent;
Async.proceedOnEvent(this, c, FlexEvent.CREATION_COMPLETE);
FlexGlobals.topLevelApplication.addElement(c);
}
when adding a child, it will not initiate the flex component lifecycle, because displayobject is flash core element, not flex.
assuming Flex4/spark. addChild adds a MovieClip, not a Flex UIElement, it doesn't even know FlexEvent type as it is a flash.core object. It will only throw addedToStage or added events (Event.added), but in unit test, it is not added to stage, because UIImpersonator is not part of the stage
I ran into this same issue today using the new Apache FlexUnit 4.2.0 release.
When trying to run the sampleCIProject included in the binary distribution, none of the tests that used Async would succeed. The exception was exactly as described above.
After looking at the source code for a while, I noticed that the core FlexUnit libraries have two flavours: flexunit-4.2.0-20140410-as3_4.12.0.swc and flexunit-4.2.0-20140410-flex_4.12.0.swc.
The first of these is intended for pure AS3 projects, while the latter is intended for projects that use Flex. The sampleCIProject included both of these libraries in the library path, and I'm assuming that it was using the UIImpersonator class from the pure AS3 library rather than the Flex-supporting one. I removed flexunit-4.2.0-20140410-as3_4.12.0.swc from the project, and lo and behold, the Async tests started working again.
Probably a bit late for you, but I hope this helps someone else.

in Flex 3.2 Having troubles converting remote object result to specific object on client side in modules

in Flex 3.2 Having troubles converting remote object result to specific object on client side in modules.
For example I have VIPSAdmin module.
it has function
private function doResult(event:ResultEvent):void {
var data_:Array = ArrayUtil.toArray(event.result);
var result:ResultDTO = data_[0] as ResultDTO;
if(!result.isError()) {
trace(result.result);
vipsAdminDTO = result.result as VIPSAdmin;
compId= vipsAdminDTO.compId; // second time dying here
}
}
Function invoked when I get data from remote objet.
First time all great,when I unload this modeule and load it again:
data_[0] as ResultDTO;
Performs fine, but
vipsAdminDTO = result.result as VIPSAdmin;
vipsAdminDTO always null!
Even when
trace(result.result);
produces [object VIPSAdmin]
What a heck I missing here!? Looks like it just cannot do
result.result as VIPSAdmin;
even when trace and debug says it is instance of VIPSAdmin
I've figured out what is the problem, problem is that when I first instantiate something in module then in main app, somehow classes are not alined even that they are identical !
So solution is to make a fake instance in application class first, then if you use that same class to make an instance in module it will work!
I do it very simple in my main application class I just added:
VIPSAdmin;
This seems to create some sort of ghost instance, which I belie will be pickup by GC later, but will build tables of instances properly! Which solved my problem.
Not sure if this is appropriate solution ! but it sure works.

clone flex component

I am trying to duplicate a flex component at run time.
For example if i have this
mx:Button label="btn" id="btn" click="handleClick(event)"/>
i should be able to call a function called DuplicateComponent() and it should return me a UI component thts exactly same as above button including the event listeners with it.
Can some one help me please??
Thanks in advance
Do a Byte Array Copy. This code segment should do it for you:
// ActionScript file
import flash.utils.ByteArray;
private function clone(source:Object):*
{
var myBA:ByteArray = new ByteArray();
myBA.writeObject(source);
myBA.position = 0;
return(myBA.readObject());
}
One note, I did not write this code myself, I'm pretty sure I got it from a post on the Flex Coder's list.
To solve that problem you should use actionscript and create the buttons dynamically.
Lets say you want the button(s) to go in a VBox called 'someVbox'
for (var i:uint = 0; i< 10; i++){
var but:Button = new Button();
but.label = 'some_id_'+i;
but.id = 'some_id_'+i;
but.addEventListener(MouseEvent.CLICK, 'handleClick');
someVbox.addChild(but);
}
I haven't tested it, but that should add 10 buttons to a vbox with a bit of luck.
You can't take a deep copy of UIComponents natively. You're best bet would be to create a new one and analyse the one you have to add a duplicate setup. To be honest this does sound like a bit of a code smell. I wonder if there may be a better solution to the problem with a bit of a rethink..
Same question as: http://www.flexforum.org/viewtopic.php?f=4&t=1421
Showing up in a google search for the same thing. So you've cut&pasted the same question a month later. No luck eh?
There is no easy way to do this that I know of. Many of a component's settings are dependent on the container/context/etc... and get instantiated during the creation process, so there's no reason to clone from that perspective.
You can clone key settings in actionscript and use those when creating new elements.
For instance, assuming you only care about properties, you might have an array ["styleName","width","height",...], and you can maybe use the array like this:
var newUI:UIComponent = new UIComponent();
for each(var s:String in propArray) {
newUI[s] = clonedUI[s];
}
If you want more bites on your question (rather than waiting a month), tell us what you are trying to achieve.
mx.utils.ObjectUtil often comes in handy, however for complex object types, it's typically good practice to implement an interface that requires a .clone() method, similar to how Events are cloned.
For example:
class MyClass implements ICanvasObject
{
...
public function clone():ICanvasObject
{
var obj:MyClass = new MyClass(parameters...);
return obj;
}
}
This gives your code more clarity and properly encapsulates concerns in the context of how the object is being used / cloned.
You are right but as per my understanding UI Components are not cloned by mx.utils.ObjectUtil.
from : http://livedocs.adobe.com/flex/201/langref/mx/utils/ObjectUtil.html#copy()
copy () method
public static function copy(value:Object):Object
Copies the specified Object and returns a reference to the copy. The copy is made using a native serialization technique. This means that custom serialization will be respected during the copy.
This method is designed for copying data objects, such as elements of a collection. It is not intended for copying a UIComponent object, such as a TextInput control. If you want to create copies of specific UIComponent objects, you can create a subclass of the component and implement a clone() method, or other method to perform the copy.
Parameters value:Object — Object that should be copied.
Returns Object — Copy of the specified Object

How can you get NVelocity to initialize correctly?

I can't get NVelocity to initialize. I'm not trying to do anything complicated, so it's just fine if it initializes at the defaults, but it won't even do that.
This:
VelocityEngine velocity = new VelocityEngine();
ExtendedProperties props = new ExtendedProperties();
velocity.Init(props);
Results in: "It appears that no class was specified as the ResourceManager..."
So does this:
VelocityEngine velocity = new VelocityEngine();
velocity.Init();
I can find precious little documentation on what the properties should be, nor how to get it to initialize with the simple defaults. Can anyone point to a resource?
A lot of pages point back to this page:
http://www.castleproject.org/others/nvelocity/usingit.html
But this page skips over the (seemingly) most important point -- how to set the properties and what to set them to.
I just want to load a simple template from a file.
Here's what I found out --
I was using the original NVelocity library, which hasn't had an update since 2003. I think it's a dead project.
I switched to the Castle Project version, and it's much easier -- in fact, it runs much like the examples on the page I linked to. It seems to set intelligent defaults for properties. I can initialize it without any properties set, but the template directory defaults to ".", so I generally set that one (do it before running "init").
To get the correct DLL, you need to download the latest NVelocity release (as of this writing it's 1.1).
Castle Project Download Page
You need to include the following files in your assembly, and make sure that their type is set to "Resource"
src\Runtime\Defaults\directive.properties
src\Runtime\Defaults\nvelocity.properties
These will then be found by ResourceLocator
src\Runtime\Resource\Loader\ResourceLocator.cs
If you get an exception on GetManifestResourceNames() as I did when trying to run Dvsl, then try modifying the ResourceLocator constructor to catch and ignore the error since the required files are in your local assembly (if you included them above) and the exception is only thrown by external assemblies (no idea why).
foreach(Assembly a in assemblies) {
String prefix = a.FullName.Substring(0,a.FullName.IndexOf(",")).ToLower();
try
{
String[] names = a.GetManifestResourceNames();
foreach (String s in names)
{
if (s.ToLower().Equals(fn) || s.ToLower().Equals(prefix + "." + fn))
{
this.filename = s;
assembly = a;
isResource = true;
}
}
} catch {
}
}

Resources