Monday, April 30, 2012

Over-optimistic but still going

Hello again, anyone willing to read this blog. As the title of this post suggests, I may have been a bit overly optimistic recently. Namely, I thought there was at least a passing chance that I could have my project at a sufficiently complete state by the end of today. Though I have been moving along quickly, I'm not quite that far along.

Thankfully, Lyndsie convinced me last week to take today off of work. I got to sleep in a smidge and have been working on my project all day long. I couldn't say how many hours I've put in today, but probably at least 8 hours of the day. I've been debating how many hours total this project has taken, and I kind of wish that I had been keeping track. My timelines have all focused around deadline dates rather than time worked (with my lack of experience, I had no way of forecasting how much time would be required for each step) so I didn't really think about it. I surmised 150 hours so far, but Lyndsie suggests significantly more. I can't even express how much I'm looking forward to finishing this baby and getting back to my everyday life!

Today's work has focused primarily on building the Recipe Builder in the GUI. In addition to laying out the elements of the main builder tab, I've almost finished the functionality. Perhaps more importantly, I've finished work on 4 pop-up windows for editing validations, instructions, foods, and ingredients. That's no small feat considering the interconnections of all the different components.

What's really interesting about working on these user interfaces is the number of features I've discovered I had planned that were real nice-to-haves but not need-to-haves. There's a lot of functionality that I thought would be in the prototype that I've had to cut for the sake of time and scope control, but the project is coming together. Most of these things I've cut have been aesthetic matters like logically sorting the validations instead of alphabetizing them and presetting sizes on the windows. As I've been advised, these things can all wait for version 2.0.

I'm just about out of time to work on this today and really just have one goal - finishing the Recipe Builder window, which at this point is mostly a matter of deciding the logic necessary to save new recipes or update current recipes.

