Archive for the ‘WebObjects’ Category

Upgrading Mac OS X Leopard Server

Friday, July 11th, 2008

I was expecting that. Fortunately, I was ready for it. So, I’ll describe some details of upgrading Leopard Server from 10.5.2 to 10.5.4 to avoid you the same trouble.

If you read my previous article about Leopard Server, you know that I had to recompile MySQL, PHP and Apache to PowerPC 32 bits, because I could not use the 64 bits version on our G5 server. The story was a bit complicated, but the idea was that I needed PostgreSQL and MySQL support on PHP. As the MySQL default installation on OS X Server doesn’t include the shared libraries, I had to recompile MySQL to be able to recompile PHP. But I could not make MySQL compile for 64 bits, so I compiled everything (including Apache) to 32 bits.

So, I was expecting it: as soon as I would upgrade my server, the installers would replace Apache with a more recent version, and it would not start because PHP and MySQL stuff was compiled for 32 bits. And it happened.

How to fix it? Simple. You have to do two things: first, remove the PowerPC 64 part from the httpd binary. Second, recompile your customized version of PHP, because PHP gets replaced too.

To remove the PowerPC 64 part of the binary, you don’t need to recompile Apache as I did before. There are two very useful commands you can use: file and lipo. If you do the following commands:


cd /usr/sbin
file httpd

The result will be:


httpd: Mach-O universal binary with 4 architectures
httpd (for architecture ppc7400): Mach-O executable ppc
httpd (for architecture ppc64): Mach-O 64-bit executable ppc64
httpd (for architecture i386): Mach-O executable i386
httpd (for architecture x86_64): Mach-O 64-bit executable x86_64

As you can see, Apple ships httpd compiled for their four possible architectures. In my case, I want to remove the ppc64 one to force httpd being executed in 32 bits. That’s where lipo comes in hand:


lipo -remove ppc64 -output httpd32 httpd
mv httpd httpd64
mv httpd32 httpd

That’s it. The ppc64 part of the binary has been removed, and a new binary was created. I then just switch the binaries, and there you go, Apache running on 32 bits mode on PowerPC:


httpd32: Mach-O universal binary with 3 architectures
httpd32 (for architecture ppc7400): Mach-O executable ppc
httpd32 (for architecture i386): Mach-O executable i386
httpd32 (for architecture x86_64): Mach-O 64-bit executable x86_64

Then I just needed to recompile PHP and everything was back on track.

Also, be careful because the 10.5.4 update will upgrade WebObjects to 5.4.2. If you are still using WO 5.3 like me, you’ll have to reinstall 5.3 again, as described in the Mike’s document.

Back from USA

Sunday, June 15th, 2008

Well, I’m back from another WOWODC and WWDC. I’m still really tired, but some quick notes:

  • As David LeBer already mentioned, Pascal did an amazing job organizing WOWODC all by himself. Great room (a bit cold on the first day ;) ), large windows and sunlight on the halls. Food (well… not that good, but after all, it’s USA!) and caffeine provided frequently. Very very nice. Suggestion for the next year: a bigger (and brighter) screen, and eventually plasma screens among the room to make it easy for people in the back to read the code.
  • I learned a lot about WO frameworks out there (like Wonder, Houdah and specially LEWOStuff that I did not know before). I met for the first time some very talented people, and of course, all the folks from the previous conferences. It’s great to be able to have technical discussions and know different views on the same problems from all those skilled and experienced people out there, face to face.
  • WWDC had some interesting news on many stuff. As you know, I cannot talk about the stuff under NDA, so I shall only say that some interesting stuff is being done on the WO side. Also, as you all know by now, the iPhone is now 3G, includes a GPS, the price was slashed, and will be available in many countries of the world. I just hope the service providers slash the data roaming prices, because that makes the iPhone useless when you go to foreign countries. Finally, Snow Leopard was announced, and, as already expected, the focus is not on new features, but on a big cleanup of the OS infrastructure. Not only this are great news for us, developers, but also shows some courage from Apple and a lot of respect for their users. They want to focus the next year on improving the quality of their OS, rather than packing it up with some new features just to win the race against the competition.
  • As a side note, the MacTech people was giving away some magazines for free to the people who were standing in line during the morning. I took the time to read most of it during my flight, and I really liked it. I was a MacTech subscriber in the past, but I cancelled it because, during my graduation, I didn’t have time to read it (it’s good to graduate on a place where you actually don’t have time to learn, isn’t it?). Maybe I’ll subscribe it again now.
  • Not related to the conferences themselves, we went to visit the bay area surroundings on Friday afternoon. We did the classic trip to the Apple and Google campuses, because we are all geeks, but we also went to the Stanford and Berkeley campuses. The Standford campus totally blow me away. You have to see it to believe it. From now on, I’ll laugh, really laugh, every time I hear a faculty from my university stating that we actually have a campus. The Berkeley campus did not impress me much. It’s more urban style, more crowded and dense. I prefer the Stanford way, with space, a huge amount of space, tons and tons of space, really. Almost made me want to return to the univ! :)

