Jack of Everything, Master of Nothing

DISCLAIMER: The views and opinions expressed in this blog are my own and do not necessarily reflect those of Oracle Corporation, its subsidiaries and/or its affiliates. The views and opinions expressed by visitors to this blog are theirs and do not necessarily reflect mine.

Wednesday, November 21, 2007

I use Ubuntu, But Why?

Those that know me well, will know that I am a desktop Linux advocate and that I completely moved my home desktop to Ubuntu after considering what I really need my computer to do. The list below is a pretty comprehensive list of what I want to be able to do with my computer:

· Run in a timely manner
· Not crash when something/anything throws a wobbly
· Internet Access (General Web Surfing)
· Internet Chat (MSN, Skype)
· Word Processing, Spreadsheets
· Storing / Editing Photos from my digital camera
· Printing Documents
· Scanning the odd document or photo
· Playing music (MP3s, Internet Radio)
· Playing Videos/DVDs
· Burning CDs/DVDs
· Simple Development & Editing Text Files

For me the switch was not about the politics of "free software vs. the almighty evil other company or proprietary software" but the fact I don't need or want a server farm to run the latest version of the software, have a bloated desktop that takes 10 minues to “load my personal settings”, have to upgrade my PC every 6 months or update my virus definitions religiously.

I migrated to Ubuntu just after Vista was released, after hearing and having a few negative experiences with Vista on other people’s hardware. For me, moving to Vista would have meant that I would need some new hardware. My home PC has a fairly modest specification consisting of Athlon XP 2000 (1.67 GHz Processor), 1GB RAM, 64 MB RAM NVIDIA Geforce 2 Graphics card, and 2 x 250gig hard drives. I could have moved to Mac but that would have meant shelling out at least £600 on hardware (something I might still consider when my current hardware starts to feel slow).

I’ve been using Ubuntu on my home servers since the “Badger” but never really felt that it was quite ready for my desktop, until Feisty. I took the plunge after weighing up the pros/cons and trying the live CD with my hardware. Do I regret it? Definitely not. For years I’d run Linux in a VM, now it is the other way round and I am running Windows in a VM for all those legacy applications that must use Windows.

The first thing that hit me was how fast my system goes on such a modest specification. Put simply, every aspect of my computing needs in the list above is covered by Ubuntu. I’ve yet to encounter a task which I can’t accomplish in Ubuntu. For me the benefits include “less” worry about mal-ware, viruses and my general security, performance and the total cost of my home computing experience is much less (More Free-Software/Free-To-Use alternatives and less hardware upgrades).

There are a few minor niggles such as driver compatibility, wireless connectivity and lack of commercial software. However, I am lucky enough to own a scanner (Packard Bell 2400), wireless card (Not sure of model, it just worked) and printers (Samsung ML-1210, Samsung ML-4550) that are ALL supported under Linux. Others might not be so lucky. The fact I am NOT a gamer also helps. The lack of commercial software refers to the unavailability of commercial software like Photoshop and Fireworks. These are pieces of software I’d be happy to pay for if they were available. Though I believe this will change over time as more and more people are starting to use Desktop specific versions of Linux such as Ubuntu. Free-to-use software such as Skype, Opera and RealPlayer are already available and have been for some time.

The simple truth is that if Windows was as performant and secure as my Linux Desktop I would have probably stuck with Windows as it does just work with most hardware.

My advice to anyone looking to buy a new PC would be to try Ubuntu first. You can download the live CD from the Ubuntu website and try it without installing it. Its also the first real distribution that doesn’t require extensive Linux or computing knowledge. You can install it and use it.

Ubuntu Website -> http://www.ubuntulinux.org
Ubuntu Forums -> http://www.ubuntuforums.org
Dell computers with Ubuntu -> http://www.dell.com/ubuntu

Labels: , , ,

Wednesday, November 14, 2007

Clear Page Cache When Using Tabs & Sub-tabs (new solution)

