Inserting Text into an Oracle Database Schema: ORA-01461

Today I ran into an interesting problem. A portion of our software saves the text of database DML statements into an Oracle schema. We had been allocating 4000 bytes of a VARCHAR2 column in order to store that text. We’ve been using this software to analyze customer’s applications for about a year now and hadn’t run into any difficulties with this setup.

Today, while persisting some data about a customer’s form application, our software started to blow up, throw Oracle ORA-01461 errors. The text of the error is “can bind a LONG value only for insert into a LONG column.” At first glance it seemed obvious enough, we were trying to insert a LONG value into a column that wasn’t a LONG column.

The first thing to realize is that a LONG value in Oracle’s database world is NOT a Long value in Java. Since there were about 6 of these types of fields being inserted into a table, that was my first bad assumption, that one of these was wrong. Of course, they all matched up to the columns in the table correctly, but assuming that something strange was going on in the driver, I manually switched these statements to setting BigDecimals instead of long’s. Naturally, this didn’t help at all.

I did turn out to be correct on one count, however. Something strange was happening in the driver. After being puzzled for a bit longer, I called in a developer to help me talk through the problem, and as often happens, just talking about the problem often brings new insight into the situation.

I realized while explaining to this developer that a LONG does not equals a Long, that the problem must lie in the text fields. Duh. So, since I was debugging at that point already, I inspected the values I was trying to insert and realized that one of the text fields was actually pretty large. So large, in fact, that the eclipse debugger couldn’t show me the entire value. It did let me know that the String i was looking at was almost 15,000 characters in length, however.

Aha! So, checking the table structure showed me that the column was set up for VARCHAR2(4000). Apparently, instead of the driver throwing an exception that the value was too large for the column, because the String is over 4000 characters long, it automatically converted it to a LONG datatype and tried to insert that resulting in the ORA-01461 error I was seeing.

To test this theory, I put in some code to check the length of the String and truncate it to 4000 characters if it was longer than that. Voila, no more errors. Of course, I’ll have some work to do to change the column type, probably to a CLOB like the rest of our really long text fields, but that is going to mean changing some code around since CLOBs are not as easily read from the database as VARCHAR2’s are, but at least the problem is isolated.

In my search for information about this error I did not see anything that mentioned this, so I thought I post it to hopefully help some other poor sucker that’s butting his head against his keyboard in frustration due to a similar issue. Hope this helps!

ADF 11g: Using Custom Properties To Create Update-Only View Objects

One of the cool features of the ADF Business Components layer in 11g is the ability to add custom properties to Entity or View objects. It’s a neat feataure but up until this point I hadn’t really any need to use them.

Then, when I was trying to implement a View object as only allowing updates, not inserts or deletes, I learned that there isn’t really a way to declaritively do this in ADF 11g. It seemed like one of those things that should be available, but the help says this:
“Some 4GL tools like Oracle Forms provide declarative properties that control whether a given data collection allows inserts, updates, or deletes. While the view object does not yet support this as a built-in feature in the current release, it’s easy to add this facility using a framework extension class that exploits custom metadata properties as the developer-supplied flags to control insert, update, or delete on a view object.”

The above quote is from section 37.11 of the Fusion Developer’s Guide for Oracle ADF. The section is actually titled “Declaratively Preventing Insert, Update, and Delete” which sounded like exactly what I wanted, but when i read the section I found that little bit of discouraging news. The last few words were encouraging, I thought using custom proerties to control insert, update, or deletes would be perfect, then I read on.

The next couple paragraphs seem to indicate that it would be a good idea to create instances of the view object that are called ViewObjectInsert, ViewObjectUpdate, and ViewObjectDelete, generic framework code could be used to look for these View instances and based on if a custom property is set then blah, blah, blah. I think it actually said something about looking up the phase of the moon also.

I’m not sure why you would want to have custom instances to determine whether or not customer properties should be looked up or not, why not just use custom properties? Anyway, that is the route I decided to take and it turned out to be pretty simple.

Chirs Muir had written an article on using custom properties to automatically convert the case of input and I used his article along with the help section of the Fusion Developer’s guide to come up with this solution. Thanks Chris!

1. Create a custom ViewObject implementation class.
This is done by creating a class that extends the Oracle View Object.

Create a New Java Class