WWDC and WOWODC 2008

Thursday, June 5th, 2008

It’s that time of the year… packing up to leave tomorrow, as I will attend WOWODC and WWDC 2008 in San Francisco. See you there!

Apple Defines a Product Road Map for WebObjects!

Monday, April 28th, 2008

In 1997. (Yes, I’m cleaning up some really old stuff)

Dr. Optimistic Locking

Sunday, April 13th, 2008

or How I learned to stop worrying and lock the EOObjectStoreCoordinator

So those of you who read the WebObjects Developer mailing list know I’m a bit obsessed about concurrency issues. Namely concurrent data write operations, specially when you have lots of derived data on the database due to performance issues.

A few months ago, I wrote an article about handling concurrent data access in WebObjects applications that included a nice solution for the problem. The thing is… it’s wrong. It’s all wrong. It doesn’t work, in the sense that it won’t give you any guarantee that you won’t discard upgrades made by other threads or instances of the application. I have to thank Chuck that looked at the code and said “doesn’t work”. Chuck is right, by definition, so when he says something doesn’t work, it just doesn’t. And he was right again.

So, in that article, I avoided the problem created by an editing context delaying the merge of the changes made by other contexts to its objects to the moment when the context is unlocked. But I made a very important mistake: I assumed WebObjects implementation of optimistic locking worked. It doesn’t. Unfortunately, optimistic locking is broken in WO due to a design flaw.

The problem is simple: you can lock everything you want. You can lock your contexts, you can use classic Java locking, you can do whatever you want. But, as long as you don’t lock the EOObjectStoreCoordinator, you can’t trust optimistic locking. Because the row snapshots are unique to a EOF stack, you can have a thread in the middle of a critical part of your code, like I showed on the previous article, and have another thread changing those snapshots simply by doing any operation that brings fresh data from the database, like a fetch specification with the refreshesRefetchedObjects option turned on. Unless you use classic Java locking to lock everything in your code where you might eventually do a refreshing fetch (which is insane), you cannot trust the row snapshots that will be used as a base of comparison for optimistic locking to be unchanged during your code critical segments.

If this sounds too confusing, think in the following example. We have an entity with attribute ATT that we want to increment using optimistic locking. Remember that the ideia is the following: we want to make sure that, if two or more threads increment the value at the same time, only one of the threads will succeed, all the others will receive an optimistic locking exception, and effectively abort the transaction (or repeat it).

So, we have two instances, INST1 and INST2 running. Assume we increment the value inside a method like the one I wrote in the previous article. Let’s now run some steps:

  1. INST2 reads ATT with value = 3. The row snapshot in the INST2 EOF stack has ATT = 3, as expected.
  2. INST1 reads ATT with value = 3. Again, the row snapshot in INST1 EOF stack has ATT = 3.
  3. INST2 increments ATT to 4, and saves the result to the database. It will naturally succeed, updating the DB and it’s own snapshot to ATT = 4. We can forget INST2 from now on.
  4. INST1, in another thread, runs a fetch specification with refreshesRefetchedObjects on. As the ATT value in the database is now 4, that thread will have ATT = 4 on the editing context that fetched the object, and (here’s the problem) the row snapshot will be updated to what’s currently in the database, which is ATT = 4.
  5. INST1, in the original thread, finally increments the value of ATT to 4 (remember, it was 3 on it’s editing context), and tries to save. It will use the row snapshot do to the optimistic locking comparison. So, what it will do, in a rough translation of SQL, is “update att to 4 where entityId is some Id and att is 4“. The red 4 comes from the row snapshot.
  6. As the value on the database is now 4, the save will succeed. The final value of ATT will be 4 and not 5, as expected after being incremented in both threads.

