Sh*t keeps breakin’

May 28, 2008

So the day after my post about the bike, I was climbing a steep hill in a high-ish gear and felt/heard a sharp SPRANG! from my rear wheel. I’ve had that loving feeling before, and sure enough, I had snapped a spoke. Fortunately only 1/2 mile from home. I took the wheel in to get the spoke replaced and the wheel trued up, and the bike shop guy called back to let me know my rear rim was cracking all over the place. The cracks are hairline now, but the wheel is eventual toast.

Spoke breaks really piss me off, because as an ex-extremely mediocre racer, I have clinical data that proves that not only am I much less powerful than I once was, but even when I was at my best I was pretty weak. Like my VO2 max topped out at 60, which is OK but hardly ‘genetic enduro mutant’ like. And I have no fast twitch to speak of, my vertical jump is 6 inches on a good day. Yes, I’m a slow guy with no endurance. So WTF on the whole spoke snapping thing? It’s not like I was pulling a (pre doping?) Vino and shattering the spent lead group of Tour elites with a blistering attack. I was climbing a freaking short not so steep hill on my way back home from work

As for the rim, well, I’m no Alberto Contador. The extra weight in my belly, fueled by late nights of coding and the incredible amount of yummy sugar snacks at the office, may be aerodynamically efficient, but it does nothing good for the power to weight ratio, and I’m afraid that my non endomorphic physique contributed to the rim fatigue.

No worries, don’t panic, said the bike shop guy. But I would start looking for a new wheel if I were you.

The thing is, the wheel is a 24 spoke Bontrager, and they dont even make those anymore. So I think it’s time to upgrade to a new set of wheels, something bomber that wasn’t made for an anorexic little grimpeur.  While a nice pair of Ksyriums would be great, I’m value-drooling over a set of Neuvation wheels, having read the reviews that rate them very high. In any case a wheelset is the best upgrade you can make on a bike, and I’m very close to springing for the rear wheel at least….

Since the rear rim is cracking slowly, I’m just going to keep an eye on it and keep riding. But the god of equipment upgrades wasn’t done with me. The next time I went out, I was just finishing my Mercer Island 2 lap AM special when I clicked out of my pedal, tried to click back in, and couldn’t get in. I rode swearing the whole time up the 14% grade to my house with one leg. Thank god for granny gears! When I took a look at the pedal, the retaining spring had cracked. This is the second pair of eggbeater pedals I’ve trashed, and I was done with the brand. That day I picked up a pair of Speedplay light actions. Installing the cleats was somewhat labor intensive, but straightforward. I was worried about finding the tiny little pedals with my feet, but had talked to enough friends that rode them to be assured that this wouldn’t be an issue. Sure enough, they felt completely natural. The best thing you can say about a pedal or a saddle is that you didn’t notice it, and these fit the bill. I’ll weigh in on their durability as time goes by.

Hopefully I can motivate to get out of bed by 5, on the road by 5:30 to do a long-ish Issaquah loop. Work is super busy these days, but a 5:30 – 8:30 session on the bike does wonders for my temperament.


WSDL Code Generation Support in Maven

May 28, 2008

Full disclosure: I once wrote SOAP services, I even wrote WSDL for them. Actually, it was while writing WSDL that I decided that SOAP was really complicated for something I didn’t want to spend too much time thinking about. That lingering ’smell’ and the resulting server load when we were servicing 1000s of fine grained RPC requests was about the time I began to really hate SOAP.

Fast forward to now, and I’m a huge fan of infinite resources and finite actions, aka REST. Why? My experiences with well designed REST interfaces is that they become intuitive once you know the domain model that the service is exposing. You ask for domain information in a kind of WYSIWIG (what you SAY is what you get) way, and that’s that. Yes, you can still maim your server with fine grained calls, but that is an orthogonal issue.

