Pages

Thursday, July 31, 2008

Try the new Oracle Metalink site build in Flex

James Ward already announced it that Oracle is using Flex for their console websites like the Enterprise Manager website but now you can try the new Oracle Metalink in Flex. The new Metalink looks really cool. Try it yourself just use your own metalink account.






Flex CRUD application with drag and drop and LifeCycle

I remade my old Drag and Drop Employee application by using Adobe LifeCycle Data Services( which is free for one cpu ). In the first edition I used BlazeDS, but with LifeCycle it is a little bit easier to do CRUD operations on an Employees table. In BlazeDS I had to made different java methods which does the CRUD operations. Now I only have to add an new Employee object to the ArrayCollection or update an Employee oject in the ArrayCollection and LifeCycle does the transaction. But LifeCycle has something extra it can push the changes to the other Flex clients which are using the same Data Service.
This are the features of the demo application. I can drag an employee in the Tree to an other department. Click on an employee and a new update Tab is shown where I can update the employee or I can create an new employee in a create employee tab.
Here are some screenshots.




To let this example work you need to do the following things.

setup lifecycle in jdeveloper

configure lifecycle for the employees table

download Flexlib for the dragable and closeable Tabs. These guys did a perfect job.

Here is the source code of java side and here is the Flex code

These are the things I needed to do.

<mx:DataService id="ds" destination="employee" message="messageHandler(event.message)"/>

<mx:ArrayCollection id="employeeArray" />

Step 1 fill the employeeArray


public function init():void{
ds.autoCommit=false;
ds.autoSyncEnabled = true;
ds.addEventListener(ResultEvent.RESULT, resultHandler);
ds.addEventListener(DataServiceFaultEvent.FAULT, faultHandler);
ds.addEventListener(DataConflictEvent.CONFLICT, conflictHandler);
var token:AsyncToken = AsyncToken(ds.fill(employeeArray));
token.kind = "fill";
}

Step 2 wait for the employee retrieving result, sort this result on departmentId and Firstname and build a new xml from the Arraycollection for the Tree.

private function resultHandler(event:ResultEvent):void
{
if (event.token.kind == "fill")
{
// fill tree
sortEmployees();
refreshTree();
}
}

private function sortEmployees():void {
var deptSortField:SortField = new SortField();
deptSortField.name = "departmentId";
deptSortField.numeric = true;
var firstNameSortField:SortField = new SortField();
firstNameSortField.name = "firstName";
firstNameSortField.numeric = false;

/* Create the Sort object and add the SortField object created earlier to the array of fields to sort on. */
var employeeDataSort:Sort = new Sort();
employeeDataSort.fields = [deptSortField,firstNameSortField];

/* Set the ArrayCollection object's sort property to our custom sort, and refresh the ArrayCollection. */
employeeArray.sort = employeeDataSort;
employeeArray.refresh();
}
public function refreshTree():void{
mainXML = new XMLDocument();
var rootXML:XMLNode = mainXML.createElement("root");
rootXML.attributes.type = "root";

for ( var i:int = 0 ; i < employeeArray.length ; i++ ) {

var department:int = employeeArray.getItemAt(i).departmentId;
var search:Array = rootXML.childNodes;
var deptXML:XMLNode = null;

if ( search.length > 0 ) {
for ( var b:int =0 ; b < search.length ; b++ ) {
if ( search[b].attributes.id == department.toString()) {
deptXML = search[b];
break;
}
}
}
if ( deptXML==null ) {
deptXML = mainXML.createElement("department");
deptXML.attributes.label = department;
deptXML.attributes.type = "dept";
deptXML.attributes.id = department.toString();
rootXML.appendChild(deptXML);
}
var firstName:String = employeeArray.getItemAt(i).firstName;
var lastName:String = employeeArray.getItemAt(i).lastName;
var employee:int = employeeArray.getItemAt(i).employeeId;

var elementXML:XMLNode = mainXML.createElement("employee");
elementXML.attributes.label = firstName+" "+lastName;
elementXML.attributes.type = "emp";
elementXML.attributes.id = employee;
deptXML.appendChild(elementXML);
}
mainXML.appendChild(rootXML);
myXml = new XML(mainXML.toString());

tree.dataProvider = myXml;
openAllNodes();
}