The problem here is the assumption EOF does when saving changes of attributes with optimistic locking enabled. EOF assumes that the row snapshots represent the original status of the objects when they were fetched to the context being saved. So, it compares the current database status with the original status to detect changes. The problem is that assumption is simply not true. There can only be one row snapshot in an EOF stack for a given row, and nothing will guarantee the snapshot doesn’t change in the middle of the critical section.

Facing this, there’s only one thing you can do: make that assumption become true. And to do that, you need to either use a different EOF stack per thread (very very high resource consumption, not only in memory but in DB connections too) or use the “big” lock in the stack. That big lock is the lock in the EOObjectStoreCoordinator. If you need absolute reliability when managing concurrent data access, you’ll have to lock EOObjectStoreCoordinator before fetching (and refreshing, of course) the objects you will change and only unlock it after saving those objects. You can do that with code like this:

EOObjectStore osc = someEditingContextOnThisThread.rootObjectStore();
try {
  osc.lock();
  // Do as I wrote on the previous article:
  // create a new editing context with fetch timestamp
  // set to "now", fetch all your objects, process them,
  // and try to save them, handling OL exceptions.
} finally {
  osc.unlock();
}

Note that I put osc.unlock() call in the “finally” segment of the try/catch wrapper. You need to take extra care to make sure that, whatever happens, you will not leave the EOObjectStoreCoordinator locked, or all your application’s database access will simply be stopped forever.

Of course, there’s a downside for this solution: while you are processing the objects inside the critical code segment, no other thread will be able to access the database, in read or write mode. I can give you two advices on this.

First, the obvious one: keep that processing as simple and fast as possible. Remember that long operations should be done in background threads with their own EOF stack or, better yet, in separate “maintenance” applications. This technique should be used only for fast operations, or the users of your application will get bored waiting.

Second, create multiple EOF stacks (a reasonable amount, like 3 or 4). This will speed up things a bit, because it will reduce the probability of a thread having to wait for another one. If you have 4 EOF stacks and you enter a critical part of your code on one of them, 75% of your threads (and that means 75% of your users) won’t take the hit. The downside is more memory usage. You’ll have multiple copies of the row snapshots, plus all the objects needed to handle the database connection. And, of course, you may have to increase the number of maximum simultaneous connections on the database, which may force you to increase the maximum shared memory and semaphores on your operating system configuration. The good part is that, if you are using Wonder, creating the EOF stacks themselves is as simple as adding a property to your Properties file. That’s right! Just set er.extensions.ERXObjectStoreCoordinatorPool.maxCoordinators=x, being x the number of EOF stacks you want. That’s it, really. It just works, and it tries to minimize weirdness by creating all the editing contexts on a session in the same stack. It’s that good. It’s Wonder!

drawImage performance on Leopard

Wednesday, February 27th, 2008

A not very fast but handy way to downscale images in a WebObjects application is using Java 2D APIs, with code like this:


BufferedImage reducedImage = new BufferedImage(newX, newY, BufferedImage.TYPE_INT_RGB);
Graphics2D g = reducedImage.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);

g.drawImage(originalImage, 0, 0, newX, newY, 0, 0, originalImage.getWidth(), originalImage.getHeight(), null);
g.dispose();

Although not blazing fast, this is enough for many applications. I could reduce a 7 Mega-Pixels image to something like 250 pixels wide in about one second, or less, in my PowerBook G4. But this was in Tiger.

In Leopard, as some of you may have noticed (and if you have applications deployed on Leopard Server, be aware) this is incredibly slow. When I say slow, I say five minutes, or even more, with the CPU being used at 100% during that time.

