Main | [Article] A Multiple Find Technique »

September 01, 2004

[Article] Introduction to Beans

by Maarten Berkenbosch
Servoy
http://www.servoy.com/

What Are Beans?

A Java Bean is a reusable software component that works with Java. You can drop a bean as an element into a Servoy form, just like you can add Tab panels, Portals, Buttons etc.

Once you select the bean in the form, a set of properties will come available to you in the Servoy property editor. Which properties of course depends on the kind of bean you are using. You may set these properties by hand (for instance: setting height and width of a bean), but you can also set them dynamically through scripting, using methods.

There’s a wide variety of beans available on the internet (Calendars, spreadsheets, word processors , charts, calculators, clocks, tickertapes etc.) as freeware, shareware, commercial etc.

In this article I will show you an example of how to implement a clock bean and a chart bean.

All we have to do is drop our beans inside the beans folder. This folder can be found inside the main Servoy folder. After that, start Servoy. That’s it.

I’ve downloaded the two beans from http://www.alphaworks.com but unfortunately they’re not available there anymore. The so called ‘Bean bag project‘, has been retired.

You can download them here.

[You're allowed to freely use/distribute them in your applications, but nevertheless please read the IBM license agreement.]

The Clock Bean

1) Create a form in your Servoy solution and open the designer.

2) Click on the coffee bean in the toolbar and select the "IClock" bean.

3) This is the result (See the properties of the selected clock bean on the right of the image below).



If we go into the data mode again the clock initially looks like this:

When we go back into designer and change the property "analogNumeralColor" like this:

...notice the change of colors.

This is in a nutshell the basis of how to use beans in Servoy. But there's more, you can also change properties of a bean dynamically.

Changing Properties of a Bean Through a Method

1) Go into designer and enter “myClock” in the “name”-property.

2) Go back to data mode.

3) Open the Method editor and create a method named “changeClockAppearance” as shown in the next picture.

Notice that the name property "myClock" appears in the elements tree of the form (clock) where I’ve put the clock Bean.

By clicking on “myClock” in the elements tree, all its properties become available in the outline column.

Now you can build a method that can change the look of the clock in various ways.

In this case I’ve made a method that:

- shows an analog clock whenever the country value in the database(!) equals "USA"

- shows a digital clock with AM/PM notation, in short notation.

The possible settings of properties can be found in the documentation that normally comes with a bean (if you're lucky ;o)).

4) Go back to the form Designer and attach this method to "onRecordSelection" property.

The method will execute each time you select another record. (browsing)

As meaningless as this example may be, you can see the possibilities of interacting with beans via event driven scripts. Let's take a look at a more interesting example—showing charts that are build on data in real time.

The Chart Bean

Example 1:

This is an overview of the top 10 customers with most nr of orders being Ernst Handel with 20 orders.

Here's the script that creates the chart:

  1. controller.loadAllRecords() //load all records in the table
  2. forms.charts.controller.sort('ordercount desc') // sort on nr of orders desc
  3. //fill chart with values
  4. for( var i=0 ; i<= 9; i++) //for 10 customers
  5. {
  6. forms.charts.controller.recordIndex = i+1 //Servoy recordindex starts counting at 1.
  7. elements.ordersPerCustomer.setLegends(i, companyname) //set the legends > pos0="..." pos1="..." etc
  8. var nrOfOrders = forms.charts.ordercount //get nr of orders from the selectedrecord and put in in a Javascriptvariable. (you can also directly set the value in line 16 with "forms.charts.ordercount"
  9. elements.ordersPerCustomer.setLabels(i,customerid) //sets the labels that are horizontally shown under the x axis
  10. elements.ordersPerCustomer.setValues(0, i, nrOfOrders)
    //The 3 parameters are:
    -range > which position within the current x position should be set
    -x position > which x position should be set
    -value > in this case , nr of orders.

    in this example we only show one value(customer total) per x position.
    However, in the next example we compare 3 products per x position.

    This means setValues would go like this:
    setValues(0,2,value) //goto 1st spot of 3rd x position and set value of product 1
    setValues(1,2,value) //goto 2nd spot of 3rd x position and set value of product 2
    setValues(3,2,value) //goto 3rd spot of 3rd x position and set value of product 3
    etc....
  11. }

Example 2:

This chart shows the revenue of 3 products compared to each other over a three years period.

The script basicly comes down to 3 loops:

1st loop over the years (shown over x axis). The input comes form the array "years". //line 9-27

2nd loop over the products (3 product revenues shown per x position). The input comes from the array "products". //line 12-26

