March 13, 2008

HowTo implement a simple loading panel with a little of scriptaculous help

Recently, I had to add a loading panel functionality (aka “please wait panel“) to a Web Application I designed for a customer of mine some months ago.
The application already implements some Ajax based functionality using the binome AjaxTags + script.aculo.us, so decided to introduce the new feature without the help of any other library.
Unluckily, script.aculo.us doesn’t offer this functionality natively, anyway the problem is nonetheless solvable in a quick and quite elegant way.

 <body onLoad="onMainLoad();">
    <div id="waitpanel">
        <div align="center"> </div>
        <div align="center"> Loading...</div>
        <div align="center"> </div>
        <div align="center"><img width="32" height="32" title="" alt="" src="../images/waiting.gif">
        </div>'
    </div>
    <div id="mainpagepanel" style="position: absolute; display: none;">
        <div>
        <form name="dataForm" class="basicForm" method="post" ONSUBMIT='return false;'>

        [..]
        The rest of actual the application logic
        [..]

    </div>

    [...]

An extract from the web main page template:

function onMainLoad()
{

    hideWaitPanel();

    //Other things to do just after the page full loading
}    

function hideWaitPanel()
{
    Element.hide('waitpanel');
    Element.show('mainpagepanel');
}

That’s all.
Maybe not the most beautiful implementation of the world but it is simple, safe and transparent to the rest of the application logic.

March 6, 2008

Instead Of triggers

Sometimes you need to insert (or update) a set of a tables with a single SQL instruction. The reasons can be many and many, let’s only say that instead of using a stored procedure or whatever, you can easily and effectly use the INSTEAD OF trigger approach.
Using INSTEAD OF triggers, you can enforce new business rules by extending or replacing the normal triggering actions of an INSERT, UPDATE, or DELETE statement.

Here a simple “real-life” example:

Having a view so defined:

CREATE OR REPLACE VIEW PM_TASKS_INSERT_VIEW AS
    SELECT EnvName, ClientName, TaskName, TimeStamp, Elapsed
      FROM PM_Environment e, PM_Client c, PM_Task t, PM_Taskrepository tr
     WHERE e.EnvID =  tr.EnvID
       AND c.ClientID =  tr.ClientID
       AND t.TaskID =  tr.ClientID

We can handle the virtual insert statement doing so:

create or replace trigger PM_TASKS_INSERT_VIEW_INS_TRG
  instead of insert on pm_tasks_insert_view
  for each row
declare
     EnvRow PM_ENVIRONMENT%rowtype  := NULL;
     ClientRow PM_Client%rowtype  := NULL;
     TaskRow PM_Task%rowtype := NULL;
     emesg VARCHAR2(250);
