Saturday, February 26, 2005

Iterators in Java

Coming from a background in C# for the past couple of years, I am so glad to see the Java SDK add constructs that I have used in the past.

In a personal project that I am working on, I had created a couple of enumeration classes.  The classes had a lookup() method that I used to allow me to assign a particular enumeration label to a variable by looking up a particular id of one of the enumeration constants.  To facilitate the lookup of a particular enumeration value, there was a private array of all the available enumerations in the particular class.  The lookup() method was pretty straight forward...


//.. lookup procedure expects an id pass in
for ( int i = 0; i < available.length; i++ ) {
    if ( available[i].getId() == id ) {
        return available[i];
    }
    return null;
}
I decided at work yesterday to come home and setup the latest milestone release of Eclipse so that I could play around with JDK 5.0.  After getting that working, I refactored my enumeration classes to be actual enum classes now that Java 5 has the new enum keyword.  With that refactoring, I was able to make use of the new for-each style of iteration that Java 5 has added.  So, my lookup() method on the enumeration classes now look like this...

//.. lookup procedure still expects an id passed in
MyEnumType[] available = MyEnumType.values();
for ( MyEnumType e : available ) {
    if ( e.getId() == id ) {
        return e;
    }
    return null;
}
I have been used to this style of construct in C# which has the for-each style of iterations for a collection.  For a new Java developer, this method might be a little harder to understand.  There is not the explicit notion of having checking each object in a particular collection like you have in C# where you say “for each ...”, but I feel like this is a little cleaner code than the style where you use the index property, which could always lead to problems itself.

Of course, Java had the older style of iterations where you could get an iterator and then calling hasNext() on each loop iteration, but it is a bit more to type and it is nice to have the compiler itself be a little smarter in situations like this where I am looping over a collection and checking every object in the collection.

Technorati Tags: , , ,

Wednesday, February 16, 2005

Using INSERT..SELECT with MySQL

I have been working on a small application at home lately which is going to use MySQL for data persistence.  I was messing around with my tables tonight and got into a situation where I wanted to add data into one table using the last inserted value from the auto_increment primary key field in another table.

According to the documentation for MySQL, I should be able to use LAST_INSERT_ID(), but I couldn't figure out exactly how to get it to pull the last inserted ID from a different table.

So, I then tried the following code...

INSERT INTO table2 (id, field1, field2) SELECT NULL, 4, id FROM table1 t WHERE t.id IS NULL;
According to some information that I found in a comment posted on the documentation for the INSERT..SELECT command on the MySQL documentation site, this should give me the last inserted ID from the first table.  Nope... this results in no errors and no rows being added to the table.  Very weird!

Finally, I came up with the following...

INSERT INTO table2 (id, field1, field2) SELECT NULL, 4, MAX(id) from table1;
So far, this seems to give me the results that I am after.

Technorati Tags:

Tuesday, February 15, 2005

Adding a new DataRow to a DataTable

This is one little item that I never can seem to remember, because I just do not use it that often, so I thought I would commit it to my blog.

When creating a new DataRow that you want to subsequently add to a DataTable, you generally create the columns that you need for the rows and then you add data values. The code for this looks something like this...

    DataTable ErrorTable = new DataTable();
    ErrorTable.Columns.Add(new DataColumn("Fault Code Namespace", typeof(string)));
    ErrorTable.Columns.Add(new DataColumn("Fault Code Name", typeof(string)));
    ErrorTable.Columns.Add(new DataColumn("SOAP Actor that threw Exception", typeof(string)));
    ErrorTable.Columns.Add(new DataColumn("Error Message", typeof(string)));
    ErrorTable.Columns.Add(new DataColumn("Detail", typeof(string)));
    DataRow row = ErrorTable.NewRow();
    row["Fault Code Namespace"] = error.Code.Namespace;
    row["Fault Code Name"] = error.Code.Name;
    row["SOAP Actor that threw Exception"] = error.Actor;
    row["Error Message"] = error.Message;
    row["Detail"] = HttpUtility.HtmlEncode(error.Detail.OuterXml);


There is a simpler way to write the code above which sets up the data values and adds the DataRow to the DataTable. That code can be written in one line like this...

    ErrorTable.Rows.Add( new object[] {error.Code.Namespace, error.Code.Name, error.Actor,
    error.Message, HttpUtility.HtmlEncode(error.Detail.OuterXml)} );


The code is definitely not more readable and is probably more of a headache for someone to come along later and maintain, but it is easier to type the first time around. :)

Technorati Tags: , , ,

Thursday, January 06, 2005

Make sure that CLASSPATH is correct

I had an issue with a java class today that I was trying to execute from the command line.  I kept getting the following error:

Exception in thread "main" java.lang.NoClassDefFoundError: Example
After doing a little research, I found that my CLASSPATH variable was set to c:\junit3.8.1\junit.jar which was not allowing the virtual machine to properly find the binaries it needed to execute the class.  After clobbering the CLASSPATH variable (“set CLASSPATH=“), everything worked as expected.

Update
Someone that I work with gave me a good tip today that I did not know regarding Java and how it parses the CLASSPATH variable.  Make sure that you have a dot in the path declaration at the end.  In other words, in my case, the CLASSPATH would be something like this:

CLASSPATH=.;c:\junit\junit3.8.1\junit.jar
For those of you who can't quite see it, that is a period at the beginning of the CLASSPATH declaration.  This tells Java to use the current directory when searching for classes and JAR files.

