<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Andrei Sabau</title>
	<atom:link href="http://www.asabau.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.asabau.com</link>
	<description>code snippets and libraries</description>
	<lastBuildDate>Wed, 03 Mar 2010 11:44:10 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>ABAP Remote Function Modules &#8211; Business Object Repository</title>
		<link>http://www.asabau.com/2010/02/abap-remote-function-modules-business-object-repository/</link>
		<comments>http://www.asabau.com/2010/02/abap-remote-function-modules-business-object-repository/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 11:26:03 +0000</pubDate>
		<dc:creator>asabau</dc:creator>
				<category><![CDATA[SAP ABAP]]></category>

		<guid isPermaLink="false">http://www.asabau.com/?p=603</guid>
		<description><![CDATA[Custom dictionary structures and remote function calls for getting bapi related data. To not reinvent the wheel, this abap part of the application makes use of existing SAP functions and dictionary structures identified by reviewing the code behind the BAPI transaction.

By running tcode BAPI you can identify the program behind the transaction from the standard [...]]]></description>
			<content:encoded><![CDATA[<p>Custom dictionary structures and remote function calls for getting bapi related data. To not reinvent the wheel, this abap part of the application makes use of existing SAP functions and dictionary structures identified by reviewing the code behind the BAPI transaction.<br />
<span id="more-603"></span><br />
By running tcode BAPI you can identify the program behind the transaction from the standard bottom window options, in this case SAPLSBF_BW. In the SE80 Object Navigator you can look this program and find out it redirects to SBF_BW function group. In this group there are subroutines conveniently named DISPLAY_BAPI, DISPLAY_BO, DISPLAY_DOCU, GET_BASE_TREE_DATA. They provide examples of retrieving repository related data using existing SAP functions.</p>
<p>ZSAB_BAPI_EXPLORER function group contains all the function modules called via SAP Jco. These modules make use of existing SAP functions, further processing the data where needed:</p>
<ul>
<li>ZGET_BAPI_DOCS &#8211; responsible for getting bo/bapi documentation based on object type and method name. Calls existing BAPI_INTERFACE_GETDOCU function.</li>
<li>ZGET_BAPI_INFO &#8211; responsible for getting full bapi info. Calls existing SWO_QUERY_METHOD function.</li>
<li>ZGET_BO_INFO &#8211; responsible for getting full bo info. Calls existing SWO_QUERY_BASEDATA function.</li>
<li>ZGET_BO_LIST &#8211; responsible for getting a table with all objects name and type. Calls existing BAPI_MONITOR_GETLIST function.</li>
<li>ZGET_BO_METHODS &#8211; responsible for getting a table with all object methods. Calls existing SWO_QUERY_API_METHODS function.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.asabau.com/2010/02/abap-remote-function-modules-business-object-repository/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Struts2 Framework with SAP JCo3 &#8211; Business Object Repository</title>
		<link>http://www.asabau.com/2010/02/struts2-framework-business-object-repository/</link>
		<comments>http://www.asabau.com/2010/02/struts2-framework-business-object-repository/#comments</comments>
		<pubDate>Sat, 20 Feb 2010 10:29:44 +0000</pubDate>
		<dc:creator>asabau</dc:creator>
				<category><![CDATA[Java EE]]></category>

		<guid isPermaLink="false">http://www.asabau.com/?p=592</guid>
		<description><![CDATA[Struts2 is being used as the application framework with a series of plugins like the convention and json plugin. Servlets get data from the ABAP stack via SAP Java Connection and return to front-end either json or html content.

Convention plugin.
Compared to default struts2 standard code annotation configuration, convention plugin supports some advanced configuration options. For [...]]]></description>
			<content:encoded><![CDATA[<p>Struts2 is being used as the application framework with a series of plugins like the convention and json plugin. Servlets get data from the ABAP stack via SAP Java Connection and return to front-end either json or html content.<br />
<span id="more-592"></span><br />
<strong>Convention plugin.</strong><br />
Compared to default struts2 standard code annotation configuration, convention plugin supports some advanced configuration options. For each struts2 action class you get to define the parent package, action url mapping(s), multiple result types at global class level or local action method level. All these using java annotations without using xml configurations files like struts.xml.</p>
<p>Here&#8217;s an example of such annotations for the GetBAPIList class, responsible for returning available methods for a given business object.</p>
<pre>
@ParentPackage("json-default")
@Action("get-bapi-list")
@Results({
    @Result(name="success", type="json"),
    @Result(name="error", location="error.jsp")
})
public class GetBAPIList extends ActionSupport {...}
</pre>
<p>The action parent package is defined as json-default, a package containing the json interceptor converting all bean properties to json format automatically. The url mapping for this class is defined as get-bapi-list. The most important feature in this example is the ability to define multiple results for the same action. A json string is returned on success and html content rendered via error.jsp is returned on error. This is not possible with standard struts2 annotations, can only be done via struts.xml configuration file which can dramatically grow in size as the application gets larger and more struts2 actions are defined and configured.</p>
<p><strong>JSON plugin.</strong><br />
With the help of this plugin all action class bean properties are serialized into json format. Something really useful when communicating with the front-end via javascript ajax calls. To have the json interceptor activated for a given action, two elements are required:</p>
<ul>
<li>the action needs to be in a package containing the json interceptor &#8211; most probably the json-default package. </li>
<li>the action needs to define the returned content type as json like in the above annotation example.</li>
</ul>
<p><strong>SAP Java Connector 3</strong><br />
There are two util classes used by all action classes to call abap remote functions:</p>
<ul>
<li>SAPDestinationDataProvider implementing DestinationDataProvider holds all info regarding abap stack and login credentials.</li>
<li>SAPConnection initializes the JCo environment by registering the SAPDestinationDataProvider via com.sap.conn.jco.ext.Environment.registerDestinationDataProvider. Also responsible for returning JCoFunction instances for abap remote functions based on the abap function string name.</li>
</ul>
<p>A typical call looks something like (code from GetBAPIInfo action class):</p>
<pre>
try {
   function = SAPConnection.getFunction("ZGET_BAPI_INFO");
   function.getImportParameterList().setValue("IM_BO_TYPE", objType);
   function.getImportParameterList().
   setValue("IM_METHOD_NAME", methodName);
   function.execute(SAPConnection.dConfig);

   structure = function.getExportParameterList().
   getStructure("EX_BAPI_INFO");
}
catch (JCoException e) {
   addActionError("JCo Error: " + e.getMessage() );
   return ERROR;
}
</pre>
<p>A JCoFunction reference to the corresponding abap remote function is acquired via custom SAPConnection util class. The function gets executed after setting the import parameters. Export parameters hold the function result and can be read via getStructure, getTable, etc.. </p>
<p>In the above case, individual properties from EX_BAPI_INFO are  accessed by structure.getString(&#8221;property_name&#8221;) such as structure.getString(&#8221;OBJTYPE&#8221;).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.asabau.com/2010/02/struts2-framework-business-object-repository/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jQuery FrontEnd &#8211; Business Object Repository</title>
		<link>http://www.asabau.com/2010/02/frontend-business-object-repository/</link>
		<comments>http://www.asabau.com/2010/02/frontend-business-object-repository/#comments</comments>
		<pubDate>Sat, 20 Feb 2010 08:17:28 +0000</pubDate>
		<dc:creator>asabau</dc:creator>
				<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.asabau.com/?p=581</guid>
		<description><![CDATA[The entry point of the application is bor.jsp getting a default struts2 action via convention plugin. It consists of two jQuery components: jsTree and UI Tabs.

jsTree
The business objects are represented as main tree nodes with their bapis as leaf nodes. The main nodes are loaded at startup via GETBOList servlet. Leaf nodes are only loaded [...]]]></description>
			<content:encoded><![CDATA[<p>The entry point of the application is bor.jsp getting a default struts2 action via convention plugin. It consists of two jQuery components: jsTree and UI Tabs.<br />
<span id="more-581"></span><br />
<strong>jsTree</strong><br />
The business objects are represented as main tree nodes with their bapis as leaf nodes. The main nodes are loaded at startup via GETBOList servlet. Leaf nodes are only loaded when a main node gets selected via GetBAPIList servlet. Data for all nodes is loaded via ajax in a json format compatible with the jsTree component. </p>
<p>Example of the json format used:</p>
<pre>
{
   "objType":"BUS4003",
   "treeData":[
      {
            "state":null,"data":"FindDetail",
            "attributes":{"method":"FindDetail","type":"BUS4003"}
      },
      {
            "state":null,"data":"SaveReplica",
            "attributes":{"method":"SaveReplica","type":"BUS4003"}
      },
      {
            "state":null,"data":"Update",
            "attributes":{"method":"Update","type":"BUS4003"}
      }
   ]
}
</pre>
<p>data property is used by jsTree to render text for the current node. state property makes the difference between leaf and non-leaf nodes. attributes properties represent whatever custom data a node holds, in our case business object identified by object type and corresponding bapi identified by method name.</p>
<p>Besides providing the interaction for browsing/selecting business objects and their corresponding bapis, jsTree has another role: it dynamically updates the urls for the Detail and Documentation tabs from UI Tabs. It also reloads the current selected tab with the corresponding new url.</p>
<p><strong>UI Tabs</strong><br />
Contains the Detail and Documentation tabs. Content is loaded via ajax under html format represented by several jsp pages: bapi_info.jsp, bo_info.jsp, generic_docs.jsp. The urls for these two tabs constantly changed based on current bo/bapi selection from jsTree. </p>
<p>The Detail tabs also serves as a place for displaying run-time errors like not being able to connect to the given abap stack.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.asabau.com/2010/02/frontend-business-object-repository/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Struts2 with SAP JCo3 and jQuery &#8211; Business Object Repository</title>
		<link>http://www.asabau.com/2010/02/struts2-with-sap-jco3-and-jquery-business-object-repository/</link>
		<comments>http://www.asabau.com/2010/02/struts2-with-sap-jco3-and-jquery-business-object-repository/#comments</comments>
		<pubDate>Sat, 20 Feb 2010 07:11:19 +0000</pubDate>
		<dc:creator>asabau</dc:creator>
				<category><![CDATA[Java EE]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[SAP ABAP]]></category>
		<category><![CDATA[Showcase]]></category>

		<guid isPermaLink="false">http://www.asabau.com/?p=569</guid>
		<description><![CDATA[// 

Application similar to SAP BAPI transaction, showing various info about existing business objects and their methods (bapis). The end result is an ajax based html front-end capable of displaying the business object repository from an abap stack via java servlets. 
jQuery Front-end
Everything happens in one main html page loading all bapi related content via [...]]]></description>
			<content:encoded><![CDATA[<div id="flowcontainer"><a id="player_bapi_explorer" style="display: block; width: 538px; height: 324px;" href="/video/java/zsab_bapi_explorer.mp4"><img src="/video/java/zsab_bapi_explorer.jpg" alt="Struts2 with SAP JCo3 and jQuery - Business Object Repository" /></a><script type="text/javascript">// <![CDATA[
     flowplayer("player_bapi_explorer", "/swf/flowplayer/flowplayer-3.1.3.swf");
// ]]&gt;</script></div>
<p><span id="more-569"></span><br />
Application similar to SAP BAPI transaction, showing various info about existing business objects and their methods (bapis). The end result is an ajax based html front-end capable of displaying the business object repository from an abap stack via java servlets. </p>
<p><strong>jQuery Front-end</strong><br />
Everything happens in one main html page loading all bapi related content via ajax calls. The bapi tree component gets its data in json format, the detail and documentation sections get their data in html format. jQuery javascript library is being used extensively for both rendering various html elements and ajax data parsing.<br />
<a href="/?p=581">More details</a></p>
<p><strong>Struts2 Framework with SAP JCo3</strong><br />
Struts2 is being used as the application framework with a series of plugins like the convention and json plugin. Servlets get data from the ABAP stack via SAP Java Connector and return to front-end either json or html content. Front-end makes requests via GET parameters.<br />
<a href="/?p=592">More details</a></p>
<p><strong>ABAP Remote Function Modules</strong><br />
Custom dictionary structures and remote function calls for getting bapi related data.<br />
<a href="/?p=603">More details</a></p>
<p>Source code: <a href="/code/java/java_zsab_bapi_explorer.zip">java</a> , <a href="/code/java/abap_zsab_bapi_explorer.zip">abap</a>. Java archive contains both the src files and the deployed webapps directory without struts2 and jco external libraries. ABAP archive contains an SAP transport request with corresponding dictionary structures and function modules.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.asabau.com/2010/02/struts2-with-sap-jco3-and-jquery-business-object-repository/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Build Automation via Ant &#8211; Facebook Photo Gallery</title>
		<link>http://www.asabau.com/2010/02/build-automation-via-ant-facebook-photo-gallery/</link>
		<comments>http://www.asabau.com/2010/02/build-automation-via-ant-facebook-photo-gallery/#comments</comments>
		<pubDate>Sun, 14 Feb 2010 15:14:12 +0000</pubDate>
		<dc:creator>asabau</dc:creator>
				<category><![CDATA[Adobe Flex]]></category>
		<category><![CDATA[Build Automation]]></category>

		<guid isPermaLink="false">http://www.asabau.com/?p=551</guid>
		<description><![CDATA[Using ant macros for extracting swf libary files from the swc runtime shared libraries, compiling the external swf modules, generating the html wrappers. Flex Ant tasks have priority over corresponding exec or java commands. This is the case for compc and mxmlc compilers. For extracting swf libraries from rsls or for generating custom html wrappers, [...]]]></description>
			<content:encoded><![CDATA[<p>Using ant macros for extracting swf libary files from the swc runtime shared libraries, compiling the external swf modules, generating the html wrappers. Flex Ant tasks have priority over corresponding exec or java commands. This is the case for compc and mxmlc compilers. For extracting swf libraries from rsls or for generating custom html wrappers, exec commands are used because there are no corresponding flex ant tasks.<br />
<span id="more-551"></span><br />
There are three related build files: build.properties, asabau_cg3_fb_config.xml, build.xml.</p>
<p><strong>build.properties</strong><br />
Defines build properties used by build.xml including paths for flex sdk, flex compilers, external modules and libraries. FLEX_HOME stands out from the low-case naming convention and is required by all flex ant tasks:</p>
<pre>flex.sdk = C:/flex_sdks/3.4.1
FLEX_HOME = ${flex.sdk}
flex.framework = ${flex.sdk}/frameworks/libs

flex.mxmlc = ${flex.sdk}/bin/mxmlc.exe
flex.compc = ${flex.sdk}/bin/compc.exe
flex.asdoc = ${flex.sdk}/bin/asdoc.exe
flex.optimizer = ${flex.sdk}/bin/optimizer.exe
flex.digest = ${flex.sdk}/bin/digest.exe

project.dir = ${basedir}/..
...</pre>
<p><strong>asabau_cg3_fb_config.xml</strong><br />
Contains additional compiler options when using mxmlc or compc flex ant tasks. Used for specifying metadata tags required by the Parsley framework that if not listed here won&#8217;t make it into the compiled swf/swc file. Extract from this file:</p>
<pre>&#60;keep-as3-metadata>
	...
	&#60;name>Metadata&#60;/name&#62;
	&#60;name&#62;AsyncInit&#60;/name&#62;
	&#60;name&#62;ManagedEvents&#60;/name&#62;
	&#60;name&#62;Command&#60;/name&#62;
	&#60;name&#62;CommandResult&#60;/name&#62;
	&#60;name&#62;CommandError&#60;/name&#62;
	&#60;name&#62;CommandStatus&#60;/name&#62;
	...
&#60;/keep-as3-metadata&#62;</pre>
<p><strong>build.xml</strong><br />
Main build file. Contains tasks for compiling each external module and library, as well as a compile_main_launcher task putting it all together:</p>
<pre>&#60;target
  name="compile_main_launcher"
  depends="init, compile_api, copyRSLs"
  &#62;
  &#60;compile_module
    input.file="${asabau_cg3_fb_authentication.src.dir}/
    AuthenticationModule.mxml"
    output.file="${release.dir}/AuthenticationModule.swf"
    /&#62;
  &#60;compile_module
    input.file="${asabau_cg3_fb_album.src.dir}/AlbumModule.mxml"
    output.file="${release.dir}/AlbumModule.swf"
    /&#62;
  &#60;compile_module
    input.file="${asabau_cg3_fb_shell.src.dir}/MainLauncher.mxml"
    output.file="${release.dir}/MainLauncher.swf"
    /&#62;

  &#60;custom_html_wrapper
    template.dir="${asabau_cg3_fb_shell.src.dir}/../html-template"
    input.file="index.template.html" output.file="MainLauncher.html"
    application="main"
    title="Facebook Photo Gallery Using Parsley Application Framework"
    swf="MainLauncher" width="1000" height="700" bgcolor="#FFFFFF"
    /&#62;
&#60;/target&#62;</pre>
<p>Before starting to compile the main launcher, some preparation tasks are performed via depends property:
<ul>
<li>init &#8211; deletes and recreates the app release directory</li>
<li>compile_api &#8211; compiles asabau_cg3_fb_api into an external swc file</li>
<li>copyRSLs &#8211; generates and copies all required rsls to the project release directory</li>
</ul>
<p>A .swf runtime shared library (rsl) is generated from a swc file by the create-rsl ant macro. A swc file is just an archive containing among other things a library.swf file. This library.swf file represents the runtime-shared-library. One needs to extract library.swf, optimize it to minimize size, update its flex digest signature to prevent runtime conflicts between libraries.</p>
<pre>&#60;macrodef name="create-rsl"&#62;
  &#60;attribute name="rsl-dir"/&#62;
  &#60;attribute name="swc-dir"/&#62;
  &#60;attribute name="swc-name"/&#62;

  &#60;sequential&#62;
    &#60;unzip src="@{swc-dir}/@{swc-name}.swc" dest="@{rsl-dir}" &#62;
      &#60;patternset&#62;
        &#60;include name="library.swf" /&#62;
      &#60;/patternset&#62;
    &#60;/unzip&#62;

    &#60;exec executable="${flex.optimizer}" failonerror="true"&#62;
      &#60;arg line="-input @{rsl-dir}/library.swf
      -output @{rsl-dir}/@{swc-name}.swf"/&#62;
      &#60;arg line="-load-config ${basedir}/asabau_cg3_fb_config.xml"/&#62;
    &#60;/exec&#62;

    &#60;delete file="@{rsl-dir}/library.swf"/&#62;

    &#60;exec executable="${flex.digest}" failonerror="true"&#62;
      &#60;arg line="-digest.rsl-file  @{rsl-dir}/@{swc-name}.swf"/&#62;
      &#60;arg line="-digest.swc-path  @{swc-dir}/@{swc-name}.swc"/&#62;
    &#60;/exec&#62;
    &#60;/sequential&#62;

&#60;/macrodef&#62;</pre>
<p>External modules are compiled using an ant macro like the one below. This makes sense because all external modules need to be compiled against the same external libraries, using the same method.</p>
<pre>&#60;compile_module
    input.file="${asabau_cg3_fb_authentication.src.dir}/
    AuthenticationModule.mxml"
    output.file="${release.dir}/AuthenticationModule.swf"
/&#62;</pre>
<p>A custom html wrapper macro &#8211; custom_html_wrapper &#8211; is being used because Flex 3 html-wrapper task doesn&#8217;t support generation of custom html code. In this case, swfobject and facebook html/javascript code is required in the main html launcher. This macro just parses an html file replacing all html occurrences of several key elements like ${swf}, ${title} with the input parameters. These elements are found in the exact same form in standard flex html-template/index.template.html files.</p>
<pre>&#60;custom_html_wrapper
    template.dir="${asabau_cg3_fb_shell.src.dir}/../html-template"
    input.file="index.template.html"
    output.file="MainLauncher.html"
    application="main"
    title="Facebook Photo Gallery Using Parsley Application Framework"
    swf="MainLauncher" width="1000" height="700" bgcolor="#FFFFFF"
/&#62;</pre>
<p>This post is part of <a href="/?p=489">Facebook Photo Gallery</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.asabau.com/2010/02/build-automation-via-ant-facebook-photo-gallery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Facebook.Connect Javascript-Flex Communication &#8211; Facebook Photo Gallery</title>
		<link>http://www.asabau.com/2010/02/facebook-connect-javascript-flex-communication-facebook-photo-gallery/</link>
		<comments>http://www.asabau.com/2010/02/facebook-connect-javascript-flex-communication-facebook-photo-gallery/#comments</comments>
		<pubDate>Sun, 14 Feb 2010 10:18:27 +0000</pubDate>
		<dc:creator>asabau</dc:creator>
				<category><![CDATA[Adobe Flex]]></category>

		<guid isPermaLink="false">http://www.asabau.com/?p=524</guid>
		<description><![CDATA[Facebook actionscript API can only make login calls by opening a new browser page to an official Facebook login page. To avoid this redirection, Facebook javascript API is used for login/logout operations. It has the advantage of presenting dhtml login/logout popups over the flex app without any user redirection. The flex app still controls all [...]]]></description>
			<content:encoded><![CDATA[<p>Facebook actionscript API can only make login calls by opening a new browser page to an official Facebook login page. To avoid this redirection, Facebook javascript API is used for login/logout operations. It has the advantage of presenting dhtml login/logout popups over the flex app without any user redirection. The flex app still controls all the authentication logic with the difference that login/logout calls are done using javascript functions via ExternalInterface.<br />
<span id="more-524"></span><br />
<strong>Overview.</strong><br />
Once the flex application initializes, a javascript check is being made to determine whether or not a valid Facebook session already exists for the current user. If it does, information about the user (name, public albums and photos) can automatically be retrieved by the flex app and instead of a login button the user gets a &#8220;welcome user&#8221; message. If a valid Facebook session doesn&#8217;t exist for the current user, a Facebook login button is being displayed. Both login and logout buttons from the flex app invoke corresponding javascript calls since the two operations are conducted via the Facebook javascript API.</p>
<p><strong>Detailed steps.</strong><br />
FB.Facebook.init from the javascript API is responsible for checking whether or not a Facebook session is already active for the current user. In a standard javascript scenario, this function is being called automatically after the html page finishes loading. In our case, FB.Facebook.init is called from the flex app once all its external modules and runtime shared libraries are loaded.</p>
<p>From asabau_cg3_fb_shell, MainLauncher.mxml</p>
<pre>// flex app is ready now, time to init the FB session
dispatchEvent(SessionEvent.newInitEvent());</pre>
<p>This session event is handled in asabau_cg3_fb_api, FBSession.as</p>
<pre>[MessageHandler(selector="fbInit")]
public function init():void {
	ExternalInterface.addCallback("sessionUpdate", sessionUpdate);
	ExternalInterface.call("init", API_KEY);
}</pre>
<p>First we register for the app swf object a sessionUpdate javascript handler. When sessionUpdate function is called on the embedded html swf object in javascript, a corresponding sessionUpdate function from FBSession.as will be called in flex. This sessionUpdate function will be called every time the Facebook session changes its status via init, login, logout Facebook operations.</p>
<p>Once the flex app has the means to listen for javascript Facebook session update events, it triggers a Facebook session initialization by calling javascript function init</p>
<pre>function init(api_key) {
    FB_RequireFeatures(["Api", "Connect"], function() {
        FB.Facebook.init(
            api_key,
            'xd_receiver.htm',
            {
                "ifUserConnected": sessionUpdate,
                "ifUserNotConnected": sessionUpdate
            }
        );
    });
}</pre>
<p>Results from the FB.Facebook.init javascript call are handled in javascript function sessionUpdate, responsible for propagating the changes to the flex app.</p>
<pre>function sessionUpdate() {
	swfobject.getObjectById("flashContent").sessionUpdate(
		sessionInfo()
	);
}</pre>
<p>The flex app receives a sessionInfo object constructed in javascript using the Facebook actionscript API</p>
<pre>function sessionInfo() {
	var info = FB.Facebook.apiClient.get_session();
	return info;
}</pre>
<p>FBSession.as from asabau_cg3_fb_api determines if a valid javascript Facebook session has been established in its corresponding sessionUpdate actionscript function. If it does, based on the established javascript session an actionscript session is created that will be used for all Facebook related calls &#8211; getting user info, public albums and photos.</p>
<pre>public var facebook:Facebook;
public var session:WebSession;

public function sessionUpdate(sessionData:Object):void {
	...
	session = new WebSession(
		API_KEY,
		sessionData.secret,
		sessionData.session_key
	);
	session.facebook_internal::_uid = sessionData.uid;

	facebook.startSession(session);
	session.verifySession();
</pre>
<p>SessionController.as from asabau_cg3_fb_authentication handles all actionscript session events including FacebookEvent.CONNECT.</p>
<pre>protected function onConnect(event:FacebookEvent):void {
	...
	dispatchEvent(UserDataEvent.newLoadEvent());
	...
}</pre>
<p>This UserDataEvent signals the flex app has reached a state when it&#8217;s now possible to query the Facebook servers via Facebook actionscript API to get user first and last name, public albums and photos, etc.</p>
<p>Login and logout events are being dispatched via the Parsley framework eventually reaching FBSession.as</p>
<pre>public function login():void {
	ExternalInterface.call("connect");
}

public function logout():void {
	ExternalInterface.call("logout");
}</pre>
<p>The corresponding javascript calls making use of Facebook Connect javascript API:</p>
<pre>// trigger connect popup
function connect() {
	FB.ensureInit( function() {
		FB.Connect.requireSession(null, true);
	});
}

// terminate all FB sessions
function logout() {
	FB.Connect.logout();
}</pre>
<p>This post is part of <a href="/?p=489">Facebook Photo Gallery</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.asabau.com/2010/02/facebook-connect-javascript-flex-communication-facebook-photo-gallery/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Parsley 2.2 and Spicelib 2.2 Implementation Details &#8211; Facebook Photo Gallery</title>
		<link>http://www.asabau.com/2010/02/parsley-2-2-and-spicelib-2-2-implementation-details-facebook-photo-gallery/</link>
		<comments>http://www.asabau.com/2010/02/parsley-2-2-and-spicelib-2-2-implementation-details-facebook-photo-gallery/#comments</comments>
		<pubDate>Sat, 13 Feb 2010 13:33:26 +0000</pubDate>
		<dc:creator>asabau</dc:creator>
				<category><![CDATA[Adobe Flex]]></category>

		<guid isPermaLink="false">http://www.asabau.com/?p=499</guid>
		<description><![CDATA[All flex applications are event driven. With Parsley messaging framework managing events is a lot more easier. You don&#8217;t have to manually dispatch and listen for events. Using Parsley defined metadata tags the code becomes cleaner, shorter, more easier to understand and maintain. Add Parsley Inversion of Control (IOC) framework and you have the means [...]]]></description>
			<content:encoded><![CDATA[<p>All flex applications are event driven. With Parsley messaging framework managing events is a lot more easier. You don&#8217;t have to manually dispatch and listen for events. Using Parsley defined metadata tags the code becomes cleaner, shorter, more easier to understand and maintain. Add Parsley Inversion of Control (IOC) framework and you have the means to easily create highly decoupled applications. Below steps take AlbumModule as a reference.<br />
<span id="more-499"></span><br />
<strong>1. Configuration.</strong><br />
As a first step, Parsley needs to know which classes it should manage via the IOC Container. For Facebook Photo Gallery this is done via mxml configuration files. Each module has its own configuration file and so does each separate module launcher, including the main launcher from the asabau_cg3_fb_shell project.</p>
<p>For example, for the AlbumModule we have the following mxml configuration files:</p>
<ul>
<li>AlbumModuleLauncherContext.mxml &#8211; Used by AlbumModuleLauncher for separate testing of AlbumModule. Contains objects outside AlbumModule needed to initialize the AlbumModule.</li>
<li>AlbumContext.mxml &#8211; Contains objects needed by AlbumModule.</li>
</ul>
<p>From AlbumContext.mxml:<br />
<code>&lt;pres:AlbumPM /&gt;<br />
&lt;pres:PhotoPM /&gt;<br/><br />
&lt;domain:AlbumList /&gt;<br />
&lt;domain:PhotoList /&gt;<br />
&lt;fb_domain:AlbumData /&gt;<br />
&lt;fb_domain:PhotoData /&gt;<br/><br />
&lt;app:LoadAlbumListCommand /&gt;<br />
&lt;app:LoadPhotoListCommand /&gt;<br />
&lt;app:SavePhotoCaptionCommand /&gt;<br />
</code></p>
<p>All of the above objects are now part of the IOC Container and will be managed by the Parsley framework. There are presentation models, model objects, command classes. All can now make use of Parsley dependency injection and messaging framework.</p>
<p><strong>2. Initialization</strong><br />
Via mxml tags, in each module top view, we specify the configuration file context location via ContextBuilder and then initialize the IOC Container via Configure.<br />
<code>&lt;parsley:ContextBuilder config="{AlbumContext}" id="context"  /&gt;<br />
&lt;parsley:Configure  /&gt;</code></p>
<p>The IOC Container configuration happens before creationComplete, this is a useful information when you want to dispatch framework registered events from the parent container to the child module. Using the &lt;parsley:Configure  /&gt; tag you know for sure that when creationComplete is triggered, IOC container and all its objects have been initialized. It&#8217;s now safe to dispatch events in the parent container, they&#8217;ll be handled in the child module.</p>
<p><strong>3. Dependency Injection</strong><br />
Each object from the IOC Container can make use of the [Inject] metadata tag and most of them do. From LoadAlbumListCommand:<br />
<code>[Inject]<br />
private var fbSession:FBSession;</code></p>
<p>This injects a FBSession singleton in the command class. Other classes injecting the same variable type FBSession will get the same singleton instance. This is the default behavior, but you can have non singleton variables if needed. For all Album and Authentication classes, fbSession represents the same Facebook session used in all Facebook calls.</p>
<p>Parsley IOC framework is responsible for adding the singleton behavior to the FBSession class at runtime. FBSession class code doesn&#8217;t contain any singleton specific code.</p>
<p><strong>4. Messaging</strong><br />
For Parsley framework to handle app custom events you need to mark them as managed events in the object dispatching them, object that is part of IOC Container. This way sender and receiver objects don&#8217;t need to know each other, messaging takes place in a decoupled manner. You don&#8217;t have to use any specific Parsley methods to dispatch events, you can do it with the standard actionscript dispatchEvent assuming at some point the sender object extends EventDispatcher. Because of this, we can talk about sender and receiver objects being decoupled from the framework as well.</p>
<p>From AlbumPM, presentation model for the view displaying the end user photo albums:<br />
<code>[Event(name="albumSelect", type="com.asabau.facebook.album.AlbumEvent")]<br />
[ManagedEvents("albumSelect")]<br />
public class AlbumPM extends EventDispatcher</code></p>
<p>From its selectAlbum function</p>
<pre>public function selectAlbum(album:AlbumData):void {
	....
	dispatchEvent(AlbumEvent.newSelectEvent(album));
	...
}</pre>
<p>All event handling is done in asynchronous Command classes via Command, CommandResult, CommandError tags. Intercept tag is being used to override the Command classes and &#8220;fake&#8221; CommandResult data. This can be useful when launching standalone modules that rely on other modules for some features. Like AlbumModule requiring AuthenticationModule to establish a Facebook connection before getting the album list. Via Intercept, we can supply a static album list data set to AlbumModule and not rely on AuthenticationModule.</p>
<p>From LoadPhotoListCommand, command triggered when above AlbumEvent.newSelectEvent gets dispatched:</p>
<pre>[Command(selector="albumSelect")]
public function execute(event:AlbumEvent):Task {
	...
	return Task;
}</pre>
<p>CommandResult and CommandError are invoked automatically by the Parsley framework when the async call represented by the Task object has completed.</p>
<pre>[CommandResult(selector="albumSelect")]
public function resultHandler(task:FBCallTask, event:AlbumEvent):void

[CommandError(selector="albumSelect")]
public function faultHandler(
	faultEvent:FaultEvent,
	trigger:AlbumEvent):void</pre>
<p><strong>5. Spicelib Task Framework</strong><br />
With Parsley 2.2 Command classes like the one above can now make use of both AsyncToken and Task objects to identify asynchronous calls. This makes a lot of sense because only a few flex async operations are capable of returning AsyncToken objects like, for example, HTTPService.send method.</p>
<p>The Facebook actionscript API doesn&#8217;t contain any methods returning AsyncTokens when doing asynchronous server calls. The Task object helps tremenduously here, we get to have the same AsyncToken functionality for any custom async operation.</p>
<p>From FBCallTask<br />
<code>import org.spicefactory.lib.task.Task;<br />
public class FBCallTask extends Task</code></p>
<preprotected override function doStart () : void {
	...
	parentCall.addEventListener(FacebookEvent.COMPLETE, parentCallComplete);
}</pre>
<pre>private function parentCallComplete(event:FacebookEvent):void {
	if (event.success) {
		...
		complete();
	}
	else {
		error(...)
	}
}
</pre>
<p>First we override the default doStart Task method, defining how the async operation starts and adding event complete handlers to it. The doStart command gets invoked automatically by the Parsley framework responsible for handling the Command class. When the async operation has completed, we either call Spicelib Task complete or error methods responsible for dispatching the corresponding events. These events are managed by the Parsley Command class where the Task object in question is being used. Based on event type either CommandResult or CommandError gets triggered.</p>
<p>This post is part of <a href="/?p=489">Facebook Photo Gallery</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.asabau.com/2010/02/parsley-2-2-and-spicelib-2-2-implementation-details-facebook-photo-gallery/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

