Wednesday, December 23, 2009

Overriding the Java toString method using For loop

This solution uses a combination of reflection, constants and regular expressions to build a meaningful toString output:



private String TO_STRING_FIELDS = "email isPKI isTrustedRoot isITU_TX509 caName"

@Override public String toString() {
try {
StringBuilder result = new StringBuilder();
//String newLine = System.getProperty("line.separator");
String[] fieldList = TO_STRING_FIELDS.split( "[\\s,]+");
Field curField = null;
for (String f : fieldList) {
curField = this.getClass().getDeclaredField(f);
result.append(" " + f);
result.append(": ");
//requires access to private field:
result.append( curField.get(this) );
}
} catch (Exception e) {
System.out.println("Error in toString for class: " + this.getClass().getName() + "\n" + e.getMessage());
}

return null;
}

Refurbishing a Morgan 30

Hull Preparation and Painting

After all the work I did restoring my Flying Scot this summer, I can imagine what a labor (of love) this Morgan 30 refurb was. There are a lot of great tips and experience to be gleaned from his notes.

Tuesday, December 22, 2009

Flex Relative paths for embedded images in buttons with @Embed

Flash, Flex and ActionScript: Relative paths for embedded images

Setting the @Embed source with an absolute path (based on flex_src root) :
<mx:Button icon="@Embed(source='/assets/blue_delete.png')" />

Wednesday, December 2, 2009

as3corelib Contains Crypto Utils for FLEX MD5 Hash

I needed to store MD5 hashed passwords in the database and was delighted to find the as3corelib already contains the necessary libraries.  While there are many more features, I only needed the MD5 Hash function so I only copied in the com.adobe.crypto.MD5 and com.adobe.utils.* files.  With the .as files added to my Flex project, hashing the password was a simple as calling:

    MD5.hash( passwordComp.getPassword() );

 

I verified that it returns the same hash as the MySQL MD5 function

UPDATE user_table SET password = MD5(‘change_me’) WHERE username = ‘sandman’

Monday, October 26, 2009

Dynamically position a Flex popup relative to a button mouse click

I was having trouble with positioning a wide popup window that was in a component nested several containers deep.  The PopUpManager.centerPopUp method would center on the container and push the window off the right edge of the screen.  To correct this, I moved the popup over 100 pixels using:

popup.x = popup.x – 100;

That worked, but the problem would come back if the window grew wider.  Bush league.  To make it a bit more reliable, I changed to use the mouseEvent localX/Y properties.  Note you have to convert the “local” coordinates to “global”:

 

      private function showPopup(event:MouseEvent):void

        {

            pop = EnotaryRegReturnPopup(PopUpManager.createPopUp(this,EnotaryRegReturnPopup,true));

            pop.title = "Please select return reasons.";

            pop.showCloseButton =true;

            pop.enotaryRegReturnList = this.enotaryRegReturnList;

            pop.buildUnselectedReturns();

           

                  // position the window next to the "add" button

            var pt:Point = new Point(event.localX, event.localY);

            pt = event.target.localToGlobal(pt);

            pop.x = pt.x - pop.width;

            pop.y = pt.y;

           

            pop.addEventListener("close",removeMe);

            pop["cancelButton"].addEventListener("click", removeMe);

            pop["okButton"].addEventListener("click",processReturns);

        }

 

 

Monday, October 5, 2009

Delete rows from DataTable using DataRow

I was surprised by the delete functionality in DataTable.  It was my understanding that when you call DataRow.Delete it marks the row for deletion, but waits for a DataTable.AcceptChanges call before actually removing them, but when I tried to delete inside a For Each dr as DataRow in dt.Rows I was getting an error “Collection was modified”.  Thankfully I ran across a thread that suggested walking backwards through the collection to avoid those types of errors.  I ended up with this to solve my problem:

 

        Do While i >= 0

            If dt.Rows(i)("KEEP_ME"))) = False Then dt.Rows(i).Delete()

            i -= 1

        Loop

        dt.AcceptChanges()

 

 

Monday, September 28, 2009

DOS BAT File Copy Rename with String Manipulation

I needed to rename a directory of files to truncate the file names to the first 5 characters (plus the file extension).  I found one example that showed how two write a FOR loop that broke out the filename and extension and passed it to a second BAT file:

for /f %%a IN (’dir /b *.txt’) do call runner.bat %%~na %%~xa

