Fiddling around with Cloud Foundry

In my spare work time the last couple days I’ve taken another good look at Cloud Foundry. I haven’t gotten to the code behind it yet, just putting it through its paces as a user. I’ve used the public cloud as well as running the virtual appliance (Micro Cloud Foundry), and the CLI as well as the STS/Eclipse plugin. It’s really a lot easier than I expected to get up and going (even the Eclipse part). I guess that’s the whole point!

When setting up the MCF appliance, I didn’t quite cotton on to what the DNS token was for (or, you know, read the docs). Cloud Foundry will apparently set up a wildcard DNS entry for you to point to your local instance.  Then you can point vmc/STS to api.{your-choice}.cloudfoundry.me and your web browser to the app URLs that come out of that, and they’ll actually resolve to the MCF VM on your local network (well, as long as you’re local too). That’s pretty cool, but I didn’t do that. I just set it up with a local domain name and added my own wildcard entry at my DD-WRT router. I had to look up how to do that – just pin the MAC address to an IP and add a line to DNSMasq config:

## wildcard for micro cloud foundry VM
address=/.mcf.sosiouxme.lan/172.31.0.140

The only trouble was that when I booted it up, I left the NIC at default config, which attaches it to a virtual network private to my workstation. I’d much prefer it available to my whole LAN, so I reconfigured it to bridge to the LAN. But then I had trouble getting MCF to accept its new address. It wasn’t clear how to do it – I don’t remember how I finally got it to work – something about offline mode. But eventually it accepted its new LAN address.

The example with the simple Ruby application is indeed simple: just install ruby and rubygems (required for the CLI anyway and even instructions for that are included!) and the Sinatra gem, and follow the instructions.

Rails proved to be a little more complicated, but mainly due to my setup. Rails 3.0 and 3.1 are supported. I had gem install Rails and got the latest: 3.2. It seems like this might work, except the simple app that you get with “rails new” uses coffeescript, which pulls in a native gem for the JS library, which can’t be bundled into the cloud app. The discussion at that link left me unclear how to remedy – remove the coffeescript gem? Wouldn’t that break stuff? Configure it to use a different JS lib via ExecJS? I wasn’t clear which, if any, of the options there wouldn’t have the same problem. Taking the path of least resistance here, I removed that rails gem and explicitly installed the most recent 3.0 instead.

This highlights one of the difficulties with a cloud platform… native code. If your code requires something that isn’t abstracted away into the platform and framework, you’re out of luck. Theoretically, you know nothing about the native host under the platform, so you can’t count on it. Just one of the prices you pay for flexibility.

Everything worked fine… except not quite? When I clicked the link to get application environment info, I didn’t get it:

Doesn’t seem to be routing that request, for some reason. It works fine if run with “rails server” naturally. Not sure what happened there, and didn’t want to mess with it just now.

Moving on to Grails and Spring MVC, I quickly set up sample apps in STS and tried them out on both the private and public instance. No problems.

The cool thing about having a local foundry, though, aside from being master of your domain, is that you can debug into your running app, which is vital if it is having a weird problem specific to the cloud environment. You just have to start the app in debug mode. The only hitch here, is that the Cloud Foundry servers don’t show up in the “Debug As… > Debug on Server” dialog:

And the “Connect to Debugger” button didn’t show up after starting the app in debug:

So, how to actually debug in? Well, it turns out it’s simple. The debugger *is* already connected to the app. I’m just not looking at the debug perspective because I couldn’t go the “Debug as…” route. I can explicitly open it (Window > Open perspective) or just set a breakpoint in the code and hit it with the browser (which automatically requests opening that perspective). Then I’m debugging as usual:

The “Connect to Debugger” button only shows up for the app when I disconnect the debugger and need to reconnect.

As far as I can tell, the Eclipse plugin has the same capabilities as the CLI, although the path may not be obvious, being a GUI. I did notice one little glitch that someone should fix (maybe me! in my copious spare time…) – if I open the foundry pane and there are no services, the services subpane is, of course, empty:

The glitch is that if I add a service (say, a MongoDB) it still doesn’t show up in the list, and I can’t then bind it to the application. I have to close the tab and re-open it by clicking on the server in the “Servers” pane (and go to the “Applications” tab… many levels of tab/pane here!):

You might have noticed the “caldecott” app sticking out above. That’s actually a bridge app for accessing services from the cloud directly. With the caldecott rubygem, you can open a tunnel between the foundry service (say a MySQL DB) and a port on your local host, such that clients (such as mysqldump) can directly access that service at that port (e.g. to make a backup or restore one). That will come in handy.

Also, just recently Cloud Foundry enabled running arbitrary workloads on the cloud (as long as they’re on supported platforms). It’s not just about webapps anymore! Another sweet development.

It’s not the errors that make me scream about Java/Maven/Spring/Eclipse

What really gets me is that I always seem to come up against ones that are not only inscrutable, but seem to be unique to me. Google brings up nothing, or brings up only irrelevant results from five years ago and a different context. Here’s my latest. In a Spring configuration file, I have:

<jdbc:embedded-database id="dataSource">
    <jdbc:script location="classpath:rewards/testdb/schema.sql"/>
    <jdbc:script location="classpath:rewards/testdb/test-data.sql"/>
 </jdbc:embedded-database>

This gets me an error in Eclipse (STS actually): “No constructor with 1 argument defined in class ‘org.springframework.jdbc.config.SortedResourcesFactoryBean'”

Huh?

Google’s not helpful. Looking at the source of SortedResourcesFactoryBean doesn’t display any evident source for the problem. Guess I’ll ask on the Spring forum and see if I can find out anything. For all I know it’s an STS bug with 2.5.1; this exact same code and setup worked before, in an earlier version of STS. But it’s probably something related to the environment, perhaps the JARs I happen to have available via Maven.

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.