Create a New Java Class

1a. Right click on the package you would like your custom class to reside in.
1b. Click on Simple File in the left pane and Java Class on the right pane.
1c. Name the file and make sure it extends the ViewObjectImpl class.

2. Create a method to check the custom property.

     private boolean isAllowed(String action) {
         boolean result = true;
         if (getViewDef() != null) {
             if (getViewDef().getProperty(action) != null) {
                String actionProperty = (String) getViewDef().getProperty(action);
                if (actionProperty != null) {
                    if ("false".equals(actionProperty)) {
                        result = false;
                    }
                }
             }
         }
         return result;
     }

3. Override the appropriate methods.
3a. Override the createRow method to check if Create is allowed, and if it isn’t throw an exception.

    public Row createRow() {
        if (isAllowed("insert")) {
            return super.createRow();
         } else {
            throw new JboException("Create not allowed in this view");
         }
    }

3b. Override the removeCurrentRow method in the same way.

    public void removeCurrentRow() {
        if (isAllowed("delete")) {
             super.remove();
         } else {
            throw new JboException("Delete not allowed in this view");
         }
    }

4. Add the necessary declarations to the View Object you wish to have these features.
4a. Add the following line to the attributes of the View Object to have it implement the framework class.

	ComponentClass="com.vgo.demo.framework.MyCustomViewObjectImpl"
Add Custom View Properties

Add Custom View Properties


4b. Add the necessary custom properties to the View Ojbect. Click on the General section of the Overview tab of the view object. Open the section for Custom Properties and click the green plus. Change the name to “insert” and the value to “false”. Click on the green plus to add another cusom property, name this one “delete” and set the value to “false”.

5. That’s it, it is that simple. Now run an Application Module that contains that View and try to insert or delete, when you do, you should see the exception that is thrown to inform the user that the action is not permitted.

Error Message for Insert Shown

Error Message for Insert Shown

As you can see, custom properties in ADF 11g are sure to prove extremely useful in the future, I am sure this is but one potential use for them.

Using Conditional Breakpoints

Conditional breakpoints are a great way to reduce debugging time and one of those features you might not even have known existed. This article will cover how to use them in 3 different ide’s including NetBeans, Eclipse and JDeveloper.

Have you ever tried to debug a problem that only occurs somewhere in a list of 100 objects? It can be a bit of a hassle.

You could put in a breakpoint and hit continue each time that breakpoint is hit until you find the problem object. This is acceptable the first time, but often the first time isn’t going to cut it.

You could put an if statement in your code to check for the condition that is causing the problem, but then you need to remember to remove that if statement after you fix the problem. Often my if statements in the past would have looked like this:

i f (problem.exists()) {

System.out.println(”This is the problem.”);

}

And I’d set a breakpoint on the System.out.println line.

A much better approach is to make use of conditional breakpoints available in most modern IDE’s.

NetBeans Breakpoint Editor

In NetBeans, create a breakpoint, the right click on the little pink square that signifies the break. Click on “Customize”. When the customize dialog comes up, check “Condition” and fill in the condition. Above is an example of this dialog in NetBeans.

Eclipse Breakpoint Properties

To accomplish the same thing in Eclipse, create your breakpoint, then right-click on the little blue dot signifying the breakpoint and choose “Breakpoint Properties”. In the Properties window, check “Enable Condition” and then fill in your condition or conditions in the box provided. An example is shown above.

Finally, to accomplish the same in JDeveloper (TP4, anyway), set your breakpoint, right click on the little red circle that appears. Then click on “Edit Breakpoint” and in the dialog that pops up, move to the “Conditions” tab. You can set your conditions there as shown in the picture above.

So now that you know, from now on, no more useless breakpoints!

And if you’ve still been debugging using System.out’s, I’m sorry I wasted your time. I’m sure Vi is just sitting there flashing it’s cursor at you waiting for you to save those changes.

Create and Deploy a JavaFX WebStart Application

I realized when I updated my FlashCard JFX game that I could not remember what I actually had to do in order to create a deployable Java WebStart application. So that I always had a simple reference to refer to, I’m posting it here. Hopefully this will help someone else.

Basically, a JavaFX application is typically deployed through Java Web Start, so I think most of these instructions will apply to any Java Web Start application. Steps 1 through9 are from the help in NetBeans itself. The part about signing the jars is from Kirill Grouchnikov’s blog.

