<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-574661030392104329</id><updated>2012-02-16T19:34:41.835-08:00</updated><category term='Charts'/><category term='Echo2'/><category term='Jeremiah Holly Abraham-Castlevania'/><category term='agile'/><category term='POI'/><category term='Hack'/><category term='software'/><category term='Dependency Injection'/><category term='jXLS'/><category term='AJAX'/><category term='co-workers'/><category term='Named Range'/><category term='project management'/><category term='communication'/><category term='Apache'/><category term='Java'/><category term='erasure'/><category term='Tags'/><category term='Guice'/><category term='Excel'/><title type='text'>amateur at best...</title><subtitle type='html'>I mean, really, aren't we all?</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>18</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-574661030392104329.post-7021584454147568990</id><published>2011-03-19T00:18:00.000-07:00</published><updated>2011-03-19T00:24:04.881-07:00</updated><title type='text'>I have a confession. (re: #tigerbloodtourney)</title><content type='html'>I cast false ballots in &lt;a href="http://www.firedupmissouri.com/"&gt;Fired Up! Missouri's Tiger Blood Tournament&lt;/a&gt;. In fact, it is likely that I decided the race between &lt;a href="http://www.house.mo.gov/member.aspx?district=106"&gt;Speaker Steve Tilley (NBPP - Perry/Ste.Genevieve)&lt;/a&gt; and &lt;a href="http://www.senate.mo.gov/07info/members/mem10.HTM"&gt;Jolie Justus (D - Freedom)&lt;/a&gt;. &amp;nbsp;It was a decision that happened by fits and starts, but it was my decision. &amp;nbsp;I am not a man to step back from my decisions. &amp;nbsp;As such, I submit to you the facts of the situation as they presented themselves. &amp;nbsp;Mistakes were made. &amp;nbsp;Yet, I know without a doubt that, ultimately, I did what was right. &amp;nbsp;I took the action that no one else would and set the course of destiny down its true and proper path.&lt;br /&gt;&lt;br /&gt;On Thursday evening, I checked in on the&amp;nbsp;immensely&amp;nbsp;enjoyable Tiger Blood Tournament. &amp;nbsp;At that time, there was nothing particularly stunning happening in the voting, although there was a lot of jocularity on twitter surrounding the event. &amp;nbsp;I noticed that most of my picks were doing pretty well, watched a couple of the YouTube videos and headed to bed. &amp;nbsp;However, the following morning I was treated to &lt;a href="http://twitter.com/joliejustus/status/48737677780058112"&gt;this shocking tweet from Senator Jolie Justus&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Now, any fool can see that either Tilley had members of his &lt;a href="http://www.firedupmissouri.com/content/just-sad-loesch-plays-dumb-tilley-phone-then-unleashes-tirade-when-hes-gone"&gt;New Black Panther Party&lt;/a&gt; up all night clicking on tiny radio buttons while plotting to give St. Louis control of the Missouri Highway Patrol and install NBPP members to the controlling board giving Tilley his own private army just in time to wrestle control of the state from &lt;a href="http://www.firedupmissouri.com/content/ten-2010-peter-kinder%E2%80%99s-ten-most-outrageous-tweets"&gt;Lt. Gov. Tweets-a-lot (R - Where the hell did we get this guy?)&lt;/a&gt;...OR somebody was running a votebot. As the votes for Tilley continued to soar, I contemplated the situation. &amp;nbsp;How could this have happened? As her previous contests had shown, Jolie Justus has to be the most universally liked politician that has ever held elected office. &amp;nbsp;Not long ago, I would have sworn that politicians had developed a forcefield to keep all that was good and honest out of the halls of every Capitol in the country. &amp;nbsp;Then Jolie Justus came along. &amp;nbsp;For goodness' sake, just look at her name. &amp;nbsp;Now, say it out loud it sounds even better. &amp;nbsp;Clearly this woman came directly from the planet Krypton to fight for truth, justice and the Missouri way.&lt;br /&gt;&lt;br /&gt;Something had to be done...&lt;br /&gt;&lt;br /&gt;Now, I'm no Jolie Justus. Which is good, because that would be weird. &amp;nbsp;However, I've heard a clich&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;é&lt;/span&gt;&amp;nbsp;or two in my day and it just so happens that "fight fire with fire" is one of them. &amp;nbsp;I really don't understand that, because I thought you were supposed to fight fire with water. &amp;nbsp;Water beats fire, fire beats earth, earth beats water. &amp;nbsp;Am I right?? &amp;nbsp;Anyway, I happen to have written a little program or two in my day. &amp;nbsp;So, I set out to even the score. FOR GREAT JUSTUS!&lt;br /&gt;&lt;br /&gt;While the robot minions of Team Tilley stuffed the ballot boxes with thousands of fraudulent votes, I toiled away through my lunch hour. &amp;nbsp;I gave up sushi! &amp;nbsp;Damn you, Steve Tilley. &amp;nbsp;Despite already being behind by what looked like an unrecoverable margin, I dedicated myself to leveling the playing field for the sake of justice (or at least Justus, but whatever). &amp;nbsp;In less than the amount of time it would have taken for me to consume a delicious caterpillar roll at Sushi Sen, I had created a monster. &amp;nbsp;Well, actually a robot...or...an Android.&lt;br /&gt;&lt;br /&gt;That's right. &amp;nbsp;I defeated Team Tilley's band of robot minions with a single, solitary cellphone.&lt;br /&gt;&lt;br /&gt;It comes down to this: I had to be home in time for dinner. &amp;nbsp;I simply couldn't sit around the office until 5 waiting for voting to finish so that I could be sure that the NBPP hadn't swarmed the polls in a last ditch effort to keep the lead. &amp;nbsp;So, my votebot went mobile. &amp;nbsp;While I drove home, my phone executed a program that I am lovingly calling "Absentee Ballot". &amp;nbsp;It gave back to Jolie Justus the comfortable lead that she so rightly deserved.&lt;br /&gt;&lt;br /&gt;I am proud of my little Samsung Captivate. &amp;nbsp;She did her part to restore Justus to the Tiger Blood Tournament. &amp;nbsp;Now that the world has been set right and Missouri snatched from Steve Tilley's clutches, I am retiring my little program. &amp;nbsp;But let this be a warning to those who would try to take the reins of Democracy from the hands of The People...wherever voter fraud rears it's ugly head, Absentee Ballot will be there and so will the Justus League.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/574661030392104329-7021584454147568990?l=amateuratbest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/7021584454147568990/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=574661030392104329&amp;postID=7021584454147568990' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/7021584454147568990'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/7021584454147568990'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/2011/03/i-have-confession-re-tigerbloodtourney.html' title='I have a confession. (re: #tigerbloodtourney)'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-574661030392104329.post-6309008921360848841</id><published>2009-12-18T21:51:00.000-08:00</published><updated>2009-12-18T21:51:27.464-08:00</updated><title type='text'>A Reply from and an Open Response to Dan Rastatter</title><content type='html'>While I have not yet received a response from Dr. Alvin Goldstein, I did hear from Dan Rastatter this evening.&amp;nbsp; I was disappointed in the response on a variety of levels.&amp;nbsp; Not only did he give no indication that he intended to change the content of his abstract with regards to the Jerry Parker case, but he also accused me of desiring revenge, being callous and complacent with regards to police corruption.&amp;nbsp; Here is his replay in its entirety.&lt;br /&gt;&lt;blockquote&gt;Dear Mr. Kimberlin,&lt;br /&gt;&lt;br /&gt;I read your email in regards to my summary of the Jerry L. Parker molestation case. &amp;nbsp;You raise a few claims that conceivably chip away at Parker's defense. &amp;nbsp;However, the case against Parker is so weak that the points you make would have little effect in changing an evaluation of his case based on the information presented in Dr. Goldstein's account. &amp;nbsp;Parker may now be attending parole hearings, but innocent persons often feel coerced into doing so.&lt;br /&gt;&lt;br /&gt;Because of the girls' youth, it is questionable whether they were old enough to give credible testimony. &amp;nbsp;Individuals that young are quite susceptible to believing and parroting opinions of adults rather than what they actually witnessed. &amp;nbsp;Secondly, the girls all failed to identify Parker in the first photo lineup they saw. &amp;nbsp;The case against Parker should have died there. Even if one ignores the girls' youth and their failure to initially identify Parker, there are many aspects to the case that are not very credible.&lt;br /&gt;&lt;br /&gt;Your email suggests you allow emotion to enter into your evaluation of the case. &amp;nbsp;The severity or emotional impact of a crime does not logically affect what the evidence proves. &amp;nbsp;Apparently you are callously willing to subject a possibly innocent person to decades of imprisonment because it is "poor taste" to seriously question his accusers.&lt;br /&gt;&lt;br /&gt;Judging from Dr. Goldstein's account, I am not at all sure the girls were molested, even if not by Parker. &amp;nbsp;It would be easy to believe that the girls got their stories from an actual event, but the details of their stories suggest that the molestation could not have happened in the way they describe. &amp;nbsp;If the girls were molested, they don't seem particularly upset about it, as they appear willing to cavalierly add to their account.&lt;br /&gt;&lt;br /&gt;In your letter to Dr. Goldstein you dispute Parker's claims and write "I tend to desire a higher level of proof for claims of any kind in order to be swayed." &amp;nbsp;However, the burden of proof is on you or the prosecution to prove Parker guilty, not on him to prove his innocence. &amp;nbsp;I am not aware of any clear evidence that a crime was committed by anyone.&lt;br /&gt;&lt;br /&gt;I am sorry that Parker murdered members of your family, if the evidence does indeed prove that. &amp;nbsp;Nevertheless, the fact that Parker may have murdered people does not mean he molested the girls. &amp;nbsp;It is unfortunate that Parker was less than polite to members of your family during his most recently trial, but few individuals take kindly to others who attempt to put them in jail.&lt;br /&gt;&lt;br /&gt;In reading Goldstein's account, I wondered why police seemed to be framing Parker. &amp;nbsp;The evidence you relate suggests that police framed him because of his past murder convictions. &amp;nbsp;Police initially told the girls that they did not believe their stories; then they suddenly decided to focus on Parker as a suspect and kept pursuing him even after the girls failed to identify him.&lt;br /&gt;&lt;br /&gt;I realize you want revenge on Parker, which he may deserve, but I would only seek such revenge in regard to provable crimes he committed. &amp;nbsp;If courts refuse to incarcerate him for these crimes, you just have to live with that. If you support police corruption in your desire for revenge, you are doing evil and are hurting people other than Parker. &amp;nbsp;Keep in mind that Parker's incarceration is never going to not provide you justice. &amp;nbsp;It is never going to bring back family members that were killed.&lt;br /&gt;&lt;br /&gt;Sincerely,&lt;br /&gt;&lt;br /&gt;Dan Rastatter&lt;br /&gt;&lt;/blockquote&gt;I felt it necessary to address his points and criticisms.&amp;nbsp; My response was as follows:&lt;br /&gt;&lt;blockquote&gt;Mr. Rastatter,&lt;br /&gt;&lt;br /&gt;I must admit that I am disappointed by your interpretation of my correspondence.&amp;nbsp; I would like to clarify the fact that I do not in any way desire revenge upon Jerry Parker.&amp;nbsp; While I would have loved to have known my grandmother and uncle, and while there is no doubt that he committed their murders, it would be completely antithetical to my own personal ethics to wish harm or hardship upon him.&amp;nbsp; Having never known my slain relatives, my sense of loss with regards to them is of more a theoretical nature than a personal or emotional one. Personally, I have nothing to gain by convincing you or Dr. Goldstein of Mr. Parker's guilt.&amp;nbsp; Furthermore, I have made no attempt to convince anyone of his guilt with regards to the molestation of the three young girls.&amp;nbsp; Quite the contrary, I explicitly stated that I would "not attempt to further argue Parker's guilt in this case".&lt;br /&gt;&lt;br /&gt;You should be aware that Dr. Goldstein made his living as an expert witness.&amp;nbsp; He was paid to testify against the credibility of eyewitness testimony.&amp;nbsp; This in and of itself is reason to read his account with a skeptical eye.&amp;nbsp; Furthermore, the evidence presented on the page in question was provided by Mr. Parker.&amp;nbsp; Dr. Goldstein readily admits that he had nothing to do with the case.&amp;nbsp; His interest in the case is to make use of it as an example of why eyewitness testimony is imperfect.&amp;nbsp; My assertion is simply that the facts that are presented on his page are questionable and incomplete.&amp;nbsp; If Dr. Goldstein feels the need to relay the story of Mr. Parker, it should be the entire story.&amp;nbsp; Putting forth only those pieces of information which support the idea that one is trying to espouse while ignoring contrary and/or harmful information is a classic example of confirmation bias.&amp;nbsp; It is foolish to take the word and evidence of the convicted as truth and parrot it as fact without investigation.&amp;nbsp; The information surrounding the handling of the investigation comes from Mr. Parker.&amp;nbsp; Dr. Goldstein did not speak with the investigators.&amp;nbsp; He did not speak with the prosecutors.&amp;nbsp; He did not speak with the defense attorney, the judge, the witnesses or even the court clerk.&amp;nbsp; He spoke with no one with any relationship to the case whatsoever, with the exception of Mr. Parker.&lt;br /&gt;&lt;br /&gt;There may well have been issues with the handling of the investigation.&amp;nbsp; There may have been serious flaws.&amp;nbsp; That does not change the fact that Dr. Goldstein's account of it is one sided and incomplete.&amp;nbsp; Anyone who reads the entirety of Dr. Goldstein's article can plainly see the bias that is displayed.&amp;nbsp; The article is peppered with unnecessary quotations used to convey sarcasm and skepticism. They are so prevalent that it detracts from the article.&amp;nbsp; Dr. Goldstein's desire to persuade the reader of the problems relating to eyewitness testimony is so strong that it colors the arguments and the text as a whole.&lt;br /&gt;&lt;br /&gt;As for my being 'willing to subject a possibly innocent person to decades of imprisonment because it is "poor taste" to seriously question his accusers', I would suggest that you read my email to Dr. Goldstein again.&amp;nbsp; I have absolutely no desire to see any innocent person imprisoned.&amp;nbsp; My comment regarding Dr. Goldstein's "poor taste" was directed exclusively to his use of quotation marks around the words victim and crime.&amp;nbsp; Of the 23 jurists who heard the testimony and evidence in the case, 22 felt that he was guilty beyond a reasonable doubt.&amp;nbsp; Neither you nor Dr. Goldstein were present for that testimony and I find it rather arrogant on the part of Dr. Goldstein to claim superiority of reasoning over all 22 of those men and women.&amp;nbsp; The simple facts of this matter are that Dr. Goldstein obtained his information from Mr. Parker and based his arguments on that information.&amp;nbsp; You obtained your information from Dr. Goldstein's account.&amp;nbsp; As such, you are working from a set of half-truths provided by a convicted murderer and pedophile and filtered by a man with a career interest in the argument that he is expressing.&amp;nbsp; You claim below that the girls "don't seem upset" about their victimization and that they "cavalierly add to their account".&amp;nbsp; I can tell you from having seen these young girls give testimony that they were upset beyond what I can describe.&amp;nbsp; The trial and testimony was clearly very difficult for them.&amp;nbsp; If you have children, as I do, you should know that it is difficult for a 10 and 11 year old to tell any story the same way twice...much less while under interrogation from a defense attorney.&amp;nbsp; So, the fact that there were differences and/or discrepancies in their testimony is not surprising.&amp;nbsp; I will agree that this makes their testimony less reliable.&amp;nbsp; However, your statement that they do not seem upset is unfounded and ill conceived.&lt;br /&gt;&lt;br /&gt;You told me in your reply that "the burden of proof is on you or the prosecution to prove Parker guilty, not on him to prove his innocence".&amp;nbsp; I agree completely that the burden of proof was on the prosecution to prove his guilt.&amp;nbsp; However, it is certainly not on me. I have nothing to do with Mr. Parker, his case or his guilt or innocence.&amp;nbsp; A jury of his peers concluded that the prosecution met that burden of proof beyond a reasonable doubt.&amp;nbsp; Therefore, he was convicted and jailed.&amp;nbsp; I do not ask you or anyone else to believe one way or the other with regards to Mr. Parker's guilt in this matter.&amp;nbsp; I only asked that the entire story be told accurately or that no story be told at all.&amp;nbsp; I cannot imagine that anyone would find this to be an unreasonable request.&amp;nbsp; Simply regurgitating information supplied by the accused is not only irresponsible, but also disrespectful to the victims of Mr. Parker's crimes and their families.&lt;br /&gt;&lt;br /&gt;I am by no means a "callous" man.&amp;nbsp; I believe that we all make mistakes in our lives and that we all should be given the opportunity to atone for those mistakes.&amp;nbsp; Mr. Parker has at no point in his incarceration made any attempt to do so.&amp;nbsp; As for your insinuated skepticism of Mr. Parker's responsibility for the 1970 murders of my grandmother and uncle (as read from "if the evidence does indeed prove that" and "may have murdered"), I would direct you to the Missouri Supreme Court verdict on the matter.&amp;nbsp; It clearly elicits a variety of physical evidence, testimony and admissions on the part of Mr. Parker which led to his conviction.&amp;nbsp; I am confident that no one, even Dr. Goldstein, would question the merits of that case.&amp;nbsp; For your reference, that verdict can be found here:&lt;br /&gt;&lt;br /&gt;http://mo.findacase.com/research/wfrmDocViewer.aspx/xq/fac.%5CMO%5CMO2%5C1974%5C19740408_0017.MO.htm/qx&lt;br /&gt;&lt;br /&gt;At the risk of repeating myself, I would like to directly address the last paragraph of your email.&amp;nbsp; I wish for no revenge of any kind.&amp;nbsp; The penalties prescribed by the courts for Mr. Parker's convictions on the charges of murder and with regards to the molestation of the three young girls are more that sufficient for me.&amp;nbsp; Clearly the courts have not refused to incarcerate him, quite the contrary.&amp;nbsp; I have in no way supported, nor will I ever support, police corruption of any kind, in any form or for any purpose.&amp;nbsp; In fact, I find it abhorrent and take exception with any attempt to suggest otherwise.&amp;nbsp; Those who abuse the power that society grants them are even more despicable than the common criminals that they are tasked to attend.&lt;br /&gt;&lt;br /&gt;It seems clear to me that you have dismissed my email as emotionally driven.&amp;nbsp; I can assure you that it was not.&amp;nbsp; I simply desired to express to both you and Dr. Goldstein that Mr. Parker is not the innocent victim that he is made out to be and to ask that either his entire story be told or that it be removed in its entirety.&amp;nbsp; An unwillingness to provide all of the information relating to Mr. Parker would only illustrate a desire to prop up an argument against the legal system over a desire to see the truth of his story told.&amp;nbsp; It is certainly your prerogative to maintain your site in whatever way you see fit.&amp;nbsp; However, I honestly hope that you are not so blinded by your desire to put forth a belief as to be unwilling to give a complete account of the stories that you use to support it.&amp;nbsp; I am sure that you can understand how detrimental that would be to the integrity of your site and your desire to see justice served.&lt;br /&gt;&lt;br /&gt;Sincerely and respectfully yours,&lt;br /&gt;-Michael Kimberlin&lt;br /&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/574661030392104329-6309008921360848841?l=amateuratbest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/6309008921360848841/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=574661030392104329&amp;postID=6309008921360848841' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/6309008921360848841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/6309008921360848841'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/2009/12/reply-from-and-open-response-to-dan.html' title='A Reply from and an Open Response to Dan Rastatter'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-574661030392104329.post-5816471165047744102</id><published>2009-12-17T08:53:00.000-08:00</published><updated>2009-12-17T08:53:44.236-08:00</updated><title type='text'>An Open Letter to Alvin G. Goldstein, PHD</title><content type='html'>Forgive me for stating the obvious, but I rarely write blog posts. Every now and again something comes up that prompts me to put in the time and effort needed to construct something in a longer form.&amp;nbsp; This is one of those occasions.&amp;nbsp; I recently came upon a website that contains information that I believe to be both factually inaccurate and misleading.&amp;nbsp; It paints a picture of a man wrongly accused and victimized by the police, his attorney and the court system.&amp;nbsp; The man in question is Jerry Lynn Parker.&amp;nbsp; Mr. Parker was convicted of the 1970 murder of both my grandmother (Hazel Marie Kimberlin) and my uncle (Michael Wayne Kimberlin) who was only eleven at the time.&amp;nbsp; An abstract of that case can be found in the &lt;a href="http://mo.findacase.com/research/wfrmDocViewer.aspx/xq/fac.%5CMO%5CMO2%5C1974%5C19740408_0017.MO.htm/qx"&gt;appeal judgment issued by the Missouri Supreme Court&lt;/a&gt;. While he maintained his innocence for many years, he has since admitted to these senseless slayings.&amp;nbsp; While out on parol, Mr. Parker was arrested and convicted of the molestation of three young girls (aged 10, 11 and 13).&amp;nbsp; In my opinion, Mr. Parker is a predator and a danger to society.&lt;br /&gt;&lt;br /&gt;What follows is an email response of the contents of the page &lt;a href="http://home.comcast.net/%7Eeyewitness_error/"&gt;EYEWITNESS ERROR --AGAIN&lt;/a&gt;.&amp;nbsp; This has been sent to Dr. Goldstein in an attempt to have him either remove the page in question or, at the very least, update it for accuracy and completeness of the story of Jerry Parker.&amp;nbsp; Please note that the statements here are my opinions and should be read as such.&amp;nbsp; If there are inaccuracies, please feel free to bring them to my attention in the comments.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Dr. Goldstein,&lt;br /&gt;&lt;br /&gt;I am writing to you with regards to your website relating the case of Jerry Lynn Parker. &amp;nbsp;As I understand, I am a bit late in getting this email to you as my father has already sent you a rather emotional response. &amp;nbsp;You should know that while seeing your site brought forward feelings of anguish and anger for him, there is no hate involved...only the pain that accompanies the loss of a parent and a sibling. &amp;nbsp;I wish that I would have gotten the chance to send my correspondence in advance of his email, as I should like to address some of your points and I fear that you are unlikely to be receptive now that you have already heard from our family. &amp;nbsp;Nonetheless, I shall attempt to persuade you against using Mr. Parker as an example for your campaign against eyewitness testimony. &amp;nbsp;As you now know, Jerry Parker murdered both my grandmother and my young uncle. &amp;nbsp;This took place before I was born. &amp;nbsp;While it saddens and frustrates me that he took away my opportunity to know them both, I also do not have the acute sense of loss that my father and aunts must have. &amp;nbsp;As such, I am able to view your arguments with a bit more detachment. I also attended the trial of Mr. Parker that concluded in his conviction for the molestation of the three young girls. &amp;nbsp;So, I have a perspective that you could not possibly attain from examining court documents.&lt;br /&gt;&lt;br /&gt;I am curious. Have ever seen a picture of Mr. Parker that was not a mug shot? &amp;nbsp;I can tell you that when the trial occurred, Mr. Parker did not have the pronounced double chin that you point to as a discrepancy between the description from the girls and the mug shots on your page. His appearance in the mug shots is largely a result of Mr. Parker pulling his head back, creating the exaggerated appearance of a double chin. &amp;nbsp;This can be plainly seen in the side-view photo on your site. The assertion that he had "fatty tumors" may be true, however he is clearly attempting to make them more prominent in the photo. Furthermore, Jerry Parker was thin at the time. &amp;nbsp;This means that the girls' assertion that the man that accosted them was less "chunky" than the man in the initial photo line up appeared was accurate. &amp;nbsp;He does appear to be carrying more weight in that picture.&lt;br /&gt;&lt;br /&gt;As for the questions regarding the differences in the cars described by the girls, I am sure that you are aware that young girls this age are not likely to be able to identify the make and/or model of a car on sight. &amp;nbsp;I am 32 years old and I am not capable of doing this without seeing it on the rear of the vehicle. &amp;nbsp;The same is true for the gun identification. &amp;nbsp;No eleven or thirteen year old girl could be expected to tell the make and caliber of a weapon. &amp;nbsp;These girls were young and frightened. &amp;nbsp;They endured a horrendous event that they likely barely understood. &amp;nbsp;To expect that their testimony would be iron clad and completely without inconsistency is simply not reasonable.&lt;br /&gt;&lt;br /&gt;You also raise questions about the defense attorney's refusal to call witnesses that would profess to his being elsewhere at the time. &amp;nbsp;If you spoke to his attorney, you would probably be aware that these witnesses were not called because they were deemed to be a liability to Mr. Parker's case rather than a help. &amp;nbsp;Mr. Parker never took the stand to defend himself either.&lt;br /&gt;&lt;br /&gt;It is clear from your site that a good deal of the information that you have was given to you by Mr. Parker directly. &amp;nbsp;You would be wise to view his stories and claims with a grain or two of salt. &amp;nbsp;I am a skeptic by nature. &amp;nbsp;I tend to desire a higher level of proof for claims of any kind in order to be swayed. &amp;nbsp;As such, I understand the problems inherent in eyewitness identification. &amp;nbsp;So, I am sympathetic with the desire to see convictions made on the basis of physical evidence. &amp;nbsp;Therefore, I will not attempt to further argue Parker's guilt in this case. &amp;nbsp;What I will say is that Mr. Parker is not an innocent victim of poor police procedure, improper defense, etc. &amp;nbsp;He is a predator. &amp;nbsp;As for his "refusal" to attend parole hearings,because of his desire to maintain his innocence, he must have had a change in conviction. &amp;nbsp;He attended his hearing in 2008 and is going to be having another hearing in January. &amp;nbsp;He also maintained his innocence in the 1970 murders until he confessed it to a bailiff during the trail involving these girls. &amp;nbsp;Yet he did not hesitate to attend the hearings that set him free to inflict harm on the innocent again. &amp;nbsp;Mr. Parker likes attention. &amp;nbsp;During the trail for this most recent crimes he would wave and sneer at our family. &amp;nbsp;He made lewd gestures toward my older cousin while leaving the courthouse. &amp;nbsp;He was snide and arrogant in demeanor throughout the trial. For years he sent Christmas cards to my family members, pouring salt in the already painful wounds that he had inflicted. &amp;nbsp;He has brought a number of law suits against the state and employees of the state on a variety of grounds, many of which are frivolous. &amp;nbsp;All of these cases have been dismissed. &amp;nbsp;Mr. Parker is no innocent man and is by no means a victim nor a model for your cause. I would request that you build your case against eyewitness testimony on a different case and leave Mr. Parker to his own faculties.&lt;br /&gt;&lt;br /&gt;Also, I would like to say that your use of quotations around the words crime and victim is in poor taste. &amp;nbsp;These young girls were victims of a horrible crime, whether you believe that Jerry Parker was the perpetrator of that crime or not. &amp;nbsp;They were deeply affected by these events and in at least one case it led a family to be torn apart. This was not something in the imagination of some silly little girls. At the very least, please treat the events with the respect and gravity that they deserve and tell Mr. Parker's complete story.&lt;br /&gt;&lt;br /&gt;Very sincerely yours,&lt;br /&gt;-Michael Kimberlin&lt;/blockquote&gt;In addition to this email, I sent a request to Dan Rastatter regarding &lt;a href="http://www.victimsofthestate.org/MO/Parker.htm"&gt;his abstract&lt;/a&gt; based on Dr. Goldstein's write up of the Parker case found on the &lt;a href="http://www.victimsofthestate.org/"&gt;Victims of the State&lt;/a&gt; website.&amp;nbsp; That email was as follows:&lt;br /&gt;&lt;blockquote&gt;Mr. Rastatter,&lt;br /&gt;&lt;br /&gt;I am writing you with regards to Jerry Lynn Parker. &amp;nbsp;You have him listed on your Victims of the State website with regards to his conviction on charges relating to the molestation of three young girls. &amp;nbsp;Your site led me to the source of your information, one Dr. Goldstein. &amp;nbsp;I have written Dr. Goldstein in an attempt to persuade him that Mr. Parker is by no means an innocent man. &amp;nbsp;I am including that correspondence below. &amp;nbsp;I should also like to request that you give your abstract of the case a second look and consider its removal from your site.&lt;br /&gt;&lt;br /&gt;I appreciate your consideration and look forward to your response.&lt;br /&gt;&lt;br /&gt;Sincerely,&lt;br /&gt;-Michael Kimberlin &lt;br /&gt;&lt;/blockquote&gt;As of the time of this post, I have not received a response from either individual.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/574661030392104329-5816471165047744102?l=amateuratbest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/5816471165047744102/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=574661030392104329&amp;postID=5816471165047744102' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/5816471165047744102'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/5816471165047744102'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/2009/12/open-letter-to-alvin-g-goldstein-phd.html' title='An Open Letter to Alvin G. Goldstein, PHD'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-574661030392104329.post-6418762438525659023</id><published>2008-10-10T20:14:00.000-07:00</published><updated>2008-10-10T20:17:31.414-07:00</updated><title type='text'>The Kimberlin Acting Dynasty</title><content type='html'>Since I have demonstrated my prowess in front of the camera in a previous post.  I thought I would let my dear old dad get in on the action.  Here he is playing the creepy school teacher (check out that jacket and bow tie) for a Springfield, MO CVB film.  Enjoy!&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="350"&gt; &lt;param name="movie" value="http://www.youtube.com/v/6EEK31gCS7M"&gt; &lt;/param&gt; &lt;embed src="http://www.youtube.com/v/6EEK31gCS7M" type="application/x-shockwave-flash" width="425" height="350"&gt; &lt;/embed&gt; &lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/574661030392104329-6418762438525659023?l=amateuratbest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/6418762438525659023/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=574661030392104329&amp;postID=6418762438525659023' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/6418762438525659023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/6418762438525659023'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/2008/10/kimberlin-acting-dynasty.html' title='The Kimberlin Acting Dynasty'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-574661030392104329.post-2166140558670224573</id><published>2008-07-08T07:59:00.000-07:00</published><updated>2008-07-08T08:21:57.079-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jeremiah Holly Abraham-Castlevania'/><category scheme='http://www.blogger.com/atom/ns#' term='co-workers'/><title type='text'>You don't have to answer that...</title><content type='html'>So, I had another funny interaction with Jeremiah Holly Abraham-Castlevania yesterday.  This one was on the phone, but it went basically like this:&lt;br /&gt;&lt;br /&gt;(While trying to debug an issue in her application...)&lt;br /&gt;Me:  Okay, I just sent you an email with a couple of configuration changes.  Put those in and we'll try it again.&lt;br /&gt;Jeremiah Holly Abraham-Castlevania:  Okay, I got it.  Do you want me to put those in?&lt;br /&gt;(crickets: *chirp*chirp*chirp*)&lt;br /&gt;Jeremiah Holly Abraham-Castlevania:  Okay, you don't have to answer that.&lt;br /&gt;Jeremiah Holly Abraham-Castlevania:  Alright, they are in.&lt;br /&gt;Me:  Okay, now try it out.&lt;br /&gt;Jeremiah Holly Abraham-Castlevania:  Do you want me to run it now?&lt;br /&gt;(again with the crickets: *chirp*chirp*chirp*)&lt;br /&gt;Jeremiah Holly Abraham-Castlevania:  You don't have to answer that either...&lt;br /&gt;Me:  You don't really need me here for this conversation, do you?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/574661030392104329-2166140558670224573?l=amateuratbest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/2166140558670224573/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=574661030392104329&amp;postID=2166140558670224573' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/2166140558670224573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/2166140558670224573'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/2008/07/you-dont-have-to-answer-that.html' title='You don&apos;t have to answer that...'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-574661030392104329.post-5373380325545307506</id><published>2008-07-01T13:54:00.001-07:00</published><updated>2008-07-01T14:00:13.454-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='erasure'/><title type='text'>Another victim of The Wall of Erasure</title><content type='html'>Ahh, Erasure....&amp;nbsp; Today I was implementing an extension to a class that performs traversing of tree-like object structures (think UI component hierarchies).&amp;nbsp; The parent class extends another type-parameterized version of an abstract class which provides general tree traversal logic.&amp;nbsp; The problem is that I wanted to check that the current node is of a type beyond that of the type parameter provided to the parent class.&amp;nbsp; So to put that into something that might actually be understandable:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;public class ParentFinder&amp;lt;T extends Component&amp;gt; extends ComponentVisitor {&lt;br /&gt;&lt;br /&gt; private T parent = null;&lt;br /&gt;&lt;br /&gt; public ParentFinder() {&lt;br /&gt;  // Set up things to travel up the tree...&lt;br /&gt;  ...&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void visit(Component node) {&lt;br /&gt;  if(T.class.isAssignableFrom(node.getClass())&lt;br /&gt;   parent = (T)node;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Survey says!  *BZZZZ* XXX *BZZZZ*  This line is no good thanks to erasure:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;  if(T.class.isAssignableFrom(node.getClass())&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And, no...you cannot do "instanceof" either.  The JVM couldn't tell you if it wanted to.  That info is G-O-N-E, gone!&lt;br /&gt;&lt;br /&gt;How dare you want to know what you are working with!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/574661030392104329-5373380325545307506?l=amateuratbest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/5373380325545307506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=574661030392104329&amp;postID=5373380325545307506' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/5373380325545307506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/5373380325545307506'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/2008/07/another-victim-of-wall-of-erasure.html' title='Another victim of The Wall of Erasure'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-574661030392104329.post-8159255787845803620</id><published>2008-06-30T08:15:00.000-07:00</published><updated>2008-06-30T09:07:07.459-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jeremiah Holly Abraham-Castlevania'/><category scheme='http://www.blogger.com/atom/ns#' term='co-workers'/><title type='text'>It's a Hate-Really Hate kind of relationship...</title><content type='html'>So, I have a lot of interesting little chats with a co-worker of mine.  We have what I can only describe as a pseudo hate-hate relationship.  Pretty much the whole thing revolves around the intentional antagonizing of one another at every opportunity.  Generally, our conversations go something like this:&lt;br /&gt;&lt;br /&gt;Abraham-Castlevania, Jeremiah Holly [9:22 AM]:&lt;br /&gt;Michael, I can't get to my test environment!&lt;br /&gt;ME [1:18 PM]:&lt;br /&gt;Is the application server running?&lt;br /&gt;Abraham-Castlevania, Jeremiah Holly [1:18 PM]:&lt;br /&gt;Yes.&lt;br /&gt;ME [3:02 PM]:&lt;br /&gt;Are you sure?&lt;br /&gt;Abraham-Castlevania, Jeremiah Holly [3:02 PM]:&lt;br /&gt;No.&lt;br /&gt;ME [3:53 PM]:&lt;br /&gt;Check.&lt;br /&gt;Abraham-Castlevania, Jeremiah Holly [4:01 PM]:&lt;br /&gt;I hate you.&lt;br /&gt;&lt;br /&gt;I have changed her name to protect the far-from-innocent.  I will state that the name that I have given her, believe it or not, is no more ridiculous than her actual name.  ;) Here is one of our more recent interactions.&lt;br /&gt;&lt;br /&gt;Abraham-Castlevania, Jeremiah Holly [10:02 AM]:&lt;br /&gt;Michael, I see this error...JVM appears hung: Timed out waiting for signal from JVM.&lt;br /&gt;Abraham-Castlevania, Jeremiah Holly [10:02 AM]:&lt;br /&gt;could that have caused the problem?&lt;br /&gt;ME [10:06 AM]:&lt;br /&gt;uh...yeah...&lt;br /&gt;Abraham-Castlevania, Jeremiah Holly [10:07 AM]:&lt;br /&gt;don't be smart&lt;br /&gt;Abraham-Castlevania, Jeremiah Holly [10:07 AM]:&lt;br /&gt;what causes the jvm to hang&lt;br /&gt;ME [10:07 AM]:&lt;br /&gt;goblins&lt;br /&gt;Abraham-Castlevania, Jeremiah Holly [10:07 AM]:&lt;br /&gt;I can't stand you&lt;br /&gt;ME [10:07 AM]:&lt;br /&gt;maybe fairies...&lt;br /&gt;Abraham-Castlevania, Jeremiah Holly [10:07 AM]:&lt;br /&gt;really really can't stand you&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/574661030392104329-8159255787845803620?l=amateuratbest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/8159255787845803620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=574661030392104329&amp;postID=8159255787845803620' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/8159255787845803620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/8159255787845803620'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/2008/06/its-hate-really-hate-kind-of.html' title='It&apos;s a Hate-Really Hate kind of relationship...'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-574661030392104329.post-8753832459045017163</id><published>2007-10-08T07:46:00.001-07:00</published><updated>2007-10-08T07:46:48.182-07:00</updated><title type='text'>Confessions of a Geek...</title><content type='html'>Just in case there was ever any question about it, my geekiness goes WAY back.&amp;nbsp; The way I figure it, better to admit fully to the existence of this tape well before my run for president.&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="350"&gt; &lt;param name="movie" value="http://www.youtube.com/v/-ys_Ip9QpZA"&gt; &lt;/param&gt; &lt;embed src="http://www.youtube.com/v/-ys_Ip9QpZA" type="application/x-shockwave-flash" width="425" height="350"&gt; &lt;/embed&gt; &lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/574661030392104329-8753832459045017163?l=amateuratbest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/8753832459045017163/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=574661030392104329&amp;postID=8753832459045017163' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/8753832459045017163'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/8753832459045017163'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/2007/10/confessions-of-geek.html' title='Confessions of a Geek...'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-574661030392104329.post-8389849542650539023</id><published>2007-10-03T08:16:00.000-07:00</published><updated>2007-12-14T07:59:06.525-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Hack'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Tags'/><category scheme='http://www.blogger.com/atom/ns#' term='Excel'/><category scheme='http://www.blogger.com/atom/ns#' term='Charts'/><category scheme='http://www.blogger.com/atom/ns#' term='Apache'/><category scheme='http://www.blogger.com/atom/ns#' term='Named Range'/><category scheme='http://www.blogger.com/atom/ns#' term='POI'/><title type='text'>@BFNH  This is a Big Fat Nasty Hack.  Be ye' warned!</title><content type='html'>The above is my recent favorite @ tag.  We all come upon those times when, no matter how much we try to avoid it, a Big Fat Nasty Hack is required.  We try to make them pretty.  We roll them in perfume, wrap them in silk and adorn them with flowers, but they remain BIG, FAT and NASTY.  It's like a warthog in a wedding dress.  Let's just call them what they are.  The @BFNH tag calls these hacks out and exposes them to the world.  Use it wisely.&lt;br /&gt;&lt;br /&gt;I ran across this situation most recently when trying to insert cells into an Excel workbook that contained functions with references to named ranges.  It would seem that Apache POI does not really support this.  POI can read these cells in, but it is unable to provide a valid "function value" for the cell when calling HSSFCell.getFunctionValue().  Instead of a good function string, it gives something like "COUNT( NO IDEA )" or some such nonsense.  Not being able to produce a function string for this type of function call, it also fails to parse a function of this type for insertion.  I really needed this functionality.  As I described in my previous post, I came upon a way to provide dynamic charts in Excel from Java.  Seeing what could be done with this, my users went a little over-the-top.  Excel reports with charts are something they have been requesting for a while, only to be rejected.  So, I set upon the creation of the plethora of new "must have" reports.  Many of the reports they want involved breaking up data into ranges and reporting on range statistics.  They also wanted to be able to play with the raw data and see the results in the charts.  This was a task.&lt;br /&gt;&lt;br /&gt;What I decided to do was create named ranges referencing the desired "raw" data ranges for periods.  Because this data is being queried based on the users parameters, the ranges must be calculated and created on the server.  I planned to then reference these ranges in the cells of a table of period statistics.  This would free me from calculating the statistics on the server and allow Excel to alter the charts as data in the ranges is changed.  The only thing that was missing was how to go about setting a cell value to something like "MEDIAN("MyWorkbook.xls"!MyNamedRange)".  I looked everywhere for a solution.  I scoured the POI mailing lists and APIs, I tried a number of variations on the formula string, I searched Krugle like mad and I got nowhere.  Not getting any response on lists or forums, and being one to take defeat likely, I took up my trusty debugger and set to probing the depths of POI.  Let me warn those of weak constitution to stop reading here.  The resulting code involves accessing the inaccessible, breaking the rules that the makers have set out for us and generally doing nasty things.&lt;br /&gt;&lt;br /&gt;I created a number of cells that contained references of the type that I required, then created expressions in the debugger to expose the internal representation of the file that POI uses.  I found that formulas are parsed into a list of references (to functions, ranges, etc.).  I found that I could create formulas that resembled the ones that I desired, using a dummy static reference as a place holder and then swap the static reference for a dynamic one of my creation.  This converts a formula like "AVERAGE(A:A)" to something like "AVERAGE("MyWorkbook.xls"!MyNamedRange)".  The thing is, the POI guys/gals didn't really intend these things to be accessed directly.  So, naturally, I promptly went against their wishes.  The following is the result.  Use it at your own risk, observe the comments and stated limitations, expand it, generalize it, whatever...but I would appreciate it if you relay any improvements back to me as well. ;)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;    /**&lt;br /&gt;     * The purpose of this method is to HACK OUT a static range reference from&lt;br /&gt;     * POI's internal representation of a single range parameter function cell&lt;br /&gt;     * and replace it with a reference to a existing named range. Because the&lt;br /&gt;     * necessary fields and methods are not meant for general use, they are&lt;br /&gt;     * inaccessible. As a result, reflection was used to obtain the necessary&lt;br /&gt;     * references. This provides an opportunity for undetected errors to creep&lt;br /&gt;     * in, as changes to these methods would not be detectable at compile time.&lt;br /&gt;     * Furthermore, as non-accessible methods, they are more likely to be&lt;br /&gt;     * subject to change with future releases.&lt;br /&gt;     * &lt;br /&gt;     * The process for replacement of references is as follows: - Retrieve the&lt;br /&gt;     * FormulaRecordAggregate from the target cell. - Reduce the FormulaRecord's&lt;br /&gt;     * expression length by 2 (area references are larger than name references). -&lt;br /&gt;     * Set the calculate on load option for the cell to true (options = 2). -&lt;br /&gt;     * Create a new named range reference and set field_2_ilbl to the index of&lt;br /&gt;     * the desired name in the workbook's name table. - Remove the static area&lt;br /&gt;     * reference from the parsed expression (index = 0). - Insert the newly&lt;br /&gt;     * created named range reference into the parsed expression (index = 0). -&lt;br /&gt;     * Smile.&lt;br /&gt;     * &lt;br /&gt;     * @BFNH  This is a Big Fat Nasty Hack. Be ye' warned!&lt;br /&gt;     * @param results  the workbook being dealt with&lt;br /&gt;     * @param targetcell  the cell in which the formula reference&lt;br /&gt;     * @param nameName the name of the named range to reference&lt;br /&gt;     */&lt;br /&gt;    @SuppressWarnings("unchecked")&lt;br /&gt;    protected void hackFunctionCellToSetNewNamePointer(HSSFWorkbook results,&lt;br /&gt;     HSSFCell targetcell, String name) {&lt;br /&gt; try {&lt;br /&gt;     short nameIndex = (short) (results.getNameIndex(name) + 1);&lt;br /&gt;&lt;br /&gt;     // Get the original formula record aggregate. This must be done&lt;br /&gt;     // via reflection, as it is not an accessible method.&lt;br /&gt;     Method method = HSSFCell.class.getDeclaredMethod(&lt;br /&gt;      "getCellValueRecord", new Class[] {});&lt;br /&gt;     method.setAccessible(true);&lt;br /&gt;     FormulaRecordAggregate original = (FormulaRecordAggregate) method&lt;br /&gt;      .invoke(targetcell);&lt;br /&gt;&lt;br /&gt;     // A static area reference is a couple of bytes larger than a name&lt;br /&gt;     // reference. So, if we don't reduce the formula record size, we&lt;br /&gt;     // will get corruption of the produced file.&lt;br /&gt;     List parsedExpression = original.getFormulaRecord()&lt;br /&gt;      .getParsedExpression();&lt;br /&gt;     short length = (short) (original.getFormulaRecord()&lt;br /&gt;      .getExpressionLength() - 2);&lt;br /&gt;     original.getFormulaRecord().setExpressionLength(length);&lt;br /&gt;&lt;br /&gt;     // Now we want to make sure that we cause the cell to be calculated&lt;br /&gt;     // on-load. The following line should accomplish that. Note, that&lt;br /&gt;     // if you have other options on the cell, they will be wiped out by&lt;br /&gt;     // this. Chances are that won't effect you though.&lt;br /&gt;     original.getFormulaRecord().setOptions((short) 2);&lt;br /&gt;&lt;br /&gt;     // Now we create a name pointer...the constructor I'm using here has&lt;br /&gt;     // not been implemented yet. If it were, we would likely not need to&lt;br /&gt;     // set the "field_2_ilbl" value. From what I can tell, this field is&lt;br /&gt;     // essentially the pointer to the name table in the workbook. We&lt;br /&gt;     // give it the name index and leave the rest alone.&lt;br /&gt;     NameXPtg nameptr = new NameXPtg(name);&lt;br /&gt;     Field nameTableIndex = NameXPtg.class&lt;br /&gt;      .getDeclaredField("field_2_ilbl");&lt;br /&gt;     nameTableIndex.setAccessible(true);&lt;br /&gt;     nameTableIndex.setShort(nameptr, nameIndex);&lt;br /&gt;&lt;br /&gt;     // Now we remove the static area reference from the parsed&lt;br /&gt;     // expression and add our name pointer in it's place. Please note&lt;br /&gt;     // that I have only tried this with functions that take a single&lt;br /&gt;     // name pointer and of those, only functions with 1 or 2 total&lt;br /&gt;     // parameters. In the case of two parameters, I have only tested&lt;br /&gt;     // when the second parameter is a constant. For example,&lt;br /&gt;     // This should work with: COUNT("MyFile.xls"!MyName) or&lt;br /&gt;     // AVERAGE("MyFile.xls"!MyName) or even&lt;br /&gt;     // QUARTILE("MyFile.xls"!MyName, 1). I would imagine that the&lt;br /&gt;     // process is similar for more complex function cells, but this is&lt;br /&gt;     // all I have needed, so that's as far as I've gone. My guess is&lt;br /&gt;     // that the length would have to be decremented once for each Area&lt;br /&gt;     // to Name conversion you do and I have no speculation about where&lt;br /&gt;     // the other area pointers might land in the parsed expression (in&lt;br /&gt;     // terms of their index).&lt;br /&gt;     parsedExpression.remove(0);&lt;br /&gt;     parsedExpression.add(0, nameptr);&lt;br /&gt; } catch (Exception e) {&lt;br /&gt;     // You screwed up and I don't care...write your own error handling.&lt;br /&gt;     // ;)&lt;br /&gt;     log.error("Bad developer...BAD!");&lt;br /&gt; }&lt;br /&gt;    }&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/574661030392104329-8389849542650539023?l=amateuratbest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/8389849542650539023/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=574661030392104329&amp;postID=8389849542650539023' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/8389849542650539023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/8389849542650539023'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/2007/10/bfnh-this-is-big-fat-nasty-hack-be-ye.html' title='@BFNH  This is a Big Fat Nasty Hack.  Be ye&apos; warned!'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-574661030392104329.post-6108733818284661937</id><published>2007-08-10T09:11:00.001-07:00</published><updated>2007-08-10T09:11:54.797-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Excel'/><category scheme='http://www.blogger.com/atom/ns#' term='Charts'/><category scheme='http://www.blogger.com/atom/ns#' term='jXLS'/><category scheme='http://www.blogger.com/atom/ns#' term='POI'/><title type='text'>Excel Charting in Java</title><content type='html'>Ahh, Excel...&amp;nbsp; I hate it.&amp;nbsp; I find it rather unintuitive, to be honest.&amp;nbsp; No, no no...that is not quite saying enough.&amp;nbsp; I find it &lt;span style="font-weight: bold;"&gt;nearly impossible&lt;/span&gt; to use.&amp;nbsp; Business folk however, love it.&amp;nbsp; In every company that I have worked for, every user group I have served has, eventually, asked for something to be output to Excel.&amp;nbsp; Of course, for us Java folk, there is good old &lt;a href="http://poi.apache.org/"&gt;Apache POI&lt;/a&gt;.&amp;nbsp; Now, POI is pretty good.&amp;nbsp; I've used it in a number of projects and have not had any stability issues.&amp;nbsp; Performance is generally acceptable when dealing with reasonable amounts of data.&amp;nbsp; It does however, have a good number of limitations.&amp;nbsp; A large subset of the Excel functions are still unimplemented and there is almost no support for charts (To be specific: charts will be preserved but cannot be altered).&amp;nbsp; This is often a big stumbling block.&amp;nbsp; Furthermore, building spreadsheets with method calls is not a very efficient process for the developer.&amp;nbsp; Creating just a single spreadsheet can require a lot of code.&lt;br /&gt;&lt;br /&gt;This is the problem I found myself up against recently.&amp;nbsp; In searching for a possible solution, I came up with a couple of really useful finds.&amp;nbsp; The first of which was &lt;a href="http://jxls.sourceforge.net/"&gt;jXLS&lt;/a&gt;.&amp;nbsp; jXLS is an excel templating framework of sorts.&amp;nbsp; It allows a designer to insert tags into a template spreadsheet which will be interpreted by jXLS and populated appropriately.&amp;nbsp; The tags utilize an expression language very similar to the EL used in JSPs or XSLT.&amp;nbsp; Developers who are comfortable with either of these technologies should feel right at home with jXLS.&lt;br /&gt;&lt;br /&gt;Basically, you can create an excel sheet and throw in some expressions like so:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://farm2.static.flickr.com/1012/1072846504_38d19205eb.jpg?v=0" alt="jXLSexpressions.png" onload="show_notes_initially();" class="reflect" height="201" width="483" /&gt;&lt;br /&gt;&lt;br /&gt;Then you run in through jXLS with something similar to:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Map beans = new HashMap();&lt;br /&gt;beans.put("item", items);&lt;br /&gt;XLSTransformer transformer = new XLSTransformer();&lt;br /&gt;HSSFWorkbook results&amp;nbsp; = transformer.transformXLS(Thread.currentThread().getContextClassLoader()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .getResourceAsStream("daysToProvideInstructions.xls"), beans);&lt;/pre&gt;&lt;br /&gt;As you can see by the fact that we get a HSSFWorkbook back from this method call, jXLS is based around POI, but it does the having lifting for the data insertion.&amp;nbsp; If you want to shove that file back out via a HttpServletResponse, you don't need much:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;response.setContentType("application/vnd.ms-excel");&lt;br /&gt;response.setHeader("Content-Disposition","attachment; filename=warrantyAgingReport.xls");&lt;br /&gt;results.write(response.getOutputStream());&lt;/pre&gt;&lt;br /&gt;Put all this in your web app and you'll get:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://farm2.static.flickr.com/1231/1072846540_644d5d04f0.jpg?v=0" alt="jXLSpopulated.png" onload="show_notes_initially();" class="reflect" height="303" width="500" /&gt;&lt;br /&gt;&lt;br /&gt;So, jXLS gives me a nice and easy solution for populating a spreadsheet with data...but, we still cannot edit the ranges of any tables that we create.&amp;nbsp; Furthermore, if we want functions to be evaluated when the spreadsheet is opened, we have to evaluate them in POI, right?&amp;nbsp; Named Ranges to the rescue!&amp;nbsp; It just so happens that we can define a dynamic range in Excel and give it a name.&amp;nbsp; We can then use those named ranges in charts, functions, etc.&amp;nbsp; This results in a those items being dynamically evaluated and gives us the results we want.&amp;nbsp; So following &lt;a href="http://pubs.logicalexpressions.com/pub0009/LPMArticle.asp?ID=518"&gt;Micro$oft's own instructions&lt;/a&gt; on the matter, we can create a couple of ranges in our template spreadsheet like so:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://farm2.static.flickr.com/1389/1071983411_97d1405491.jpg?v=0" alt="namedExcelRanges.png" onload="show_notes_initially();" class="reflect" height="251" width="411" /&gt;&lt;br /&gt;&lt;br /&gt;Using those ranges in a chart gives us the following:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://farm2.static.flickr.com/1135/1072114545_38511b94a8.jpg?v=0" alt="dynamicallyRangedChart.png" onload="show_notes_initially();" class="reflect" height="265" width="500" /&gt;&lt;br /&gt;&lt;br /&gt;Now we have the dynamic Excel charts we need, generated via our Java web application with very little excess effort.&amp;nbsp; So, while I still hate Excel...today I hate it from Java just a little less. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/574661030392104329-6108733818284661937?l=amateuratbest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/6108733818284661937/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=574661030392104329&amp;postID=6108733818284661937' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/6108733818284661937'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/6108733818284661937'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/2007/08/excel-charting-in-java.html' title='Excel Charting in Java'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-574661030392104329.post-6036978336510964700</id><published>2007-08-02T09:02:00.001-07:00</published><updated>2007-08-02T09:02:48.712-07:00</updated><title type='text'>Austrailian Echoes</title><content type='html'>&lt;p&gt;Would you like a &lt;a href="http://forum.nextapp.com/forum/index.php?showtopic=4212"&gt;fork&lt;/a&gt;, sir?&amp;nbsp; It looks like the Echo2 community has finally made that option a reality with the &lt;a href="http://www.karora.org/?q=node/8"&gt;Cooee&lt;/a&gt; project.&amp;nbsp; Cooee (an Austrailian &lt;a href="http://en.wikipedia.org/wiki/Cooee"&gt;"Over here!"&lt;/a&gt;,&amp;nbsp; of sorts) is being put forth by &lt;a href="http://www.karora.org"&gt;Karora&lt;/a&gt;, an open source group with routes in Melbourne.&amp;nbsp; The "openness" of the Echo2 project under the guidance of NextApp &lt;a href="http://forum.nextapp.com/forum/index.php?showtopic=1529"&gt;has been questioned&lt;/a&gt; by the user community for &lt;a href="http://forum.nextapp.com/forum/index.php?showtopic=1105&amp;amp;st=15"&gt;some time now&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I am, personally, torn on this issue.&amp;nbsp; I empathize with the issues raised by Karora.&amp;nbsp; I think that the leadership of the Echo2 project have given the community the impression of being forsaken or, worse yet, irrelevant.&amp;nbsp; However, I am still a little unsure of the timing.&amp;nbsp; Echo seems to be on the verge of a fairly major release and I can't help but wonder if waiting for that code to surface might have been worth it.&amp;nbsp; What is done is done, however and Karora can always spend some time merging code. :)&lt;/p&gt;&lt;p&gt;I want to wish the best of luck to the core Karora team in gaining acceptance as well as momentum.&amp;nbsp; A little competition never hurts...&lt;br /&gt;&lt;/p&gt;&lt;p style="text-align: right; font-size: 8px"&gt;Blogged with &lt;a href="http://www.flock.com/blogged-with-flock" title="Flock" target="_new"&gt;Flock&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/574661030392104329-6036978336510964700?l=amateuratbest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/6036978336510964700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=574661030392104329&amp;postID=6036978336510964700' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/6036978336510964700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/6036978336510964700'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/2007/08/austrailian-echoes.html' title='Austrailian Echoes'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-574661030392104329.post-4006503041389352791</id><published>2007-08-01T11:39:00.001-07:00</published><updated>2007-08-01T11:39:04.314-07:00</updated><title type='text'>Work, school and other such obstacles...</title><content type='html'>So, school, work, and life have gotten in the way of posting recently.&amp;nbsp; Summer classes are always time consuming.&amp;nbsp; I am working on a couple of different tutorial ideas right now.&amp;nbsp; I've got SCRUM, JavaFX and the Swing Application Framework in my sights at the moment.&amp;nbsp; SCRUM is almost ready to go, I can decide on the App Framework or JavaFX to follow it up though.&amp;nbsp; I've begun work on both, but hit the breaks when everything else picked up.&lt;br /&gt;&lt;br /&gt;To those of you reading, my apologize for the delay.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/574661030392104329-4006503041389352791?l=amateuratbest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/4006503041389352791/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=574661030392104329&amp;postID=4006503041389352791' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/4006503041389352791'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/4006503041389352791'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/2007/08/work-school-and-other-such-obstacles.html' title='Work, school and other such obstacles...'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-574661030392104329.post-624903046175734420</id><published>2007-06-19T13:38:00.001-07:00</published><updated>2007-06-19T13:38:37.598-07:00</updated><title type='text'>Podcasting Tutorials?</title><content type='html'>So, I've been thinking a lot about the kind of information that I want to convey here.  I am very fond of the tutorial format.  The problem is that I am not really convinced that blogging tutorials is appropriate.  The reason that I say this is that my tutorials tend to get long-winded rather quickly (as does anything that comes out of my head).  Tutorials seem to be a better fit for the multi-paged, online magazine format.  The problem I have with going that route is two fold.  First of all, I have no desire to spend time trying to convince some online editor to publish my tutorials.  Yes, I could always do it myself, but I really do not think that my goals match up with that format.  I, like many of you out there, am a busy guy.  I think I do a pretty good job of keeping current, but it takes a significant effort.  This is an effort that, sadly, most developers either do not have the time or the motivation to undertake.  My answer to this problem has been multi-pronged.  First, I utilize the wonderful service provided by Netvibes to keep my time spent having to jump from site to site at a minimum.  Secondly, (and this is something that Netvibes also helps with) I practice active "time shifting".  What I mean by this is that I utilize technology to help me make something out of the time in my day that is lost to the abyss.  The time I am talking about is that spent in the car, in lines, waiting for other people or even performing the less "thought intensive" parts of my day job.  Now, I do not want to give anyone the idea that I put all of those minutes to actively advancing myself.  A good many of those minutes get devoted to things that are nothing but mind candy.  I do, however, listen to a number of podcasts that take aim at intellectual topics or attempt to educate their listeners in some way or another.&lt;br/&gt; &lt;br/&gt; This got me thinking: would a podcast be a good format for tutorials of this type?  While there are a number of podcasts that address software development, most of them focus on news or interviews.  From what I can tell, there really is not much out there providing active training to the community.  Personally, I know that I would listen to a podcast of this type...but that goes without saying.  What I am stuck on is whether or not audio is a format that would be widely accepted for this purpose.  I have a number of tutorials canned and ready to go.  So, I am contemplating recording a few of them up front to determine if there are any hurdles to getting this type of information across in an audio format...and maybe syncing that audio with a "screencast" if I get ambitious.  If it goes well, maybe I will release them and see what everyone has to say.  If the response is good, I'll keep it up.  I am a bit concerned about being able to create tutorials at a rate that would keep a listener base coming back.  However, if I get enough feedback, I may try to balance that out by requesting tutorial submissions from listeners.  We'll see...it is really just a thought at this point.&lt;br/&gt; &lt;!-- technorati tags begin --&gt;&lt;p style="font-size:10px;text-align:right;"&gt;technorati tags:&lt;a href="http://technorati.com/tag/Podcasting" rel="tag"&gt;Podcasting&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Software" rel="tag"&gt;Software&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Training" rel="tag"&gt;Training&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Tutorials" rel="tag"&gt;Tutorials&lt;/a&gt;&lt;/p&gt;&lt;!-- technorati tags end --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/574661030392104329-624903046175734420?l=amateuratbest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/624903046175734420/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=574661030392104329&amp;postID=624903046175734420' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/624903046175734420'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/624903046175734420'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/2007/06/podcasting-tutorials.html' title='Podcasting Tutorials?'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-574661030392104329.post-7522999949340157170</id><published>2007-06-19T13:05:00.000-07:00</published><updated>2007-06-19T13:22:53.304-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Dependency Injection'/><category scheme='http://www.blogger.com/atom/ns#' term='AJAX'/><category scheme='http://www.blogger.com/atom/ns#' term='Guice'/><category scheme='http://www.blogger.com/atom/ns#' term='Echo2'/><title type='text'>Drink More Guice...</title><content type='html'>&lt;p&gt;Okay, okay...this post is, seriously, a long time coming.  I have not posted anything for a while for a number of reasons.  I could give the details, but there aren't enough of you out there who are going to care.  So, I'll skip it and get into the goodies.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Reading this may actually kill two birds with a single stone for many of you.  For the example project that I put together here, I made use of the &lt;a href="http://nextapp.com/platform/echo2/echo/"&gt;Echo2 &lt;/a&gt;framework.  There are a number of reasons that I chose to do this.   First of all, I think that dependency injection (D.I.) can be particularly beneficial when working in a component model.  I think the switch to a real component model in Java GUI development is long overdue, particularly in the world of web UI development.  So, I am hoping that this example will convey the ease with which a simple UI can be created using a framework like Echo2 or GWT as well as provide a few simple, yet useful, ways to leverage D.I. when creating a user interface.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;We have all seen dependency injection brought into the main stream by the Spring Framework.  As many of its proponents will tell you, Spring is a very powerful and highly configurable tool, whose usefulness goes way beyond simple dependency injection.  Many people see Guice as a competitor to Spring, and in some ways it is.  However, Guice is not nearly as broad in functionality as Spring.  Guice is aimed at being fast and simple for dependency injection only. One immediately evident difference between Spring and Guice is Guice having fully embraced annotations in its implementation of DI.  While I must point out that while the JavaConfig project has brought annotation based configuration to Spring, the implementation is, arguably, more complex and results in a more intrusive presence in the most common circumstances where DI is being used.  If you are familiar with Spring and JavaConfig, much of this will become evident as I continue.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Enough of this blathering, let's look at some code.  I am going to start with what many tutorials will save to the end: the point of injection.  Ideally, D.I. should be something that is as invisible as possible.  Far too often you see people directly accessing a framework's DI context directly in several different places in their application code.  This is a situation that I will try to avoid in this tutorial.  To that end, I am going to try to find a place where injection can happen once and the effects will flow throughout the rest of the application.  In an Echo2 application this choice is simple, every Echo2 application instance is feed off and attached to the user session via a WebContainerServlet implementation:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;package com.amateuratbest.examples.guice;&lt;br /&gt;&lt;br /&gt;import nextapp.echo2.app.ApplicationInstance;&lt;br /&gt;import nextapp.echo2.webcontainer.WebContainerServlet;&lt;br /&gt;&lt;br /&gt;import com.amateuratbest.examples.guice.layout.LayoutModule;&lt;br /&gt;import com.google.inject.Guice;&lt;br /&gt;import com.google.inject.Injector;&lt;br /&gt;import com.google.inject.Module;&lt;br /&gt;import com.google.inject.servlet.ServletModule;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * This is where all the Guice-iness goes on.  We will look for our injector&lt;br /&gt; * in the ServletContext, create it if necessary and then inject our newly&lt;br /&gt; * constructed ApplicationInstance.  All done!&lt;br /&gt; * &lt;br /&gt; * @author mkimberlin&lt;br /&gt; */&lt;br /&gt;public class TestGuiceServlet extends WebContainerServlet {&lt;br /&gt;&lt;br /&gt;   private static final long serialVersionUID = 2715828643772899566L;&lt;br /&gt;&lt;br /&gt;   /* (non-Javadoc)&lt;br /&gt;    * @see nextapp.echo2.webcontainer.WebContainerServlet#newApplicationInstance()&lt;br /&gt;    */&lt;br /&gt;   @Override&lt;br /&gt;   public ApplicationInstance newApplicationInstance() {&lt;br /&gt;      TestGuiceApplication newApp = new TestGuiceApplication();&lt;br /&gt;      // This uses the Injector class name as the attribute name...&lt;br /&gt;      Injector injector = (Injector) getServletContext().getAttribute(&lt;br /&gt;            Injector.class.getName());&lt;br /&gt;      if (injector == null) {&lt;br /&gt;         injector = Guice.createInjector(new Module[] {new LayoutModule(), new ServletModule() });&lt;br /&gt;         getServletContext().setAttribute(Injector.class.getName(), injector);&lt;br /&gt;      }&lt;br /&gt;      injector.injectMembers(newApp);&lt;br /&gt;      return newApp;&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;In order to avoid constructing the injector more than once, I am keeping it in the ServletContext.  If one isn't in context when I need it, it can be instructed by specifying the configuration modules that contain the desired configuration.  Yes, you read that right.  The configuration is done in Java, not XML.  For the purposes of this example, I have a set of two modules that will be used for injection.  In this case, I have one application specific module (LayoutModule) and one Guice-provided module (ServletModule).  If you are working with a web application, you will almost definitely want to include this second module, as it defines injection scopes for request and session as well as providing bindings for injection into the request, session or response.  It should be noted that there is nothing preventing the use of different modules as dictated by your applications needs.  Module selection could be done based on user preferences, branding, or any number of other concerns.  The main thing here is that, if I do things right, we should never see an injector again.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Now that we've seen our &amp;quot;point of entry&amp;quot;, as it were, let us grab a quick look at those configuration modules:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;package com.amateuratbest.examples.guice.layout;&lt;br /&gt;&lt;br /&gt;import nextapp.echo2.app.Column;&lt;br /&gt;import nextapp.echo2.app.SplitPane;&lt;br /&gt;&lt;br /&gt;import com.amateuratbest.examples.guice.annotations.NamedAnnotation;&lt;br /&gt;import com.google.inject.AbstractModule;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * This class contains the DI bindings for the main layout components.&lt;br /&gt; * &lt;br /&gt; * @author mkimberlin&lt;br /&gt; */&lt;br /&gt;public class LayoutModule extends AbstractModule {&lt;br /&gt;   public static final String BANNER = "banner";&lt;br /&gt;   public static final String NAVIGATION = "navigation";&lt;br /&gt;&lt;br /&gt;   @Override&lt;br /&gt;   protected void configure() {&lt;br /&gt;      bind(Column.class).annotatedWith(new NamedAnnotation(BANNER))&lt;br /&gt;         .to(BannerColumn.class);&lt;br /&gt;      bind(SplitPane.class).annotatedWith(new NamedAnnotation(BANNER))&lt;br /&gt;         .to(BannerSplitPane.class);&lt;br /&gt;      bind(SplitPane.class).annotatedWith(new NamedAnnotation(NAVIGATION))&lt;br /&gt;         .to(NavigationSplitPane.class);&lt;br /&gt;&lt;br /&gt;      &lt;br /&gt;      // Note that if you uncomment the following lines you will get a compile&lt;br /&gt;      // time error.  Guice's use of generics means a far less error prone&lt;br /&gt;      // configuration process.  If this were done in a config file, you would&lt;br /&gt;      // have to wait until run time to discover your mistake.&lt;br /&gt;      //&lt;br /&gt;      //bind(Column.class).annotatedWith(new NamedAnnotation(BANNER))&lt;br /&gt;      //   .to(BannerSplitPane.class);&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;This module, lovingly dubbed &amp;quot;LayoutModule&amp;quot; extends the abstract class AbstractModule that is provided as a part of Guice.  As you can see, you only need to override the configure() method and specify the bindings that you would like Guice to honor when doing injection based on this configuration.  The first two calls to bind() produce bindings for the given classes for any case where the target is annotated with a named annotation constructed with the name &amp;quot;banner&amp;quot;.  Using named annotations like this is simply one way to accomplish multiple bindings for the same class.  The third call to bind() produces a second binding for the SplitPane class.  However, this binding only applies when the target was annotated with a the NamedAnnotation for &amp;quot;navigation&amp;quot;.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The section of code that has been commented out can be uncommented to see how Guice's &amp;quot;config in code&amp;quot; approach results in a less error-prone configuration.  Static typing results in a compile time error if you have configured a binding that doesn't make sense.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;This next piece of code has a couple of methods that are requesting injection.  What is worth attention in these is the fact that there was no binding necessary.  If you look at the earlier configuration module, you will not find anything that creates a binding for these classes.  Crazy Bob Lee and his ilk at Google appear to have put a good deal of effort in to minimizing the amount of configuration you have to do (of which this is but one example).  In this particular case, I just need to make sure that any new instances get a rootWindow and layoutPane.  Since Window has an available default constructors, Guice will just take care of things for us without having to be told.  LayoutPane is a similar, but not identical circumstance, but I will investigate that in a moment.&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;package com.amateuratbest.examples.guice;&lt;br /&gt;&lt;br /&gt;import nextapp.echo2.app.ApplicationInstance;&lt;br /&gt;import nextapp.echo2.app.Window;&lt;br /&gt;import nextapp.echo2.app.componentxml.ComponentXmlException;&lt;br /&gt;import nextapp.echo2.app.componentxml.StyleSheetLoader;&lt;br /&gt;&lt;br /&gt;import org.apache.commons.logging.Log;&lt;br /&gt;import org.apache.commons.logging.LogFactory;&lt;br /&gt;&lt;br /&gt;import com.amateuratbest.examples.guice.layout.LayoutPane;&lt;br /&gt;import com.google.inject.Inject;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * Very simple implementation of the Echo2 ApplicationInstance.  Normally, we&lt;br /&gt; * would not want to have a check that is "injection aware", per se...but I did&lt;br /&gt; * here for "instructional" purposes.  Now I think I'll use some "more quotes",&lt;br /&gt; * "just because" i think they are "groovy".&lt;br /&gt; * &lt;br /&gt; * @author mkimberlin&lt;br /&gt; */&lt;br /&gt;public class TestGuiceApplication extends ApplicationInstance {&lt;br /&gt;   private static Log log = LogFactory.getLog(TestGuiceApplication.class);&lt;br /&gt;&lt;br /&gt;   private Window rootWindow;&lt;br /&gt;   &lt;br /&gt;   private LayoutPane layoutPane;&lt;br /&gt;   &lt;br /&gt;   /* (non-Javadoc)&lt;br /&gt;    * @see nextapp.echo2.app.ApplicationInstance#init()&lt;br /&gt;    */&lt;br /&gt;   @Override&lt;br /&gt;   public Window init() {&lt;br /&gt;      try {&lt;br /&gt;         setStyleSheet(StyleSheetLoader.load("/style.xml", Thread.currentThread().getContextClassLoader()));&lt;br /&gt;      } catch (ComponentXmlException e) {&lt;br /&gt;         log.warn("Could not load default styles for routine builder.");&lt;br /&gt;      }&lt;br /&gt;       &lt;br /&gt;      if(rootWindow == null) {&lt;br /&gt;         rootWindow = new Window();&lt;br /&gt;         log.debug("Injection Failed...");&lt;br /&gt;      } else {&lt;br /&gt;         log.debug("Injection Worked...");         &lt;br /&gt;      }&lt;br /&gt;      rootWindow.setContent(layoutPane);&lt;br /&gt;       return rootWindow;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public Window getRootWindow() {&lt;br /&gt;      return rootWindow;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   @Inject&lt;br /&gt;   public void setRootWindow(Window rootWindow) {&lt;br /&gt;      this.rootWindow = rootWindow;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public LayoutPane getLayoutPane() {&lt;br /&gt;      return layoutPane;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   @Inject&lt;br /&gt;   public void setLayoutPane(LayoutPane layoutPane) {&lt;br /&gt;      this.layoutPane = layoutPane;&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Unlike with Window, Guice is not using a default constructor for LayoutPane:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;package com.amateuratbest.examples.guice.layout;&lt;br /&gt;&lt;br /&gt;import nextapp.echo2.app.ContentPane;&lt;br /&gt;import nextapp.echo2.app.SplitPane;&lt;br /&gt;&lt;br /&gt;import com.amateuratbest.examples.guice.ComponentUtil;&lt;br /&gt;import com.google.inject.Inject;&lt;br /&gt;import com.google.inject.name.Named;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * Constructs and contains the main layout components of the application.&lt;br /&gt; * You will notice the constructor parameters are named.  In this example&lt;br /&gt; * I'm using named mostly to avoid writing a bunch of custom annotations.&lt;br /&gt; * This may or may not be the right approach for your project.&lt;br /&gt; * &lt;br /&gt; * @author mkimberlin&lt;br /&gt; */&lt;br /&gt;public class LayoutPane extends ContentPane {&lt;br /&gt;   private SplitPane bannerSplitPane;&lt;br /&gt;   private SplitPane navigationSplitPane;&lt;br /&gt;&lt;br /&gt;   @Inject&lt;br /&gt;   public LayoutPane(&lt;br /&gt;            @Named(LayoutModule.BANNER) SplitPane bannerSplitPane,&lt;br /&gt;            @Named(LayoutModule.NAVIGATION) SplitPane navigationSplitPane) {&lt;br /&gt;      super();&lt;br /&gt;      this.bannerSplitPane = bannerSplitPane;&lt;br /&gt;      this.navigationSplitPane = navigationSplitPane;&lt;br /&gt;      &lt;br /&gt;      add(bannerSplitPane);&lt;br /&gt;      bannerSplitPane.add(navigationSplitPane);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /**&lt;br /&gt;    * @return the navigationSplitPane&lt;br /&gt;    */&lt;br /&gt;   public SplitPane getNavigationSplitPane() {&lt;br /&gt;      return navigationSplitPane;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /**&lt;br /&gt;    * @param navigationSplitPane the navigationSplitPane to set&lt;br /&gt;    */&lt;br /&gt;   public void setNavigationSplitPane(SplitPane navigationSplitPane) {&lt;br /&gt;      ComponentUtil.replaceChild(bannerSplitPane, this.navigationSplitPane,&lt;br /&gt;            navigationSplitPane);&lt;br /&gt;      this.navigationSplitPane = navigationSplitPane;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /**&lt;br /&gt;    * @return the bannerSplitPane&lt;br /&gt;    */&lt;br /&gt;   public SplitPane getBannerSplitPane() {&lt;br /&gt;      return bannerSplitPane;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   /**&lt;br /&gt;    * @param bannerSplitPane the bannerSplitPane to set&lt;br /&gt;    */&lt;br /&gt;   public void setBannerSplitPane(SplitPane bannerSplitPane) {&lt;br /&gt;      ComponentUtil.replaceChild(this, this.bannerSplitPane, bannerSplitPane);&lt;br /&gt;      this.bannerSplitPane = bannerSplitPane;&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;In this case I have made Guice aware of a constructor available for use during injection with the @Inject annotation.  Furthermore, I have annotated the parameters of said constructor in such a way as to trigger the bindings that I presented in the LayoutModule.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Another instance of injection in this example application that deserves calling is in the NavigationSplitPane.  Let's take a look at its constructor:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;@Inject&lt;br /&gt;public NavigationSplitPane(Column buttonColumn, ContentPane mainPane, ContentDAO contentDAO) {&lt;br /&gt;   ...&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Here again, there is a constructor being marked for injection, and again there are default constructors being used without configuration.  The last parameter deserves a few words, and not only because it is highly irregular to construct a GUI component by handing it a DAO...but that's not the point here.  ;)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;As you might expect, ContentDAO is an interface.  So, how did Guice know what to do for it?&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;package com.amateuratbest.examples.guice.dao;&lt;br /&gt;&lt;br /&gt;import com.amateuratbest.examples.guice.dao.mock.ContentDAOImpl;&lt;br /&gt;import com.google.inject.ImplementedBy;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * Simple DAO interface with a default implementation annotated for Guice.&lt;br /&gt; * Using the ImplementedBy annotation allows the developer to supply a default&lt;br /&gt; * implementation in the event that there is no explicit binding for an&lt;br /&gt; * interface.  This is the case 90% of the time for most projects.&lt;br /&gt; * &lt;br /&gt; * @author mkimberlin&lt;br /&gt; */&lt;br /&gt;@ImplementedBy(ContentDAOImpl.class)&lt;br /&gt;public interface ContentDAO {&lt;br /&gt; public String getContent();&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Some people are going to balk at this right off of the bat.  &amp;quot;WHY does my interface know about its implementation?!?&amp;quot;  However, I think you have to see this as something that is available for your convenience (and boy is it convenient) and not a required part of working with Guice.  If we developers are honest with ourselves, or simply inspect our code, it is clear that most interfaces we create use a single implementation 80+ percent of the time.  This makes those 80+ percent easy.  Obviously if this is an interface that you are going to package as a public API for some B2B system, you probably want to avoid this type of dependency.  Most of the time that is not the case, however.  Most of your interfaces only exist on the server and only have one implementation in the first place.  So, it is up to you to decide when using this &amp;quot;default implementation&amp;quot; feature is appropriate&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I have not presented all of the code contained in the example application in this tutorial.  I would encourage you to &lt;a href="http://mkimberlin.googlepages.com/GuiceTest.zip"&gt;download&lt;/a&gt; and deploy the application for yourself.  Plop the war in tomcat and off you go...all of the dependencies are included in the project zip file.  You will then be the proud papa (or mama) of a rich web application developed with only a few Java classes, and without touching any javascript directly, which manages to hydrate itself successfully with only one initial point of injection.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/574661030392104329-7522999949340157170?l=amateuratbest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/7522999949340157170/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=574661030392104329&amp;postID=7522999949340157170' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/7522999949340157170'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/7522999949340157170'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/2007/06/okay-okay.html' title='&lt;a href=&quot;http://mkimberlin.googlepages.com/GuiceTest.zip&quot;&gt;Drink More Guice...&lt;/a&gt;'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-574661030392104329.post-2281937562361973336</id><published>2007-04-13T07:19:00.001-07:00</published><updated>2007-04-13T07:19:43.508-07:00</updated><title type='text'>Geekfest is good for the soul!</title><content type='html'>&lt;p&gt;So, this post was originally going to be all about Google &lt;span&gt;Guice&lt;/span&gt;.  After writing for a few paragraphs, I realize that if I ever got to &lt;span&gt;Guice&lt;/span&gt; this would be the longest &lt;span&gt;blog&lt;/span&gt; post of all time.  So, tomorrow you get &lt;span&gt;Guice&lt;/span&gt; and today you get &lt;span&gt;Geekfest&lt;/span&gt;!  "What the heck is &lt;span&gt;Geekfest&lt;/span&gt;?", you might ask, or maybe not, &lt;strong&gt;but you should&lt;/strong&gt;.  Yes, I am sure there is some concert or conference or some such wonder by that name...but, we do not care for such things.  &lt;span&gt;Geekfest&lt;/span&gt; in this conversation is a few hours that the team that I work on puts aside every other week to encourage, even require, developers to take the time to keep their skills up-to-date and share their experiences with the group.  Think of it as on-the-job training that even the veterans need.  I have been on so many teams that do not make learning a priority.  On most of those teams, training would be provided only if there was an impending need.  This is a disastrous way to do things.  First of all, we as developers &lt;i&gt;absolutely must&lt;/i&gt; stay current if we want to stay employed.  Furthermore, we as organizations must keep the skills of our development staff current if we wish to be able to compete in the marketplace.  Now, we can simply expect developers to keep themselves current.  We can put in the job description that a developer must advance the knowledge of the team, or stay current with market trends or run a freaking marathon...but that does not make it happen.  Even for those developers who are self-motivated enough to do these things on their own, what percentage of them go around to the group and make sure everyone knows what they know?  Not very many, I can tell you.  We geeks tend to be made up of a high percentage of the less-than-social crowd.  A lot of people just do not feel comfortable doing this.  So, what happens to that knowledge?  Maybe it gets utilized, maybe that person puts it to work on a project or more likely it wastes away.&lt;/p&gt;  &lt;p&gt;Managers and team leads: You have a responsibility to ensure the best performance of your teams.  You have a responsibility to facilitate the growth of those around you.  Do not forget this.  Yes, I know that you have to get the project done.  Yes, I know that it is already 3 weeks behind schedule (that is your fault too, but we will talk about that in another post).  None of that matters.  Admit it!  Two or three hours every other week will not be noticed as even a blip in your time line.  What do you get out of this?  You get a team that feels like their development is important enough to you &lt;i&gt;and to the organization&lt;/i&gt; to make it a priority.  Have you ever felt that way?  Does your organization put you first?  Make it happen for your employees, it makes a world of difference.&lt;/p&gt;  &lt;p&gt;Maybe all that touchy-&lt;span&gt;feely&lt;/span&gt; &lt;span&gt;mumbo&lt;/span&gt; jumbo is not enough to convince you.  So, let us take a look at the basic rules that will allow us to realize some actual benefit &lt;span&gt;for&lt;/span&gt; the team:&lt;/p&gt;  &lt;ol&gt;&lt;li&gt;Thou shalt not skip the 'fest, no matter how busy you are...only actual emergencies qualify as an excuse for absence.&lt;br/&gt; &lt;/li&gt; &lt;li&gt;Thou shalt not investigate anything directly related to project work during the 'fest.&lt;/li&gt; &lt;li&gt;Thou shalt share your experiences with the group &lt;i&gt;before leaving&lt;/i&gt; the 'fest.&lt;/li&gt; &lt;li&gt;Thou shalt capture the results of your investigation at some level on the 'fest &lt;span&gt;wiki&lt;/span&gt;.&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;Now, that isn't asking all that much is it?  Do you see where the increased benefit comes in here?  No, well let me wax poetic on that for a bit. :)&lt;/p&gt;  &lt;p&gt;We have already addressed the fact that, if left to their own devices, only a fraction of of the group will actively expand their horizons and that only a fraction of those will share a fraction of what they learn with the group.  Wow...that is a lot of fractions and a lot of lost knowledge.  What makes &lt;span&gt;Geekfest&lt;/span&gt; different?  Everyone learns what everyone was learning!  I scream, you scream we all scream for...oh, &lt;span&gt;never mind&lt;/span&gt;.  Even the thickest headed of management will see the benefit of this.  If a team of six goes into a room and spends two hours investigating different topics then each one shares what they learned, what do you get?  Let us do a bit of arithmetic. 6 people do 2 hours of work and share that with the team of 6...&lt;span&gt;hrrrm&lt;/span&gt;: 6 x 2 x 6 = 72 hours with of gathered knowledge.  You invested 12 man hours.  Need I say more?  Now of course our implementations of this will be less than perfect.  Still, this is a great deal for an organization  What will happen if we let developers do this on their own?  We have to start dividing instead of multiplying.  Oh, and those developers who were learning on their own...do you think they stop because of this new found study time?  Not from my experience.  If anything, they are spurred forward in their &lt;span&gt;endeavours&lt;/span&gt;. This is a big fat win for everyone involved.&lt;/p&gt;  &lt;p&gt;Now, you have read this.  It all makes perfect sense to you.  How could you not have seen this before?  So, what are you going to do about it?  If you are a manager or team lead, schedule the meeting now.  Do not wait.  You and I both know it will get swept under the table.  If you are a developer, suggest it to your boss.  If you do not feel comfortable being that forward then send them a link to this post.  Tell them your friend that works over at the major competitor said his team has been doing this for months and how much they are gaining from it.  The entire industry will be all the better for it.&lt;br/&gt; &lt;/p&gt;  &lt;!-- technorati tags begin --&gt;&lt;p style="font-size:10px;text-align:right;"&gt;technorati tags:&lt;a href="http://technorati.com/tag/Agile" rel="tag"&gt;Agile&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Software" rel="tag"&gt;Software&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Development" rel="tag"&gt;Development&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Learning" rel="tag"&gt;Learning&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Training" rel="tag"&gt;Training&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Guice" rel="tag"&gt;Guice&lt;/a&gt;, &lt;a href="http://technorati.com/tag/ROI" rel="tag"&gt;ROI&lt;/a&gt;&lt;/p&gt;&lt;!-- technorati tags end --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/574661030392104329-2281937562361973336?l=amateuratbest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/2281937562361973336/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=574661030392104329&amp;postID=2281937562361973336' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/2281937562361973336'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/2281937562361973336'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/2007/04/geekfest-is-good-for-soul.html' title='Geekfest is good for the soul!'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-574661030392104329.post-922299229216457842</id><published>2007-04-10T09:04:00.001-07:00</published><updated>2007-06-15T09:07:20.235-07:00</updated><title type='text'>Domain Driven Design...revisiting good ol' fashion OO.</title><content type='html'>&lt;p&gt;A few weeks ago I attended the Gateway Software Symposium put on by the guys from &lt;a href="http://www.nofluffjuststuff.com/"&gt;No Fluff Just Stuff&lt;/a&gt;.  While I was there, I got the opportunity to listen to &lt;a href="http://www.agiledeveloper.com/blog"&gt;Venkat Subramaniam&lt;/a&gt; talk about domain driven design.  I almost skipped out on it for something else, but Venkat's knack for speaking is always good for an enjoyable lecture at the very least...so I went for it.  As expected, Venkat gave a great talk.  While the content convinced me even further that DDD is essentially a repackaging of old ideas, it also made me realize that some of the things that have bothered me about some of the ways we utilize patterns, and how many of them are even &lt;i&gt;enforced as standards&lt;/i&gt;.  This is just evil.   Some of this stuff is so ubiquitous that we just accept it as perfectly normal.  How many of you have worked on a project that looks something like the one below (hopefully with a few more classes)?&lt;/p&gt;  &lt;p&gt;&lt;img src="http://static.flickr.com/1417/552649801_e44b7d2549.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;I know that I have...and not just one.  Now, mind you, this project is trying really hard to have good practices.  It wants to reduce tight coupling...heck, it might use DI a la Spring or Google Guice.  What it does more than anything is insult our intelligence.  When I see a project like this, it makes me wonder why all this poor User has been scattered all over creation.  I feel like this project is trying to be a self-describing code cookbook.  It practically begs you to right a BO, a controller, a DAO, a model object and a factory for every class you create.  Now, I know we all hear a lot of people telling us not to put business logic in with our model.  I say, "Bullocks!"...put logic where it belongs, wherever that may be.  Sometimes our objects want to know how to do things for themselves.  Not only that, but why are we all so afraid of maintaining state in our applications?  Yeah, it comes with some complications...but sometimes those complications are &lt;i&gt;worth it&lt;/i&gt; and even &lt;i&gt;appropriate&lt;/i&gt;.&lt;/p&gt;  &lt;p&gt;I want us to start taking a hard look at what the users are saying about how they work.  Listen to what they are doing...how they are working now.  You probably had a professor use the old analogy of the bicycle and how all bicycles have a few attributes and actions that are common to them.  That same professor probably talked about 10-speeds and how they have some extra attributes and actions that a plain old bicycle might not. I often wonder what this professor would think of seeing:&lt;/p&gt;  &lt;pre&gt;int gear = bicycleBO.getCurrentGear(tenSpeed);&lt;/pre&gt;&lt;pre&gt;bicycleBO.setGear(tenSpeed, gear+1);&lt;/pre&gt;&lt;p&gt;I will tell you exactly what he would say:&lt;/p&gt;  &lt;pre&gt;tenSpeed.upShift();&lt;/pre&gt;&lt;p&gt;I am not advocating that we go back to the days of gigantic all encompassing classes...where a bicycle knows how to do anything that one might possibly want to do with it.  I mean, I might want to hang my bicycle from a tree, but that does not mean that my bicycle should know how to climb trees.  I am merely saying that we need to stop worrying so much about applying patterns across the entire landscape of a project and start thinking about the design that fits best.&lt;br /&gt;&lt;/p&gt;  &lt;!-- technorati tags begin --&gt;&lt;p style="font-size: 10px; text-align: right;"&gt;technorati tags:&lt;a href="http://technorati.com/tag/domain" rel="tag"&gt;domain&lt;/a&gt;, &lt;a href="http://technorati.com/tag/driven" rel="tag"&gt;driven&lt;/a&gt;, &lt;a href="http://technorati.com/tag/design" rel="tag"&gt;design&lt;/a&gt;, &lt;a href="http://technorati.com/tag/java" rel="tag"&gt;java&lt;/a&gt;, &lt;a href="http://technorati.com/tag/patterns" rel="tag"&gt;patterns&lt;/a&gt;, &lt;a href="http://technorati.com/tag/misuse" rel="tag"&gt;misuse&lt;/a&gt;&lt;/p&gt;&lt;!-- technorati tags end --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/574661030392104329-922299229216457842?l=amateuratbest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/922299229216457842/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=574661030392104329&amp;postID=922299229216457842' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/922299229216457842'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/922299229216457842'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/2007/04/domain-driven-designrevisiting-good-ol.html' title='Domain Driven Design...revisiting good ol&amp;#39; fashion OO.'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-574661030392104329.post-2187099483184574066</id><published>2007-03-30T21:20:00.000-07:00</published><updated>2007-03-30T22:02:18.113-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='software'/><category scheme='http://www.blogger.com/atom/ns#' term='project management'/><category scheme='http://www.blogger.com/atom/ns#' term='communication'/><title type='text'>Fresh Blood</title><content type='html'>No, no, no...I'm not going all &lt;a href="http://scottsigler.podshow.com"&gt;Scott &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Sigler&lt;/span&gt;&lt;/a&gt; on you.  (Go get Ancestor tomorrow, Junkies!!!)&lt;br /&gt;&lt;br /&gt;I am talking about breathing life into that dead project.  We have all been there.  You are assigned to a project where momentum appears unattainable and you fear the worst.  If you are a project manager and this is your project that I am talking about, big red flashing warning lights should be going off for you right now.  When the dynamics of a project team go stagnant and the momentum has died off (if it ever existed), it may be time to call in some fresh blood.&lt;br /&gt;&lt;br /&gt;Let me make it clear that I am not suggesting that adding new people in the middle of a project is going to solve all your problems.  As most of us in the real world are aware, this is rarely an option.  Often only projects of the highest priority and visibility have the freedom to infuse their team with "resources" at a whim.  Furthermore, this will often be counter productive.  What I am suggesting is much more benign that any of this.  I am saying simply that the &lt;span style="font-style: italic;"&gt;right&lt;/span&gt; person can breath new life and vitality into a project.  So Mr. Manager, if you happen to find yourself in the sorry position of needing to fill a vacancy on a project that is already flailing, turn it into an opportunity.  Do not simply fill the slot with someone who can crank out that code.  Take the time to find someone who has a focus on team communication.  Experience with agile development practices can bonus points to your candidate.  Finding these candidates is no easy task, but they are out there...and if you are having a hard time getting your hands on the right person, just give &lt;a href="http://www.ociweb.com"&gt;my employer&lt;/a&gt; a ring.  I am sure they would be happy to let you know when I will being freeing up.  ;)&lt;br /&gt;&lt;br /&gt;Someone who is excited to dive in and learn from the team, who has focus on the user community and goes out of their way to encourage involvement from everyone can turn a failing project upside-down.   When it works, the change is dramatic.  Let us hope that your project is not need of such a "magic-maker"...but remember that it is never too late to make a necessary change.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/574661030392104329-2187099483184574066?l=amateuratbest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/2187099483184574066/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=574661030392104329&amp;postID=2187099483184574066' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/2187099483184574066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/2187099483184574066'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/2007/03/fresh-blood.html' title='Fresh Blood'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-574661030392104329.post-1493960329491150997</id><published>2007-02-14T11:46:00.001-08:00</published><updated>2007-02-14T11:49:30.500-08:00</updated><title type='text'>Down with JSP!!!</title><content type='html'>&lt;p&gt;&lt;span&gt;Okay&lt;/span&gt;, &lt;span&gt;okay&lt;/span&gt;...that's a bit of a troll, I admit.  However, I have been doing Java based web applications for what must be more than 7 years now and I am honestly sick of &lt;span&gt;JSPs&lt;/span&gt;.  Now, before I get all ideological on you, I want to point out that I am not sure that we are ready to completely eliminate the &lt;span&gt;JSP&lt;/span&gt; from the planet.  I will tell you that the average developer of Java web &lt;span&gt;apps&lt;/span&gt; is spending &lt;strong&gt;way&lt;/strong&gt; too much time looking at these things.  &lt;span&gt;JSPs&lt;/span&gt; are nasty, dirty things that are difficult to put together and even worse to maintain.  Now, I'm sure some people reading this will start thinking things like "this guy probably still uses &lt;span&gt;scriptlets&lt;/span&gt; everywhere" or other such blasphemies.  I will assure you this is not the case.  I use all the happy little &lt;span&gt;taglibs&lt;/span&gt; that are supposed to make my life so much easier.  Yeah, well they don't...&lt;/p&gt;  &lt;p&gt;So, it's obvious that I am getting a bit hot-in-the-collar about this.  However, I think that most of us who care about such things realize that the old familiar style of web development just isn't doing it any more.  I am tired of switching from XML to Java to &lt;span&gt;SQL&lt;/span&gt; to &lt;span&gt;CSS&lt;/span&gt; and on and on and on.  I am tired of writing unnatural form bindings and silly validation scripts.  I am tired of not being able to interface with the components on my web &lt;span&gt;UI&lt;/span&gt; in the same way I would any other components in my application; via a Java &lt;span&gt;API&lt;/span&gt;.  Now, that there are frameworks that are getting there.  I have used &lt;a href="http://nextapp.com/platform/echo2/echo/"&gt;Echo2 &lt;/a&gt;and fiddled with &lt;a href="http://code.google.com/webtoolkit/"&gt;&lt;span&gt;Google&lt;/span&gt; Web Toolkit&lt;/a&gt; a bit, and they are on their way.  I am really excited to see the switch to a component and event paradigm in web frameworks.  I wish that &lt;a href="http://java.sun.com/javaee/javaserverfaces/"&gt;&lt;span&gt;JSF&lt;/span&gt;&lt;/a&gt; had not been so little so late.  However, I guess that change is in the air and we really will not know where we are going until the dust clears.  &lt;span&gt;Wherever&lt;/span&gt; that may be, I sure hope we get there soon...because, if I have to write another &amp;lt;%@ &lt;span&gt;taglib&lt;/span&gt; prefix="c" &lt;span&gt;uri&lt;/span&gt;="/WEB-INF/&lt;span&gt;tld&lt;/span&gt;/c.&lt;span&gt;tld&lt;/span&gt;" %&amp;gt;, I'm not sure I can take responsibility for my actions...&lt;br /&gt;&lt;/p&gt; &lt;br /&gt;&lt;!-- technorati tags begin --&gt;&lt;p style="font-size: 10px; text-align: right;"&gt;technorati tags:&lt;a href="http://technorati.com/tag/Java" rel="tag"&gt;Java&lt;/a&gt;, &lt;a href="http://technorati.com/tag/JSP" rel="tag"&gt;JSP&lt;/a&gt;, &lt;a href="http://technorati.com/tag/JSF" rel="tag"&gt;JSF&lt;/a&gt;, &lt;a href="http://technorati.com/tag/Echo2" rel="tag"&gt;Echo2&lt;/a&gt;, &lt;a href="http://technorati.com/tag/GWT" rel="tag"&gt;GWT&lt;/a&gt;&lt;/p&gt;&lt;!-- technorati tags end --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/574661030392104329-1493960329491150997?l=amateuratbest.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://amateuratbest.blogspot.com/feeds/1493960329491150997/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=574661030392104329&amp;postID=1493960329491150997' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/1493960329491150997'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/574661030392104329/posts/default/1493960329491150997'/><link rel='alternate' type='text/html' href='http://amateuratbest.blogspot.com/2007/02/down-with-jsp.html' title='Down with JSP!!!'/><author><name>mkimberlin</name><uri>http://www.blogger.com/profile/03110006799533072499</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://3.bp.blogspot.com/_FvoOxqFmLj8/SypR_XDhZiI/AAAAAAAAABk/RL0O7ekUwvg/S220/face.jpg'/></author><thr:total>0</thr:total></entry></feed>