While I think that most of the rest of the world feels the same way about REST vs SOAP, i.e. Amazon AWS serves 85% of their requests over REST, that (sadly) is not the case. This weekend, I found myself in the unfortunate position of having to make a bunch of SOAP calls to a service that publishes documents. While most services circa 2008 would use RSS/Atom to do this, these guys haven’t quite made the conceptual leap. Maybe they’re still trying to figure out the whole series of tubes thing, I know I am.

The thing is that I’ve killed the brain cells that were responsible for all things SOAP. I mean it was more a case of ‘put them out of their misery with a few stiff pints’, but death is death, and that information had left my building. So I amped up the metal tunes and googled away for a while.

My (very modest) goals for the weekend, given that it was really nice out and I wanted to play with my kids and ride my bike:

(1) generate client code from the company’s WSDL file.

(2) do this as part of a build process.

Pretty basic stuff, I needed to find a Java client generation tool and hook it into Maven. I figured that lots of people had done this already and I would be standing on the shoulders of giants. Well, that turned out to be the case, sort of…

One problem I have with WS* in general is that there are so many different tools claiming to do the same thing. In the case of WS*, there are many different tools released by Apache that all generate clients from WSDL using their own baked versions of wsdl2java, a tool used to generate the server proxies from WSDL.

Muse: “The Apache Muse Project is a Java-based implementation of the WS-ResourceFramework (WSRF), WS-BaseNotification (WSN), and WS-DistributedManagement (WSDM) specifications. It is a framework upon which users can build web service interfaces for manageable resources without having to implement all of the “plumbing” described by the aforementioned standards.” WOW. Still reeling from all the T&FLAs in that sentence. I think Muse might be helpful, but I don’t know how much I end up getting ‘for free’.

Axis: Apache Axis is an implementation of the SOAP (“Simple Object Access Protocol”) submission to W3C. Hey, that sounds pretty straightforward. But wait, that doesn’t really tell me much! Do they handle client and server side dev? Also, what is the difference between Axis and Axis2?

CXF: Apache CXF is an open source services framework. CXF helps you build and develop services using frontend programming APIs, like JAX-WS. These services can speak a variety of protocols such as SOAP, XML/HTTP, RESTful HTTP, or CORBA and work over a variety of transports such as HTTP, JMS or JBI. Hmmm, again with the TLAs. Also, I don’t need the swiss army knife here, I’m not writing a multi protocol service, I’m writing a dumb as crap service consumer.

All three frameworks above claim to have something called wsdl2java, which does what it says. Lacking any other differentiation points, I decided to try them all. I was taking the “I don’t want to know sh*t about the underlying technology approach”. In other words, I really didn’t care about WSDL, I just wanted to generate some damn code and be done with it.

Try #1: Muse: whoops, it didn’t like my WSDL because there were 2 port elements:

~/muse/bin/wsdl2java.sh -wsdl newsdatasecure.asmx.xml -proxy
java.lang.RuntimeException: [ID = 'OnePortPerWSDL'] The resource inspector can only process WSDLs with one port element. The WSDL can have multiple portTypes, but only one concrete service and port.
at org.apache.muse.tools.inspector.ResourceInspector.getPortType(ResourceInspector.java:662)
at org.apache.muse.tools.inspector.ResourceInspector.run(ResourceInspector.java:876)
at org.apache.muse.tools.generator.analyzer.SimpleAnalyzer.inspect(SimpleAnalyzer.java:409)
at org.apache.muse.tools.generator.analyzer.SimpleAnalyzer.analyze(SimpleAnalyzer.java:348)
at org.apache.muse.tools.generator.Wsdl2Java.run(Wsdl2Java.java:178)
at org.apache.muse.tools.generator.Wsdl2Java.main(Wsdl2Java.java:270)

Wait a minute. WTF is a port element? Damn, I need to read up on WSDL. (Later….) OK, here are my notes.

Next Up: Apache CXF or Axis? Who’s got more Maven Love?