1. Use NetBeans - there are other ways, but this is a requirement to follow my way.

2. Install the JavaFX plugin.

3. After running your project locally and making sure it works and all the dependencies are there, right click on the project and choose “Properties” from the menu.

4. Choose Categories: Application -> WebStart.

5. Check “Enable WebStart”.

6. Fill in the codebase to the directory where you will copy up the dist folder to on your web server. For me it is “http://www.java-hair.com/downloads/flashcardjfx/dist”

7. Choose “Run” from the Properties list.

8. Name the configuration and check “Run with Java Web Start”.

9. Clean and build your project.

10. Cd to the dist directory of your Java FX project.

11. Run keytool using something similar to this:

keytool -genkey -keystore javahair.keys -alias http://www.java-hair.com/ -validity 365

12. Sign your main jar by running something similar to this:

jarsigner -keystore javahair.keys -storepass ***** FlashcardJFX.jar http://www.java-hair.com/

13. Cd to the lib directory in your dist and sign all the jars there like so:

jarsigner -keystore ..\javahair.keys -storepass ***** javafxrt.jar http://www.java-hair.com/

14. FTP all the contents of your dist directory to your webserver to the codebase directory you specified in step 6.

Now link to the launch.jnlp file in that directory and you should be good to go.

The older articles in this how-to can be found here:

Learning JavaFX

JavaFX Example - FlashCard Game

JavaFX FlashCard Source Code and Web Start Link

Adding Sound to the FlashCard JavaFX Game

Adding Sound to the FlashCard JavaFX Game

I finally had a small amount of time to look into adding sound to my flashcard java fx example, something I have wanted to do for a while now. When I finally got the time, I realized that it isn’t so difficult since most of the hard work has already been done.

The first step in adding any major functionality to an application like this is searching Google to see if anyone has done this before. I found an example of using MP3’s in a JavaFX application, but I didn’t like it. I didn’t like it because the article seems to point to using this embeddedmp3 library which I did not see the source for. The library in the article, however, is based on JLayer, and JLayer is what I used for my FlashCard game.

After including the 1.0 version of JLayer into my project, I created a utility class to be used for playing the np3 files. I called it Mp3.java.

What I wanted was a class that would hold a reference to the mp3 to be played for a particular card, so I decided that it would have a private attribute to hold that location. My first mistake was forgetting the type of application I was dealing with and I used a String pointing to the actual file to hold the location. I looked at what I was doing for images and just did the same sort of thing.

For the images I was storing them inside the jar itself in a package “flashcardjfx.img”, so for the mp3’s I put them in a package called “flashcardjfx.sounds”. The constructor for my Mp3 class (which at this point, is not really a util anymore, but once I put it in that package I was too lazy to move it) takes a String that is the location. I saw that the JLayer Player needs an InputStream so I created a FileInputStream on that location and was storing that.

When I tried to test my application, I kept getting an error that the file could not be found. I think when I moved the mp3’s to a c:\sounds directory, they were found, but that wasn’t going to help me much when I deployed. So, what to do? Well, after playing around with it for a little while, it dawned on me, that the String I was passing to the Image was not for a file, but a URL. Of course, right? I am dealing with JavaFX here and an application running via Web Start. So… once I changed my reference from a File to a URL, bingo!, it all started coming together.

My MP3 class is shown here, it is also now included in the down-loadable source code.

public class Mp3 {
    private URL url = null;

