Thursday, January 31, 2008

Onward

The rest of the quickstart demo went pretty smoothly. Not surprising, considering that it was largely a matter of typing (or copy and pasting) sample code into real files.

But now the fun begins: problems. The truth is that you don't understand how a technology or combination of technologies works until you've had to fix them when they're supposed to work.

So, first problem: Exception stack trace in my Tomcat log. I am not going to drop the entire stack trace into the blog at this point, but let me describe how I'm handling this. First, I skimmed the stack trace looking for references to code that I know to be mine. In this case there are no "quickstart." files anywhere in the stack trace, so I know it's not my Java code. Now, here are the first few lines of the stack trace:

SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from ServletContext resource [/WEB-INF/applicationContext.xml]; nested exception is java.lang.NoSuchMethodError: org.springframework.beans.factory.xml.ParserContext.registerBeanComponent(Lorg/springframework/beans/factory/parsing/BeanComponentDefinition;)V
Caused by: java.lang.NoSuchMethodError: org.springframework.beans.factory.xml.ParserContext.registerBeanComponent(Lorg/springframework/beans/factory/parsing/BeanComponentDefinition;)V
at org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser$AopAutoProxyConfigurer.configureAutoProxyCreator(AnnotationDrivenBeanDefinitionParser.java:130)
at org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser.parse(AnnotationDrivenBeanDefinitionParser.java:79)

The most obvious problem appears to be an error parsing applicationContext.xml. Probably I have a typo in there somewhere. However, I can't find one after glancing over the file for five minutes and that is almost certainly enough time for now. So I'm going to do something annoying. I typed this one in by hand and probably fat-fingered something. So I'm going to copy-and-paste the file contents from the demo and see if that makes the problem go away. If it doesn't then I'll have to use my brain and nobody wants that.

That doesn't make the problem go away! Crap. Time to do some Google searches on the exception messages.

And Matt Raible comes through again. Dude is rapidly becoming my hero. A thread on the AppFuse mailing list suggests that there might be collisions between various Spring jars. I'm reorganizing my build path, let's see how this works.

...nope. OK, time to review my build path, make sure I have everything I need. Yes, this would have been a good time to have used Maven, I know.

Hey, it turns out that I ignored a bunch of Hibernate jars earlier -- specifically the Hibernate Annotations and Hibernate Entity Manager jars. I'll grab them now. And that doesn't solve the problem either. Same error.

Clean, refresh, delete the deployment, rebuild, redeploy... and it's a whole new suite of errors! But these are more comprehensible. They can go in another post.

Continuing the Struts 2 / Spring / Hibernate Toy

If you are just joining us, I am working my way through this.

I'm working on the provided PersonServiceImpl. Eclipse can't find the @Transactional annotation, which is apparently org.springframework.transaction.annotation.Transactional. Thought I had all the Spring jars -- guess not. http://www.docjar.com/ -- which should be in every developer's bookmark list -- suggests that it is found in spring-dao.jar, which I don't have. It looks like I don't have it because it doesn't exist.

I have a hunch here and it turned out to be right. Rather than relying on Eclipse's Spring enablement guck, I went right to the site to download the latest Spring distribution, and grabbed it. Unpacked it, grabbed spring.jar, dropped it into my project. There, right there, is the org.springframework.transaction.annotation package. I had assumed -- wrongly -- that Eclipse's Spring capability enablement would include spring.jar. Sigh.

Adding jars to the project

It just occurred to me that if you have this feed copied to your livejournal friends list you're going to hate me, because there's no way that I know of to hide crap behind a cut. So, er, sorry. But this is mostly for my future reference, and so being spammy is good from my perspective. And maybe if somebody else needs a hand in the future they might find these posts and get something good out of them.

So, I made a 'quickstart' project in MyEclipse, and added it to the deployments listed under my Tomcat 6 server in the 'servers' tab.

Now it's time to download and add 24 jar files to my project. Although MyEclipse 6 doesn't support Struts 2 yet, I'm going to try and handle the Hibernate jars with MyEclipse's "add Hibernate capabilities" feature, let's see how this goes. I need the Hibernate Core, Hibernate Annotations, and Hibernate Entity Manager features, 16 jars in all.

This guide says I need antlr.jar, asm.jar, asm-attrs.jar, cglib.jar, dom4j.jar, jdbc2_0-stdext.jar, ehcache.jar, hibernate3.jar, xml-apis.jar, and commons-collections.jar from the Hibernate Core. MyEclipse provides all of these in the Hibernate 3.1 Core Libraries module; it also adds commons-logging, jaas, jaxen beta (I have no idea what jaxen is), jta, log4j, and xerces.

