Checking out Hibernate with STS

I have cause to revisit my post about importing a git checkout into Eclipse. I need to take a look at the Hibernate code, which is on github at git://github.com/hibernate/hibernate-orm.git, and given the somewhat convoluted nature of this code, I need an IDE to help navigate it.

Now, I hear that with Eclipse Indigo (3.7), which is included with the latest STS 2.9 (which is what I use), the EGit plugin is included out of the box (which, for the purposes of this post, is what I’m doing – completely stock install). That’s helpful. See, previously, if you wanted to do something with git, you would find no evidence within Eclipse that it could. If you figured “there must be an extension for that” and searched for “git” from the extensions wizard, there would be no hits. Because what you needed to look for was “JGit” or “EGit” – you big dummy. An example of what I consider low discoverability that’s pervasive in Eclipse/STS. But I digress.

At least EGit has had a couple years to bake since my post. I went to File->Import->Git->Projects from Git and put in the URI above. This seems pretty straightforward:

Image

I’m not sure why it parses the URI into Host and Repository path here. Is there some reason you’d want to customize these?

In the next step, I pick the branches from the repo I want and proceed to the “local destination” dialog.

Image

These steps might be somewhat confusing to those who don’t know git and just want to take a look at some code. Since git is distributed, you don’t just get a point-in-time checkout from a repo, you get your own copy of the repo – or as much of it as you want. Basically it’s asking where I want my copy of the repository and checkout to go. The checkout (“initial branch” here) will go in the directory, and the repo will go in a .git subdirectory. “origin” is the name given to the repository I cloned this from, in case I want to sync with that later. That might be kind of obvious to someone familiar with git, but how about some tips for those who aren’t?

My question: why doesn’t this all simply default to being inside the workspace? What’s a workspace for, if not the project contents? As you can see, the default is to create a ~/git directory and checkout/clone the repo there.

Next step, three inscrutable options for how to deal with the resulting project(s) that have been checked out:

Image

OK. These seriously need some explanation. What do these do?

“Import existing projects” gets me nowhere in this case, as it requires Eclipse project descriptors to be included in the checkout, and they’re not. Arguably, they probably shouldn’t be. I just get the error “no projects found” if I try this. But that means I need to figure out myself how to get Eclipse/STS to interpret this checkout properly.

“Use the New Project wizard” is an option I don’t really understand. It just dumps you into the new project wizard you would get by clicking the new project button (generally the first button in the toolbar). This is also where you end up if you click “Finish” instead of “Next” anywhere along the way. I guess I could make use of the directory just created. I  also can’t go “back” and choose another option from here; cancel, and I’m back to square one. In general, I find the “New Project wizard” one of the most confusing things about Eclipse/STS, because there are so many options, many sounding similar yet meaning something completely different, and no explanations of what you can expect to get. Do I really have to go looking for doc that should be a click away? I digress.

“Import as general project” basically just creates a project with the given content and no organization. STS recognizes the different file types, of course, but there’s no concept of where the classpaths begin, how to build and test the project, anything like that – just plain directories with content. This won’t get me to my goal, which is to be able to look up class hierarchies, implementors of interfaces, etc. However, having done this, I can try to configure the project to get it to where STS understands these things.

I’m interested in the 3.6 branch of Hibernate, which is a Maven project (you can tell from the pom.xml – woe betide you in the Java world if you don’t recognize Maven when you see it. The “master” branch seems to be using Gradle). So I can right-click the project and Configure -> Convert to Maven Project.

By the way, let me point out something that didn’t work at all: creating a new project with the wizard “Maven -> Checkout Maven Projects from SCM”.

Image

This is apparently not aware of the EGit plugin, because there’s no SCM protocol listed here (the first box  is greyed out). If I click “Finish” here nothing happens except the dialog exits. I think it would probably work if I added a m2e SCM connector like the link suggests, but how would I know to do that?