And using a second example that covered DOS string manipulation, I put together this batch file that accepts two parameters and does a substring to get the first 5 characters of the first parameter:

set file=%1
set file=%file:~0,5%
ren %1%2 %file%%2

 

Thursday, September 17, 2009

Creating an Asynchronous ASP.NET Page To Initiate Batch Processes

I recently created a page that gave the user the option of initiating a long-running batch process.  The batch required repeatedly calling external web services that would have taken far too long for a user to wait for the traditional page processing model.  But, by using ASP.NET asynchronous execution to initiate the batch process on a separate thread, the page response is excellent.  I started by working through this excellent tutorial on asynchronous execution, but quickly ran into problems when I began calling web services.  Creating an asynchronous process involves writing a method that can execute without needing anything from the HttpContext (Application, Page, Session, Cache, Configuration, etc.) since this is not available when you use BeginInvoke to run your subroutine.  This presented me with an issue since my project had a library that we used to setup web service instances (with WSE security), but that library relied on the HttpContext’s Application object.  To work around this limitation, I created a private inner class that encapsulated the web service references. 

    Private Class WebSvcInstances

        Public FSI As MyWseSVc1 = GetMyWseSVc1

        Public PSI As MyWseSVc2 = GetMyWseSVc2

    End Class

The inner class was passed into the batch method while the Application object was still available and providing the objects the batch would need later.

To start off, create the subroutine you want to initiate asynchronously:

    Private Sub InitiateBatch(ByVal wsRefs As WebSvcInstances)

Create a Delegate in your code behind with the same signature as the subroutine:

    Private Delegate Sub Batch_Delegate(ByVal wsRefs As WebSvcInstances)

Then you can initiate your subroutine in a page event like so:

    Dim batchDelegate As InitiateBatch_Delegate

    Dim wsRefs As New WebSvcInstances

    batchDelegate = New InitiateBatch_Delegate(AddressOf InitiateBatch)

    Dim asyncResult As IAsyncResult

    asyncResult = batchDelegate.BeginInvoke(wsRefs, Nothing, Nothing)

You can read up on BeginInvoke to learn more about the callback features.  I didn’t need to be notified when the execution finished, so I just set those to Nothing

Before and AFTER


It hasn't taken quite as long as the lack of blog posts would have you believe, but the refurbishment of Flying Scot 338 is nearly complete. In addition to the fairing and painting, I've just finished replacing the gooseneck and standing rigging, installing a boom whoopie, turtle bags and guy hooks. I hope to get the transom port, bow bag, and stem band on before the Boathouse Regatta this weekend. I am SO glad I have a Flying Scot since the class builder has been SUPER helpful including instructions with all of the replacement parts.

Painting recap:

After talking to another club member who did the same paint job (but rolled everything) I should have been more aggressive with sanding the primer. I was concerned about sanding too much off and not hiding the yellow gel coat so I wet sanded with 220. My friend said he used 80-100 on the primer which I now wish I had done (with a long board)...but time was limited. I didn't think I'd have a chance to put a 2nd primer coat on.
I am very impressed with the shine and durability of Interlux Brightsides so far. I don't think I've scratched any paint off, though it's only been a couple months of light use.
During the refurb, I decided to tackle the bottom as well, painting it with VC Performance (a 2-part epoxy) and given that experience, I think I would be more willing to attempt a 2-part poly for the topsides next time. A warning about VC Performance though: it is extremely thin (runny), being designed to spray on. They say it is possible to brush/roll it on, but it would seem far easier to spray given my limited experience. My "spray rig" consisted of a $99 compressor and $15 gravity fed gun, both from Harbor Freight.

Centerboard:

As earlier pictures showed, my centerboard was in terrible shape. The leading edge was so badly damaged, there was actually a large accumulation of clay between the lead balast and the outer fiberglass causing a bulging in the airfoil shape. I ended up cutting out a curved section of fiberglass from the leading edge (both sides) and repairing it with about 4-5 layers of 1.5oz mat. I faired the repair and other leading edge defects with Interlux Watertite and finished with two coast of VC Performance (after removing LOTS of bottom paint) the board looks almost new.

Thursday, May 14, 2009

Removing boat bottom paint