Step 3 When we want to change an employee we have to find this employee, we will use a filter function and I add the code for an update and an insert

private function filterEmployees():void {
employeeArray.filterFunction = processFilter;
employeeArray.refresh();
}

private function removeFilterEmployees():void {
employeeArray.filterFunction = null;
employeeArray.refresh();
}


private function processFilter(employee:Object):Boolean {
return parseInt(employee.employeeId) == searchEmployeId;
}

// update
var employeeLocal:Object = null;
// search the employee
searchEmployeId = employeeId;
filterEmployees();
// if found we can update the department.
if ( employeeArray.length == 1 ) {
employeeLocal = employeeArray.getItemAt(0);
}
removeFilterEmployees();

employeeLocal.departmentId = departmentId;
employeeLocal.email = email;
employeeLocal.firstName = firstName;
employeeLocal.lastName = lastName;
employeeLocal.jobId = jobId ;
employeeLocal.hireDate = hireDate;


ds.commit();
var token:AsyncToken = AsyncToken(ds.fill(employeeArray));
token.kind = "fill";

// insert
employee = new Employee();
employee.employeeId = employeeId;
employee.departmentId = departmentId;
employee.email = email;
employee.firstName = firstName;
employee.lastName = lastName;
employee.jobId = jobId ;
employee.hireDate = hireDate;
employeeArray.addItem(employee);
ds.commit();
var token:AsyncToken = AsyncToken(ds.fill(employeeArray));
token.kind = "fill";

Wednesday, July 23, 2008

Load balancing with AS 10.1.3 and with Web Cache

This week I had to setup load balancing on three 10.1.3 OC4J containers so the load is spread is over the servers and when an oc4j container spontaneous reboots the others servers can handle the load until the container is back. We had a little problem where the production server (windows 32bits) gave a out of memory exception, an out of swap error and the application users had to wait for 5 minutes before they can work again.
I first used Oracle Web Cache which is a 10.1.2 Application Server product. This was pretty easy but very stupid in 10.1.3. ( the second part of this blog I will show you how easy this is in 10.1.3
The first step in Web Cache is to configure the listening ports for the load balancer.


In my case Web cache will listen on port 80 and 7778.

Now we can add the application servers ( original servers)

Define a website url for which you want to load balance, I will use the Enterprise Manager Website /em

The site is /em/
Add a site to server mapping where we connect the site em to the availible AS server
Now we have to make sure that a new web session is always run on the same original server else we cannot log in.

Use for the em website as session JSESSIONID and OC4J-based as binding mechanism. We are now ready with Web Cache. The only thing still to do is to add a virtual hsot to the httpd.conf of the Application Servers. We have to do this else the em website is redirected to one of the application server instead of the load balancer adress.


NameVirtualHost XPCND7010XMP.work.local:7777
<VirtualHost XPCND7010XMP.work.local:7777>
ServerName XPCND7010XMP.work.local
Port 80
</VirtualHost>
XPCND7010XMP.work.local:7777 is the application server on port 7777.
inside VirtualHost we use the adress of the load balancer.
That's all in webcache.

You don't have to do this in 10.1.3. Just install on the load balancer a http server ( custom install in the application server installer ).
Add in every AS Home the following topology lines to the opmn.xml and you have a cluster.

<notification-server interface="ipv4">
<port local="6100" remote="6200" request="5003"/>
<ssl enabled="true" wallet-file="$ORACLE_HOME/opmn/conf/ssl.wlt/default"/>
<topology>
<discover list="*233.0.0.2:1500"/>
</topology>
</notification-server>
On the application servers you don't need the http servers anymore so you can disable.
In this cluster you can have only one Enterprise Manager application so you have to disable it on all the application servers except one. ( server.xml and default-web-site.xml )
That's all in 10.1.3