Flex OLAP Benchmarks

I ran some benchmarks for the OLAP components in Flex. The OLAP components allow you to perform you’re OLAP operations client side out of the box. You *can* utilize the SDK interfaces and move your processing to the backend, should you have too much data for the browser.

That said, the benchmarks below should help define the line for “too much data.”

Record Structure:

Course:String
School:String
GradeLevel:String
SubjectArea:String
Grade:Number (Our measure)

Records / Processing Time (s)

1,000 / 3 sec
5,000 / 12 sec
10,000 / 22 sec
15,000 / 33 sec
20,000 / 43 sec

The processing times listed above are for the *client* side processing time. The data was loaded from the server before starting the benchmark.

I ran the benchmarks at various rollup depths (multiple hierarchies) which the components actually handled very well, the processing time was not significantly affected.

Extending the dataset to 125K+ records caused errors with the script timeouts occurring.

For datasets above 5-10K records, I’d suggest moving the processing to the server and passing the results to the UI. (assuming you’re looking to leverage the OLAP components as provided)

BlazeDS Custom Authentication

Here are the steps to roll your own BlazeDS Custom Authentication:

You’ll need to write a Java Class that implements the following class(es):

flex.messaging.security.LoginCommand;
flex.messaging.security.LoginCommandExt;

For example:

package com.dl.login;

import flex.messaging.security.LoginCommand;
import flex.messaging.security.LoginCommandExt;

import com.dl.login.UserVO;

public class LoginProxy implements LoginCommand,LoginCommandExt
{
public Principal doAuthentication(String username, Object attributes)
{

String password = (String)attributes;
//At this point you’d typically check against a datastore / LDAP / etc

if(username.equals(“riafan”) && password.equals(“mysecret”))
{
UserVO vo = new UserVO(username);
return vo;
}
return null;
}

public boolean doAuthorization(Principal user, List roles)
{

UserVO u = (UserVO)user;

if(u == null)
return false;

for(int i=0;i<roles.size();i++)
{
String role = (String)roles.get(i);
if(u.hasRole(role))
return true;
}
return false;
}

public boolean logout(Principal arg0) {
// TODO Auto-generated method stub
return false;
}

public void start(ServletConfig arg0) {
// TODO Auto-generated method stub

}

public void stop() {
// TODO Auto-generated method stub

}

public String getPrincipalNameFromCredentials(String arg0, Object arg1) {
// TODO Auto-generated method stub
return null;
}
}

In this example UserVO must implement java.security.Principal

package com.dl.login;

import java.security.Principal;

public class UserVO implements Principal
{

public String [] groups;
public String username;

public UserVO(String username)
{
this.username = username;
// Make sure we apply the array groups (roles) this user belongs to at some point 🙂
}

public String getName() {

return this.username;
}

public boolean hasRole(String role)
{
for(int i=0;i<groups.length;i++)
{
if(groups[i].equals(role))
return true;
}
return false;
}

}

Okay, now we just need to point the services-config.xml to our class
<security>

<login-command class=”com.dl.login.LoginProxy” server=”all”>
<!– a.k.a. true = per ‘tab’ authentication –>
<!– when set to true a browser refresh will also reset auth –>
<per-client-authentication>false</per-client-authentication>
</login-command>

<security-constraint id=”trusted”>
<auth-method>Basic</auth-method>
<roles>
<role>guests</role>
<role>accountants</role>
<role>employees</role>
<role>managers</role>
</roles>
</security-constraint>

</security>

That’s it.

To actually secure a destination, use the remoting-config.xml

<destination id=”AlertProxy” >
<properties>
<source>com.dl.alerts.AlertDAO</source>
<scope>application</scope>
</properties>

<security>
<security-constraint ref=”trusted”/>
</security>

</destination>

jQuery, Objective C

I’ve been diving into both as I’m looking to land some more iPhone projects. I’m really excited with the breath of fresh air the platform provides.

The big question this year….

WWDC 2010 or MAX 2010

MAX has been great, I’ve met some really great members of the community. For those of us who are Flex veterans, the conference seems a bit light, at least that’s the impression I’ve had the past two years.

Looking over the 2009 sessions of WWDC, I’m impressed, looks like a lot of great sessions.

Cheers
Josh

Debugging Apache

Problem: Apache quit working

Solution: Debug via gdb httpd2

Apache quit working after some network changes. The error log contained numerous

child pid 20038 exit signal Segmentation fault (11) lines.

Running gdb httpd2 along with a backtrace (bt) revealed the function / line of code throwing the error. The problem was quickly tracked down to the LDAP config (ldap.conf).

BlazeDS Context.xml

While deploying a BlazeDS project, I ran into a small problem that the META-INF/context.xml was not being loaded by tomcat.

The context.xml has a simple JNDI datasource defined

Reading up on the tomcat docs it became obvious that tomcat was loading the Adobe BlazeDZ tomcat/conf/context.xml.

Java Soap Client