I would like to note something that this experience is teaching me - the value of programming to an interface! Most of my classes have a method to write to the database. They also share a number of other methods involving lists and refreshing data. Though I have named all of these methods the same and have copied code between them (oh, by-the-way, really important to make sure everything's been renamed. Spent a log of debugging time finding mistakes), I find that I forgot to do a couple in my earlier work. For example, I apparently never got around to coding the Recipe class to write to the database. How silly is that? I've got my form ready to save this sucker and have to go back and write the database writer!

Short story long - if I'd written the Interface earlier (which I considered) I would have not been allowed to leave out these methods and would have remembered them earlier. Yet another live and learn experience.

Here's the final news of the night - I just finished the rather lengthy code to save a recipe to the database and guess what - now my program won't run. Apparently it can no longer find the Recipe class, which is really preposterous! Through process of elimination (and logic) I can determine conclusively that there's a problem in the new database writer method. And voila, a few minutes of searching and it's taken care of (ironically, I didn't really change anything in the end but went back to how it was when I started).

And that's all the work I am going to do on this sucker today. My remaining tasks include:

  1. Write the Recipe Builder update logic
  2. Write the Recipe Builder delete logic
  3. Write the HTML builder for Recipes
  4. Write the database interaction methods for the Meal, Meal Plan, and Daily Plan classes
  5. Update the meal planner tab based on the successes and failures of number 4
  6. Write the GUI logic for the meal planner tab (all three interaction methods)
  7. Write randomizer logic for meal plans
  8. Design GUI for meal plan randomizer
  9. Design GUI for shopping lists
  10. Design logic for shopping lists
  11. Design printer control for shopping lists and meal plans
  12. Write Capstone Project Paperwork and submit it.
  13. CELEBRATE!!!!!!!! (when I pass, anyway)

Sunday, April 29, 2012

Back on Track

As I had hoped, my brother-in-law helped set me back on the right track. As I mentioned, he is a skilled developer and really helped me get out of my myopic view that was sending me into a spiral of failure. I think I shall refer to this spiral as Uzumaki (Japanese for spiral, but it sounds cooler). We toyed around with a couple of things and refreshed my memory about how to build a GUI in NetBeans. I've now got a working version of the recipe listing tab where I just need to build the HTML for the recipe output and that tab will be finished.

Moving on, I'm grabbing my notes on the recipe builder page (thank heavens I drew something up a while back) and am building it this morning. I was able to copy the selection triggers and code from the recipe display page to easily create the recipe selection code on the builder page. I've created all the recipe properties and written the code to populate the recipe properties and instructions and ingredient lists whenever a recipe name is selected. I've even finished a button to clear the recipe builder in preparation for storing a new recipe.

Next on the agenda is figuring out how to create JDialogs in NetBeans so I can have popups to add elements to each validated list...

Check that one off the list, too! I am cruising along today, kicking butt and taking names. At this point, it may even be possible to have a working prototype by the end of tomorrow - so I can get to work on the documentation in time for my deadline. This is getting exciting!

I've been putting off writing the full set of logic for deletion requests but to finish the validation editor, think I may need to revisit this. I've got the basics in place for an object to delete its related entry from the database, but now I need to start thinking about foreign key constraints. For example, if a user wants to delete a cooking method, say 'Bake', what will happen to those recipes that already use this method? I think I configured the foreign key constraints to simply set the related values to null (of course, did I configure the object builders to handle nulls?) but am not sure if it will work. The logic I may need to implement is to have the GUI search through the Recipes list for instances of 'Bake' and deny the request to delete it if any are found. That would control the situation without needing to handle the null values, but could get annoying. Then again, unless you recently added one by mistake, why would you delete a method? Especially if you've used it before?

This same set of questions will come up for the other two validations I'm allowing the user to modify as well - ethnicities and food types.

I think this might be a good time to overwrite the equals() methods in my objects. Otherwise, how will I determine if the object chosen for deletion exists in other recipes. If I've coded this program right, the same object should be used in all places, but I have no way of knowing for certain. Should I take the risk?

It is really easy to determine equality for validation package objects because they just have one attribute to compare. So I went ahead and overwrote the equals method on the Ethnicity class and the Method class and was able to successfully set up Add and Delete buttons for them. I still need to do the same for Food Types, but it's late and I need another break. I'll either come back to this tonight or tomorrow morning.

Until next time, be well!

Saturday, April 28, 2012

Work on the GUI begins!

Lately I find that every time I think about working on my project, I get seriously depressed. That's not very conducive to success, but I feel so overwhelmed at this point with my deadline being so close and so many features of my program not implemented. Again I have very little experience programming a Java GUI (Graphical User Interface) and none of that experience is from WGU. All of my GUI-building was done when I was a student at the University of Utah. I really wish I had been able to stay there for my degree. The coursework may not have been as applicable as what I've learned (a lot more theory, math, and obscure things that won't mean much compared to the broad, applicable work I've done in my current studies) but at least it would have been more structured and would have involved a ton more hands-on work (of which WGU is pitifully lacking). That being said, I've made my bed and now have to sleep in it, despite the scratchiness of the fabric.

So again I start as a total novice and have to work out how to design and implement a fully-functional, complex GUI without much knowledge about how that's accomplished. Oh, and I have less than 2 weeks to learn and create it. I can see why I'm so stressed and depressed.

But enough complaining for now, if I don't start I'm guaranteed never to finish. So here goes...

First off, I sketched out a GUI in NetBeans a couple of months ago, to help wrap my mind around how I wanted everything structured. At the time, I envisioned a tree-like structure to list the available recipes, grouped by whichever field I felt was appropriate (I was thinking of meal parts or main ingredients, or categories, or... other things...). So I built in a couple of JTrees 'cause they looked very polished and appropriate. Now that I'm actually starting to code things, I've learned that a JTree is considered one of the hardest Swing elements to work with. I tried to go ahead with it anyway and it only took about half an hour today before I realized it was a dead end.

I think this is another example of controlling scope. I originally envisioned this type of interface, but the primary scope of my project is a working skeleton, not a polished, distributable piece of software. I am going to have to yet again make a command decision - with the resources available (limited time), I cannot complete this level of structure. It can always be added in later, should I decide to continue it. Throwing out the JTree in lieu of an alphabetized list of Recipes (or Meal Plans on the other tab) should work faster and get things running.

Another design change is the recipe builder. The meal planner builder fits just great inside the meal planning tab but the recipe builder requires significantly more space and variability. I was originally going to have a pop-up window but I have no idea how to tie windows together, or really how to create sub-windows and things. Luckily, I've already built the design based on Tabbed Windows so I'm just going to create a new tab for the recipe builder.

Two more hours of work into the GUI and I'm even more lost than when I started. I guess it's time to solicit some help. We're off to Springville to get a bit of advice/assistance from my super-intelligent brother-in-law. Here's hoping!

Thursday, April 26, 2012

Creating deletion logic - for reals this time

As you may have noticed in my last post, I had plans to complete the deletion logic yesterday. Though I did manage to do some research on the various auto-options, I didn't actually get any code written. Today I'm going to work on the coding.

To start, I have decided to change my foreign key constraints on all of my tables to cascade updates and set to null on deletions. Though this may obscure bug-searching later, I think it will be easier to handle null values than to handle SQL exceptions. Time will tell, of course. And this will probably necessitate some form of orphan searching in the future to clean up any data that becomes unreachable. I'm willing to take that risk to get this project finished in my required time frame.

Less than 30 minutes into coding the deletions, I ran into a bit of an oversight. I didn't really think out in advance how to determine equality. It seemed so simple and straightforward at the beginning that I forgot I need to create the equals() and hashCode() methods. Now I've gone to the work of having each method check one or more attributes of an object for equality when I could really have just coded these two methods in each class and others could just call on them. I don't really have time to seek out these codes I've made so will just have to live with the ungraceful and difficult-to-maintain way I've set it up. Perhaps a future release will improve upon this.

Forgetting these methods and having forgotten all the ins and outs of comparators, I'm going to have to have a very unpolished finished product in order to come in on time. I'm going to avoid the extra scope of making everything sortable for now and just get the down and dirty working. Sorting can be added in a future release as well.

You know what the saddest part of all this is? I probably could have cut out hours and hours of coding if I'd remembered my original plan of using database hits for a lot of these actions instead of trying to code and encapsulate them in Java objects. I created unique IDs for all of my tables so I would just need the ID (the primary key) to reference them from other tables, and then here I go trying to compare whole objects. Blech! What was I thinking?

Live and learn, I guess, which is really what I'm here to do. One thing I'm learning fast is that this stuff gets complicated rather quickly. Experience should help improve my ability to simplify things but I don't think I'm going to go into much coding professionally. It just gives me a headache to design at this level and I like to be a diverse IT person rather than specialized.

I am also noticing certain lack of consistency to my naming schemes that's starting to annoy me. For example, in Java, I've coded some of the IDs in caps and some in lowercase. It didn't seem like a big deal at the time, but now I'm really glad NetBeans gives me pop-ups so I can reference the right spellings. I'm also starting to see the value of programming to an interface - since many of my tables interact in the same way, it would really have helped to enforce consistency and remind me of my original design so I didn't get sidetracked on some of my methods.

All that being said, I've thrown together some usable (if not particularly smart or elegant) deletion methods and am now considering the main work of the recipes in the logic layer to be complete, at least as semi-functional skeletons.

I should probably start working on the meal plan portion and create all the same functionality, but like I said, I'm getting quite the headache with my failure to be consistent and don't really want to extend that. Also, I need to start creating a user interface so I can start work on my documentation. After all, my end-point for this project is not a fantastic, beautiful, professional piece so much as a skeleton that can be grown into a professional piece. At least that's how I'm viewing it.

When I say I'm going to start working on the User Interface, I totally mean that tomorrow I'm going to start working on it. I am totally fried tonight and don't expect to have much success by pushing forward in this state.

Wednesday, April 25, 2012

Vacation's over, back to work

We flew into Salt Lake last night at around midnight and slept until about noon today.  I'm still WAY tired, but there's still a lot of work to do, both for the home and for Chef Helper, so I guess I'll rest when I'm dead.  So here we go...

One thing I've been having a really hard time with on this project is avoiding scope creep.  Well, more scope change with a little creep mixed in.  As I've coded some of these connections, I've realized that they would work better re-factored a bit.  For example, I created the food types class to group food by its general type (i.e. dairy, meats, vegetables, etc) with the thought that I can group the shopping lists based on these types.  The way I've explained it to people, this is to make shopping easier, going from section to section.  But as I've built the relationships, I've realized that it's not as good of a grouping as I'd originally thought.  A better grouping would be specifically based on shopping area.  Let me explain - one of the food types is 'vegetables'.  It's a good type, trying to keep them all together, but the more I think about it, the more I realize there are actually three or four places in a supermarket where you'll find vegetables: fresh, frozen, canned, and perhaps even dried.  I have this insane urge to re-factor my system to take this into account, but I don't have the time to do so.  Instead I have to make do and hope that making-do doesn't suck up more time than re-factoring would.

That being said, the recipe classes in the logic layer are almost complete.  I have ways to add to the various parts, update them, and list/iterate through them for manipulation.  I've written the classes so that each component handles its own and only its own updates.  I'm thinking of this as a bottom-up model because you start with the smaller components and build them up into the overall components.  Again I have this scope-creep option nagging at me to allow top-down transactions, so you can make changes at the recipe level and it will pass the work down to the smaller components.  Again I don't have time to build this level of logic into the system and have to just ignore the urge to creep.

All this leads me to my current predicament - now that I have add, modify, and iterate/list capacities, I need to add delete capacities to each class.  That's what is on the docket for today and I'm hoping to finish it.  My major concern going into this is how to handle foreign key constraint issues.  I'm debating between having each class check the master lists before allowing a deletion and strictly denying such a delete or providing a cascade delete option to wipe out all dependent objects as well.  I know SQL databases have ONUPDATE and ONDELETE capacities, but I'm really not familiar enough with them to trust that they'll behave as I expect.

Okay, so I didn't get to work on this yesterday and totally forgot to post it, so even though this post says today, it was really yesterday. Yup, you heard it here, folks, this was yesterday. And don't let anyone tell you different.

Wednesday, April 18, 2012

Snippets here, tidbits there...

It's day three of the Chameleon Conference and I am ready for my real vacation.  The classes have been good and I've picked up a lot of good ideas, but I'm getting more tired every day.  Considering how jet-lagged I was to start, this decline is particularly sad.

Parts of these courses are bits I'm already familiar with so I'm trying to remote in and add work whenever I can, but there really isn't much time.  I have managed to create the database writer for another class but am probably not going to get much more done today.

But hey, I'm practically on vacation - a much-needed and well-deserved vacation (if you ask me, anyway) so I'll try not to worry too much until I get back next week.

Sunday, April 15, 2012

Last day to work before Florida

As the title of this post suggests, this is my last day of homework before leaving for Florida. It's really just a partial day since I have plants needing to go into the ground and final preparations to make before morning.

I sat down expecting to jump right in to attempting to fix my method of writing notes to the database. It turns out I just had to change one thing and suddenly it all worked. I had no idea I was so close when I stopped the other day!

With that fabulous realization, I'm saving my tester code so I remember how to use it properly (so I don't have to go through that mess again) and am moving on to other database-writer methods.

Wednesday, April 11, 2012

Database Modification Logic

Onward and upward, I dare say.

With my Florida trip less than 4 days away, I'm really pushing to get as much of ChefHelper completed as possible. So I'm working on writing methods for each class to write to the database.

Here is one thing that should really help this process - I don't intend on making the validation lists updateable through the GUI. So I don't need to write methods for these. I don't have time to work in ways to control their update so I just won't allow updates. This only applies to the commitment, meal part, fraction, and measure validations, since foodstuffs, food types, ethnicities, and methods need to be extensible. I guess I'm really half and half.

I'm starting on Notes because they only have a single foreign key constraint. Then I'll branch out to some of the other areas. Well, that wasn't as good an idea as I'd originally thought. You see, the Notes table is one of the few where I've included dates. Working with dates in Java is a lot more complicated than you'd expect. So instead of blasting through Notes and moving on to my next Database-writing victim, I had to take a refresher course on dealing with dates and work out how to handle null dates (just in case).

I was hoping to use a standard writeToDB() method for all of my classes, which would determine if an INSERT or an UPDATE was warranted and just do so. I started to get confused while building two simultaneous similar (yet different) SQL strings to use, so kept the same method and separated the implementation into two private methods. I think this will help keep things clearer, though it does add one more area to check if I need to debug the writing process. I'll have to test this pretty thoroughly before giving it the all-clear.

Yup, the date stumped me for tonight. I can't seem to figure out out to convert a java.sql.date to a java.Calendar.date and it's already half past midnight. It's a good thing I'm going into work late tomorrow! I'll be back to sort this date crap out Friday night or Saturday. Oy!

Tuesday, April 10, 2012

It's alive- IT'S ALIVE!!

Okay, so the title of this post might be a bit of an overstatement. ChefHelper is not really alive, so much as starting to form up from the primordial ooze and take its first breath of very real air. After yesterday's full-on programming sessions and some work this evening, I have successfully created and tested all the methods needed to:

  1. Retrieve all the recipe information in my database
  2. Convert that data into recipes and all their parts, every load, from scratch to objects to listings
  3. Easily access master lists of each component
  4. Print a text version of the eggplant recipe (and any other recipe I add with few null values) 
I am very excited to have gotten to this point, but there's still a long way to go. It took a long time to properly figure out how to load everything and in which order (dependencies can throw you for quite a loop!).  Oh look at that, I was just reviewing my EER diagram (I found out that that stands for Extended Entity Relationship - who knew?) and forgot to add the Notes list to the recipe class. I'll get right on that...

Now that I've created this template for 11 classes, Notes were not a challenge. Okay, so there were a few hold-ups, but not bad overall.

I'm pretty much done for the evening - I'm out of time and need to de-stress a little before going to bed, but I'd like to lay out what's next in this process.

Like I said, I now have all the methods and members in place to store all the lists in the Java portion. This sets me up rather well for adding the methods that INSERT, UPDATE, and DELETE from the database. I may have mentioned earlier that I've encapsulated this functionality in my Database class, so other classes just need to have ways to build SQL DML Strings to pass to this class. 

I'm planning on having each object know how to write itself to the database. Then the GUI only has to provide ways to select the object and tell it to do its job. The GUI will probably just create a blank member of each class to work with and then verify all requirements are met before being allowed to save it. I've got a bunch of ideas of how to accomplish this but we'll see what happens when I get that far. 

After completing and testing this functionality, I only have two major program pieces to build: the meal planning classes and objects (which should be easier now) and the GUI. Put it all together and I'll hopefully have everything running (cross your fingers, pray for me, wish upon eyelashes, stars, and satellites) by the end of the month. Which gives me one month to complete all the documentation and get it submitted with enough time for revisions, should any be required. The timeline is still very tight but I'm still very determined. 

Monday, April 9, 2012

Duplication of work (oops) and Recipe Creation Sequence

With the clock ticking down WAY faster than I'd like, and with a week and a half hiatus on the horizon, I'm squeezing in every possible minute to work on Chef Helper. Then I'm writing code as fast as my hands can type, hoping that what I'm doing will work.

Unfortunately, I spent the last couple of days working on some functions that apparently I'd already completed. I guess a week ago or so, I built the methods to load my validation classes from the database and put them all into a separate class called validations. I decided a couple of days ago that each class should have the methods to load itself and keep a list of all the created objects of its type. I forgot I'd created loaders for the validations and just retyped them all into their classes from scratch. A simple copy and paste would have saved hours of work. Oy!

I did finish all of the loading methods and members of the validations and am moving on to the more complicated classes. I keep getting mixed up and turned around regarding some of the relationships. So I've had to go back to my initial database loader SQL script and try putting in at least a recipe or two. I've avoided putting in any recipes as yet, simply because they are a lot of work to enter directly and will be significantly easier to load through the finished program. But, of course, I need examples to work with to build the finished program.

I grabbed a recipe that looked good for my first example - Eggplant Parmesan. After I added the needed validations, I realized there was one recipe layout issue I hadn't counted on in ChefHelper. This recipe has the ingredients listed in three groups. How can I accomplish ingredient grouping, I wonder? I did go ahead and create all the necessary validations to make a blank ingredient, so I can at least create spacing. Which will do for now.

With that concern dealt with, I proceeded to create all the requisite components of the Eggplant Parmesan recipe, starting from the ground up. This is the same procedure that I will have to do programmatically in my user interface, so it's good to delineate here:

  1. Check that the requisite measure, fraction, meal part, and commitment exist. Since these validations are meant to be static, they should already exist and shouldn't be extended. 
  2. Check to make sure the needed food type exists. If it doesn't, create it. If it does, bring it in from the food types master list.
  3. Check to make sure the needed ethnicity exists.  If it doesn't, create it. If it does, bring it in from the ethnicities master list.
  4. Check to make sure the needed method exists.  If it doesn't, create it. If it does, bring it in from the methods master list.
  5. Check to make sure the needed foodstuff exists.  If it doesn't, create it. If it does, bring it in from the foodstuffs master list.
  6. Create a new Recipe. Feed into the constructor the known and applicable values. The only requirement at this point is a name. 
    • I realized at this point that the name needs to be unique because I won't get an ID until I store the record and I need the ID to store everything else. I don't want to have to refactor all the connections in the database this far into development, so instead of changing the name to be a primary key I instead require simply that it be unique and then check it against the master list before allowing the user to store a recipe.
  7. I now search for the recipe's ID by querying the database by name. This ID will be used in Ingredients, Instructions, Notes, and Meals.
  8. I created each Ingredient. Since I've already checked that the needed foodstuffs exist, this is simply a matter of plugging in the needed constructor and feeding it all the values. One of these values is the recipe ID I determined earlier.
    • It was perhaps a good idea to use a complicated recipe for my demo, because it showed me that I needed more space for the preparation. I didn't anticipate really long instructions but when adding a whole item, I found I needed space for the description of the size and volume of that item. In my example, this amounted to: 1-pound, peeled and cut crosswise into 1/2-inch-thick-slices, each, for two eggplants. I increased the varchar for prep from 45 characters to 100.
  9. I created each Instruction. This was simply a matter of plugging in the needed constructor and feeding it all the values. One of these values is the recipe ID I determined earlier, and it's the only validated value.
Wow, it was only 9 steps but for 19 ingredients and 4 instructions, it took me in the neighborhood of 2-3 hours to create it using direct SQL. I am quite looking forward to accomplishing the same feat far more quickly using my user interface.


Now comes the fun parts I've been dreading - creating constructors for these last 3 classes.  Perhaps the best way to go about this is to create a very basic constructor and use the getter and setter methods to handle all the object attributes...

I tried to start with Ingredient, but it needed a Recipe object to associate itself with. So I tried to start with Instruction, but it also needed a Recipe object to associate itself with. It became clear that I needed to start with Recipe. But guess what Recipe needs? An ArrayList of Ingredients and an ArrayList of Instructions. Oh, and a primary Ingredient and a secondary Ingredient. Yeah, I kinda painted myself into a corner here.

So how did I get to this state? To handle the multiplicity of the Ingredients and Instructions, I had to associate them with their recipe through a foreign key in their tables. To build the objects in Java, I needed the Recipe to contain lists of Ingredients and a list of Instructions.

I've got some ideas on how to refactor to get away from this, but I figure this post is already way too long. If you're still awake, I'll see you next time!

Monday, April 2, 2012

Back in Business

Having finally (FINALLY!) figured out how to get my JDBC driver to load, I've moved on to the next step.  I'm still not feeling the urge to try to figure out the GUI (there's just an overwhelming amount I need to know) and am instead focusing on loading the data from the database and storing it somewhere accessible in the program.

I spent a couple more hours today writing up a validations class which I used to query the database for 8 different validations lists.  These include the list of food types, food stuffs, measurements, fractions, ethnicities, cooking methods, time commitments, and meal parts.  Other than the time commitments and meal parts, theses categories should all be extensible.  Furthermore, by grouping them all into a single class, I just have to have my main program load the class and the loader methods and these lists will be available whenever I need the user to pick from them.  This should, in essence, control user input and only allow accepted, sortable values.  If I reference these later, I should be able to avoid any foreign key failures when trying to update database tables.

The next step is a still a bit nebulous for me.  I have a way to query for validations and can probably use a similar method to query for Recipes, Instructions, Ingredients, Notes, Meals, Daily Plans, and Meal Plans.  However, I'm still trying to decide where to store the master collections of these objects.  I figure that to build the recipe trees in the GUI, I'm going to need a way to create objects for all of these entries in the database and then need a way to iterate through them.  So where should I store a master list?

I'm leaning toward creating a static ArrayList in each class with a load method to populate it from the database.  Then to get the list of recipes, for example, it should be a simple matter of Recipe.getRecipes().  I think.  Another approach would be to create a container class that just maintains these master lists.  I will need ways to sort these lists, convert them to hashes, and search through them, so maybe it's a good idea to put all of these things in the same class.  Or I could keep the lists with the classes and create a Converter class to change them as needed for each usage.  Decisions, decisions...

Of course, the hardest part about planning this is that I don't know what kind of memory hit we're talking about.  I mean, my project is to build a functional skeleton of the program and I think these methods will work swimmingly.  But how far can this program grow with this approach? 100 recipes? 1000? How slow will access be to the foodstuffs list once 10,000 foodstuffs have been entered?

For my purposes, I guess it doesn't matter up front.  If I continue to grow this program after graduation, I'll need to refactor to address these issues, should they come up.  But for now it's best to follow the advice I've been receiving since I first learned to program - know and limit your scope.  Right now, my scope is a skeleton,  and I have a very short time frame to complete it in.  So I will just pick a method and go with it and refactor later if necessary.  And I've decided to keep the master lists with each class and have my main program load them up with the program and just reload them as needed.

Chef Helper is really coming along now.  If I've done this right, I should only have a few major milestones to complete.  The first one after storing these values will be to create modification code in my database objects so I can store new and updated values to the base tables.  I've read about a way to turn my query engine into an interactive sort of system but need to explore it further.  It seems like it's a setting on the ResultSet where I can modify it directly and it will automatically pass on the modifications to the database. We'll have to see about that.

After that little piece, I'll need to finish designing the GUI and figure out how to use Listeners to load and update the screens as they're used and needed.  Once that's tied together and everything is integrated, I'll need to to some testing/debugging (I forgot to include that in my schedule) and then start on the documentation.  I don't recall what all will need to be recorded, but I know the end will include artifacts derived from this blog as well as my ERD and a user's guide for Chef Helper.

So back to the programming for me while I still have some time before going back to work tomorrow. I may need more time off...

ClassNotFoundException is the biggest pain in the ass ever!

Over the past few days, I've deviated a bit from my schedule, despite the fact that I just recreated it.  Right now I should be working on the Java classes that encapsulate the different parts of recipes and meal plans, but after creating the barebones classes with setter and getter methods, I felt it would be difficult to test any methods without having some basis for loading the objects.  In other words, I felt it would be difficult if not impossible to make sure my classes work unless I can load them interactively from the database.

A little while back, I found a bunch of really good templates for connecting my Java program to the MySQL database.  I especially liked one that separated the difference pieces of registering the connection, obtaining a connection, and using the connection.  I decided to use these pieces and separate out execution code to take a SQL statement and return a ResultSet object, leaving it up to the calling class to iterate through that and create the respective objects.  My goal was simply to only have a basic set of static methods to handle all of the database interactions so that I don't have to recreate the database connection controls in other objects.

While I think my code is set up right and should work, I'm stymied by the dumbest thing.  The very first step in using JDBC doesn't want to work and I can't think of any reason why not!

For those of you unfamiliar with JDBC, the very first step is to register what kind of database you'll be connecting to.  It takes the simplest line using a method from the Class class - Class.forName("com.mysql.jdbc.Driver");  I've read through numerous books and countless websites and this is simply the only line that's used to register the database.  They all mention that part of the registration is that you have to have the JDBC jar file in the CLASSPATH variable and then this line in your program and voila! you're good to go.

And that's where the title of this post comes into play.  I have set the CLASSPATH variable to match the JDBC containing folder.  I've set it it reference the folder and file.  I've tried both settings with 3 different JDBC builds.  I've tried this in the NetBeans IDE and I've tried it in the BlueJ IDE.  Though I've been able to access the database from NetBeans in the Services dialog, and have verified I can reach all the tables, I still can't connect my program to it.  I've uninstalled and reinstalled MySQL many times with different security settings (though I don't figure that's the problem). Hours and hours now I've been working on this. 3 days I've been working on this.

And every single freaking time I try this first step to database connectivity, completely independent of any attempt to actually connect or query the database, the Class.forName("com.mysql.jdbc.Driver"); fails with the same exception - java.lang.ClassNotFoundException: com.mysql.jdbc.Driver.


I'm at a loss.  I don't know where to turn or who to ask.  I've read other people's examples, I've read forums, I've read user guides and wikis and websites.  And every single one of them says this should work.  Without this piece working, my entire project might as well be scrapped and I might as well accept failure.  So if anyone reading this has any ideas, any ideas at all... help... please! 


*Update: I did it. I don't quite know how, but I did it.  I re-installed SQL Server with Norton disabled after reading something about how the firewall may block all incoming connections to the database.  Still no success but my NetBeans Services thing stopped working.  Then I came across this website: http://www.linglom.com/2007/12/05/accessing-mysql-on-netbeans-using-jdbc-part-i-create-a-connection/ and found my solution.  I couldn't get my code to work or connect to the right JDBC connector until I followed this website's instructions to add the JDBC driver to the package library.  Suddenly everything started working and I can move on. YAY!!!!