begin
   	--
	  -- Retrieve all the key from the Names...
	  --
   BEGIN
      select *
      into EnvRow
      from PM_ENVIRONMENT
      where upper(EnvName) = upper(:NEW.EnvName);
   EXCEPTION
      WHEN NO_DATA_FOUND
      THEN
           raise_application_error (-20001,
                                   'No environment found for the name: ' || :NEW.EnvName);
      WHEN TOO_MANY_ROWS
      THEN
           raise_application_error (-20002,
                                   'Too many environments rows found for the name: ' || :NEW.EnvName);
      WHEN OTHERS THEN
           emesg := SQLERRM;
           raise_application_error (-20003,
                                   'Generic error found trying to retrieve the environment: ' || emesg);
   END;

   BEGIN
      select *
      into ClientRow
      from PM_Client
      where upper(ClientName) = upper(:NEW.ClientName);
   EXCEPTION
      WHEN NO_DATA_FOUND
      THEN
           raise_application_error (-20011,
                                   'No client found for the name: ' || :NEW.ClientName);
      WHEN TOO_MANY_ROWS
      THEN
           raise_application_error (-20012,
                                   'Too many client rows found for the name: ' || :NEW.ClientName);
      WHEN OTHERS THEN
           emesg := SQLERRM;
           raise_application_error (-20013,
                                   'Generic error found trying to retrieve the client: ' || emesg);  

   END;

   BEGIN
      select *
      into TaskRow
      from PM_Task
      where upper(TaskName) = upper(:NEW.TaskName);
   EXCEPTION
      WHEN NO_DATA_FOUND
      THEN
           raise_application_error (-20021,
                                   'No task found for the name: ' || :NEW.TaskName);
      WHEN TOO_MANY_ROWS
      THEN
           raise_application_error (-20022,
                                   'Too many task rows found for the name: ' || :NEW.TaskName);
      WHEN OTHERS THEN
           emesg := SQLERRM;
           raise_application_error (-20023,
                                   'Generic error found trying to retrieve the task: ' || emesg);
   END;

   	--
	  -- Insert the new row on the "FACTS": table
	  --
    BEGIN
      insert into PM_TASKREPOSITORY (EnvID, ClientID, TaskID, TimeStamp, Elapsed)
             values (EnvRow.Envid, ClientRow.Clientid, TaskRow.Taskid, :NEW.TimeStamp, :NEW.Elapsed);
   EXCEPTION
      WHEN WHEN DUP_VAL_ON_INDEX THEN
      THEN
           raise_application_error (-20031,
                                   'Fact already inserted: ' || :NEW.TaskName);
   END;

end PM_TASKS_INSERT_VIEW_INS_TRG;

As you can see, we’re inserting on the table PM_TASKREPOSITORY INSTEAD OF on the view PM_TASKS_INSERT_VIEW and - before of that - we look for additional values and so on.
The said piece of SQL is executed each time we issue an INSERT INTO PM_TASKS_INSERT_VIEW VALUES(…).
As already said, easy and very effective!

For more details click here.

February 22, 2008

Select * From Babilonia

SQL uses human-readable expressions to define query statements… and like others human languages, SQL is spoken in a lot of different dialects.
Googling around looking for the implementazion of a simple CREATE TABLE statement for a SQLite database, I found SQLZoo that, in a very clever and easy way, exposes all the different implementations for a specific SQL command.

Useful and educative!

February 19, 2008

Android Developer Challenge

ADC - Logo

I’m a little late, but Google has launched - about a month ago - the Android Developer Challenge, which will provide $10 million in awards — no strings attached — for great mobile apps built on the Android platform.

Even if the core of Android is built in C/C++, the Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.

February 18, 2008

Base64: Sun vs. rest of the world

Looking for some quick & dirty Base64 encoding and decoding functions you can find more than one example using the classes sun.misc.BASE64Encoder and sun.misc.BASE64Decoder. Beware: all the packages under the tree sun.* are part of the Sun JDK and they are not part of the public API. That means, for instance, that using SDK implementations from IBM or HP your code can stop working…
So, because you *want* to write portable applications you should use other public implementations like the one provided by the Apache Commons project: Commons Codec.

import org.apache.commons.codec.binary.Base64;

[....]

byte[] decodedEntity = Base64.decodeBase64(base64EncodedEntity.getBytes());

February 15, 2008

The fucking tip of the day - XHTML

From XHTML 1.0 The Extensible HyperText Markup Language (Second Edition) par 4.2:

XHTML documents must use lower case for all HTML element and attribute names. This difference is necessary because XML is case-sensitive e.g. <li> and <LI> are different tags.

Now, maybe you’ll understand because your XHTML processor doesn’t handle your <TABLE> tags …

February 14, 2008

A Flying Saucer brings us PDFs

Flying Saucer - aka xhtmlrenderer - it’s a Swing based XML+CSS layout engine.
In other words, it renders to the screen your XHTML (and your applied Stylesheet) like a normal web browser. As you could easily presume, Flying Saucer is primary intended for embedding web-based user interfaces into Java applications (like iTunes or modern IDEs like NetBeans or Visual Studio).
Definitely, right now it cannot be used as a general purpose traditional web browser since it does not support the malformed legacy “raw” HTML found on the web. Though, it would be possible
integrating, for instance, some kind of HTML pre-processor able to clean-up the crappy “old-style” code - JTidy and TagSoup are the most famous tools in this area.

