Global View Sample

The globalview-ui plugin adds 2 global views, one accessible from a Home page shortcut and the other one from an Administration inventory node. Each view calls a java service implemented in globalview-service, EchoService and GlobalService. GlobalService implements data persistence in a local file. The sample also demonstrates the use of an ExceptionTranslatorService for converting a Java exception into a Flex error.

globalview-ui

Usage

The plugin globalview-ui requires globalview-service to run. Import both projects in Eclipse, build and deploy the bundles to the server, putting globalview-service first. Start a client session, you should see a Global App button in the Home view, under Monitoring. Click on it to open the Global App "Main View". Click the Hello button to call the java service returning "World!".

You can switch to the Settings View either by clicking the link with that name, or switching to the Administration area in the LHS navigator where a Global App > Settings entry is visible.

Once in the Settings View type change some values and click Update. This calls GlobalService on the java side to save the new settings in a local file on the server side, i.e. settings are persistent accross user sessions or even server restarts.

Implementation notes

In plugin.xml: extension points vise.home.shortcuts and vise.global.view are used to add a Home shortcut and global views as in the helloworld sample. In addition this sample uses vise.navigator.nodespecs twice to add 2 nodes to the LHS inventor: first to create the Global App category, second to add Settings underneath. That node opens the Settings View by referencing its extension id in <navigationTargetUid>.

In MainViewMediator.as: this class dispatches a com.vmware.ui.events.NavigationRequest event to jump to another extension view. Notice that the event metadata must be added at the top of the class, otherwise the framework won't take that event into consideration!

In SettingViewMediator.as: this class also uses a NavigationRequest event to jump back to the MainView. The view is initialized with a proxy call to read the settings from the server _proxy.getSettings(onGetSettingsResult). The result is a GlobalSettings object serialized from Java to Flex, which is assigned directly to the settings field of the view.

In GlobalSettings.as: notice the [RemoteClass] metadata tag which allows to register the equivalent java class with Flex to preserve type information during serialization.

In EchoServiceProxy.as, GlobalServiceProxy.as: each proxy class declares the Java service being used and the methods to call. This is the standard way to leverage the platform's BaseProxy.

SettingEnum.as shows how to implement an ActionScript type that maps to a Java enum.

Other configuration files need to be setup properly for the java service calls to work: WEB-INF/web.xml, WEB-INF/spring/bundle-context.xml containing the OSGI references, and META-INF/MANIFEST.MF adding com.vmware.samples.globalview to its Import-Packages. See Calling a Java service from the client in the SDK Tutorial for a more detailed discussion.

For more on localization implementation in this sample, see helloworld-i18n-ui.

globalview-service

Description

This project implements the two services used by globalview-ui, EchoService and GlobalService, as well as the ExceptionTranslatorService used to convert Java exception. They are exposed as OSGI services and are available to any bundle on the server.

Implementation notes

The public interfaces EchoService and GlobalService allow to separate the services' API from their implementation. It is not required to use interfaces for a java service but it's a good pattern to follow, it also helps for code maintenance and for testing.

EchoServiceImpl.java doesn't do much since it returns the message sent from the client. In a real world application your java services will probably be more complex but remember that they must remain light-weight processes, and be used only as "pass-through" to communicate between the client and vCenter Server or other data sources.

GlobalServiceImpl.java is more interesting as it implements data persistence in a local properties file. However, data persistence on the VWC server is only recommended for simple configuration data, anything more complex should be handled by calling a back-end server or database.

SettingEnum.java is a java enum that maps to SettingEnum.as on the FLex side.

Notice that the project contains a lib folder with additional libraries required for compilation. None of these bundles need to be added to plugin-package.xml as they are already present in the server repository.

The configuration files required to publish the two java services correctly are:

Exercises

  1. Change GlobalServiceImpl to persist settings in an XML format or to a back-end database.
  2. Change GlobalSettings to a more complex object to see how the ActionScript-Java serialization works.

Exception Translation from Java to Flex

This section describes the steps used in this sample to convert Java exceptions when using BlazeDS. You can apply the same configuration in your plugin.

To quote the SpringSource doc on custom exception translators: "In order to propagate useful information back to the Flex client when an exception occurs on the server, the original exception must be translated into an instance of flex.messaging.MessageException. If special translation logic is not applied, a generic "Server.Processing" error will propagate to the client that doesn't give the client the chance to reason on the real cause of the error to take appropriate action. Special exception translators are configured by default for transforming Spring Security exceptions into an appropriate MessageException, but it could also be useful to provide custom translation for your own application-level exceptions.""

Service layer configuration

The following changes should be made to the Java plugin.

  1. Add the ExceptionTranslatorService class as shown in this sample.
  2. Add the spring-flex-core osgi library and two BlazeDS core libraries to the project in order to compile ExceptionTranslatorService. (You can keep a copy of spring-flex-core-1.5.2.RELEASE.jar, blazeds-core-4.0.1.21287.jar and blazeds-common-4.0.1.21287.jar in the project's lib folder, but there is no need to include those libraries with the plugin package because they are already part of Virgo.
  3. Define the bean in bundle-context.xml and the osgi:service in bundle-context-osgi.xml as for any service:
    <bean name="ExceptionTranslatorServiceImpl" class="com.vmware.samples.globalview.ExceptionTranslatorService"/>
    
    <osgi:service id="ExceptionTranslatorService" ref="ExceptionTranslatorServiceImpl"
            interface="org.springframework.flex.core.ExceptionTranslator" />
    
  4. Finally the plugin's MANIFEST.MF must import the right packages:
     org.osgi.framework,
     org.springframework.flex.core,
     flex.messaging

UI layer configuration

The following changes should be made to the UI Flex plugin.

  1. Edit the plugin's bundle-context.xml to add an osgi:reference to the new ExceptionTranslatorService, and to include a flex:exception-translator parameter to the message-broker configuration:
       <flex:message-broker id="globalview-ui-broker" services-config-path="/WEB-INF/flex/services-config.xml">
          <flex:exception-translator ref="ExceptionTranslatorService"/>
          <flex:remoting-service default-channels="secure-amf, amf" />
       </flex:message-broker>
       
       <osgi:reference id="ExceptionTranslatorService"
          interface="org.springframework.flex.core.ExceptionTranslator"
          bean-name="ExceptionTranslatorServiceImpl"/>
  2. In the callback from the plugin's java service event.error.message contains the error message that was set in ExceptionTranslatorService.translate().
  3. If you want to detect specific exceptions and process them differently in the UI then use event.error.faultCode which contains the exception class name. You could have application-defined or runtime exceptions which require more meaningful error messages. See how the callback SettingViewMediator.onSetSettingsResult() handles FileNotFoundException.

Testing your exception translator

You should always test the translator configuration and your UI error handling code with some generated real or fake exception. In the case of globalview it's easy to force a FileNotFoundException: update the settings once to create the file C:\ProgramData\globalview\settings.properties, and then make it read-only. The next time you update the settings you should see the error message below.

See also: Other samples - SDK Tutorial - FAQs - Flex API docs - Java API docs