We setup the scanner portion of our office printer/scanner/fax machine today. Upon scanning, the printer/scanner/fax images the document, saves it as a PDF and emails out to whomever you picked to send the image to. I received the PDF in my email in my client of choice, Thunderbird (version 2.0.0.9 (20071031) using IMAP) and when attempting to open it, received the following error message from Adobe Acrobat reader:
"The was an error opening this document. The file is damaged and could not be repaired"
I downloaded an alternative Win32 PDF reader, Foxit Reader, and gave that a shot, only to receive a similar message. I contacted a colleague who also received the test message to find out she was able to open the PDF with no issues using Outlook. With that info, I went to my webmail client and was able to open the PDF file with no issue. So the problem was with Thunderbird.
After a quick Google search, I found several postings from other folks with a similar predicament, mostly from attempting to hook Thunderbird to the new released Gmail IMAP ports. I came across the following nugget of information which immediately corrected my problem....
Original source thread
In the "about:config" section of Thunderbird (Tools > Options > Advanced > Config Editor) look for the "mail.imap.fetch_by_chunks" and " mail.server.default.fetch_by_chunks" values and set them to "False".
Mozillazine gives some more information about what this value actually does here
Tuesday, November 20, 2007
Sunday, November 11, 2007
Oracle Mix
Saw on the Oracle AppsLab blog a reference to Oracle Mix. I signed right up because I like the direction Oracle is taking with trying to encourage and foster a tighter sense of community among itself and its users. I am hoping this is one step closer to creating an environment where the community (especially on the apps side) can share and contribute projects openly (i.e., sourceforge).
So if you are interested, invite me to join your group in the Mix.
http://mix.oracle.com
So if you are interested, invite me to join your group in the Mix.
http://mix.oracle.com
OpenWorld 2007 - Day 0
Great day for a drive to San Francisco. Joe took me detour past the old Oracle headquarters in Belmont on Davis Drive where he used to work.
Check-in was a breeze cause we are alum. Oracle doesn't give out much swag at all, go we got the usual book bag, notepad, umbrella and various adverts.
We made it to the keynote at 5:45PM to hear Larry recount the history of Oracle. He even showed a pic of the old offices in Belmont (the ones we toured earlier in the day). Some of the ex-cast of Saturday Night Live (Kevin Nealon, Darrell Hammond, and I can't remember the other one) where there to add some humor to the mix.
The reception after the keynote had the usual food and drink.
Up tomorrow...
08:30-10:15 - Keynote Charles Phillips
11:00-12:00 - Intro to Oracle BI Publisher
12:30-13:30 - Oracle SOA Suite Best Practices
14:00-14:45 - Keynote ?
15:15-16:15 - Highlights of Agile PLM
16:45-17:45 - Ready, Set, XML - Using Oracle XML Data
18:00-19:00 - Keynote ?
19:30- - OTN Night
Check-in was a breeze cause we are alum. Oracle doesn't give out much swag at all, go we got the usual book bag, notepad, umbrella and various adverts.
We made it to the keynote at 5:45PM to hear Larry recount the history of Oracle. He even showed a pic of the old offices in Belmont (the ones we toured earlier in the day). Some of the ex-cast of Saturday Night Live (Kevin Nealon, Darrell Hammond, and I can't remember the other one) where there to add some humor to the mix.
The reception after the keynote had the usual food and drink.
Up tomorrow...
08:30-10:15 - Keynote Charles Phillips
11:00-12:00 - Intro to Oracle BI Publisher
12:30-13:30 - Oracle SOA Suite Best Practices
14:00-14:45 - Keynote ?
15:15-16:15 - Highlights of Agile PLM
16:45-17:45 - Ready, Set, XML - Using Oracle XML Data
18:00-19:00 - Keynote ?
19:30- - OTN Night
Tuesday, November 6, 2007
Oracle OpenWorld 2007
Been buried the last several weeks working on our HCM 8.9 Absence Manage implementation. This project is quite a change from the usual since there hasn't been much technical work to date, most of the time has been focused on validating formulas and other setup data.
I am scheduled to be at OpenWorld next week and am very excited to be attending. There are lots of good sessions held by Oracle and I feel fortunate to be able to attend sessions held by big name folks like Tom Kyte, Jim Marion, Shay Shmeltzer, et al. I also have a list of questions that I hope to get some potential answers too from the experts roaming in the exhibit hall.
The best thing about conferences like this is the energy. You can't help but get excited and energized about technology and the potential it has. Compare this to a typical morgue-like day at work, and I always come back wishing everyday was an OpenWorld day.
I am scheduled to be at OpenWorld next week and am very excited to be attending. There are lots of good sessions held by Oracle and I feel fortunate to be able to attend sessions held by big name folks like Tom Kyte, Jim Marion, Shay Shmeltzer, et al. I also have a list of questions that I hope to get some potential answers too from the experts roaming in the exhibit hall.
The best thing about conferences like this is the energy. You can't help but get excited and energized about technology and the potential it has. Compare this to a typical morgue-like day at work, and I always come back wishing everyday was an OpenWorld day.
Thursday, October 11, 2007
PeopleTools 8.4x - Finding references to a particular record field
Found a feature today that I had never seen before (don't laugh if you've been using it for years). If you bring up a record in Application Designer and right-click on a field there is an option to Find Definition References - Record Field. In the past I had always just opened the field and from the Edit menu selected Find Definition References, which brings back usage of the field on any object (record, page, peoplecode, etc.). The Find Definition References - Record Field limits the search to only the usage of that field on that particular record.
It is always nice to find a feature like this when you really need it...
It is always nice to find a feature like this when you really need it...
Thursday, September 27, 2007
IRC still alive and well
It had been a long time since I'd been on Internet Relay Chat (the real IM), so the other night I fired up Chatzilla and checked out a few channels like #jquery, ##java, ##linux and saw quite a bit of conversations taking place. If anyone reading this knows of good channels related to things like Java, general open source, portals, or enterprise development please drop a comment.
Wednesday, September 26, 2007
Commented out code...please use version control
I had to look through some code today to troubleshoot an issue. The code had tons of comments. You might say, wow that's a good thing right? Wrong, the comments were not comments about what the code was doing (or trying to do). Instead, the comments were commenting out old code dating back who knows how long. This makes the code so difficult to read and understand when the lines of old junk outnumbers the lines of code that is actually live and doing something.
There are so many great, free revision control systems available today (subversion, git, mercuial, bazaar), old code belongs in a revision control system and not in current code.
There are so many great, free revision control systems available today (subversion, git, mercuial, bazaar), old code belongs in a revision control system and not in current code.
Tuesday, September 25, 2007
Dynamic Application Class loading in PeopleSoft
When Application Classes were first introduced in PeopleTools and they included interfaces, I knew that there had to be some way to dynamically load an application class. A lot of my recent work has been in the HR Recruiting module (Candidate Gateway) that delivers hundreds of classes.
Quite a few of the classes handle things like page layout and validation, things we definitely wanted to modify. They even delivered a lot of "factory" like classes that their code calls and all it does is return an object of a certain type. It seemed like a perfect setup for being able to customize the look and feel and behavior by simply supplying custom application classes. However, the implementation classes are hardcoded in the factory methods. So while there is a way to substitute the implementation of a certain class it still requires a modification to delivered code.
The Approvals Framework, on the other hand, is a perfect example of how application classes should be used. It is completely built around the concepts of dynamically loading classes at runtime based on values entered in setup tables. No code modifications are required, you just create your class and enter the fully qualified name in a setup table. The framework looks up the class you specify, loads it up dynamically at runtime and then calls the methods on it.
An example (code changed to protect the innocent):
The framework can then lookup the class name in a setup table and call the methods it provides. It knows what methods it can call based on the fact that my class must extend a class they know about (BaseEventHandler).
PeopleSoft, which knows nothing about my custom class, is able to load it up and use it. This is a very powerful and elegant way to provide custom functionality without requiring anything more than an entry in a setup table. Unfortunately, I haven't yet seen many places where this type of extensibility is used in PeopleSoft 8.9.
Quite a few of the classes handle things like page layout and validation, things we definitely wanted to modify. They even delivered a lot of "factory" like classes that their code calls and all it does is return an object of a certain type. It seemed like a perfect setup for being able to customize the look and feel and behavior by simply supplying custom application classes. However, the implementation classes are hardcoded in the factory methods. So while there is a way to substitute the implementation of a certain class it still requires a modification to delivered code.
The Approvals Framework, on the other hand, is a perfect example of how application classes should be used. It is completely built around the concepts of dynamically loading classes at runtime based on values entered in setup tables. No code modifications are required, you just create your class and enter the fully qualified name in a setup table. The framework looks up the class you specify, loads it up dynamically at runtime and then calls the methods on it.
An example (code changed to protect the innocent):
class MyEventHandler extends BaseEventHandler
method onApprove();
method onDeny();
...
...
end-class;
...
The framework can then lookup the class name in a setup table and call the methods it provides. It knows what methods it can call based on the fact that my class must extend a class they know about (BaseEventHandler).
Local string &clazz = /* sql lookup here */;
Local BaseEventHandler &object;
&object = CreateObject(&clazz) as BaseEventHandler;
&object.onApprove();
PeopleSoft, which knows nothing about my custom class, is able to load it up and use it. This is a very powerful and elegant way to provide custom functionality without requiring anything more than an entry in a setup table. Unfortunately, I haven't yet seen many places where this type of extensibility is used in PeopleSoft 8.9.
Sunday, September 23, 2007
Notepad++ 4.3 released
Notepad++, my favorite text editor, released version 4.3 this week. Looks like mostly bug fixes and a few new features.
AJAX and PeopleSoft
After Ethan sent me the link to the PeopleSoft Auto-Save with Ajax post on the ITToolbox site I was inspired to try AJAX on a PeopleSoft page (and excited to try the jQuery library for the first time as it looked very cool). The blog post on the ITToolbox site had some great javascript code, but offered no details on how the whole thing was put together. Below are the exact steps I took to add AJAX to a page in PeopleSoft.
Before I get started I want to point out that I decided against trying the auto-save feature. While I think that this type of feature would be extremely useful in some use cases, I feel the Component you implement it with must be designed for it. Auto-saves should be saved as drafts and should not effect the current data stored in the tables. When the user actually clicks some sort of Save button, only then should the auto-saved data replace the data that existed before.
To simply my AJAX/PeopleSoft experience I decided to just create a dynamic DIV on an existing page. The DIV is updated periodically by sending an AJAX request to an IScript function which returns HTML that is placed directly into the DIV. This was done with PeopleTools 8.46.17.
Step 1.
I opened the Page I wanted to AJAX-ify and added an HTML Area control to the top of the page (specifically I added DERIVED_PTP.HTMLAREA).
Step 2.
I downloaded jQuery 1.2.1. I grabbed the "packed" version which is the smallest weighing in at only 26kb. As the ITToolbox entry hinted at, I tried adding the downloaded contents to an HTML object. However, when I tried to save the object in Application Designer I got the following error:
Object size exceeds 32K limit. Proceed with Save?
It let me save it anyway so I named the HTML object FR_JQUERY. When I opened up the page I received several javascript errors and when I looked at the cache javascript file that was created I found it was truncated. This happened when I used the code from the ITToolbox site:
In order to make it work I added the contents of the packed jquery.js to a Message Catalog Entry (more details below).
Step 3.
I created an HTML object named FR_ISSUE_LOG_SRCH_DHTML with my code and a bind variable that I would later replace with the jQuery library. Here's the HTML object code:
FR_ISSUE_LOG_SRCH_DHTML HTML Object
Step 4.
On the Page Activate event I added the following code to populate the HTMLAREA field I had previously added to the Page.
What is noteable here is that the entire contents of the jquery.js file are stored in the Message Catalog and placed in the HTMLAREA using the %bind(:1) substitution variable. In our environment we can not easily added files to the webserver directory, so this provided a nice solution that did not require me to add any files to the webserver.
Step 5.
Finally, I created an IScript function that simply does a SQL Fetch for all rows entered in our custom table for the particular user viewing the page.
This was just an experiment on my part and only rates a 1 out of 10 on the coolness meter. My primary motivation was just to see how feasible it was to use AJAX on a PeopleSoft page. I was quite happy to find that it was easier than I expected (save for my little issue with placing the jquery.js code on the page). Also, I was able to dabble a lot with jQuery and find that it makes DOM manipulation and AJAX very easy and I will find a use for it in my next project.
Unlike the ITToolbox post, I was not attempting to interact with the component processor. Trying to involve actions by submitting the form information to the component processor and doing partial page updates is fairly complex and in my opinion looks like it can be prone to error. For the next couple of projects I think I'll stick to IScript type page refreshes to build my comfort level until a point when I am ready to do field validation and auto-saves.
Before I get started I want to point out that I decided against trying the auto-save feature. While I think that this type of feature would be extremely useful in some use cases, I feel the Component you implement it with must be designed for it. Auto-saves should be saved as drafts and should not effect the current data stored in the tables. When the user actually clicks some sort of Save button, only then should the auto-saved data replace the data that existed before.
To simply my AJAX/PeopleSoft experience I decided to just create a dynamic DIV on an existing page. The DIV is updated periodically by sending an AJAX request to an IScript function which returns HTML that is placed directly into the DIV. This was done with PeopleTools 8.46.17.
Step 1.
I opened the Page I wanted to AJAX-ify and added an HTML Area control to the top of the page (specifically I added DERIVED_PTP.HTMLAREA).
Step 2.
I downloaded jQuery 1.2.1. I grabbed the "packed" version which is the smallest weighing in at only 26kb. As the ITToolbox entry hinted at, I tried adding the downloaded contents to an HTML object. However, when I tried to save the object in Application Designer I got the following error:
Object size exceeds 32K limit. Proceed with Save?
It let me save it anyway so I named the HTML object FR_JQUERY. When I opened up the page I received several javascript errors and when I looked at the cache javascript file that was created I found it was truncated. This happened when I used the code from the ITToolbox site:
<script src="%JavaScript(FR_JQUERY)"></script>
In order to make it work I added the contents of the packed jquery.js to a Message Catalog Entry (more details below).
Step 3.
I created an HTML object named FR_ISSUE_LOG_SRCH_DHTML with my code and a bind variable that I would later replace with the jQuery library. Here's the HTML object code:
FR_ISSUE_LOG_SRCH_DHTML HTML Object
<div id="new-issues">
</div>
%Bind(:1)
<script type="text/javascript">
var pollInterval = 15000;
function getIssues()
{
$("#new-issues").load("/psc/pshome/.../WEBLIB_..IScript_...");
setTimeout("getIssues()", pollInterval);
}
getIssues();
$("#new-issues").css({
left:"600px",
position: "absolute",
width: "250px",
fontSize: "9px",
padding: "2px",
});
</script>
Step 4.
On the Page Activate event I added the following code to populate the HTMLAREA field I had previously added to the Page.
Local string &jquery = MsgGetExplainText(31000, 3, "message not found");
DERIVED_PTP.HTMLAREA.Value = GetHTMLText(HTML.FR_ISSUE_LOG_SRCH_DHTML, &jquery);
What is noteable here is that the entire contents of the jquery.js file are stored in the Message Catalog and placed in the HTMLAREA using the %bind(:1) substitution variable. In our environment we can not easily added files to the webserver directory, so this provided a nice solution that did not require me to add any files to the webserver.
Step 5.
Finally, I created an IScript function that simply does a SQL Fetch for all rows entered in our custom table for the particular user viewing the page.
This was just an experiment on my part and only rates a 1 out of 10 on the coolness meter. My primary motivation was just to see how feasible it was to use AJAX on a PeopleSoft page. I was quite happy to find that it was easier than I expected (save for my little issue with placing the jquery.js code on the page). Also, I was able to dabble a lot with jQuery and find that it makes DOM manipulation and AJAX very easy and I will find a use for it in my next project.
Unlike the ITToolbox post, I was not attempting to interact with the component processor. Trying to involve actions by submitting the form information to the component processor and doing partial page updates is fairly complex and in my opinion looks like it can be prone to error. For the next couple of projects I think I'll stick to IScript type page refreshes to build my comfort level until a point when I am ready to do field validation and auto-saves.
Thursday, September 13, 2007
Just wanted to follow-up my previous post about Log4j in PeopleCode and post the actual log4j.properties file that I used. Using this file along with the code posted previously is all you would need to get started.
log4j.rootLogger=WARN, rolling
log4j.appender.screen=org.apache.log4j.ConsoleAppender
log4j.appender.screen.layout=org.apache.log4j.PatternLayout
log4j.appender.screen.layout.ConversionPattern=%d %-4r [%t] %-5p %c %x - %m%n
log4j.appender.rolling=org.apache.log4j.RollingFileAppender
log4j.appender.rolling.Threshold=DEBUG
log4j.appender.rolling.File=/some/directory/log4j.log
log4j.appender.rolling.MaxFileSize=20480KB
log4j.appender.rolling.MaxBackupIndex=5
log4j.appender.rolling.layout=org.apache.log4j.PatternLayout
log4j.appender.rolling.layout.ConversionPattern=%d %p [%c{4}] %M %m%n
Friday, September 7, 2007
Log4j in PeopleCode
Jim's PeopleSoft Journal had a good entry on using Log4j in PeopleCode. This first article assumed that you would have control over the log4j.properties file in your environment. Jim also posted a follow-up on Log4j and Peoplecode Part II where he discussed how to programmatically configure the logging. This is nice for those, like me, that do not have access to modify the $PS_HOME/appserv/classes/log4j.properties file.
The programmatic approach works well, but I didn't want to hardcode all that information in each event I want to log information in. You can point log4j to an alternative logging file using the code below, that way you can keep control of the logging level and setup of the appenders in a file that is easy to modify. Of course, this assumes that in your environment you have some access to a directory where you can store the file and grant write access to it for the daemon that runs the application server.
Note: I got tripped up initially because I didn't read Jim's code closely enough and tried using CreateJavaObject out of habit instead of GetJavaClass. Since both methods are static (i.e., can't create an instance of a Logger) it blew up with an error.
The programmatic approach works well, but I didn't want to hardcode all that information in each event I want to log information in. You can point log4j to an alternative logging file using the code below, that way you can keep control of the logging level and setup of the appenders in a file that is easy to modify. Of course, this assumes that in your environment you have some access to a directory where you can store the file and grant write access to it for the daemon that runs the application server.
Local JavaObject &log4jConfig = GetJavaClass("org.apache.log4j.PropertyConfigurator");
&log4jConfig.configure("/some/directory/log4j.properties");
Local JavaObject &log = GetJavaClass("org.apache.log4j.Logger").getLogger("edu.csufresno.cis.HRS_CE_RESUME.PageActivate");
&log.info("hi from peoplecode");
Note: I got tripped up initially because I didn't read Jim's code closely enough and tried using CreateJavaObject out of habit instead of GetJavaClass. Since both methods are static (i.e., can't create an instance of a Logger) it blew up with an error.
Pouring through logs
Been doing an inordinate amount of tracing and debugging lately. Our ERP system dumps a lot of junk to the logs. The following command is my friend.
I like to be able to follow the file as lines are added and also like to send the output to a log file that I can open in an editor so I can so more regex type searches.
tail -f trace.log |tee $HOME/mylog.log
I like to be able to follow the file as lines are added and also like to send the output to a log file that I can open in an editor so I can so more regex type searches.
Tuesday, September 4, 2007
Log4J - email notification of production errors
There are a couple of things I try to do before I sit down to write Java code for even the smallest project (cause they always grow). One is creating an ant build script and the other is creating a log4j configuration file and adding log4j to my library path. I used to sprinkle System.out.println's throughout my code and now I've gotten in the habit of using the logging library.
I hadn't used the SMTPAppender, but recent issues with production code got me thinking about it so I'd have a heads up before users starting yelling. Below is the log4j.properties file that's worked well so far. The code is all custom so I have total control of all log.error and log.fatal statements, so when I get an email I know exactly what the issues is. Wouldn't be possible if I still used System.out.
Just a note, took me a few runs to figure out that I needed mail.jar and activation.jar in my classpath. After that, smooth sailing.
I hadn't used the SMTPAppender, but recent issues with production code got me thinking about it so I'd have a heads up before users starting yelling. Below is the log4j.properties file that's worked well so far. The code is all custom so I have total control of all log.error and log.fatal statements, so when I get an email I know exactly what the issues is. Wouldn't be possible if I still used System.out.
log4j.rootLogger=ERROR, SMTPAPPENDER, rolling
log4j.appender.screen=org.apache.log4j.ConsoleAppender
log4j.appender.screen.layout=org.apache.log4j.PatternLayout
log4j.appender.screen.layout.ConversionPattern=%d %-4r [%t] %-5p %c %x - %m%n
log4j.appender.rolling=org.apache.log4j.RollingFileAppender
log4j.appender.rolling.Threshold=DEBUG
log4j.appender.rolling.File=/tmp/csufresno-hrsrecruit-cnv.log
log4j.appender.rolling.MaxFileSize=20480KB
log4j.appender.rolling.MaxBackupIndex=5
log4j.appender.rolling.layout=org.apache.log4j.PatternLayout
log4j.appender.rolling.layout.ConversionPattern=%d %p [%c{4}] %M %m%n
log4j.appender.SMTPAPPENDER.To=me@myaddress.com
log4j.appender.SMTPAPPENDER.layout=org.apache.log4j.PatternLayout
log4j.appender.SMTPAPPENDER=org.apache.log4j.net.SMTPAppender
log4j.appender.SMTPAPPENDER.Subject=[hrsrecruit] ERROR
log4j.appender.SMTPAPPENDER.BufferSize=512
log4j.appender.SMTPAPPENDER.From=myapp@myserver.com
log4j.appender.SMTPAPPENDER.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
log4j.appender.SMTPAPPENDER.SMTPHost=mysmtp.server.com
log4j.logger.edu.csufresno.cis=INFO
Just a note, took me a few runs to figure out that I needed mail.jar and activation.jar in my classpath. After that, smooth sailing.
Sunday, September 2, 2007
Vista, no thanks
In early August we received new laptops at work, some very nice dual core Dell Latitudes with a couple gigs of RAM. Now I can finally have JDeveloper and SQLDeveloper open at the same time. I have forgone installing Microsoft Office and instead am rolling with OpenOffice 2.2, no regrets. Still a Thunderbird fan, what's Outlook? The main Microsoft software I rely on is the OS, Windows XP.
In a year we are supposed to upgrade to Vista and MS Office 2007. Based on what I've seen of Vista so far I think that will be the time to move to Linux. Many in IT where I work have moved to MacOS and while I admire the BSD-like OS under the covers, I'd just be trading one corporate vendor for another. In addition, most of the software that I need to run in order to do my job is either not available on the Mac or is in beta. There is not one tool I use that requires MacOS. There are quite a few tools I use that are available for both Windows and Linux. For those cases where a Linux version is not available I can use Wine or an XP guest OS in VMWare Server.
So I have one year to decide what distro to run. I've been running Ubuntu on my home laptop for about the last 8 months. It's a nice distribution, very easy to setup and use. It has given me a great appreciation for the Debian packaging system. I have it narrowed down to either a Debian or Redhat distribution. Redhat would be a good choice because it'll likely replace our Sun Solaris boxes in the near future. I've been working with CentOS in a VMWare image for a little while and found I really like both the workstation and server installs. As for a Debian distro I think I would go with plain old Debian. While Ubuntu does have a large user base, I need very few of the features that are Ubuntu specific. I dislike some the configuration changes I've seen lately in Ubuntu (i.e., their choice of replacing the inittab with event.d). I want my Linux system to be as standard as possible if I go with Debian and I think Ubuntu is starting to stray away from Debian a little too much and I don't want to end up running a distro that forks from Debian.
I think the main decision will depend heavily on package management, I know Debian's apt-get is excellent. For now I need to continue playing with CentOS to see how Yum stacks up.
In a year we are supposed to upgrade to Vista and MS Office 2007. Based on what I've seen of Vista so far I think that will be the time to move to Linux. Many in IT where I work have moved to MacOS and while I admire the BSD-like OS under the covers, I'd just be trading one corporate vendor for another. In addition, most of the software that I need to run in order to do my job is either not available on the Mac or is in beta. There is not one tool I use that requires MacOS. There are quite a few tools I use that are available for both Windows and Linux. For those cases where a Linux version is not available I can use Wine or an XP guest OS in VMWare Server.
So I have one year to decide what distro to run. I've been running Ubuntu on my home laptop for about the last 8 months. It's a nice distribution, very easy to setup and use. It has given me a great appreciation for the Debian packaging system. I have it narrowed down to either a Debian or Redhat distribution. Redhat would be a good choice because it'll likely replace our Sun Solaris boxes in the near future. I've been working with CentOS in a VMWare image for a little while and found I really like both the workstation and server installs. As for a Debian distro I think I would go with plain old Debian. While Ubuntu does have a large user base, I need very few of the features that are Ubuntu specific. I dislike some the configuration changes I've seen lately in Ubuntu (i.e., their choice of replacing the inittab with event.d). I want my Linux system to be as standard as possible if I go with Debian and I think Ubuntu is starting to stray away from Debian a little too much and I don't want to end up running a distro that forks from Debian.
I think the main decision will depend heavily on package management, I know Debian's apt-get is excellent. For now I need to continue playing with CentOS to see how Yum stacks up.
Podcasts
I am trying to make up for lost time since I haven't posted in a long, long, long time. Here my list of podcasts that I regularly listen to....
- bsdtalk
- Casting from the Server Room
- FLOSS Weekly
- Google Developer Podcast
- In the Trenches
- The Java Posse
- Linux Reality
- OnSoftware
- Oracle TechCasts
- Perlcast
- Software Engineering Radio
- SourceTrunk
iText - Java PDF library
I recently had to do some tuning on a project I had done that involves converting and merging documents into PDF format. The main performance issue turned out to be poor performing sql and a function-based index fixed it. I decided to try tuning a few other pieces of code and that brought me to try an newer version of the iText library...wow was I pleasantly surprised.
In the project I use iText to merge PDF documents into a single document and also use it to convert TIF and JPG files to PDF format. The ERP system this project was going to be a part of shipped with iText 1.02 so that is why I initially decided to use that library for the PDF manipulation. As part of my tuning effort I decided to try the latest version, 2.0.4. On average performance improved over 40%. As an added bonus some TIF files that failed to convert in the prior 1.02 version were handled flawlessly by the newer release.
In the near future I would like to compare the performance against other Java PDF libraries (such as PDFBox) to see how iText compares. The code that handles the PDF manipulation is isolated from the rest of the logic and implements an interface so it shouldn't be too difficult to try the test since the implementing class is plugable.
Couple lessons learned for me are:
In the project I use iText to merge PDF documents into a single document and also use it to convert TIF and JPG files to PDF format. The ERP system this project was going to be a part of shipped with iText 1.02 so that is why I initially decided to use that library for the PDF manipulation. As part of my tuning effort I decided to try the latest version, 2.0.4. On average performance improved over 40%. As an added bonus some TIF files that failed to convert in the prior 1.02 version were handled flawlessly by the newer release.
In the near future I would like to compare the performance against other Java PDF libraries (such as PDFBox) to see how iText compares. The code that handles the PDF manipulation is isolated from the rest of the logic and implements an interface so it shouldn't be too difficult to try the test since the implementing class is plugable.
Couple lessons learned for me are:
- Write classes that do one thing and do it really well. I was lucky here, my project is relatively small and the code was well isolated making the upgrade in versions easy to test side by side.
- For sourceforge projects that I rely on I will sign up for the release mailing list and try out new versions. Open source projects like iText are continually evolving. I made a huge mistake of thinking that the art of PDF manipulation would not have advanced much since the release of 1.02 (which I think was sometime in 2004).
- iText is a great PDF library for Java. I had never used this library before this project but had heard a lot about it. What really impresses me the most about the project is the documentation and the fantastic examples on the site. I was able to use a lot of code from the examples and that left me to focus more on my program's logic rather than on the details of merging PDF files or converting images to PDF.
Friday, June 22, 2007
All Derived, All The Time (I wish...)
I have been working on a PeopleSoft inquiry page a bit this week. I was looking at the specifications for the page and saw I didn't need to create any physical objects in the database (tables or views) to do what I needed to do. I was planning on just using derived tables and values and just loading up a rowset with data from PeopleCode and pushing the rowset to the grid. I was using an existing derived table at row level 0 and created an additional derived table with all of the fields I needed for row level 1 (the grid). Everything derived. I added my fields at row level 0, added my grid object, added the fields I needed for the grid from the derived record and attempted to save. Error message of no data found in row level 1. What? I went back and looked, verifying that I had added the fields. Tried to save again. Same error. I went and showed one of my colleagues who also theorized that what I was trying to do should work. He got the same error. He added a field from a table that physically exists in the database and it saved. So the moral of the story is that in a PeopleSoft page, you can have all derived field at row level 0, but you must have at least one field that physically exists in the database in row level 1 for the page to work.
This posting probably is rambling and doesn't flow well, but hey, it's late on a Friday...
-E
This posting probably is rambling and doesn't flow well, but hey, it's late on a Friday...
-E
Thursday, June 21, 2007
PeopleSoft and Firefox, Part One
I wanted to leave the door open for part two, if ever need be...
One ongoing gripe I have with Firefox is the speed of the browser in PeopleSoft. IE is hands down faster and I have yet to figure out why. Does IE cache more of the HTTPS pages where Firefox does not? Does the IE Trident rendering engine just work better with PeopleSoft than the Gecko rendering engine in Firefox? Did a very un-thorough Google search with nothing much to show for it. If anyone has an ideas or opinions, please post a comment.
One ongoing gripe I have with Firefox is the speed of the browser in PeopleSoft. IE is hands down faster and I have yet to figure out why. Does IE cache more of the HTTPS pages where Firefox does not? Does the IE Trident rendering engine just work better with PeopleSoft than the Gecko rendering engine in Firefox? Did a very un-thorough Google search with nothing much to show for it. If anyone has an ideas or opinions, please post a comment.
Wednesday, June 20, 2007
NotePad++
We have been test-driving Notepad++ around here for the past couple of days. With the recent release of Textpad 5, we have been looking to see what else is available out there that is open source. We have been big Textpad fans for the last several years and have been looking forward to the changes that were coming with release 5, but the load time to open the app is huge. We have been conditioned for software to be lightning fast, so Textpad 5 left us wanting. I tried to revert back to Textpad 4, but had all kinds of little registry gremlins that caused me grief.
We have PSPad in the running too, but it has the same app load delay as Textpad 5 (but it has a ton of cool features).
Anyway, we will be using Notepad++ here, probably until next week until another text editor draws our attention.
We have PSPad in the running too, but it has the same app load delay as Textpad 5 (but it has a ton of cool features).
Anyway, we will be using Notepad++ here, probably until next week until another text editor draws our attention.
Open Source Desktop Encryption Solutions
Let me throw out a couple of scenarios:
1.) You get a call from a user who needs a data extract of "XYZ" data. You run the extract, export the data to a spreadsheet and send the data back to the requester.
2.) You have 10 databases you work in, all with different passwords.
Consider these questions:
In scenario 1, what if the extract had some sensitive information in it? Where is that extract, in your local temporary folder? Is that temp folder under your profile (probably not) and who has access to it? What if it is sitting in your local temp folder and your laptop grows legs...
In scenario 2, do you remember all of you passwords or do you store you passwords in text docs locally, in a wiki, post-it note on your desk, etc. to make it easier to access the userid/ passwords?
TrueCrypt: This software allows you to create a encrypted partition in a file (yes, a file) on your harddisk that you can mount as a volume in the OS. Save anything you want to it.This is perfect for using as a temp directory. Provides a solution for scenario 1. If your laptop does take up jogging, the file is a bunch of gibberish without the passphrase.
KeePass: This software fixes the problem presented in scenario 2. The software basically keeps an encrypted database of your any userid/passwords you want to store. Add as many as you want. You only need to remember the single, encrypted passphrase to access the database.
Both of these products are available on multiple platforms. I can only vouch for the effectiveness on Windows XP.
Just to have one less thing to remember, save your KeePass database inside of your TrueCrypt partition.
1.) You get a call from a user who needs a data extract of "XYZ" data. You run the extract, export the data to a spreadsheet and send the data back to the requester.
2.) You have 10 databases you work in, all with different passwords.
Consider these questions:
In scenario 1, what if the extract had some sensitive information in it? Where is that extract, in your local temporary folder? Is that temp folder under your profile (probably not) and who has access to it? What if it is sitting in your local temp folder and your laptop grows legs...
In scenario 2, do you remember all of you passwords or do you store you passwords in text docs locally, in a wiki, post-it note on your desk, etc. to make it easier to access the userid/ passwords?
TrueCrypt: This software allows you to create a encrypted partition in a file (yes, a file) on your harddisk that you can mount as a volume in the OS. Save anything you want to it.This is perfect for using as a temp directory. Provides a solution for scenario 1. If your laptop does take up jogging, the file is a bunch of gibberish without the passphrase.
KeePass: This software fixes the problem presented in scenario 2. The software basically keeps an encrypted database of your any userid/passwords you want to store. Add as many as you want. You only need to remember the single, encrypted passphrase to access the database.
Both of these products are available on multiple platforms. I can only vouch for the effectiveness on Windows XP.
Just to have one less thing to remember, save your KeePass database inside of your TrueCrypt partition.
Wednesday, May 23, 2007
OSAlt - Open Source Alternative Software
I came across this site this morning while looking through my LifeHacker RSS feed. OSAlt is a very cool site where you can enter what type of application (business, communications, etc), or a specific application and find any open source alternatives to it. I am frequently looking for open source alternatives to commercial applications and I am definetely going to be adding this site as one of my first places to search (along with sourceforge.net).
Sunday, May 6, 2007
Recently while working in our HR system I came across some interesting OO design.
I would expect this kind of terminology from an HR person (employees being just commodities that can be thrown in a shopping cart), but what developer with any self respect would write up code like this? They, after all, are just an employee.
Besides the method naming, the code had a lot of problems and didn't work as documented. That I expected, but would have been easier to take if the naming wasn't so offensive.
&someobject.ShopForEmployees();
....
....
&someobject.CopyShoppingCartToRowset(&RS_Employees);
I would expect this kind of terminology from an HR person (employees being just commodities that can be thrown in a shopping cart), but what developer with any self respect would write up code like this? They, after all, are just an employee.
Besides the method naming, the code had a lot of problems and didn't work as documented. That I expected, but would have been easier to take if the naming wasn't so offensive.
Tuesday, March 20, 2007
Friday, January 5, 2007
Thunderbird 1.5.09 vs Outlook 2003: Can O' Spam
I find myself constantly battling between my desire to use standardized business software (ie Microsoft products) and the desire to have software make me more productive and make my life easier. I gave Outlook another shot today (I was feeling guilty about using Thunderbird) and quickly kicked myself. We have a listserv at work that spammers seem to really enjoy flooding with spam. Unfortunately, it is a listserv which we need and frequently use. Thunderbird utilizes a Bayesian filter, so it learns what a spam email looks like based on what you have told it is spam. In contrast, Outlook allows you to whitelist/blacklist senders, so any known spammers get filtered. The downside to Outlook (and upside to Thunderbird) is that when you are getting spam and good email from a sender, you can't just filter the messages you don't want. It's all or nothing. Thunderbird doesn't care who it is from, only what the content of the message is. With all of the communication that we get through email and with the regularity that listservs and email accounts get compromised by spammers, Thunderbird's Bayesian filter wins hand down.
I should be getting a copy of Office 2007 in the near future and will give Outlook 2007 a shot to see if any improvements on the spam filtering have been made. I will blog another posting with my results.
Please don't interpret this as being a Microsoft hater. I think Outlook is an very capable email client, in certain situations, preferable to Thunderbird regardless of the spam issue. If you use Microsoft Exchange or POP3 email, Outlook is the best, hands down. If you use IMAP for your email, Thunderbird has the edge. Outlook 2003's handling of the IMAP protocol is "clunky". I use IMAP for my work email, so there is little incentive to stay using Outlook 2003, for now.
I should be getting a copy of Office 2007 in the near future and will give Outlook 2007 a shot to see if any improvements on the spam filtering have been made. I will blog another posting with my results.
Please don't interpret this as being a Microsoft hater. I think Outlook is an very capable email client, in certain situations, preferable to Thunderbird regardless of the spam issue. If you use Microsoft Exchange or POP3 email, Outlook is the best, hands down. If you use IMAP for your email, Thunderbird has the edge. Outlook 2003's handling of the IMAP protocol is "clunky". I use IMAP for my work email, so there is little incentive to stay using Outlook 2003, for now.
Thursday, January 4, 2007
Cross Platform Open Source (Javascript, HTML, CSS) IDE
Ran across a very nice plugin for Eclipse over the holiday break named Aptana. I already had the latest version of Eclipse installed so I just installed it as a plugin. Did a quick test using the Yahoo! User Interface (YUI) library to do a quick and dirty AJAX page that automatically updated weather info (from Yahoo Weather rss feeds).
I had been searching for a good open source tool to aid in developing xhtml/css/javascript pages and was mainly interested in command completion/suggestion. This one was the best of all I checked out. The code assist features worked great and I found the help features to be great, especially when dealing with css/javascript. I didn't try out the javascript debugger.
http://www.aptana.com
I had been searching for a good open source tool to aid in developing xhtml/css/javascript pages and was mainly interested in command completion/suggestion. This one was the best of all I checked out. The code assist features worked great and I found the help features to be great, especially when dealing with css/javascript. I didn't try out the javascript debugger.
http://www.aptana.com
Killing an oracle session to remove a lock
I always have to search around for the right commands in order to remove table locks in Oracle. Thought I'd post and hopefully will remember I can look her for it in the future. Below seems to work at least in 8/9i.
Identifying the locks:
Deep Six the session:
The SID and the SERIAL# fields can then be used to issue the kill command:
Using this combo I almost never have to resort to a "kill -9 OS_PID" on the database server itself.
Identifying the locks:
SELECT l.inst_id,
SUBSTR(L.ORACLE_USERNAME,1,8) ORA_USER,
SUBSTR(L.SESSION_ID,1,3) SID,
S.serial#,
SUBSTR(O.OWNER||'.'||O.OBJECT_NAME,1,40) OBJECT, P.SPID OS_PID,
DECODE(L.LOCKED_MODE, 0,'NONE',
1,'NULL',
2,'ROW SHARE',
3,'ROW EXCLUSIVE',
4,'SHARE',
5,'SHARE ROW EXCLUSIVE',
6,'EXCLUSIVE',
NULL) LOCK_MODE
FROM sys.GV_$LOCKED_OBJECT L
, DBA_OBJECTS O
, sys.GV_$SESSION S
, sys.GV_$PROCESS P
WHERE L.OBJECT_ID = O.OBJECT_ID
and l.inst_id = s.inst_id
AND L.SESSION_ID = S.SID
and s.inst_id = p.inst_id
AND S.PADDR = P.ADDR(+)
order by l.inst_id
Deep Six the session:
The SID and the SERIAL# fields can then be used to issue the kill command:
ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;
Using this combo I almost never have to resort to a "kill -9 OS_PID" on the database server itself.
Subscribe to:
Posts (Atom)