GEMVC is now being used at JSC within the astromaterials department to create a common framework for all their curatorial applications! Their principal developer even converted my supplied demo to all Flex 4 which will be updated in the near future. Thanks Nancy!
In the last release I added a stupid bug which has now been corrected. I also added an IMVCApplication class which you can use in your Flex 4 projects to get rid of the Flex 4 compiler error that occurs when you reference MVCApplication directly in your files.
MVCSparkApplication was added to the framework for your Flex 4 Spark applications to extend. It functions the same way as the MVCApplication class for Flex 3. The Ant build files for the library and the demo were modified to support building either Flex 3 or Flex 4 with Flex Builder or Flash Builder.
Also, a minor change was made such that you can now pass in the location of your services.xml file (or even pass in the stream yourself, all optional of course) instead of the default config/services.xml.
All the features blogged up to this point have now been placed in a downloadable official release. The release zip contains a pre-compiled gemvc.swc, generated asdocs, and pre-compiled demo application.
This release has a completely rewritten (and much much nicer looking) doc file explaining all the new features.
GEMVC has become more than just an MVC framework. With the additional support of Web Services, HTTP services, messaging, watchable events, and logging it is growing into a more full featured Flex Application framework. Down the road I expect to add custom classes for myself and others to support automatically loaded configuration files, help files, and anything else that makes sense. Any ideas are always welcome.
GEMVC is now being used by the astromaterials division, engineering directorate, Altair program, and ISS here at Johnson Space Center. Its usage continues to grow so download the distribution and let me know what you think!
I have finally gotten around to creating a simple demo application that illustrates the majority of GEMVC's features. It is in the demoapp directory off the main trunk. You can create a flex project to build it or if you have ant you can use the included build.xml file (see comments in build file). GEMVC also has its own build.xml file as well.
The Demo uses ColdFusion for the backend remote service and assumes gemvc is checked out into the web root or there is a CF mapping for gemvc. The Demo also illustrates the use a dynamic tree that uses GEMVC services to load each branch upon opening.
GEMVC 1.5 official release is imminent.
The ability to send headers for AMF remoting calls is supported in the lower level flex classes but not exposed in the RemoteObject class. GEMVC now includes (in the trunk of SVN) its own extension of the RemoteObject and Operation classes that allow you to set these headers. All you have to do is set the headers global on your AMF Service or set them on the MVCAMFCommandInfo class when you call your remote service. One caveat though: These headers are not placed in the HTTP headers, they are actually encoded in the AMF packet (why?) so your backend AMF gateway must be able to retrieve them. With Coldfusion 8 I have not been able to access these headers but I have included them anyway in case other configurations can.
For those of you who want to use the Flex Logging framework to send your log messages to a remote service you can now do it by simply referencing the "gemvc" filter like so:
myLogger = Log.getLogger("gemvc"); myLogger.info("this is a log message");
the message will be redirected to any log services you may have set up on the server side (see previous blog post).
The old logging methods on the MVCApplication class are still there, the only difference being is that they now use the Flex Logging Levels as well (mx.logging.LogEventLevel). These levels are converted to the equivalents that the backend service uses which may be different. In your logging service entry in your services.xml you will also need to add a mapping to the pre-defined service log levels like so:
<LOGGINGSERVICE ALIAS="log" SERVICE="myLogger" ENDPOINT="remoteLog" FATAL_LEVEL="0" ERRORLEVEL="1" WARNLEVEL="2" INFOLEVEL="3" DEBUGLEVEL="4" TRACELEVEL="5"/>
If you are using the MVCAMFService or MVCWebService you can now use a MVCAMFServiceInfo class or MVCWebServiceInfo class when calling a service method to provide additional parameters, such as showBusyCursor, on a method-by-method basis. They mimic the options in the AMFOperation and WebServiceOperation classes. Check out the changes from the trunk. If anyone wants a pre-built swc let me know. I have been waiting to do another release until I added a demo application (I actually have one that is built on an application framework on top of GEMVC but it relies on a SQL-Server db).
If you ever have multiple events that run simultaneously on common data or GUI controls (for example manipulating multiple tree controls all bound to the same model variable) you have wait until one event is finished before executing the other. Previously, the only way to do this was to have your event handlers set a global flag and your event that dispatched the events must check this flag and then use callLater to keep looping until the flag is set. Now, GEMVC includes a MVCWatchableEvent class that all your events can extend. In your event handlers you can now automatically watch an event for it to complete and then perform further actions. You only need change your dispatchEvent call in the calling event handler and place a done() call in the event that you are watching when the event processing is complete. For example, I have an event handler that among other things uses a shared object to restore the state of various trees in the application. Since I have multiple trees that all share the same data provider they have to be done sequentially. So inside handleEvent() of my event I call:
var ev:ExpandHierarchyEvent = new ExpandHierarchyEvent(model.savedState.data.savedInfo);
Inside my ExpandHierarchyEvent I place a call to done() when my event completes normally.
Make sure both events extend the MVCWatchableEvent class.
Update your code from the trunk to get the new change.
I have added support for the HTTPService and WebService Flex tags as their own gateways in the GEMVC trunk. I have not fully tested them so will document more about them when they have but you can see from the service locators and the gateways what the syntax is and what additional methods are available.
The CommandInfo class has had two additional properites added: objectToEnableOnFault and objectToEnableOnResult. With these you can disable controls that activate events inside their events so a user cannot click the control twice (or technically and entire window or pane) while it is still processing. So inside my handleEvent the first thing I do is say: target.enabled = false (you can also explicity list the control you want to disable with context.mycontrol.enabled = false, but using the control that dispatched the event is cleaner) then before each service call I use code like: var info:MVCServiceInfo = new MVCServiceInfo; info.objectToEnableOnFault = target; That way if an error occurs, gemvc will automatically re-enable the control so you don't have to worry about it. You can also set info.objectToEnableOnResult = target if you want your control automatically re-enabled because your event is complete. Otherwise you add the line at the end of your event before your last service call. Sometimes you may have to set target.enabled = true yourself at the end of your event as well if you have a case where based upon on a condition you call a service or you just exit. I have seen in my applications where if you select GUI controls too fast errors can result. This is most critical with events that update the db but I have also used it on selection events that change the screen (like filters) because these can cause errors as well if you select them too quick. In order for target.enabled to work you need to make sure that the control you want to disable dispatches the event. Currently, in a combo box, for example, you just say click="dispatchEvent(..)" but now you should say comboboxid.dispatchEvent(...) otherwise you will get the enclosing UIComponent (Canvas, Pane, VBox, etc.) as the target (which is some cases may be a good thing as it is in mine).