Flex Builder Import Web service errors in autogen code - apache-flex

I'm trying to import a web service with the Flex builder feature (Data > Import Web Service). The process proceeds as expected and the classes are generated based on the web service description. The code is generated with compile errors in it though.
There are 20 errors of 2 varieties. I've included a sample of the errors below.
It looks like an error in the auto gen. The auto gen code is trying to dispatch an object of ArrayCollection type. As far I know that isn't possible.
Does anyone have advice or has anyone had similar problems?
Error examples:
1067: Implicit coercion of a value of type net.responsys:ListTablesForCampaignResultEvent to an unrelated type flash.events:Event. Responsys/src/net/responsys ResponsysWS57.as
1119: Access of possibly undefined property headers through a reference with static type net.responsys:ListFolderContentsResultEvent. Responsys/src/net/responsys ResponsysWS57.as

If they are both from an "Event" class, it might be a scoping problem. Try qualifying all of the Event instances, e.g. look into the generated code and wherever you see a flash Event, add flash.events before it.
So a declaration of a flash event might look like:
var event:flash.events.Event
instead of
var event:Event

Related

NullPtr exception while getting country names and country codes in backoffice

After upgrading to Intershop CM 7.10.18.1, we are getting NullPtr exceptions while opening store detail page in backoffice.
ISML template for store details is EditStore_52.isml, which includes ISCountrySelectBox module, which futhermore calls getCountryNamesAndCodes() method.
That method fails with NullPtr exception because of underlined call which returns null.
We are wondering whether this is a bug and whether the intended code was supposed to be:
countriesMap.put(country.getId(), country.getDisplayName(currentLocale));
Please advise on workaround for this situation.
The following is a stack trace for exception.
Intershop delivers address data which can be imported/export through Operations backoffice (e.g. Login at https://localhost:8443/INTERSHOP/web/WFS/SLDSystem using Organization Operations). Out of the box such address data looks like this:
<country>
<id>DE</id>
<custom-attributes>
<custom-attribute dt:dt="string" name="displayName" xml:lang="de-DE">Deutschland</custom-attribute>
<custom-attribute dt:dt="string" name="displayName" xml:lang="fr-FR">Allemagne</custom-attribute>
<custom-attribute dt:dt="string" name="displayName" xml:lang="en-US">Germany</custom-attribute>
</custom-attributes>
</country>
As you can see, it only contains displayName attribute values for de-DE, fr-FR and en-US. A possible workaround in your case would be to export data, include missing attribute values and import it again.
Please note: The work to deliver a fix for this is already in progress. I'm sorry for the inconvenience.
The more convenient way (because editing xml import files is tedious) would be to replace the erroneous implementation using guice module override. In a nutshell:
Copy paste the original implementation of class com.intershop.component.region.internal.geoobject.LocalizedCountryNamesProviderImpl into a class of your own in your custom cartridge. For example: I just created a class AppSFLocalizedCountryNamesProviderImpl in cartridge app_sf_responsive to test this.
Adapt above method according to your needs
Create an override module (See Cookbook - Dependency Injection and ObjectGraphs). Following my example the modules configure operation should look like this:
#Override
protected void configure()
{
bind(LocalizedCountryNamesProvider.class).to(AppSFLocalizedCountryNamesProviderImpl.class);
bindProvider(com.intershop.component.foundation.capi.localization.LocalizedCountryNamesProvider.class)
.to(AppSFLocalizedCountryNamesProviderImpl.class);
}
Publish your cartridge, Restart your server

Metadata for Exceptions thrown by a class

Flash builder lets me insert metadata for events fired by a class, example:
[Event("myEvent", "flash.events.Event")]
public class MyClass() {
}
Is there any way to do the same for Exceptions?
Currently I have checked here, and can't see it documented. Perhaps it's not even worthwhile, what are your thoughts.
There are ways to create your own metadata; and add that into your app at compile time. Use the keep-as3-metadata compiler argument.
It will be up to you to write code to do something with it at runtime; or to build IDE extensions to make use of the code while writing the code.
To access such metadata at runtime, you'll need to perform some type of introspection. Here are some docs and another StackOverflow Question about this.
Many Flex Frameworks make use of custom metadata.

Actionscript Webservice set result format as e4x

I'm trying to use Webservice component in my Flex 4 application.
I need to use this in Actioncript and not using MXML tags.
I'm able to invoke the WSDL operations successfully, but the resultFormat is Object by default.
How do I set it to e4x?
var lookupService:WebService = new WebService();
lookupService.wsdl =url;
lookupService.loadWSDL();
lookupService.doLookup.addEventListener(ResultEvent.RESULT, lookupResultHandler);
lookupService.doLookup.addEventListener(FaultEvent.FAULT, faultHandler);
lookupService.doLookup(lookupString);
I tried to set the format by
lookupService.resultFormat = "e4x";
But this is not working. The calls are not even going through when I do this.
Can you please provide your suggestions for implementing this using AS3?
If you take a look at the two web service classes, you'll realize that resultFormat is not a property on either of them. Resultset is a property on the operations array.
If that doesn't help, you'll have to quantify "not working." What isn't working? Are you getting compile errors? Are you getting runtime errors? IS the data not being returned? Is the data not be returned as XML?
You'll probably have to set this up in MXML and dissect the generated ActionScript to figure out the appropriate AS3 syntax.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/rpc/soap/WebService.html

Setting the WebServiceWrapper endpointURI at run time

I'm in the middle of switching from Flex Builder 3 to Flash Builder 4, and one of the problems I have run into is that support for web services in 4 is substantially different. In both IDE's I am able to import a WSDL for my web service and it will generate the appropriate client classes for communicating with the service. The generated code in each is different.
In my Flex3 code I was able to access the endpointURI property of the mx.rpc.soap.AbstractWebService, but in the Flex4 code that is generated, the new class extends com.adobe.fiber.services.wrapper.WebServiceWrapper which does not have the endpointURI property.
My project has mulitple game servers and the player picks which server they want to play on. In the past if the player wanted server 1, I would set the endpoint URI to http://game1.server.com/service.asmx, and like wise if they wanted server 2 I would set the endpoint to http://game2.server.com/service.asmx.
What am I looking for to accomplish this in Flash Builder 4?
Short Answer:
var s:ClassThatExtendsWebServiceWrapper = new ClassThatExtendsWebServiceWrapper;
s.serviceControl.endpointURI = 'http://service.com/service.asmx';
Long Answer:
Well I finally found a solution. Adobe seems to have made this much harder than it should have been.
Web Service classes that are generated by Flash Builder 4 extend the com.adobe.fiber.services.wrapper.WebServiceWrapper. WebServiceWrapper has a property called serviceControl that can be used to control the service. The problem is that not all the members of serviceControl are accessible at the application code level. Lets assume that I have a web service called GameService. When I use the data tool to connect to the web service by providing a WSDL, Flash Builder will create two classes for me automcatically.
internal class _Super_GameService extends
com.adobe.fiber.services.wrapper.WebServiceWrapper
{ ... }
public class GameService extends _Super_GameService
{}
_Super_GameService contains all the automatically generated code to make calls to the web service. GameService contains no code itself, but unlike _Super_GameService, it is public. The idea here is that any enhancements that we need to make can be made to GameService, then later on if we need to update, _Super_GameService can be regenerated, but out changes to GameService will not be overwritten by the code generation tool.
Now this leads us to usage of these generated classes. Typically all I should have to do is create an instance of GameService and call a method on it. In this example DoSomethingAwesome is a method available on the web service.
var gs:GameService = new GameService();
var token:AsyncToken = gs.DoSomethingAwesome();
Now this will call the service using the URI of the service specified in the WSDL file. In my situation I wanted GameService to connect to a different URI. This should have been simple, but things fell apart.
My first problem was that viewing the documentation on WebServiceWrapper (http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/com/adobe/fiber/services/wrapper/WebServiceWrapper.html) did not render properly in Firefox. So when I was reading the documentation I wasn't getting the full picture. This really needs to be fixed by Adobe.
Viewing the documentation in another browser helped me find out about the serviceControl property of WebServiceWrapper. serviceControl is declared as a mx.rpc.soap.AbstractWebService. AbstractWebService does have an endpointURI property which makes the following code valid.
var gs:GameService = new GameService();
gs.serviceControl.endpointURI = 'http://game1.service.com/GameService.asmx';
The other problem I had is that for some reason the endpointURI property of serviceControl does not appear in the Intellisense context menu. So since I didn't see serviceControl in the online documentation at first, and I didn't see endpointURI in intellisense, I didn't realize the property was there to be set.
If you look at the source for AbstractWebserivce, (http://opensource.adobe.com/svn/opensource/flex/sdk/trunk/frameworks/projects/rpc/src/mx/rpc/soap/AbstractWebService.as) there doesn't seem to be an Exclude tag to explain why endpointURI does not appear in the Intellisense context menu. So I don't know what is going on there.
You should be able to override the endpointURI on the WebService. But I'm not sure where to do that with the generated code since I use <s:WebService/>.
This is the only way I could get it to work, in the generated stub for your service:
import com.adobe.fiber.core.model_internal;
Also:
/**
* Override super.init() to provide any initialization customization if needed.
*/
protected override function preInitializeService():void
{
_needWSDLLoad = false; // to prevent loading the default WSDL
super.preInitializeService();
// Initialization customization goes here
wsdl = "http://localhost/yourservice?wsdl";
_needWSDLLoad = true;
model_internal::loadWSDLIfNecessary();

React to change on a static property

I'm re-writing an MXML item renderer in pure AS. A problem I can't seem to get past is how to have each item renderer react to a change on a static property on the item renderer class. In the MXML version, I have the following binding set up on the item renderer:
instanceProperty={callInstanceFunction(ItemRenderer.staticProperty)}
What would be the equivalent way of setting this up in AS (using BindingUtils, I assume)?
UPDATE:
So I thought the following wasn't working, but it appears as if Flex is suppressing errors thrown in the instanceFunction, making it appear as if the binding itself is bad.
BindingUtils.bindSetter(instanceFunction, ItemRenderer, "staticProperty");
However, when instanceFunction is called, already initialized variables on the given instance are all null, which was the cause of the errors referenced above. Any ideas why this is?
You have 2 options that I am aware of:
Option 1
You can dig into the code that the flex compiler builds based on your MXML to see how it handles binding to static properties. There is a compiler directive called -keep-generated-actionscript that will cause generated files to stick around. Sleuthing through these can give you an idea what happens. This option will involve instantiating Binding objects and StaticPropertyWatcher objects.
Option 2
There is staticEventDispatcher object that gets added at build time to classes containing static variables see this post http://thecomcor.blogspot.com/2008/07/adobe-flex-undocumented-buildin.html. According to the post, this object only gets added based on the presence of static variables and not getter functions.
Example of Option 2
Say we have a class named MyClassContainingStaticVariable with a static variable named MyStaticVariable and another variable someobject.somearrayproperty that we want to get updated whenever MyStaticVariable changes.
Class(MyClassContainingStaticVariable).staticEventDispatcher.addEventListener(
PropertyChangeEvent.PROPERTY_CHANGE,
function(event:PropertyChangeEvent):void
{
if(event.property == "MyStaticVariable")
{
someobject.somearrayproperty = event.newValue as Array;
}
});
I think you need to respond to the "PropertyChanged" event.
If you're going to do that, use a singleton instead of static. I don't think it will work on a static. (If you have to do it that way at all, there are probably a couple ways you could reapproach this that would be better).
var instance:ItemRenderer = ItemRenderer.getInstance();
BindingUtils.bindProperty(this, "myProperty", instance, "theirProperty");
After fiddling with this for a while, I have concluded that this currently isn't possible in ActionScript, not even with bindSetter. It seems there are some MXML-only features of data bindings judging by the following excerpt from the Adobe docs (though isn't it all compiled to AS code anyways)?
You cannot include functions or array
elements in property chains in a data
binding expression defined by the
bindProperty() or bindSetter() method.
For more information on property
chains, see Working with bindable
property chains.
Source: http://livedocs.adobe.com/flex/3/html/help.html?content=databinding_7.html
You can create a HostProxy class to stand in for the funciton call. Sort of like a HostFunctionProxy class which extends from proxy, and has a getProperty("functionInvokeStringWithParameters") which will invoke the function remotely from the host, and dispatch a "change" event to trigger the binding in typical [Bindable("change")] Proxy class.
You than let the HostProxy class act as the host, and use the property to remotely trigger the function call. Of course, it'd be cooler to have some TypeHelperUtil to allow converting raw string values to serialized type values at runtime for method parameters (splitted by commas usually).
Example:
eg.
var standInHost:Object = new HostFunctionProxy(someModelClassWithMethod, "theMethodToCall(20,11)");
// With BindingUtils.....
// bind host: standInHost
// bind property: "theMethodToCall(20,11)"
Of course, you nee to create such a utlity to help support such functionality beyond the basic Flex prescription. It seems many of such (more advanced) Flex bindings are usually done at compile time, but now you have to create code to do this at runtime in a completely cross-platform Actionscript manner without relying on the Flex framework.

Resources