I ran into a short problem writing a Java SOAP client. I was using the Axis[2] wsdl2java class to generate my Java classes. The latest version of wsdl2java has omitted the -T parameter that’s used to specify the SOAP version for the generate classes. The client’s soap endpoint only accepts SOAP 1.1 (not 1.2) so this proved to be a problem. I downloaded an older version of Axis [1.4] so I could specify the -T 1.1 and build against SOAP 1.1.
Download hip hop songs mp3
Buy Levitra Vardenafil
This time around the generated Java classes are missing the soap envelope headers needed by the service. I found a great article covering this exact problem.

The only change needed from there was in the service stub…

The org.apache.axis.soap.SOAPConstants.SOAP12_CONSTANTS needed to be changed to org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS. I was a bit surpised to see those constants after building w/the wsdl2java -T 1.1 argument.

Disclaimer: I’m not a SOAP *expert* so feel free to provide feedback 🙂

Glassfish LCDS Flex Up Next

It’s been a busy year getting a J2EE and Data Warehousing education. I’m wrapping up the ETL portion of a large Data Warehousing project. The next phase of the project is building a Flex front-end for the warehouse. I’m looking forward to using the Spark Architecture in Flex 4 for the UI, we should be able to generate some amazing UIs.

Cheers
Josh

Debug Server/Client LCDS Java Helloworld in Flex Builder

Prerequisites

Install Flex Builder
Install LCDS Data Services
Install WTP in Flex Builder

Here’s a simple project that shows you how to create a simple Hello World for Flex + Java via LCDS. I’ll also show you how to debug the server [java] code as we move along.

File->New->Flex Project

  • For application server type select J2EE
  • User remote object access
  • LiveCycle Data Services
  • Create combined Java/Flex project using WTP
  • 01 Setup

    Select the target runtime. You will need to click ‘New’ to create one if none are available.

    02 Server

    Create a new target runtime if needed.

    03 Tomcat

    04 Tomcat

    05 Server

    Be sure to change your Output URL to match the LCDS [tomcat] config (defaults to 8400)
    06 Setup

    Run->Debug->Other

    Again, make sure the URLs are using the correct port

    07 Debug Server

    Project->Properties->Flex Server

    08 URL Context

    Okay, are setup is complete now we’re ready to code.

    Here’s the MXML

    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">

    <mx:Script>
    <![CDATA[
    import mx.controls.Alert;
    import mx.rpc.events.ResultEvent;
    import mx.rpc.events.FaultEvent;

    private function sayHello():void
    {
    testService.getOperation('sayHelloTo').send(txtName.text);
    }

    private function onFault(event:FaultEvent):void
    {
    trace(event);
    }

    private function onSayHelloToResult(event:ResultEvent):void
    {
    Alert.show(event.result as String);
    }

    ]]>
    </mx:Script>

    <mx:RemoteObject id="testService" fault="onFault(event)" destination="helloDest">
    <mx:method name="sayHelloTo" result="onSayHelloToResult(event)"/>
    </mx:RemoteObject>

    <mx:TextInput id="txtName" x="10" y="10"/>
    <mx:Button click="sayHello()" x="178" y="10" label="Go"/>
    </mx:Application>

    Note the destination=”helloDest” line, we’ll have to configure a LCDS destination with this name in a few steps…

    Create a simple java class to test against:

    
    public class HelloWorld {
    
    	public String sayHelloTo(String name)
    	{
    		return "Hello " + name;
    	}
    }
    
    
    

    And finally, we need to setup the destination

    To do so, edit \WebContent\WEB-INF\flex\remoting-config.xml, adding the following

    <destination id="helloDest">
    <properties>
    <source>HelloWorld</source>
    </properties>
    </destination>

    That’s it, now we are ready to test.

    Set a breakpoint on the on ‘return “Hello ” + name;‘ line in you’re java code.

    Launch the server in debug mode

    09 Server

    Now, launch the flex app [in debug mode if you want to debug the front end as well].

    Type your name in the input box and click ‘Go.’

    You’ll see your breakpoint being caught, both server [java] side and client side 🙂

    Flex Project Archive

    Install WTP in Flex Builder

    A quick walkthrough on installing the Web Tools Platform (WTP) in Flex Builder.

    Help->Software Updates->Find and Install

    Help Software Update

    Search for new features to install

    Search for New

    Select the [Europa] discovery site

    Europa

    Select ‘Web and JEE development’

    You may need to click ‘Select Required’

    WTP

    AMFPHP Support for JSON POSTs

    I found myself wanting to use JSON POSTs (not just GETs) with AMFPHP. Here’s the addition.

    Open up core\json\app\Gateway.php.

    After

    $rawArgs = explode('/', $args);

    add the following

    if(isset($_POST) && count($_POST) > 0)
    {
    $len = count($rawArgs);
    // Check for and remove [last] empty arg from URL '/' explosion
    if($len && trim($rawArgs[$len-1]) == "")
    unset($rawArgs[$len-1]);

    // Append the POST variables
    for($i=0;$i

    The format of the post variables would be argNo=value
    Ex.
    Backend Function

    public function ResetPassword($username,$password,$oldpassword)
    {
    // Code HERE
    }

    Javascript POST parameters for the latter

    request.send("0=" + escape(username) + "&1=" + escape(oldpassword) + "&2=" + escape(newpassword));

    Hoping to jump into ZendAMF soon 🙂