I read somewhere that the best tool for removing bottom paint is your checkbook. After my experience, I would have to agree, but it can be done. Apparently the pros sandblast the stuff off. Not being a pro, I turned to Google and read about several different methods for DIY: scraping, stripping, and sanding being the top three. In the end, I believe the most efficient way is to scrape AND sand.
Important tip: have a file in your pocket and keep the scraper sharp. The copper bottom paint dulls the scraper quickly. To sharpen, you have to lay the file down and hold the scraper perpendicular to the file. Just a few strokes makes a huge difference.
Flying Scot #338 had several layers of bottom paint so scraping removed a bunch of material, but did not remove the last layer of paint. The picture above shows the results of scraping on the right and after sanding on the left. I sanded using a 1-2 punch of a 6" sander with 50 grit lightly and carefully run over the paint to remove 95% and then a 5" orbital sander with 80 grit to get the last bit off and smooth out the agressive grit. This process took about 1 hour for the first side, second side TBD...

Monday, April 27, 2009

Fairing and repainting a Flying Scot

I will be blogging regularly about this year’s refurbishment of Flying Scot 338. Last weekend I removed all of the hardware including rub rails. This weekend I removed the centerboard (with the help of the club hoist). Launched the 338 onto dry land – a very unnaturally feeling. And, with the help of 3 club members, flipped the hull onto low sawhorses. Next up, cutting the bad balsa out of the aft deck and removing the bottom paint. I feel itchy already.

Take a look at that centerboard. I got a chance to give it a close inspection while we were…uh…sideways a few weeks ago. I think I see why light air has never been kind to us!

Thursday, April 9, 2009

Configuring Oracle XE connection pool in Glassfish and Using JPA

I followed these instructions for creating an Oracle JDBC datasource. I needed to download the Oracle JDBC driver (ojdbc14.jar) into my <Glassfish>/lib directory and restart the server. After that the “Ping” was successful.

In “step 2” I had to specify 4 properties: user, password, url, and xa-driver-does-not-support-non-tx-operations.

Next I needed to create a JDBC resource that my persistence.xml file would reference.

With those tasks complete, I modified an existing EJB 3 JPA project to utilize the new connection pool. All that was necessary was to change two lines in the persistence.xml file. First was to point to the new JNDI name:

<jta-data-source>jdbc/AMRPool</jta-data-source>

And second was to change the “toplink.platform.class.name” (now deprecated) to:

<property name="toplink.target-database" value="Oracle"/>

After redeploying the JAR the CUSTOMER table was added to my schema. I re-ran the test client and was delighted to find a record in the table. Bravo to the Java community!

Wednesday, April 8, 2009

Excellent EJB 3 Persistence Tutorial

It had been a long time since I have visited the land of Java. When I was a regular traveler there, I remember feeling inundated by the rapidly progressing proliferation of APIs. JMS, JNDI, RMI, CMP, and on…and on…and ON. The technologies and vendors were spawning and/or evolving so fast and from so many directions it was difficult to stay current. From what I can see the frameworks have matured and are stabilizing. While there are still many innovations occuring, the rate of change does not appear to be the dizzying pace that I remembered.

To get up-to-speed on the current J2EE release, I dutifully installed the latest version of the open source Java EE 5 implementation…something called GlassFish. It has a decidedly un-Microsoft feel about it. I had flashbacks of all the previous Weblogic/Tomcat/Apache configuration nightmares and had to steel myself for navigation through the narrow passages in the reefs surrounding a modern Java app server. I have found…in general…that Java technologies are much less tolerant of the neophyte and the learning curve seems significantly steeper than the reciprocal Microsoft technology (“platform agnostic”…I know…I know).

I also downloaded the Java EE tutorial and attempted to follow it using Eclipse instead of the recommend NetBeans because I had previously used Eclipse and thought it was generally a great IDE. In doing so, I ran into trouble with creating the EJB example that was entirely related to my inexperience…and the 50 different project types Eclipse now ships with out of the box. I left the Sun script and started working through simple JSP examples just to get some tiny amount of momentum built. After following the online documentation, success was not far behind.

Then I ran across the EJB 3 persistence topic and decided that looked interesting, particularly hibernate.org. The top tutorial on the matter…as declared by Google, was from Web Age Solutions. It was short enough that it didn’t scare me off so I dove in with low expectations of a working example. I was pleasantly surprised by the author’s accuracy and brevity. The logical and successful progression was refreshing and rewarding. By the end of the tutorial, I had a basic understanding of the Java Persistence API (JPA) and a new level of respect for the current Java specification. Bravo!