Flying Saucer demo

However, I’m not going to talk about Flying Saucer as a web browser. In-fact, Flying Saucer is also a very interesting and really promising tool to render your well formatted XHTML files to PDF, thanks to a pretty integration and collaboration with the iText libraries.
Until now, the most appealing method to accomplish such task was to use Apache FOP and a lot of XSL transformations: boring, difficult and slooooow. Almost if you - like me - don’t like a lot to loose hours wondering because a <xsl-copy> don’t do what is supposed to do (and then realize you misunderstood some arcane reference).
With Flying Saucer + iText all you have to do is to make sure to have well formatted XHTML and then to write down few lines of Java code.
Something like that:

String url = new File(xhtmlFile).toURI().toURL().toString();
OutputStream os = new FileOutputStream(pdfFile);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(url);
renderer.layout();
renderer.createPDF(os);
os.close();

That’s all. Really.

Actually, even if the conversions work, almost using the Release 7, I found more than one bug in the rendering output of the tables. Now a new preview snapshot of the Release 8 is available and, reading the changelog, a lot of bugs and problems seem to be fixed. Let’s go to give it a try…
In the next days (or weeks), additional details (and maybe more), HOW-TOs and best practices working with XML, HTML, Java and PDF.

February 11, 2008

Little blogs growth

Playing around with the WordPress stuff, I just published a new section called My Tools: a first unsorted list of utils and apps that are installed in first instance each time I set up my workstation.

Also, I’m wondering if I’m still loving the current blog layout template.

February 8, 2008

Snipplr!!

Every coder has his own little big secret case with a bunch of quick&dirty functions and methods. Even more when using some old crappy (make up)language like PHP, XSL and so on. With Snipplr you can keep all of your frequently used code snippets in one place that’s accessible from any computer. You can share your code with other visitors and use what they post, too.

Actually, I never used it. And, yes, it doesn’t seem very populated. But, hey, they’ve a nice Wordpress plugin, so I thought it was nice to give it a try.

Let’s post my two first (really awsome) snippets!

Extract the file name (without the extension) from a full pathname

  1. public static String getFileNameWithoutExtension(String fileName) {
  2.         File tmpFile = new File(fileName);
  3.         tmpFile.getName();
  4.         int whereDot = tmpFile.getName().lastIndexOf('.');
  5.         if (0 < whereDot && whereDot <= tmpFile.getName().length() - 2 ) {
  6.             return tmpFile.getName().substring(0, whereDot);
  7.             //extension = filename.substring(whereDot+1);
  8.         }   
  9.         return "";
  10.     }

Extract the extension of a file from a full pathname

  1. public static String getFileExtension(String fileName) {
  2.         File tmpFile = new File(fileName);
  3.         tmpFile.getName();
  4.         int whereDot = tmpFile.getName().lastIndexOf('.');
  5.         if (0 < whereDot && whereDot <= tmpFile.getName().length() - 2 ) {
  6.             return tmpFile.getName().substring(whereDot+1);
  7.         }   
  8.         return "";
  9.     }

Now, the problem is: How to change that fucking background color?

February 6, 2008

Hello World

IPsec: Initialized Security Association Processing.
IP Filter: v3.4.33 initialized.  Default = block all, Logging = enabled
ad0: 122MB <Matt's blog 512M> [978/8/32] at ata0-master BIOSPIO
Mounting root from ufs:/net/md0c
Found configuration on ad0.
stray irq 7
Initializing timezone... done
Initializing PC cards... failed (probably no PC card controller  present)
Configuring firewall... done
Configuring LAN interface... done
Configuring WAN interface... done
Configuring OPT1 (OPT1) interface... done
Starting syslog service... done
Starting webGUI... done
Starting DNS forwarder... done
Starting WebService service... done
Starting Blog interface... done
Hello World