Alright, so now I have a Maven project. Right away in the top-level pom.xml I get a “Project build error: Unresolveable build extension: Plugin org.jboss.maven.plugins:maven-jdocbook-style-plugin:2.0.0 or one of its dependencies could not be resolved: Could not find artifact org.jboss.maven.plugins:maven-jdocbook-style-plugin:jar:2.0.0 in central (http://repo1.maven.org/maven2)”. I happen to know what this is about because I know there are a bunch of JBoss dependencies not in Maven Central. How would I know that if I didn’t know? Google, I guess. Fortunately searching for that exact error message gets me right to a StackOverflow question about exactly the same thing, which someone has helpfully solved. I love SO, I just hate that it has to exist. Documentation is always about how to use something the right way, not what to do when something goes wrong. SO fills that gap.

So, add the repository information to the pom.xml – or, better, to my Maven settings.xml (which I had to create since STS is providing Maven in this setup) and on to the next problem. Two, actually (always seems to be the way of it – removing a build problem just uncovers more). These are related to “Missing artifact commons-logging”. A little Google sauce on that turns up this blog post (like the name, kinda like my blog!) about the death of the commons-logging dependency. Gotta love trying to support these old builds from a public ever-changing repo. Problem is, the Hibernate pom (actually the parent pom, which is in a subdirectory! huh?) uses the hack from that article, but the repo supplying the dummy dependencies seems to be down. So perhaps I should try the exclusions suggested by commentors in that blog? I found something that looks handy: in the pom dependency hierarchy, right-click and choose “Exclude Maven artifact”:

Image

Sadly, this doesn’t work:

Image

But here’s another StackOverflow suggestion. This seems to work, after removing the existing commons-logging dependencies and adding those ones in the parent pom, and (finally) right-clicking on the project, Maven -> Update project configuration. The errors are gone, and (I suspect) so is all the Maven-fu I can expect today.

Unfortunately I’m still not at my goal – I just have the Maven nature working now.

Turns out, this wasn’t quite the right path. What I’m looking at here are multiple Maven projects, with interdependencies. There’s no way I’m ever going to get anything useful from this in a single STS project. What I need to do is import these as multiple projects. In the meantime, delete the existing project (but leave the checkout) so it doesn’t get in the way.

So here’s what I do: File -> Import -> Existing Maven Projects and enter the path to my local checkout as the “Root Directory”:

If I select all the projects, they’ll all be created as interdependent workspace projects, each with build path and so forth configured according to Maven.

With lots of errors, of course… thousands, in fact. But let me start with the Maven problems, which are probably the source of the rest. Looks like all of the Maven errors are of the form “Plugin execution not covered by lifecycle configuration: org.jboss.maven.plugins:maven-injection-plugin:1.0.2:bytecode (execution: default, phase: compile)” – with a different plugin each time. I remember the import screen warned about some problems that would need to be resolved later – this seems to be what it was talking about.

Well, much later now, I think the Maven errors were mostly irrelevant. Those were due to the change to the m2eclipse plugin which broke the world for a lot of Maven users in Eclipse. Most of them were things that looked like it was safe to have m2eclipse “ignore” as recommended there. I went ahead and ran some of the goals that looked important (antrun:run and injection:bytecode in hibernate-entitymanager, the latter in hibernate-core) from the command line. Not sure they made much difference. I did Maven -> Update Project Configuration on everything changed and most of the red X’s went away.

I also ran into this problem and crashed a few times just by mousing over the “Window->Browser” menu before adding “-Dorg.eclipse.swt.browser.DefaultType=mozilla” to my STS.ini to avoid it.

At this point, the only problem seems to be that hibernate-entity has a ton of tests with imports like this:

import org.hibernate.ejb.metamodel.Customer_;
import org.hibernate.ejb.metamodel.Order;
import org.hibernate.ejb.metamodel.Order_;

… and then goes on to use these classes with underscores, which aren’t there. Evidently they’re supposed to be generated at some point, but I’m not sure how. I don’t really care about running these tests, just wanted to look at the framework code, so although STS reports 14382 Java problems, I can consider my work done here. Boy, that was easy!

One more note: I went back and added the git SCM connector for m2eclipse to try it out. It worked… but poorly. The way that worked was to select “git” for the scheme, then put in the git:// URI for the project, then wait for a popup to select the projects to import. If I reversed order or didn’t wait, I got either an error or nothing after hitting “Finish”. Hmm… hope that’s better in the next update. And, interestingly… the checkout/repo went into the workspace.

Advertisements

Im-a build me some Spring samples (Part 1: petcare) #fail

Just more examples of commonplace Eclipse/Java things that drive me nuts. I should say up front that the version of Eclipse I’m using is actually SpringSource Tool Suite (STS) version 2.3.2.RELEASE, running on the 1.6.0_20 64-bit Sun HotSpot JVM on Fedora 13.

There’s a trove of Spring sample projects over at https://src.springframework.org/svn/spring-samples/ – very helpful. So I had Eclipse check some out and import them as projects. Funny thing, there seem to be a lot of complaints about XML. I’m getting a little more savvy, let’s see if I can resolve these.

Pet Care

spring-petcare-3.0.xsd

From petcare’s servlet-context.xml, we get the good old “Referenced file contains errors (http://www.springframework.org/schema/petcare/spring-petcare-3.0.xsd).” OK – I’m pretty familiar with that. If you try to go to the URL given, SpringSource’s server redirects you to the home page. Seems the “petcare” schema just didn’t quite make the list with the rest of the framework – I can understand that. But what URL should we use instead?

Well, not surprisingly, the petcare projects contains its own XSD; it’s in /src/main/resources/org/springframework/samples/petcare/util/config/ – so how do I use that as the URL? Well, one way is to use the svn tree from the website; then the schemaLocation is https://src.springframework.org/svn/spring-samples/petcare/trunk/src/main/resources/org/springframework/samples/petcare/util/config/spring-petcare-3.0.xsd. Would have been nice if the project just did that, wouldn’t it? I would think that, distrusting SpringSource not to move/change it again, you could refer to it relative to src/main/resources/META-INF/spring/appServlet/servlet-context.xml as ../../../org/springframework/samples/petcare/util/config/spring-petcare-3.0.xsd (feeling the pain yet?) or copy it to the same directory and just refer to it as spring-petcare-3.0.xsd – but neither of these seems to work on deploy, while the web URL does. There’s a file META-INF/spring/spring.schemas that appears to be intended to specify where to look in the project for the schema, but I’m not sure how it’s supposed to be referred to in Eclipse to make this work.

Here’s a really great error Eclipse has on one of the XML elements that refers to the schema: “- schema_reference.4: Failed to read schema document ‘spring-petcare-3.0.xsd’, because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.” So which is it? Good grief. Would it really be hard to make messages like this actually useful? This is so frustrating.

Amazingly enough, if you try to deploy and you haven’t cleaned this up, Tomcat goes and tries to download the XSD as well and fails if it comes out wrong. So there you have it: your ability to deploy seems to depend on whether the right web sites are up at the right time. I imagine there’s a Tomcat or context.xml setting to disable this behavior.

Spring NamespaceHandler for petcare:resources

OK. So now I’m pointing at the right XSD, but I still have problems with servlet-context.xml. Actually it’s only a warning, but: “Unable to locate Spring NamespaceHandler for element ‘petcare:resources’ of schema namespace ‘http://www.springframework.org/schema/petcare'&#8221; – again with the “Unable to locate” business. That crap sure gets old. Why don’t you give me some kind of clue? Where did you look, where should I look? Actually I think I understand this and it’s trying to say there’s no “resources” element defined in the XSD. But there certainly is, so I don’t really know what this is on about. It seems to work anyway on deploy so I’ll ignore for now.

root-context.xml: Build path is incomplete

On to root-context.xml, another Spring bean file. This has three errors listed. The first two are really confusing: Next to line 22 which looks like this:

<!-- Embedded H2 Database -->

I have the error “Build path is incomplete. Cannot find class file for org.springframework.samples.petcare.users.PetcareAuthenticationFailureHandler”. Next to line 24 which looks like this:

<jdbc:script location="classpath:schema.sql" />

I have the error “Build path is incomplete. Cannot find class file for org.springframework.samples.petcare.users.PetcareUserService”. WTF? Actually Eclipse helpfully gave me a clue below on line 56, which looks like this:

<import resource="security.xml" />

This has the warning “Validation warning occured in imported configuration file ‘src/main/resources/META-INF/spring/security.xml'”. Yes, as it turns out that file has errors on lines 22 and 24, where  they make a lot more sense. But they’re not reported in security.xml; they’re reported against irrelevant lines in root-context.xml, which just includes it. Truly mind-boggling.

Now from this, plus the “Build path is incomplete. Cannot find class file for org.springframework.samples.petcare.util.templating.DefaultStringTemplateFactory” on line 29, I gather the build path is incomplete. But all those files look to be provided by this project and the build paths seem to be set up fine. So what the heck is going on?

At this point I checked my system and noticed that after installing some unrelated things, Fedora has chosen java-1.5.0-gcj as my compiler. I don’t think Eclipse is using this, and theoretically it shouldn’t matter anyway, but I shut down Eclipse, reconfigure alternatives so the Sun JDK is again providing the default javac, restart Eclipse, and clean the project. Somewhere in there, the complaints went away.

page.jsp Type mismatch

Now I’m left with just one actual error in src/main/webapp/WEB-INF/layouts/page.jsp. Only, when I open that file, Eclipse doesn’t list any errors. I have to go down to the “Markers” tab to find it:

page.jsp line 62 Type mismatch: cannot convert from boolean to String

Line 62 is a completely innocuous HTML div. Eclipse is just bonkers. I delete the marker and now my petcare project is free of red Xes. I deploy and it works. That might be enough for some people… but now, what about all those warnings?

Unresolvable warnings

Our old friend servlet-context.xml still has a warning next to <petcare:resources> that says “Unable to locate Spring NamespaceHandler for element ‘petcare:resources’ of schema namespace ‘http://www.springframework.org/schema/petcare'&#8221;. I feel I’ve been as clear as possible about the petcare schema so I really don’t know what more there is to say. So let’s leave that (or delete it).

Under src/main/resources, log4j.xml complains “The file cannot be validated as the XML Schema “/home/luke/Documents/workspace-sts-2.3.2.RELEASE/petcare/src/main/java/log4j.dtd (No such file or directory)” that is specified as describing the syntax of the file cannot be located.” This seems to be universally ignored – as I recall, I saw some bogus explanation as to why it was bad to specify a URL for this DTD. You would think Eclipse could just supply the DTD itself, or find it somewhere in the log4j JAR in my Maven dependencies. I don’t have a clue what to do about this so I leave it.

The final warnings are in src/main/webapp/WEB-INF/views/appointments/calendar.jsp, where Eclipse is complaining about data-* attributes on some HTML tags. As I recall these attribute “extensions” are part of the HTML standard so I don’t know why Eclipse is complaining. No way to shut it up without disabling validation entirely, so again let’s leave it. And that’s it for petcare.

Memory (classloader) leak

BTW, petcare has a big fat memory leak in it somewhere, because after you’ve re-deployed a few times, you get a PermGen error. Nice going. I can use this to hone my memory-leak-debugging skills soon.

(No) Fun with ant, SWF, Eclipse

It’s a little thing. But when you install ant on fedora, nevermind the huge list of dependencies, there are some optional ant parts that aren’t installed unless you ask for them by name (thus “optional”). I tried to follow the directions for building Spring Webflow examples and got a lovely BUILD FAILED due to missing components. I’d be more specific but since running ant again it’s scrolled WAY off my terminal buffer, but it’s a lot like this one.

I guess since Java folks are used to pain, the whole routine of figuring out “where the hell am I supposed to get this class/JAR/whatever from” with very little information must be old hat. I appreciate being told not to panic (Java tools abound in scary-looking error messages) but it might have been a little more helpful to give me some guesses where I might find this missing component. Maybe some common JARs to look for, or a hint that I might want to look for optional ant components and install them.

In this case, simple enough. Fedora has the optional ant components in various packages (ant-junit, ant-trax in this case) and I can just have yum install them. BTW, the yum search key? Not “ant” (too much output) but “optional”. Although actually “ant-” works better. Sadly yum doesn’t do anything useful with “install ant-*”.

Ah, time for more Eclipse fun after I import the built examples. Error: Can not find the tag library descriptor for “http://www.springframework.org/tags/form&#8221;. Yes, but why not? Where did you look? Where should I look? “Type mismatch: cannot convert from boolean to String –  standard.jsp line 53. Eclipse doesn’t even show an error on that line, it only shows up in the “Markers” section, and anyway there’s nothing wrong with the jsp. I’m not making this up, someone else has the same problem! No solution posted though.

This sort of thing makes me so mad I could spit

Often projects have external dependencies. Sometimes their whole job is to resolve external dependencies. Maven, yum, rubygems, heck CPAN!

These projects should be built as if their dependencies are trying to deliberately sabotage them. Reminds me of the talk I saw at Uberconf that drove home that point: stuff goes wrong, so you gotta protect yourself at all of the integration points.

When it comes to external dependencies, if something goes wrong, you really need to point the user in the right direction. You need to say “here’s what I was looking for, and here’s why I was looking for it, and here’s where I looked, and here’s what I got, and here’s what’s in my cache, and here’s the problem, and here’s what you can do once you’ve figured out why I got the wrong answer.” Then the user has some idea what to pursue. When they get an error like “Could not resolve dependency xyz” then guess where they end up? Posting desperately on some forum somewhere. Or Googling for that forum post.

Which brings me to today’s offender: Eclipse. Oh, Eclipse. Despite copious (even overwhelming) feedback to the user, how rarely you succeed in producing useful diagnostics. It’s bad enough when you’re installing a plugin and one of the dependencies in some repo is missing. Then you at least have a fighting chance of realizing that it was a dependency and who might be to blame. But Eclipse also validates XML against the stated DTD, and guess what? That’s an external dependency. And guess what happens when something goes wrong with that dependency?

Evidently Eclipse caches the broken DTD and refers to that to declare your XML invalid with the useful error message: Referenced file contains errors (http://tuckey.org/res/dtds/urlrewrite3.0.dtd). For more information, right click on the message in the Problems View and select "Show Details..."

Now that I look at the error, it’s actually better than I first read. It does blame the DTD, and it does say where it got it. At first I read this more like “Your file has errors.” (Helpful! Also what someone would see if they didn’t know what a DTD was for.) OK. Once I downloaded that file myself, I could see that it was broken. Actually tuckey.org seems to be sporadically serving that file wrong.The second time I downloaded it, it was fine. That’s going to happen, though, see? That’s sabotage. The really broken part here was that Eclipse actually cached that broken DTD after downloading it. You’d think that having detected it was broken, it might retry the download each time a validation was needed. It might provide you a mechanism to request a new download. It might actually inform you that the file is cached, for those of us not familiar with Eclipse internals.

A helpful error message would have been something like: “Eclipse tried to validate this XML file’s schema with the DTD downloaded from http://tuckey.org/res/dtds/urlrewrite3.0.dtd (as specified in the file) and cached at the location /some/path/urlrewrite3.0.dtd. This DTD file has errors; please check the DTD URL specified and the cached file to determine the source of the errors. To clear the cache and try the same URL again, (follow these instructions).”

it’s the little things (Eclipse packaging)

Hold on to your hats, everyone. Those of you that wear hats, anyway, which is probably not many, so hold onto whatever seems appropriate in your situation. Or just generally brace yourself.

I just discovered what everyone else already knows about creating nicely separated source folders in Eclipse without turning your Package Explorer into a nasty expanded tree: create your clean but unnavigable source tree, then right-click => Build Path => Use as source folder. All the source folders you set will be shown as flat paths at the beginning of the project instead of a tree somewhere below your libraries.

Now why didn’t I know this already? Time to look for “Eclipse for Dummies” I guess.

Viewing source in eclipse with Android SDK (the easy way)

Forgot to mention, I finally got that article up on viewing source in Eclipse. I found the resources on how to do it weeks ago but wanted to write it up properly with screenshots and everything and was too busy! Anyway it’s over here:

http://android.opensourceror.org/2010/01/18/android-source/

I have a few things yet to do though:

  • This gives some hints on getting exactly the right version of source as opposed to a branch
  • Need to alter my published sources to comply with the license (oops)
  • Move the images and downloads to better hosting :-/

In other news, I need to look through this thread and see if I can get debugging a device to work in Fedora 12.

Activity odds n ends, and eclipse platform source attach

It’s worth noting this bit of oddity about adding headers/footers to ListView and the ListView getting a wrapped adapter. On the other hand, he implements no empty view. I went back and looked at my reference app for a lot of how I want things to work, gtasks (wish the developer would open source it!). And wouldn’t ya know it – the text entry field that he has as the header? can’t be reached by navigation. I don’t feel so bad now :-) Though it’s still a nifty implementation I want to copy.

Another thought about having an “Add item” list header/footer – if it’s in the footer, the virtual keyboard will helpfully cover it up so the user can’t see what s/he is typing. So that’s a good argument for having it in the header. Though I think I’m gonna just try having a header element that acts like a list item and goes elsewhere to create a new item; I don’t think it’ll even require a custom adapter.

An interesting tidbit: Activity.finish() evidently is not a trap door like “exit” in C or bash; whatever method you’re in continues execution, and only when you complete whatever callback you’re in the middle of (since *everything* in an Activity is driven by some callback) does the Activity see that it’s time to leave and heads for the exits in an orderly fashion (first calling onPause() where you can helpfully check isFinishing() to perform any last-minute actions, then onStop, then onDestroy). I guess it seems obvious now that I think about it, but it was surprising at first.

Checking for isFinishing() in onPause() is probably a better way to handle the back key than onKeyDown() which gets called on every type of keypress.

I need to make a note to read this post on styles and themes more thoroughly. For now I’m just gonna use it to find out what I can put in textAppearance :-)

Ooh! A more coherent post about attaching platform source in Eclipse! It’s not trivial (which is good to know) but doesn’t look too bad. IRC folks helped me with that… damn IRC folks can be helpful! This was written quite some time ago, so I think it could use a little updating. Notably, you want to get a version of the repos that matches what you’re developing against. It’s not immediately evident which branch names to use – there doesn’t seem to be a logical scheme like “release-1.0, release 1.1, release 1.5…” When repo gets a project, it lists the branches and tags for it, which look something like this:
 * [new branch]      cupcake    -> korg/cupcake
 * [new branch]      cupcake-release -> korg/cupcake-release
 * [new branch]      donut      -> korg/donut
 * [new branch]      donut-release -> korg/donut-release
 * [new branch]      eclair     -> korg/eclair
 * [new branch]      master     -> korg/master
 * [new branch]      release-1.0 -> korg/release-1.0
 * [new tag]         android-1.0 -> android-1.0
 * [new tag]         android-1.5 -> android-1.5
 * [new tag]         android-1.5r2 -> android-1.5r2
 * [new tag]         android-1.5r3 -> android-1.5r3
 * [new tag]         android-1.5r4 -> android-1.5r4
 * [new tag]         android-1.6_r1 -> android-1.6_r1
 * [new tag]         android-1.6_r1.1 -> android-1.6_r1.1
 * [new tag]         android-1.6_r1.2 -> android-1.6_r1.2

…but often with a lot of clutter that varies from project to project. Now if you try to do repo -b with one of the tags (which seem logically named), it complains, probably because tags aren’t branches. Maybe there’s a flag to access those. But to get a branch, the way to go seems to be getting it by codename, i.e. cupcake, donut, eclair. Those are probably moving targets, while -release ones will be old. (You can’t win.)

And then when you’ve finally downloaded it, it needs moving around before you can even use it. And then there’s the poor guy saying his download never finishes. You know what? After I’ve got this figured out, maybe I’ll upload snapshots of zipped-up attachable code for each release to my free web hosting space for others to use without all the fuss :-)