    public Mp3(String url) {
        try {
            this.url = new URL(url);

        } catch (IOException ex) {
            Logger.getLogger(Mp3.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void play() throws FileNotFoundException, JavaLayerException {
        try {
            //Make sure to open and close the player each time!
            Player mp3Player = new Player(url.openStream());
            mp3Player.play();
            mp3Player.close();
        } catch (IOException ex) {
            Logger.getLogger(Mp3.class.getName()).log(Level.SEVERE, null, ex);
        }
    };  

}

Simple, right? Not much to it. To use it in my FlashCard JavaFX class I had to add a private variable to hold the “Mp3″.

private attribute mp3: Mp3;

Then, at the end of the flip() operationI added this line:

mp3.play();

And that is about it to get it to play.

For the constructor, I added a String to the location of the mp3 and I just set my mp3 variable to a new Mp3 instance based on that location:

   operation FlashCard.FlashCard(aWord:String, anImage:String, aMp3:String) {
      mp3 = new Mp3(aMp3);
      word = new Word(aWord);
      cardImage = new CardImage(anImage);
   }

Now to create a new flashcard, I just pass in the mp3 location as well as the word and the image location.

insert new FlashCard("cat", "{__DIR__}/img/cat.png", "{__DIR__}/sounds/cat.mp3") into flashcards;

It has dawned on me that if I keep the naming structure the same, I only need to pass in the word, but that may be too much menial cleanup work for something that is just an example.

So the new source is available where the old source was: here.

The application itself can be launched by clicking here. You can thank my youngest daughter, Cassie and myself for the voicework. I will probably update with a version that does not use my voice, as either her’s or her sister’s is much better.

The older articles can be found here:

Learning JavaFX

JavaFX Example - FlashCard Game

JavaFX FlashCard Source Code and Web Start Link

I’ll be posting an article about deploying since I couldn’t remember how to do it this time either.

ADF 11g Master-Detail Part 2

This tutorial explains how to add some useful functionality to the Master-detail page we created in the last tutorial. The first thing you will need to do in order to follow along is to follow the steps in that post.

Today we will add some functionality to allow the user to add, edit, and delete employee records from the detail table.

1. Adding Read-Only Views

1a. Before we get started with the view, let’s add a couple of ADF Business Components to our Model layer. We are going to want to create a couple of drop down lists, so to do that, we need a Read Only view that can populate the drop down list.

1b. Right-click the Model project, choose New, then choose ADF Business Components from Tables.

1c. Do not choose to create any Entity objects since we have the two we already need from last time. Same deal with Updateable Views, so click Next on both of those screens.View of ADF LOV

1d.On Step 3 of the “Create Business Components from Tables” wizard, select Employees and Locations and choose to create Read-Only Views for those two tables. Rename the new Employee View to ManagerView.

2. Adding “List of Values”

2a. Open the EmployeView in the Model project. Click on the ManagerId attribute.

2b. Underneath, on the toolbar that says “List of Value” click the green plus-sign to open the List of Values wizard. Click the green plus and choose the ManagerView from the left-hand list of available view and move it to the right-side list of View Accessors. Click OK.

2c. In the top pane, open the ManagerView and click on EmployeeId, then click the green plus underneath the “List Data Source” pane. JDeveloper should add ManagerId under View Attribute and EmployeeId under List Attribute which means it is linking the managerid in the EmployeeView to the EmployeeId in the ManagerView.

2d. Click on the UI Hints tab and choose “Choice List”.

2e. Repeat the steps to create a “List of Values” for Department using the Departments view.

3. Create an Edit Page

3a. Make an Edit page for Employees. Create a new JSF JSP page in the ViewController project. Let’s name this page employeeEdit.jspx. If you feel like it, drag a panelHeader onto the page and change the label to “Employee Edit”.

3b. Open the AppModuleDataControl under the Data Controls pane on the left-hand side of JDeveloper. Open the DepartmentsView1 node and drag EmployeesView3 onto the panelHeader in your jspx page.

3c. The ManagerId and DepartmentId fields should show that the component is a choice list based on the UI Hint we provided to the View. You can change it here, but you do not have the option here to change it to a popup List of Values, to do that, you must change it back in the UI Hints on the View. Click on “Include Submit Button” and click “OK”.

4. Create a Task Flow

4a. Let’s create our first Task Flow. To do this, right-click on the View project and select New. From the menu, select Web Tier -> JSF on the right side of the wizard and ADF Task Flow on the left.

4b. Name the task flow masterDetail-task-flow-definition.xml. Make sure you don’t have “Create with Page Fragments” checked and click OK.

4c. In the properties of the task flow, on the behavior tab, set the data-control-scope to “isolated”. In TP4 it is set to “shared” by default and would therefore require a parent task flow.

4d. Drag a “View” component from the ADF Task Flow component toolbar onto the Task Flow design sreen. Name this View “masterDetail”. In the properties panel, set it’s page property to the masterDetail.jspx page.

4e. Drag another “View” component, set it’s name to “employeeEdit” and set the page property to the employeeEdit.jspx page you just created.

4f. Drag a “Control Flow Case” component and drop it onto the masterDetail View object. Then drag it over to the employeEdit View object. Name the Control Flow Case “edit”.

4g. Create a Control Flow Case going from employeeEdit to masterDetail and name it “return”.

4h. Back on the emoplyeeEdit.jspx page set the action for submit to “return”.

5. Getting it to actually Do Something

5a. To make the components lay out nicely, drag a panelGroup layout component over in between the department table and the employee table. Then drag the employee table into the panel group.

5b. Add a button to the panel group. Change the label on the button to “Edit”. Set the action to “edit”. Notice that the name you had provided in the Control Flow Case is available for use as an action for the button. This is a beautiful thing.

5c. Add Commit and Rollback buttons to the page by dragging them from the AppModuleDataControl.

6. Play With It!

You now have added a seperate edit page to the application, hooked it up using a task flow, and rolled all of it into one transaction, all without writing a single line of Java code. If you are a Java developer, you may be wondering what’s going on under the covers and I encourage you to dig in and find out! You’ll especially want to understand how task flows work and how the transactions are managed.

Anyway, I’ll leave as a next step for the student to add a create button.

How To Create A Master-Detail Page in ADF 11g

This article builds upon the last article in which we created an updatable Departments list page. In this tutorial, I will expand upon that page by adding a detailed list of Employess in the page that refreshes when the user clicks on a new department row. I will use a partial page refresh so that only the Employee table refreshes, not the entire page.

1. The first thing to do is to create the business components as described in the first tutorial. When you are creating the business components from tables be sure to select Departments and Employees both.

2. Next, create a JSPX page in the ViewController Project.

3. Drag a panelHeader component onto the page and set the text property to “Department Master Detail”.

4. Drag a panelGroupLayout component onto the page and set the alignment property to “Horizontal”.

5. Drag the DepartmentsView1 view instance from the AppModuleDataControl into the panelGroupLayout and choose Tables -> ADF Table from the menu presented to you. In the pop-up I deleted all the fields except for DepartmentId and DepartmentName, select row selection at least from the options on top, in this example I selected all three options, row selection, sort, and filter. Set the id property of the table to “departmentMaster”. You need to make sure that row selection is enabled so that ADF will enable you to select a row in the table and this is the event that will trigger the detail table to refresh. Be sure to Save All.

6. In the AppModuleDataControl, open the DepartmentsView1 node and drag the EmployeesView3 view instance into the panelGroupLayout. Choose Tables -> ADF Read-Only Table and select the columns you want to appear. Also check off at least row selection when creating the table. The key for this is to make sure that you use the view instance that is associated with your “master” view, in this case DepartmentsView1, if you use the other EmployeesView instance, the list of employees will not be in sync with what you select in the Departments table.

7. In the properties of the of the emplyees table set the id to “employeesDetail” and set the partial triggers property, found in the Behavior tab to the id of the master table, i.e. “departmentMaster”. This will tell ADF to refresh the employees table when an event is fired on the departments table. Be sure to Save All.

At this point, you have created a page that will allow you to select a row in Departments thereby refreshing the list of associated employees. We have not yet added any button to actually accomplish anything really useful yet, but we will get to it soon.

One item to note is that this will work as described in Tech Preview 3 of JDeveloper 11g, if you are using Tech Preview 4 to follow this tutorial you will notice that this will only work once or twice before you get a whole mess of validation errors. This is because of a problem with the Technical Preview 4 build that includes a JSF library that isn’t what it was developed with, the discussion is described here. The best fix for now is in the view of the jspx page, switch to the source view and comment out all of the tags that you find in there.

The Dark Side of Frameworks: Part II

My last post about frameworks criticized the Spring JDBC Template construct. I don’t really have anything against Spring in particular, I had just stumbled across the JDBC Template a few days earlier and thought it may help make my point. My point, which I attempted to illustrate by that post, was not that the Spring JDBC Template is useless, it is that frameworks in general, which exist to simplify development of complex technologies, by their nature redirect that complexity somewhere else. Hopefully that new complexity is less than the underlying technology and this is often the case. As an architect/designer/developer you should be aware of that the trade-off exists, what the trade off is going to be and make an informed decision.

1.  Configuration Files

Since I used Spring as an example once before, let’s move on to another one of my other favorite frameworks, Struts. Struts has seemed to have fallen out of favor of late, with many developers now hopping on the JSF bandwagon, including our shop. I had to basically be dragged away from it and forced into JSF. However, even though Struts was my framework of choice for years, it had some problems that really bugged me and are issues that still exist today in many frameworks.

One of the nice things about Java is that you can use a smart IDE and it will spot a lot of careless errors for you, especially simple typos. This is important for someone like me who likes to type fast and can tend to be somewhat careless. What I found with Struts is that I often had problems first setting up projects. For some reason I would always end up with a typo in the struts-config.xml file that would cause it to break when starting my application. Struts was never very good at letting me know what the exact problem was and this never ceased to infuriate me, so much so in fact, that one of our products, Rev, was born out of that frustration because it insured that I wouldn’t have to worry about typos impeding my ability to get an application up and running quickly. I continued to use Struts because it’s benefits outweighed it’s difficulties, it didn’t abstract too much of the HTTP layer so I could still understand what was going on pretty easily.

2.  Too much abstraction

Next, for me, came JSF. I actually only started using it because a project we were working on required a technology that was built upon JSF. Once I started using it, I could appreciate how it’s abstraction of the HTTP layer really made things easier for developers, especially for newbies who didn’t really know much about the HTTP layer. All of this abstraction, however, made it difficult to understand what was happening underneath the covers or exactly how it was happening. Some of the simple Javascript patterns I had been using in Struts to solve some common problems became more difficult. Have you ever looked at the source HTML to a JSF-backed page? It’s not nearly as simple and straight-forward as a page developed from Struts. I am still uncomfortable with the fact that I don’t know exactly how to create a request in JSF to accomplish some things seemingly trivial things, whereas the same things in Struts were really easy.

The other problem that I found as we continued to use the framework was that I could have developers who understood JSF and worked in it really well, but they didn’t understand some of the underlying concepts. When something unexpected happened, they weren’t sure where to look. This would occur when a developer’s first experience with developing web applications was with JSF.

That same problem occurs with any framework, since by their nature they abstract the complexity of some underlying technology. This is all well and good until things break. Obviously, Java itself is an abstraction of underlying technology, do I think we’d all be better off going back to assembly language and programming web applications in that? Of course not, but I think as a developer you should be aware of the pro’s and con’s of the frameworks you use.

You should also take it upon yourself to learn something of the underlying technologies so you aren’t completely clueless. I have interviewed plenty of so-called JSP developers who couldn’t tell me what pieces of code were executed on the server and which on the client, who didn’t understand the underlying concept that once your page was executing in the browser, you weren’t able to execute java commands inside a function in a page. I could understand how a newbie might have some problems with that, but an “experienced” JSP programmer?

3.  The Problem with Fixing #1 and #2

Often, with frameworks that become popular, it’s because the abstraction they provide is more useful than the underlying technology by itself and any new complexities it may introduce, it allows developers to become more productive, hopefully much more productive.

In my opinion, Oracle’s new version of ADF, 11g, is a framework that does just that, but it isn’t without it’s share of compexities either. ADF 11g makes a lot of building a web application declaritive. This may be a good thing, but again, you run into the problem of having to deal with many XML files. Oracle alleviated this problem to a very large degree by creating JDeveloper 11g which can handle building and validating the XML files for you. However, now we have a new problem. There are some mismatches between JDeveloper 11g and ADF 11g. In some cases, just because JDeveloper tells you something is wrong doesn’t mean it is wrong and won’t work. This hints at a larger problem: that both JDeveloper and ADF need to be maintained and released on the same cycles. If one falls behind in respect to changes that were made to the other, the usefulness of the collaboration between the two is degraded.

Also, again in ADF 11g, there is a larger issue. That is, if something acts in an unexpected manner, the developer now needs to understand an additional layer of complexity in order to debug the problem. Often the developer will need to resort to asking the experts via a forum or a bug report. Even if the product is open source and the developer could access the code itself, finding and fixing a problem deep within the framework will obviously detract from the usefulness of the framework itself.

None of these “dark sides”of frameworks are reasons not to use them, I use or have-used all of them, these are just issues that you should be aware of and investigate before using a framework. My “issues” (some may describe these as pet peeves) can be distilled into two main items, 1. Increased abstraction often leads to less understanding and 2. Declarative programming creates its own problems.

Obviously we are going the way of more abstraction, not less.  It will be  a great day when we no longer have to worry about the framework we are using breaking and exposing us to the dirty underbelly of technology behind it all.

</rant>

The Dark Side of Frameworks

Framework seems to be a pretty hot buzzword these days. Not that it hasn’t been for years, but now more and more clients are asking for frameworks for all kinds of things. Frameworks upon frameworks actually.

The most recent example is a client who wanted a framework that would wrap the way you could call stored procedures via JDBC. I was originally against the idea, but being all about customer service, I know when to give up the fight and just roll with it. What one of my developers ended up creating is a framework that wraps JDBC and allows you to save a few lines of code per procedure call, not bad really, but not really enough to change my mind about the whole thing in general.

I could see why they liked the idea, it did hide some of the perceived complexity from the user of the framework, but the reality was it really didn’t do too much more than make sure the close statement was in a finally block and allow the user of the framework to bypass seting all the parameters in a callable statement.

One framework we looked at using instead of creating our own was the Spring framework’s wrapper for JDBC. I don’t want to start a flame war, but honestly, what’s the deal with that monstrosity? What does it actually simplify? From the examples in the documentation I looked at, it seemed simple enough, but that was only because it was doing simple things. When I took a look at called Stored Procedures it didn’t look so simple any more.

Take the example of calling the sysdate() function from Oracle. This is the code for JDBCTemplate:

import java.sql.Types;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.sql.DataSource;

import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.datasource.*;
import org.springframework.jdbc.object.StoredProcedure;

public class TestStoredProcedure {

    public static void main(String[] args)  {
        TestStoredProcedure t = new TestStoredProcedure();
        t.test();
        System.out.println("Done!");
    }

    void test() {
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("oracle.jdbc.OracleDriver");
        ds.setUrl("jdbc:oracle:thin:@localhost:1521:mydb");
        ds.setUsername("scott");
        ds.setPassword("tiger");

        MyStoredProcedure sproc = new MyStoredProcedure(ds);
        Map results = sproc.execute();
        printMap(results);
    }

    private class MyStoredProcedure extends StoredProcedure {

        private static final String SQL = "sysdate";

        public MyStoredProcedure(DataSource ds) {
            setDataSource(ds);
            setFunction(true);
            setSql(SQL);
            declareParameter(new SqlOutParameter("date", Types.DATE));
            compile();
        }

        public Map execute() {
            // the 'sysdate' sproc has no input parameters, so an empty Map is supplied...
            return execute(new HashMap());
        }
    }

    private static void printMap(Map results) {
        for (Iterator it = results.entrySet().iterator(); it.hasNext(); ) {
            System.out.println(it.next());
        }
    }
}

This is as excerpted from Chapter 11 of the Spring Framework Reference Documentation.

I am positive that if I showed that to the client as an implementation they would ask for a framework to wrap it to hide the complexity and what is the point in that?

The same thing is accomplished just using JDBC as follows:

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.SQLException;

public class TestStoredProcedure {

    public static void main(String[] args){
        TestStoredProcedure t = new TestStoredProcedure ();
        t.test();
       System.out.println("Done!");
    }

    public void test() {
        Connection connection = getConnection();
        String myDate = null;
        try {
            myDate = test(connection);
        } catch (SQLException e) {
            //Might want to do something more useful here.
           e.printStackTrace();
        } finally {
            try {
                connection.close();
            } catch (SQLException e) {
                //don't care right now if we can't close it.
            }
        }
        System.out.println("Date:"+myDate);
    }

    public String test(Connection conn) throws SQLException {
        String result = null;
        CallableStatement proc = conn.prepareCall("BEGIN ? := sysdate(); End;");
        proc.registerOutParameter(1, java.sql.Types.DATE);
        proc.execute();
        result = proc.getDate(1).toString();
        proc.close();
        return result;
    }

    public Connection getConnection() {
        Connection conn = null;
        try{
            Class.forName("oracle.jdbc.OracleDriver");
            conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe","scott","tiger");
        } catch (ClassNotFoundException e1) {
            e1.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

}

So what was gained with the framework? To me it doesn’t seem like much. I’m not sure where the exceptions went to, do I get a Runtime exception if sysdate isn’t a function? I guess it means the user doesn’t have to access the CallableStatement or ResultSet directly and that *may* be a good thing to some people. IMHO saving yourself from learning JDBC just means that you won’t know what the problem may be when things start to go wrong and you just limited your skillset to a framework that not everyone is going to use.

Many frameworks are useful and I realize this part of the Spring framework is one small piece that probably isn’t used by very many people, but again, that’s kind of my point. Why bother with that piece at all?

How To Create An Editable List Page in ADF 11g

For those of you wondering how my presentation turned out in Atlanta this past Monday, I can tell you, it turned out very well technically, but as far as attendance was concerned it wasn’t exactly an arena-sized audience. I think the user’s group itself is more centered around DBA’s which is typical for these types of events.

This post covers one of the basic techniques I demoed in my presentation on Monday. A simple editable list page. I will do a series of posts starting with this basic concept and expanding upon it in subsequent posts adding functionality as we go.

An Editable List Page

A common type of functionality in a lot of Oracle Forms applications is to have a list of records in a block and allow the user to edit those records, delete those records, and even create new records.

In ADF 11g, this would translate to a JSP page that allows you to list the rows in a View, edit and delete from those rows and also create new rows. This functionality is actually very easy to create.

Let’s go over it step by step.

1. Create a new application in JDeveloper (File -> New -> Application(Fusion App)

JDeveloper will use a template to create the basic project and file structures needed for an ADF application.

2. Create the necessary Business Components from Tables.

Right-click on the Model project JDeveloper created in the previous step. In the New dialog, open the Business Tier node and choose ADF Business Components. In the right pane, choose Business Components from Tables.

You will now need to create a new database connection. Click the New button where it appears next to Database Connection. Set the name to something appropriate and set the attributes accordingly. You can use the Test Connection button to insure it gets created correctly.

Click OK and you should be back at the ADF Business Componens Wizard.

Click the Query button to the right of the wizard and JDeveloper will return a list of available tables and views that you can create Entities from. Select Departments and move it over to selected, then click on the Next button.

The next screen is the Updateable View Objects Screen, move the Entity over to the “Selected” column. Press “Next” and take all of the defaults until you can click “Finish”.

Click the “Save All” button.

3. Create the JSP Page

Right click on the ViewController project. Select “New”.

From the left pane, choose Web Tier -> JSF, from the right pane, choose “JSF Page’. Click “OK”.

Give the page a name like departmentList.jspx (We use the x at the end to denote an XML compliant JSP page, but it isn’t necessary).

Once the page has been created, open the Component Palette. Make sure the component list is “ADF Faces”. From the layout pane, choose the panelHeader and drag it onto the page. Click on the properties panel and change the text propery to “Department List”.

From the right side of the IDE, in the Data Controls pane, open the AppModuleDataControl. Click on the DepartmentsView1 object and drag it into the panelHeader. Choose Tables -> ADF Table from the create menu that pops up. At the confirmation dialog check Sorting, Filtering, and Row Selection to enable these features for the table. JDeveloper will create a table on the JSP page.

Next, drag a panelGroupLayout component from the Component Palette over to the panelHeader. Click on the properties list and change the layout from scroll to horizontal.

Next, open the DepartmentsView1 node in the AppModuleDataControl, open the Operations folder, drag the CreateInsert button into the panelGroupLayout. Click on properties and change the name of the button to “Add”.

Drag the delete button from the Operations folder over into the panelGroupLayout.

Open the Operatons folder of the AppModuleDataControl itself, it will have two operations, Commit and Rollback. Drag them over into the panelGroupLayout next to the other two buttons.

Congratulations! You’ve done it. Right click on the JSPX file and choose Run to see your masterpiece in action. You should be able to add rows into the table, edit existing row, and delete existing rows. None of it will be persisted to the database until you click “Commit” and you can always “Rollback” all your changes. You should also be able to filter the table with the input boxes on top and Sort it with the little triangles on the columns.

If you play with this example you may notice a couple little “bugs” or “features”. In my next post I will discuss a couple of these and how to mitigate them.

In the following weeks I will be expanding upon this simple demo to include ADF Task Flows and creating separate pages for creates and edits as well as a Master-Detail page or two.