3rd loop over foundset of order_items based on year and product_id. This loop summarizes the revenue per product. // line 19-24

  1. var years = new Array
    (
    '01-01-1996...31-12-1996|dd-MM-yyyy',
    '01-01-1997...31-12-1997|dd-MM-yyyy',
    '01-01-1998...31-12-1998|dd-MM-yyyy'
    )
    //In javascript you can store data in Arrays like this:
    var myArray = new Array('text1','text2',text3',etc...)

    to get information out of arrays, do this:
    var x = myArray[0] // returns "text1"
    var y = myArray[2]// returns "text3"
  2. var products = new Array('7','40','51') //create an array of product_id's you want to compare
  3. //fill chart with values
  4. for(var i=0 ; i<years.length ; i++) //loop(nr1) through the years array (3 values)
  5. {
  6. elements.parallelChart.setLabels(i,i+1996) //set the labels that are horizontally shown under the x axis
  7. for(var j=0 ; j < products.length ; j++) //loop(nr2) through the product id's(3 values)
  8. {
  9. controller.find() //start a find request
  10. order_details_to_orders.orderdate = years[i] //search for orderdate via relation to orders table
  11. productid = products[j] //AND search for product_id in orderdetails table
  12. controller.search() //perform search
  13. var totalSold = 0 //create a variable that stores totalRevenue in next loop
  14. for(var k = 0 ; k< controller.getMaxRecordIndex() ; k++) //loop(nr3) through the foundset of orderdetails
  15. {
  16. controller.recordIndex = k+1 //start at first record. Servord recordindex starts at 1
  17. elements.parallelChart.setLegends(j,order_details_to_products.productname) //set the legends of the chart with current product
  18. totalSold = totalSold + (quantity * unitprice) //store (quantity * price) in the totalSold variable
  19. } //close loop nr3
  20. elements.parallelChart.setValues(j,i,totalSold ) //set the value in the chart:
    j = current spot within x position (products)
    i = current x position (years)
    totalSold = value
  21. } //close loop nr2
  22. } //close loop nr1

Example 3:

This example will show the same result using an SQL statement to retrieve data.

Benefits:

  1. Much, much faster.
  2. More flexible.
  3. No need to fill your solution with dozens of relations and forms just for the sake of reporting.
  4. Results can be shown anywhere in your solution because the SQL statement isn't linked to a form.

For those of you who aren't familiar with SQL, in one of our next articles we will do a tutorial on SQL, using an SQL generator build in Servoy.

[It's really worth the (small) effort to understand the basics of SQL.]

  1. var years = new Array
    (
    " '01-01-1996'AND'12-31-1996' ",
    " '01-01-1997'AND'12-31-1997' ",
    " '01-01-1998'AND'12-31-1998' "
    )
    //
    store the strings needed to find a certain year in an array.

    You can retrieve them in a loop again with years[i].
  2. for(var i=0 ; i<years.length ; i++) //start loop
  3. {
  4. elements.parallelChart.setLabels(i,i+1996 ) //set the labels that are horizontally shown under the x axis
  5. var query = "select products.productname,"+
    " SUM(order_details.quantity * order_details.unitprice)"+
    " from orders, order_details, products"+
    " where orders.orderid = order_details.orderid"+
    " and order_details.productid = products.productid"+
    " and products.productid IN (7,40,51)"+
    " and orders.orderdate BETWEEN "+ years[i] +
    " group by products.productname"+
    " order by products.productid asc"
    //This query basically gets the following information per loop(year):

    productName1 | totalRevenue
    productName2 | totalRevenue
    productName3 | totalRevenue

    Notice that with SQL, you don't have to do another loop to summarize the revenue per product
  6. var dataset = databaseManager.getDataSetByQuery(controller.getServerName(), query, null, 10000);
    //puts the query into the variable dataset.
    parameters:
    1) server to connect to
    2) query as defined
    3) you can set an array here if you're query looks like this
    "select * from table where id = ?
    If you're array is ('12','34','56') the databaseManager will actually query for all ids that contain the values in the aray.
    4) maximum returning records

    ____________dataset[1]__ |__dataset[2]__
    rowIndex1= productName1 | totalRevenue
    rowIndex2= productName2 | totalRevenue
    rowIndex3= productName3 | totalRevenue
  7. for( var j = 1 ; j <= dataset.getMaxRowIndex() ; j++ ) //start the loop through the dataset
  8. {
  9. dataset.rowIndex = j; //set the rowIndex
  10. elements.parallelChart.setLegends(j-1,dataset[1]) //set the legends with productname
  11. elements.parallelChart.setValues(j-1,i,dataset[2] ) //set the value with totalRevenue
  12. }
  13. }

One last remark about the chart bean. Be aware of the fact that when you're browsing through records using a chart, you might want to clear it first, before putting new data into it. Here's an example:

Suppose you are in record nr1 showing a chart with 8 columns and you're about to browse to the second record. If the second record only has data for filling the first 6 columns, the last 2 columns will still show results from the previous record. To avoid this, you should empty the chart, by doing a loop first that sets all values to empty ("").

As we have seen in this article, JavaBeans are very well integrated with Servoy and extremely easy to use.

Thanks to the support of JavaBeans it is possible to extend the functionality of servoy very easily.

There are thousands of opensource and commercial beans available on the internet.

A few starting points:

www.javashareware.com

www.techemployment.com

www.jfind.com

www.freewarejava.com

www.freedownloadscenter.com

www.jars.com

| Posted by David Workman on September 1, 2004 at 03:24 PM in Articles | Permalink

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a00d8341c8d8153ef00d83472e39369e2

Listed below are links to weblogs that reference [Article] Introduction to Beans:

Comments

Are these links broken?www.javashareware.com

www.techemployment.com

www.jfind.com

www.freewarejava.com

www.freedownloadscenter.com

www.jars.com

Posted by: John Pollard | Dec 2, 2004 5:51:26 PM

Those URL's work, but yes...the links are dodgy.
Seems David made a typo along the line somewhere.
Just copy/paste the URL and they'll work.

Posted by: Robert J.C. Ivens | Dec 12, 2004 6:40:04 AM

Post a comment