http://www.webagesolutions.com/knowledgebase/javakb/jkb006/index.html

Wednesday, March 4, 2009

Data densification using Oracle Partitioned Outer Joins

I ran across a feature of Oracle 10g called Partitioned Outer Joins while tracking down the answer to another problem. Rather than get side tracked, I made a note to check them out at a later time and I’m glad I did. I frequently get specifications for reports where the data has gaps, but the report should be continuous, regardless of the presence of the data. The typical example is when you want a customer sales report, but some months a customer has no orders. Oracle-Developer.Net has a great article explaining how to create just such a query (and proper use of WITH). The first helpful piece of SQL is a WITH clause to generate a “time dimension” of continuous months

WITH year_months
AS (SELECT To_char(Add_months(DATE '2004-01-01',ROWNUM - 1), 'YYYYMM') AS year_month
FROM dual
CONNECT BY ROWNUM < 12)

Adding the Partition clause turns out to be quite straightforward:

SELECT co.name,
ym.year_month,
Nvl(Sum(co.amt),0) AS total_amount
FROM year_months ym
LEFT OUTER JOIN customer_orders co
PARTITION BY (co.name)
ON (To_char(co.dt,'YYYYMM') = ym.year_month)
GROUP BY co.name,
ym.year_month
ORDER BY co.name,
ym.year_month;

Wednesday, February 25, 2009

Use Oracle Table Function to Encapsulate and Modularize your Data Layer

I finally ran into a situation where I wanted the functionality of a Table Function so I was forced to learn the PL/SQL way to do this. In this case, the benefits of accepting parameters made the Table Function a clear winner. To start off you need a table:

CREATE TABLE cool_people (
cp_id NUMBER(8,0),
first_name VARCHAR2(30),
last_name VARCHAR2(30))

Next you need a new TYPE that describes a single “row” of your Table Function’s output. In my contrived example, I’m only returning a formatted name:

create or replace TYPE PEOPLE_OBJ AS OBJECT(

PERSON_NAME VARCHAR(100));

Now that we have created the new type of OBJECT, we can declare a TABLE of that new type:

create or replace TYPE PEOPLE_TABLE AS TABLE OF PEOPLE_OBJ;

Now we can create our function that accepts a parameter of CHAR:

CREATE OR REPLACE FUNCTION
TFN_GET_COOL_PEOPLE (formatName CHAR)
RETURN PEOPLE_TABLE PIPELINED
IS
fName VARCHAR(30);
lName VARCHAR(30);
p1 PEOPLE_OBJ := PEOPLE_OBJ(NULL);
CURSOR C1 IS
SELECT FIRST_NAME,
LAST_NAME
FROM COOL_PEOPLE;

BEGIN
OPEN C1;
LOOP
FETCH C1
INTO fName,
lName;

EXIT
WHEN C1%NOTFOUND;
IF formatName = 'Y' THEN
p1.PERSON_NAME := lName
|| ', '
|| fName;
ELSE
p1.PERSON_NAME := fName
|| ' '
|| lName;
END IF;
PIPE ROW (p1);
END LOOP;
RETURN;
END TFN_GET_COOL_PEOPLE;

You can then use the function in a FROM clause:


SELECT * FROM TABLE(TFN_GET_COOL_PEOPLE('N'));

Monday, February 23, 2009

Private stored procedures in an Oracle package

I never knew you could write a procedure in a package that isn’t declared in the package declaration.  It’s kind of like a private function/subroutine since it can’t be called by anything outside of the package…which is how I discovered this “feature”.  I was trying to call an “undeclared” procedure from a different package.  I had already written another procedure that called it from its own package, so I was mighty confused about the error I was getting: “MY_PROC must be declared” but now it makes perfect sense. 

One other discovery I made is that you can pass NULL as a parameter to another procedure instead of declaring a null valued variable.

Tuesday, January 6, 2009

Using GeoIP's GeoLite to find an IP address City using C# .Net

There’s a terrific open source product offered by MaxMind called GeoLite City that is a binary (or CSV) database for doing IP location lookups.  There are many flavors of the GeoIP API that provide optimized access to the .DAT file, including C# and VB.Net (Country only).  The C# version is a collection of 5 classes and is very easy to use:

Dim ls As New LookupService("C:\GeoIP\GeoLiteCity.dat")
Dim IPLoc As Location = ls.getLocation(IPString)