The quickstart guide says that Hibernate Annotations should provide ejb3-persistence.jar, jta.jar, and hibernate-annotations.jar. MyEclipse's Hibernate Core gives jta.jar. The other two aren't provided by MyEclipse, so I will need to grab them.

The quickstart guide says that "Hibernate Entity Manager" should provide
hibernate-entitymanager.jar, javassist.jar, and jboss-archive-browsing.jar. MyEclipse's library plugin does not provide any of these, so I'll have to go grab them as well. No problem.

For now I'll add the Hibernate 3.1 Core library to my project, and go out and get the other Hibernate libraries that I need. I'll take the defaults for the Hibernate config file (putting it in src/hibernate.cfg.xml) because I don't have strong opinions about where it belongs.

Hm. After another page of the wizard, the wizard is now asking me about creating Hibernate SessionFactory classes and stuff. I'd better check the quickstart to see if it's got suggestions as to how I should set that junk up.

After reviewing the quickstart, I'm going to hold off on having a wizard-created SessionFactory. I can always create one later if I need it.

OK, that's done. Now I notice the quickstart has references to spring.jar. I could probably just enable the Spring capabilities within MyEclipse. MyEclipse's Spring 2.0 Core libraries includes a lot of stuff that I may not need. If I were working with a team I would probably hold off for the time being, but since it's just me and I'm confident that I know what's in all these jars, I'll add them all wizardishly too.

By default MyEclipse wants Spring's applicationContext.xml in "src". I know I don't want it there; the quickstart wants it in WebRoot/WEB-INF/ and I am inclined to agree, so off it goes. Also, I'm not going to create a Spring LocalSessionFactory, because the quickstart appears to be doing things differently.
Using the instructions mentioned in the previous post I'm going through and creating myself a toy configuration for this app.

I had thought previously that I could just create a new project in MyEclipse and use MyEclipse's "add capabilities" features to get the stuff I want. But MyEclipse doesn't, as of yet, support Struts 2. So I'm going to stick with doing things the old fashioned way.

First step -- grab Tomcat and install it -- as expected, no problems there. Configure MyEclipse to recognize this Tomcat installation by going to Preferences -- MyEclipse -- Servers -- Tomcat -- Tomcat 6, click "Enable," click the "Browse" button next to "Tomcat home directory," and find the root of my Tomcat installation. The other arguments are automagically populated from there, hit Apply, hit OK. Go down to the 'Servers' tab in MyEclipse, select this Tomcat 6 server, click the exciting green start arrow, Tomcat starts up just fine.

Now start up MySQL -- hm, it won't start -- check properties for the MySQL service, find that it points to a directory that doesn't exist.

I should point out that this is an inherited machine that wasn't wiped before it was handed over. Sigh.

So, grab MySQL, install it -- now everything seems OK, except that I have an old, nonfunctional MySQL service in my service list in addition to the new functional one. I'll live.

Make a note in my lab notebook as to the usernames and passwords for Tomcat and MySQL. Yes, it might be slightly insecure but my memory is even less secure.

These quickstart instructions next provide a handy little SQL script to create a 'Person' table. Open up the MySQL Query Browser, open a new script tab, copy, paste, execute -- no dice. Syntax error. Huh. The syntax looks right to me:

CREATE TABLE 'quickstart'.'Person' (
'id' INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
'firstName' VARCHAR(45) NOT NULL,
'lastName' VARCHAR(45) NOT NULL,
PRIMARY KEY('id')
)
ENGINE = InnoDB;

But the MySQL query browser is complaining that I've got a syntax error near the second line. OK, let's check out the online refs, what is the correct syntax for CREATE TABLE in MySQL 5.0? I should mention that MySQL's online reference is just great, at least for this basic stuff. Detailed syntax, lots of examples.

Poke around for ten minutes to look for answers to this, can't find any. Ten minutes seems like a good enough time-boxing, so I'm just going to use the MySQL query browser's GUI to replicate the same code that is here.

Just for reference, here is the autogenerated SQL that the query browser came up with to create this table after I did the happy clicky:

DROP TABLE IF EXISTS `quickstart`.`person`;
CREATE TABLE `quickstart`.`person` (
`id` int(10) unsigned NOT NULL auto_increment,
`firstName` varchar(45) NOT NULL,
`lastName` varchar(45) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Grand.

Wednesday, January 30, 2008

Good intro -- Struts 2 + Hibernate

Another good link, something to look at from work: Struts + Spring + JPA (Hibernate).

Monday, January 28, 2008

Struts 2 Links

Here is a free online PDF intro to Struts 2. No idea how good it is... yet.

A decent description of the post/redirect/get pattern for web app request management.

No, Seriously

I swear. Struts 2. It's just that today was spent fighting fires and -- God help me -- documenting the 'as-is' state of the app.

Tomorrow: Documenting what I'm doing with Struts 2 and Hibernate.