So it was pretty obvious that short of hacking the provider WSDL, I wasn’t going to get the love I needed from Muse. That left two choices, CXF, which felt very framework-wonkish, and Axis/Axis2, which felt very vague. I decided to step back a little bit and see what kind of support both approaches had in the build world. After all, I wanted to integrate client side codegen into a build process, where WSDL changes would immediately show up as compilation failures.

This was the quintessential Yak Shaving exercise. Which might be a great way to spend a cold, blustery day, but not a sunny (in Seattle!?!) 75 degrees day. Turns out CXF and Axis2 have maven plugins.

Axis2 has the wsdl2code plugin. CXF has a wsdl2java plugin. At this point I was thinking I was out the door. My previous maven experiences with integrating plugins were largely a cut, paste, and go exercises, using mvnrepository.com or other maven POM file syntax I could get from the documentation.

I tried CXF and quite simply couldn’t get it to work. Specifically mvn generate-sources, or any of the variants proposed in various bug lists didn’t work.

My next option was Axis2. I got it working, but only after some effort detailed below.

The wsdl2code plugin from Axis2 claims to generate code as long as you simply follow the plugin instructions and insert the following plugin config information into your POM:

 <build>
    <plugins>
    <plugin>
    <groupId>org.apache.axis2.maven2</groupId>
    <artifactId>axis2-wsdl2code-maven-plugin</artifactId>
    <executions>
    <execution>
    <goals>
    <goal>wsdl2code</goal>
    </goals>
    </execution>
    <configuration>
    <packageName>com.foo.myservice</packageName>
    </configuration>
    </executions>
    </plugin>
    </plugins>
</build>

Unfortunately, that isnt valid POM schema. You need to embed the configuration element in the execution element:

 <build>
    <plugins>
    <plugin>
    <groupId>org.apache.axis2.maven2</groupId>
    <artifactId>axis2-wsdl2code-maven-plugin</artifactId>
    <executions>
    <execution>
    <goals>
    <goal>wsdl2code</goal>
    </goals>
    <configuration>
    <packageName>com.foo.myservice</packageName>
    </configuration>
    </execution>
    </executions>
    </plugin>
    </plugins>
</build>

That at least produces a valid POM. However, when I ran
mvn clean install

I recieved the following error:

java.lang.NoClassDefFoundError: javax/wsdl/WSDLException
at org.apache.axis2.maven2.wsdl2code.WSDL2CodeMojo.execute(WSDL2CodeMojo.java:396)
at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:443)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:539)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalWithLifecycle(DefaultLifecycleExecutor.java:480)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:459)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:311)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:278)
at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:143)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:334)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:125)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:280)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
at org.codehaus.classworlds.Launcher.main(Launcher.java:375)

CRAP! You mean the plugin is puking because it can’t resolve a dependency? Christ, isnt this the stuff that maven is supposed to resolve?

I did some more thread googling, and found here that I needed to add the following dependency as well as change the groupID and add a specific version number:

<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.6.2</version>
</dependency>

<plugin>
<groupId>org.apache.axis2.maven</groupId>
<artifactId>axis2-wsdl2code-maven-plugin</artifactId>
<version>1.3</version>
...

Now I had WSDL code generated in Maven, but that code didn’t actually compile…hmmm. No good.

My last gasp effort to generate some client stubs was to use Axis, which has noted here, has now been replaced with Axis2.

However, desperation leads to an open attitude, and when I downloaded axis-1.4, and did the following:

java -cp ./lib/axis.jar:./lib/commons-discovery-0.2.jar:./lib/commons-logging-1.0.4.jar:./lib/saaj.jar:./lib/jaxrpc.jar:
./lib/wsdl4j-1.5.1.jar \
org.apache.axis.wsdl.WSDL2Java ~/foo.wsdl

I generated WSDL that actually compiled, and ran. Moral of the story? Stay the F*ck away from SOAP, it’s 2008 after all!