Technorati Tags: ,

Friday, December 10, 2004

Adding a DataTable to a DataSet

I have been doing a lot of web service work for my job lately. I am getting data back from application and returning it to PeopleSoft. I ran into a small issue when trying to setup a new DataSet. I wanted to include only certain rows of data from one of the tables that I was getting back in the DataSet that the web application, which I am integrating into our online system, was returning.

The line of code that I was using to add the DataTable to my DataSet was quite simple...

dtNewData.Tables.Add( dsAppData.Tables[0] );
Almost immediately, I found that was causing a real problem. I kept getting an error that said “DataTable already belongs to another DataSet”. I did some searching on Google and finally found that you cannot simply add a table to a DataSet that already exists in another DataSet. Luckily, there are ways around this.

The most simple way to get around this issue is to make a copy of the table before adding. This is achieved with a very simple change to the line of code above:

dtNewData.Tables.Add( dsAppData.Tables[0].Copy() );
Unfortunately, this did not meet my needs, because I only need the first few rows of data from the original table. My final code ended up looking like this:

dtNewData = dsAppData.DataSet.Copy();
while (dsAppData.Tables[0].Rows.Count > RequestedRows)
{
DataRow dr = dsAppData.Tables[0].Rows[dsAppData.Tables[0].Rows.Count-1];
dsNewData.Tables[0].Rows.Remove(dr);
}
This created a copy of the entire DataSet and just removes the unwanted rows at the end of the table. Originally, I did a clone of the table and used ImportRow(), but this method seems to be just a little faster.

Technorati Tags: , , , ,

Saturday, November 20, 2004

DataTable.ImportRow method confusion - DUH!

I wrote some code in a web service the other day to pick off the first few rows of a data in a DataTable that was returned to me from someone else's data engine. The code that I wrote looked something like this:

DataTable dsTemp = new DataTable();
for (int i = 0; i <>

When I started testing the code, I found that my table was coming back with zero data rows. I was puzzled by this, because I had read the documentation for ImportRow, which states:
Calling NewRow adds a row to the table using the existing table schema, but with default values for the row, and sets the DataRowState to Added. Calling ImportRow preserves the existing DataRowState, along with other values in the row.

Well, after doing a little searching on the web, I realized that I had read this documentation incorrectly. I thought that the “existing table schema” that it was referring to was the table that you are importing the rows from, which would give your new table the same schema. Wrong! You must already have your schema set for the table that you are importing rows into. Thus, to fix my code, I made a couple of small changes:
DataSet dsTemp = ds.Clone();
for (int i = 0; i <>

Once I made this change to the code, the data was returned from my web service just as I had expected. You live and learn.

Tuesday, October 26, 2004

Consuming Web Services with HTTP Post

When I first started working on a web service project a few weeks ago, I put together a small ASPx page that uses HTTP Post to call the web service. This made it somewhat simple to test. I could easily change the input values and re-submit without having to change some code and recompile an application that uses the web service.

This worked great on my laptop where I accessed everything on localhost. As soon as I migrated the project to our development server for testing that all changed. I spent a couple of days trying to figure out if I had inadvertently changed my web service code and caused this problem. I ended up writing that application that I mentioned to see if that would work. To my bewilderment, it did.

After doing some searching, I finally found some very useful information in ASP.NET Unleashed, Second Edition last night that helped solve my problem. For security reasons, in ASP.NET 1.1 a web service can only be accessed using SOAP. HTTP Post and HTTP Get are both disabled by default. HTTP Post still works on a local machine, which is why I did not have a problem at first.

To enable the use of HTTP Post or HTTP Get from remote machines, you will have to edit the Web.Config file for your project:















XML to XHTML via XSLT - revisited

I worked on the XSLT project again today. I am basically taking a dataset from a web service and putting it in a tabular format for display. I successfully applied the stylesheet enhancements today. That was a no-brainer. I had never worked with stylesheets in HTML before, so I did not realize just how easy it would be. The project that I am working on is, obviously, quite simple, but it is nice to do something different and learn something new for a change.

One thing that I definitely learned about XSLT today is that you should have well formed tags. In other words, every tag must have an end tag.

Wow! Working sure makes the day go by faster. I should do it more often!

Monday, October 25, 2004

SOAP Message Content-Length

I am working with someone to properly understand how to call an ASP.NET web service from PeopleSoft. After several tries, I finally saw down at the keyboard Sunday night and put together some code to call the web service from a Java application. I learned very quickly that if you do not have all your ducks in a row, most likely, the SOAP request will not work.

The thing that I struggled with the most last night was getting the Content-Length value set properly. When I thought I had it set just right, I would use the code to access a different web service with different parameter names and it would no longer work.

I finally figured out after a lot of trial and error that the Content-Length value in the POST header for the SOAP message only includes the length of the content in the SOAP message body, which is encompassed by the tags.

XML to XHTML vis XSLT

Too many acronyms there. I started playing around with a new technology today. Welll, it is new to me, anyway. I am having to transform some data from a web service into HTML. I have only started working with XSLT. I am doing some very basic transformations which takes the data in the XML dataset and put it in a tabular format that is easily read by the viewer of the pagelet.

I downloaded the Unicorn XSLT Processor to do the transformations after I created my XSLT. It is command line driven, but it works well for what I am doing.

One thing that I need to do next is learn how to apply a style sheet (CSS) to the HTML as I do the transformation so that I can get the proper look that I want.