There are two reasons that lead to this. The first (which is not a problem in itself, but it’s a cause of the problem): Apple switched from Quartz to Sun2D graphics engine as the default one for Java applications on Leopard. So, all your image manipulation is being done using the Sun pipeline now. This would not be a problem, except for the second reason: the Apple JVM implementation has a bug that is slowing Sun’s pipeline drawImage method to a crawl. Actually, that was not the real reason. I testes this on FreeBSD (using Diablo JDK) and the speed was similar to Leopard’s. Sun2D is REALLY slow, to the point of being useless. I’m now using ImageMagick.

The only solution for now is forcing the application to use Quartz engine. You can do that using the command line option -Dapple.awt.graphics.UseQuartz=true. And, of course, file a bug on this!

Avoid escaping URLs in Apache rewrite rules

Thursday, January 24th, 2008

Today we started hacking some Apache rewrite rules to make some URLs a little more friendly. All of the URLs we are rewriting are entry points for our application, which in the WO world means direct actions.

All of them contain queries parts. These are the arguments in a URL, like http://domain.com/something?arg=value&anotherArg=anotherValue. Well, everything was running fine until we accessed an URL with a escaped character. We had the following rule:


RewriteRule ^/optOut(.*) /cgi-bin/WebObjects/OurApp.woa/wa/optOut$1 [R]

When we tried to access the URL http://domain.com/optOut?email=me%40domain.com, we got:


http://domain.mac/cgi-bin/WebObjects/OurApp.woa/wa/optOut?email=me%2540domain.com

Note the last part or the URL. The problem is that the original % in %40 (the escape code for @) was being itself escaped, leading to a corrupt URL. The result of calling formValueForKey on this was me%40domain.com.

After googling for a while, I found out many people have this problem, but surprisingly I could not find a decent solution. I saw hacks with escape internal functions and PHP weird variables that obviously wouldn’t help me at all, and I was starting to get nervous.

Well, while reading the rewrite module documentation, I found the solution right there: the NE option. According to the docs:

‘noescape|NE’ (no URI escaping of output)
This flag prevents mod_rewrite from applying the usual URI escaping rules to the result of a rewrite. Ordinarily, special characters (such as ‘%’, ‘$’, ‘;’, and so on) will be escaped into their hexcode equivalents (’%25′, ‘%24′, and ‘%3B’, respectively); this flag prevents this from happening. This allows percent symbols to appear in the output(…)

Well, this is it. I saw so many pages with people asking about this problem without getting any answers that I was not very confident on this, but I tried to change the rule for:


RewriteRule ^/optOut(.*) /cgi-bin/WebObjects/OurApp.woa/wa/optOut$1 [R,NE]

And that’s it. It’s now working as it should, producing the correct URL:


http://domain.mac/cgi-bin/WebObjects/OurApp.woa/wa/optOut?email=me%40domain.com

Apparently, it’s that simple.

A decent XML validator

Sunday, January 20th, 2008

As written on all the good practice books about development, I write my applications ready for localization. To do that in WebObjects, one should put all the localizable strings in a strings file. In WebObjects applications, a strings file may be written in two formats: the Apple’s weird .plist format and XML. I use XML, because it looks more… well… I don’t really know, but I prefer it.

Anyway, some days ago I did a mistake in one of those files. I did something like: <string>Some String/string>. As you can see, I forgot the < character in the closing tag. When I run the application, all I got was this:


The element type "string" must be terminated by the matching end-tag "“.: Parsing failed in line 1155, column 3

This is totally useless, as the line 1155 is actually the line before the last one in the file (the one that closes the “dict” entity). And yes, it’s a big file. Obviously, checking all the lines manually in undoable, even if I only checked the modified ones after the last commit (I added/changed many strings since then). So, the easiest way was to find a XML validator on the web, and hope it would point me the error.

How surprised I was when all the validators I found in the first two result pages pages of Googling for “XML Validator” reported exactly the same error as WebObjects itself. Great. Just great. And finally, I found one validator that saved the day. This guy, although a bit slow, showed me the exact line where the error was. So, bookmark this. Really. It’s the best XML validator around! And yes, just so that you don’t forget the link, let’s just mention it one more time!