Previously I posted a solution for clearing page cache of a target page when a user clicks a sub-tab. While my solution works there is much cleaner way of achieving this involving the use of APEX_UTIL.CLEAR_PAGE_CACHE().

Using the same scenario, consider that we need to clear the page cache of the page that we will be re-directed to, before it loads. The solution is very similar but requires no modification of the target page.

Firstly, create a new application page process

Navigate to Applications -> Shared Components -> Application Processes and hit “Create” in the application builder.

Create a process which runs “On Submit: After Page Submission – Before Computations and Validations”.

In Process Source type the following

IF (:REQUEST = 'T_YOUR_TAB_NAME’) THEN
APEX_UTIL.CLEAR_PAGE_CACHE(your_page_number);
END IF;

T_YOUR_TAB_NAME can be identified from the developer mode or
using firebug in Firefox on the specific tab your interested in.

That's it! Now when a user clicks on a sub-tab the target page's, page cache will be cleared before it loads. To clear the cache for another tab, just add a new block to the application process you have created.

Labels: , ,

Apex Gotchas


While Apex is an intuitive easy to use development environment it can cause some frustrations and has a number of gotchas that are worth been aware of. The following are a few I've discovered over the last couple of months.

Validations of type PL/SQL Expression without conditions

This little beauty caused me an hour and half worth of grief.

Set up a pl/sql validation of type pl/sql expression, give it a name but leave the condition entry blank.

When you run the page you will see “Invalid PL/SQL Expression” at the top of page before the header and rest of your page.

POP LOV, display description return value returns “undefined”

If you have a page item (Select List), which uses an LOV query, and have enabled null columns (but not specified a null value) you can typically expect the value in the session state to be “%null%” after the page has been submitted.

However it appears that if you have a “Popup LOV, display description, return value” item then the null value actually gets submitted to the session state as “undefined” and not “%null%”. Although this one is easier to spot it more of an annoyance and just appears odd as it actually returns “undefined” to the display area too.

Setting Page Items in Validations, Report Regions and PL/SQL Function Body Conditions

Have you ever worked on a bit of functionality where you're effectively hacking it to get it to work with the good intention of re-factoring it later and make it look pretty?Well on one occasion where I had forgot to go back and re-factor a particular page I had worked on I discovered that I had set a page item within a validation.

Logically thinking, I personally would not expect to see a page item set in a validation (your circumstances may be different). Apex allows you to make an assignment to a page item anywhere you can place PL/SQL blocks (E.g. report regions returning SQL Queries, item/region conditions (I.E. function body returning boolean), LOV Queries. Generally speaking I'd expect such a function to be carried out in process. The old saying , “just because you can doesn't mean you should” comes to mind.

I feel this is a good example demonstrates the need for standards and consistency when developing Apex Applications if not for your own sake then for the poor person who is going to support your application once your gone. More about good practice in a later post.

I did have one more gotcha, concerning dates but can't remember the specifics, if I do I'll add it to the list, likewise if anyone has any more please feel free to add them to the comments section and I'll update the post.

(The gotchas may not apply to versions of Apex greater than 2.2.1 unfortunately the project I was working on was at that particular version)

Labels: , ,

Ending the Silence

It has been well over 3 months since my last post and I know its lame but “I just have not had the time”.

Since then I’ve been coding and documenting as my long stint at my last client came to an end last week. After a hard day at the office, touching a computer is the last thing I’ve wanted to do. However my blog-topic list has got ever longer where I’ve jotted down idea but not had the time to follow them up and there has been some exciting developments on the Oracle Landscape.

So if you a regular reader, fear not, I am still alive and there will be more posts coming over the next couple of weeks.

Thursday, July 12, 2007

Oracle 11g is here

Yesterday saw the launch of Oracle 11g. Eager to get my hands on a copy I popped over to OTN but was disappointed to find that its not yet available for download. However there are a stack of white papers looking at the new features. You can access them here:

http://www.oracle.com/technology/products/database/oracle11g/index.html


Hopefully it will be made available soon. I'm keen to try out the native binary XML support as well as further improved flash back features.

Labels: ,

Friday, July 06, 2007

Clear Page Cache When Using Tabs & Sub-tabs

Update - 14th Nov 2007 : I have posted a cleaner solution to this at http://kristianjones.blogspot.com/2007/11/clear-page-cache-when-using-tabs-sub.html

Most pages you create in Apex have a number of modes that govern when processes, items and regions are displayed, executed or evaluated. Typically this involves setting a hidden page item and testing your condition against that item in the “Conditional Display” pane within the developer mode.

When developing applications with tabs (and sub tabs) you’ll discover that you cant process the request value for your tab as Apex manages the branch conditions for you.

An example scenario may be where you want to clear the page cache only on new requests. One method to get round the problem is to create a hidden item on page 0 and called “P0_PAGE_NEW”

Navigate to Applications -> Shared Components -> Application Processes and hit “create” in the application builder.

Create a process which runs “On Submit: After Page Submission – Before Computations and Validations”.

In Process Source Type the following
IF (:REQUEST = 'T_YOUR_TAB_NAME’) THEN
:P0_PAGE_NEW := 'Y';
END IF;
Now you can create a “On Load – Before Header” session state page process to clear the session that is conditional on :P0_PAGE_NEW being set to ‘Y’. Once you’ve cleared the page cache, just set :P0_PAGE_NEW to ‘N’ in a “On Load – Before Header” pl/sql page process which runs unconditionally with the following source:

begin
:P0_PAGE_NEW := 'N';
end ;
The cache should now be cleared with every new page visit.

Now imagine, you have one or more tabs which point to the same page. Ideally you would like to have each tab a cause a different action or set of items to be displayed (hypothetically). To do this you can just add to the application process you have created but instead you would set you page mode type item on the page. From there it is a simple matter of conditioning your processes, items and regions to executed or be displayed against that page mode item

Labels: , ,

Tuesday, June 19, 2007

Create table as select for LOV generation


If your creating Apex applications on a regular basis then sooner or later you will have made use of LOVs. Recently I needed to create an lov using the data contained within USER_TAB_COLS as a starting point.

A feature of Oracle DDL allows you to create and populate a table from a sql query. For example
create table test_lov_table as
init_caps(replace(COLUMN_NAME,'_', ' ')) COLUMN_NAME
,CHAR_LENGTH
from user_tab_cols
where TABLE_NAME = 'my_table';


The above code only serves as an example but got me thinking whether this technique could be useful anywhere else. Purely speculating I thought that this could be something to consider if your migrating data from older systems and need to take portions of your data model to create reference data tables for LOVs. Another purely hypothetical situation where this may speed things up is where you need to map one schema's tables, columns to another's tables and columns (through the respective user_tab_cols table) i.e for the purpose of interfacing two data models again.

Labels:

Wednesday, May 16, 2007

Call Java Methods from ApEx

For those new to ApEx it may not be immediately obvious that it is possible to execute Java Methods from ApEx. Newbies to Oracle database programming may also be surprised to know that you can actually embed Java in the database at all! The fact that this is possible make the Oracle Database Server very powerful making almost everything possible. If you cant code it in PL/SQL then try Java, If you can't use Java then perhaps you are doing something wrong (or need to go back to basics).

Why would you want to call Java from ApEx applications?

PL/SQL is great but there are occasions when you may need to perform complex processing that simply is not possible with PL/SQL, is too complex to implement or requires the use of third party APIs. One such example may be an image conversion process, which converts a GIF to a JPEG programmatically (granted I know this is possible with Oracle Intermedia).

As regular readers know I’m currently involved in a piece of work which requires various third party Java APIs which can strip out user entered data from a PDF to XML. We then process this relationally using good old pl/sql and relational views over xml. Apologies to those who thought this post might be looking at that topic, I am still writing it up and need to prepare suitable example, which can be downloaded and played with, so please bear with me.

Pre-requisites

  • Oracle Database with Java Support ( See Product Matrix )

  • A DB schema with relevant schema privileges to execute Java.

  • ApEx (pretty much any version will do)

How do you do it?

Calling Java from the Database is a fairly trivial task typically consisting of the following 3 steps.

  • Writing the Java Classes

  • Loading the classes/code into a target database schema

  • Creating a PL/SQL Wrapper round the Java Method you wish to call.

If you need to load pre-compiled java classes into your schema you can use a very useful tool called loadjava. You will need to use this utility if you have existing JAR files and APIs. Hopefully I’ll explore loadjava in a later post, for the moment I would like to concentrate on demonstrating a very simple example of calling a Java method from within Apex. I’m afraid that means it is a “hello world” example as it does not require any pre-compiled classes to be loaded into the database.

Step 1. Create Java Class

The following code creates and compiles a java class called HelloWorldExample. Notice that any method you wish to call from pl/sql must be declared as static. You can copy and paste the following code into sqlplus or sqldeveloper.


CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "HelloWorldExample"
AS
public class HelloWorldExample
{
HelloWorldExample hello;

public HelloWorldExample()
{
hello = new HelloWorldExample();
}
public static void sayHello(String forename, String surname
, String outString[])
{
outString[0] = "HELLO WORLD more specifically hello" + forename
+ " " + surname;
}
public static void main(String[] args)
{
//no method
}
};
/
show errors java source "HelloWorldExample";
/
You should see :
AND COMPILE Compiled.
No Errors.

Step 2: Create a pl/sql call spec/wrapper

In order to use your Java method from Apex or PL/SQL you must create a pl/sql call specification wrapper round each Java method you wish to run from PL/SQL.

Again copy and past the following code into sqlplus/sqldeveloper:

CREATE OR REPLACE PROCEDURE HELLO_WORLD(p1_forename in VARCHAR2
, p2_surname in varchar2, p3_outString out varchar2)
AUTHID CURRENT_USER AS LANGUAGE
JAVA NAME 'HelloWorldExample.sayHello(java.lang.String
, java.lang.String , java.lang.String[])';
/
show err;
/
Step 3: Execute to test

Executing this Hello World example is as easy as declaring an anonymous block and calling the method from within within. For example:

declare
p_forename varchar2(4000) := 'KRISTIAN';
p_surname varchar2(4000) := 'JONES';
p_msg varchar2(4000) := null;
begin
hello_world(p_forename, p_surname, p_msg);
dbms_output.put_line(p_msg);
end;
Again if completed correctly you will see :
Anonymous block completed
HELLO WORLD more specifically hello KRISTIAN JONES
Hopefully this has served as a gentle introduction into embedding Java classes in the database. You can call this from procedure from ApEx page as a pl/sql process just substitute in your page items. If anyone has any queries please leave a comment. I'll do my best to reply.

Labels: , , , ,

Wednesday, May 02, 2007

ApEx - BRANCH_TO_PAGE_ACCEPT

A colleague who also works for Oracle Consulting has recently blogged about a very useful and not so well known feature of ApEx. BRANCH_TO_PAGE_ACCEPT is a special type of request value which basically allows you to branch to a page, passing in a page item value, skip the page rendering and goes straight to page processing.

Effectively this feature allows you to submit a page with a number of page item values to another page (where the processing functions are located) without the user actually visiting the page through interaction.

The post can be found here: http://atulley.wordpress.com/2007/04/30/branch_to_page_accept/

Although I can think of a number of potential uses for this I don't want to steal Andy's thunder. So I suggest you check his blog from time to time, he has some excellent stuff on there.

Labels: , , ,


 

View My Stats RSS Feed (Atom)