Profiling WebObjects applications

Friday, November 30th, 2007

Recently I had to profile a WO application for memory leaks (more exactly, unintentional retention of objects that prevented them from being garbage-collected). Some quick notes:

  • Eclipse TPTP will not work on Mac OS X. Period. Although Eclipse allows you to install it without complaining, it does not work at all.
  • I found this nice article about profiling and trouble-shooting in Java. Page 37 describes how to do what I initially wanted, although I didn’t need to get that far.
  • There are a lot of nice tools to help you peek inside the environment of your Java applications right there on your hard drive. I used jconsole. It’s really easy to use. First, add the -Dcom.sun.management.jmxremote VM option when launching the application. On Eclipse, this would be the “VM Arguments” in the “Arguments” tab of the Run Panel. Second, just open a terminal and write “jconsole”. Attach to the running app, and have fun.
  • Instruments (aka xRay) on Leopard has only one Java instrument, Java Threads. It appears to be almost useless on Java profiling. Yet another reason to stay on Tiger for now.

Welcome to the Leopard WebObjects mess

Tuesday, October 30th, 2007

So, you thought Leopard and WebObjects 5.4 would bring some good news to WebObjects developers, right? Well… so did I.

I’m not even going to talk much about Leopard itself. It’s clearly an unfinished product, with dubious interface “improvements”, and totally unstable, at least on PowerPC macs. I try to keep my blog tecnhically-centered, and not based on personal opinions, but please Apple… you can do much better than that. Stop playing arround with the iPhone and concentrate on what really matters.

Well, about WO… Leopard has a new version of WebObjects, 5.4. It has some bug fixes and improvements over the previous versions, but unfortunately there are still a lot of show-stoppers that keep me from installing Leopard (and as you can guess from the last paragraph, I’m not specially motivated for that).

The first one is that Wonder still does not compile on 5.4. So, if you use Wonder (and you should), you must bring WebObjects 5.3 to Leopard. It’s not a very complicated process, but of course, it means trashing the brand new version. The good news is, if you use Wonder, you don’t really need WO 5.4, because almost all the features are already implemented on Wonder. The ideia is installing 5.4 (basically to get the Apache 2.2 adaptor), them trashing everything else, and finally installing 5.3. I installed it from the xCode 2 DMG and it worked fine. Anyway, Milke did an excellent (as always) document about his trip back to 5.3 on Leopard.

You should note the detail that the plists for LaunchD to boot WOTaskD and WOMonitor are not even in Leopard Client. Apparently, someone actually forgot to include that in the release. Assuming that most people develop without direct connect enabled (I don’t know how true this assumption is, but at least I do!), implying that they actually need WOTaskD to be running, it’s a bit scarry to see that actually no-one at apple tested this, or else they would find out that the files were not included. It surely doesn’t boost my confidance on all this.

Also, I develop using virtual hosts. Basically I set the adaptor URL, in WOLips launch options, to be something like http://aVirtualHost.mac/cgi-bin/WebObjects. I kept getting the “No instance available” message until I run “sudo hostname -s aVirtualHost.mac” on the command line and restarted every WO-related process (apache, WOTaskD, and the app itself). BTW, note that the file included in apache2 configuration for vhost configuration has errors, and will actually kill apache at launch if you don’t remove both examples that come with it (the error is in the logging configuration for both sample virtual hosts). Even worse, if you are trying to look for apache error logs in the error_log apache file as you always did on tiger… forget it. This kind of errors are now thrown to /var/log/system.log.

But the biggest show-stopper is EOGenerator. You do use EOgenerator, don’t you? EOGenerator was based on the same frameworks as the Apple WO tools, like EOModeler. Apple moved those frameworks from “deprecated” to “dead” with Leopard, so EOGenerator went to the grave with them. Relax, there will be a Java replacement included on WOLips, but it’s still not there. Well, talk about living in the information age… the EOGenerator is out! :)

So, if you are an WebObjects developer wondering about jumping to Leopard… my adviced is, wait. Unless you don’t use Wonder and EOGenerator, which is highly unlikely.