Monday, November 29, 2004

Wrestling with Axis

More on Axis. Started playing with the examples, and got 1 and 2 working just fine. That .jws thing is pretty cool.

Then I got to example3. I got the MyService.java and Client.java files to compile fine, then ran AdminClient on deploy.wsdd to deploy them. Got a "401 Unauthorized" back in an AxisFault, and went looking for how to setup admin security. Poked around a bit, and found not much on AdminClient. Started looking at AdminServlet, which said not much, and AxisServlet, which has a WSDL that just exposes an AdminService method, but says nothing about how to configure it on the back end.

I had seen mention of server-config.wsdd, but when I looked for it, I didn't find it. Eventually, I grepped the docs for mention of it, and found in reference.html that Axis will create it if it doesn't exist, and will add to it when you deploy things. So I created it, and added a globalconfiguration section and an adminPassword parameter. The 401 went away, replaced instead by a "500 Internal Server Error" and a voluminous stack trace.

Looking at the exception output, it said "Invalid WSDD element 'globalConfiguration' (wanted 'deployment')", which contradicts reference.html. Ah, (oops), it wants that globalConfiguration wrapped in a deployment tag. (Googled and found an example server-config.wsdd, and mirrored the relevant parts of that; did I mention that I love Google?)

So now my AxisFault says "Server.NoService", and "The AXIS engine could not find a target service to invoke! targetService is null" when I run AdminClient. Seems that if server-config.wsdd is missing, AdminService (and Version) get deployed, but if server-config.wsdd is present, only those services listed therein get deployed. Okay, fine, how do I deploy AdminService manually? No wsdd file ships with Axis, it seems (apart from the ones in the samples dir).

I then reread the install instructions, that say that "the client" (presumably AdminClient) has a default password, so I decide to go look at the source and find out what the default password is (on the server) so I can provide it to the client; I assume that it's out of sync. In the process, (of looking through the Axis CVS), I find a server-config.wsdd that has reasonable-looking entries for AdminService (and Version). Plopped them into my server-config.wsdd, kicked Axis via Tomcat, and I'm back to a 401. Grrr.

After looking at the Admin.java source in CVS, I decide to at least try enabling the remote access, just in case. Sure enough, I make that change, and life is fine; "AdminClient list" returns the blob of XML expected. Harumph. I'm doing this all on one box, so why didn't it see that I'm local?!

Okay, back to what I had been doing. I run the example3 deploy.wsdd, and it accepts it. Running AxisServlet lists MyService. Running Client says "The AXIS engine could not find a target service to invoke! targetService is null". This is what I got before when Axis wasn't running anything, but now, if I do a "AdminClient list", it shows MyService, with allowedMethods of "*" and a correct classname.

Now, oddly enough, I went looking for the .class file under Tomcat, under WEB-INF/classes, and found an old version, that I'm guessing shipped with Axis and that I had copied over when I installed Axis under Tomcat. So I replace that with the one I just compiled. I undeployed, and the file remained. So is this where the file gets deployed? And do I have to place the .class file(s) myself, or does the deploy.wsdd and AdminClient take care of that?

I removed MyService.class, undeployed, and deployed, and can find no MyService.class anywhere under tomcat/webapps. So I copied it there. Same error. Un/redeployed (via AdminClient and the wsdd files). Same error.

If I go to the MyService URL, Axis says "Hi there, this is an AXIS service!", while if I go to another, invalid one, Axis says "No service is available at this URL". So I'm guessing that Axis at least knows that it should know about the service. But from Client, hitting either MyService or a known invalid one both generate the "targetService is null" message. Kicked Axis, then Tomcat. Same error. Removed every copy of MyService.class I could find. Same error, and yet the un/redeploy worked fine. How *does* this work?

Ran happiness page again, installed mail.jar (just for grins), and kicked Axis. Ran AxisServlet page, and got message saying "Fault - Could not find class for the service named: samples.userguide.example3.MyService. Hint: you may need to copy your class files/tree into the right location (which depends on the servlet system you are using)." Nice of them to confirm that.

Copied MyService.class file into Tomcat's webapps/axis/WEB-INF/classes/samples/userguide/example3. Reloaded AxisServlet, and the "Fault" message went away. Still get the "targetService is null" message, but at least I can see that I need to place the class files myself, and that I'm doing so in the right place. Time to post to the board, methinks.

Or just Google for "targetService". Found a message from Steve Maring (thanks, Steve) saying that you can't just pull down an incomplete version of server-config.wsdd, or use deploy.wsdd in its place. Instead, extract it from axis.jar, and modify it to include what you need. Did so, re-enabled remote admin, kicked Axis, redeployed the example, and it worked. All's well that ends well, I suppose, but somebody deserves a "grrrr"!

Tuesday, November 23, 2004

Tomcat Manager

Okay, Tomcat has a Manager (which can be discovered via RTFM) that can redeploy a webapp without bouncing the whole thing. RTFM. It's your friend.

Spring and Axis

Started looking into Spring. Inversion of Control (IoC) and Dependency Injection are pretty cool things. (See Martin Fowler's article for more info on that.) Spring uses IoC/DI to remove dependencies from your objects, turning them into POJO's, which in turn makes them much easier to test. And Spring makes using web services (via JAX-RPC, anyway) a much easier task.

So I'm now setting up Axis. You plop it into Tomcat, then run a test page to see if all's well. It wasn't. It complained: "Error: could not find class javax.activation.DataHandler from file activation.jar". I have a few different versions of activation.jar on my box; I copied the one that came with Spring into axis/WEB-INF/lib, but Tomcat didn't see it without a restart. (There's probably a better way to get it to see it; I'll look into that shortly...)

With activation.jar in place, Axis' test page is all happy, so I tried out a couple of the samples, and got NullPointerExceptions. Poked around on Google a bit, and it seems that Axis 1.1 doesn't play nice with JDK 1.5. Grabbed Axis 1.2RC2, installed it, replaced it in Tomcat, added activation.jar, got the happy page working, tried the samples, and viola (as they say in France), I get proper responses.

Thursday, November 18, 2004

SuSE and my Muvo

I had played around under Gentoo with my old USB keydrive, and got it to do a directory listing, but not read or write. It was still on my list of things to pursue at some point. So it was with a wee bit of trepidation that I plugged in my Creative Labs Muvo NX MP3 player into my work box, (running SuSE 9.1). See, I really, really needed my .emacs file from home to be able to work like I am accustomed to.

Well, nothing to see here, folks. I plugged it in, heard some HD chatter, and got a dialog asking me if I wanted to open a KDE app when new media is detected. It found the drive, mounted it under /media, and popped up a file browser. Copied off the desired files, pruned a few podcasts that I listened to on the way in to work this morning, and I'm good to go. Even better, I can now work in Emacs like I like.

I'm liking SuSE more and more.

Wednesday, November 17, 2004

Bruce Eckel on Thinking in a Different Language

GatorJUG has (or had, I can't find the archives at the moment) a podcast of Bruce Eckel talking about programming languages. The point he made (or at least the one I was most interested in; he talked about a couple of things) was that you think differently in different languages.

One example he gave was about dynamically loading a class at runtime. In C++, it's possible (he said), but not something you're likely to even think about doing. In Java, it's quite easy, making it something that you'll probably run across at some point. And while you can dynamically create classes at runtime in Java, in Python it's a very simple exercise. Using each language gives you a different insight on solving problems, and mixing languages can be a real boon to solve a given problem, given the strengths of each.

He also mentioned the type differences among C++, Java and Python, and how loosening up type restrictions greatly changes the nature of solving some problems.

He also mentioned the applicability of this idea to natural langauges as well. This is something I've been greatly curious about, and is one of the reasons I'd love to learn a 2nd language. I'd love to see just how different expressing given ideas or thoughts are between two languages, and whether thinking in another language would change those ideas, somehow. (Maybe next month...)

Ant, Java and SuSE Mixup

My "new", current, (temporary) work machine is an older box with 190MB RAM, which isn't quite up to the task of running Netbeans. (NB takes up more than that by itself.) So I've dropped back to coding in Emacs, and running the NB project Ant script (and Ant) from the command line. (I should get a better machine by next week.)

Which brings us back to the question of how to setup the taskdef classpath without using the NB dialogs. It looks like NB wires stuff up before calling Ant during builds, but doesn't make it apparent what gets wired or to what values.

I ended up using properties for the XDoclet jars, chaining them together into another property for the classpath required for a single taskdef, and putting that property into the taskdef's classpath attribute.

Then it wouldn't compile. My setup was thus: Java 1.4.2 was already installed on the machine, I then installed 1.5 manually (i.e. not via SuSE's mechanism, as they didn't have 1.5, at least in YaST), and then installed Ant via YaST. The Ant script (in /usr/bin/ant), for some reason, was assuming that I was using a 1.3 JDK, and when run, ant said "Unable to locate tools.jar. Expected to find it in /usr/lib/SunJava2-1.4.2/lib/tools.jar". Took me a while, but I found the line in /usr/bin/ant that referred to 1.3, changed it to 1.5, then looked at the setJava script, and created the proper .conf file in /etc/java. And voila, no runs, no drips, no errors.

Thursday, November 11, 2004

More on Ant Paths

Tried running build.xml from the command line, and got errors regarding XDoclet. Makes sense; I mentioned earlier that I added the XDoclet jars in the Additional Classpath entry under Ant settings in Netbeans, which means that they're not listed in the build.xml itself. Gotta change that.

Odd XDoclet Error

Tried to get XDoclet to generate a .wsdl file; got error saying something about an ambiguous subtask definition for deploymentdescriptor. Couldn't figure out what to do about it, and Googling revealed nothing useful. I had two targets, one each for wseedoclet and ejbdoclet. I combined them, and it worked.

I decided to blog this, so I moved wseedoclet back to its own target to get it to generate the error message again, and it worked. Go figure. Even after doing a clean and build, etc.

Tuesday, November 09, 2004

Netbeans, Ant and XDoclet

Today, I played around with getting NetBeans 4.0 Beta 2, Ant 1.6.2 and XDoclet 1.2.2 to talk together and play nice. (NB 4.2b2 comes w/Ant 1.6.2 built in; XDoclet is separate.) The goal was to get JBoss into the mix as well, but that'll probably have to wait until tomorrow.

I created a simple project (Hello, from the Mastering EJB 2.0 book). NB shows the build.xml file under the Files tab (and not on the Project tab, where I was first looking for it). build.xml expands to show all targets; most of the targets live under nbproject/build-impl.xml, and several are empty and can be overridden in build.xml. (The overridables are listed in a comment.)

For background, Ant build files set up chains of dependent targets. NB's default is default, which depends on dist and javadoc. dist in turn depends on init, compile, pre-dist, do-dist and post-dist, which it most likely runs in that order; each of these depend on others, and so on.

So I added various tags to my simple bean file. At the class level, I added an @ejb.bean tag, with name and type attrs. jndi-name and local-jndi-name attrs also look useful. I also added an @ejb.interface-method tag to my one business method.

In build.xml, I added an ejbdoclet target, with an embedded task of the same name, depending on init. The destdir attr looked most useful, and I added an excludedtags and verbose attr as well. I then added remoteinterface, localinterface, homeinterface and localhomeinterface elements (all empty), and a fileset that listed my one source file, explicitly.

I'm pretty sure there's a better way to list my source files. I tried **/*.java, but with my destdir putting the generated files into my source dir (which may be a problem), compiling a 2nd time gives me interfaces for my interfaces, which is wrong. So for the moment, I'm listing each file separately, and will be looking for a better way. Like having a "generated" directory that's separate, or something. Suggestions welcome.

Then I troubleshot it. First off, it couldn't find the ejbdoclet task. Played around with the compile classpath, to no avail. Found that I could add an Ant classpath element under the taskdef, but that felt unwieldy, especially as I had 5-6 jars eventually to add. Was about to separate it out as an Ant typedef, then thought that since Ant is a proper part of NB, there should be a config option. There was, under Tools/Options, Building, Ant Settings, Additional Classpath. Added several files there (xdoclet, xdoclet-ejb-module, xjavadoc, commons-logging and -collections, and jboss-j2ee.jar), and life was good.

I was also getting empty bean interfaces. Seems I forgot to put the @ejb.interface-method on the method, but adding the tag fixed that.

One thing made it slightly harder than it should have been. I had intended to start out with a very simple stateless session bean, and mimic xdoclet's sample. It turns out that xdoclet's sample stateless session bean was a sample of how *NOT* to let xdoclet generate the interfaces for you. Bad choice on my part. Ah well.

Wednesday, November 03, 2004

Shared Library Woes

Pulled down Sun's J2EE SDK, and ran the installer, which couldn't find libstdc++-libc6.2-2.so.3. Found what I thought was the Gentoo package, but all were masked. Set ~x86 in ACCEPT_KEYWORDS in /etc/make.conf, emerged, and tried the installer again; no luck. Googled, and found that the file is part of the libstdc++2.10-glibc2.2 package; did emerge search, but didn't find it. qpkg -f libstdc++-libc6.2-2.so.3 turned up nothing. Googled again, found libstdc++2.10-glibc2.2 in a .deb file on packages.debian.org.

Okay, now how do I pry apart a .deb file on a Gentoo system? Wikipedia knew; it's an ar file, that contains .tar.gz files. No sweat, extracted the file, the installer didn't find it; remembered to run ldconfig; didn't find it; looked for the file; didn't find it. what!?

Re-extracted it, looked closer, and saw that it's just a link; extracted the link target, copied that as the link name, ran ldconfig, ran the installer, found it; whew.

I couldn't imagine that Gentoo didn't have this somewhere, so went back and searched the forums. Didn't find it. Googled for it, saying 'libstdc++-libc6.2-2.so.3 site:gentoo.org'. Found it, it's in lib_compat. emerged that, and life's good.

Tuesday, November 02, 2004

PostgreSQL == Good

Despite having finished the emerging that I thought might have been causing problems, Eclipse continues to crash (I will pursue this later).

I worked through the PostgreSQL tutorial and docs, and got things running on my machine. I'm liking PostgreSQL as well; table inheritance looks like a neat thing. I'm sure there are times when I wish I'd had this. And I assume you can do things like abstract base tables as well, which I certainly wish I could have had elsewhere.

emerging libgnomecanvas stopped with a complaint about not finding index.sgml. Again, I searched the Gentoo forums; finding a message saying to re-emerge gtk-doc; no luck. A followup said to try USE="-doc" emerge, which worked. Same thing happened with libgnome and libgnomeui, same solution.

Missing gconf-2.0.pc during emerge

During an emerge of gnome-vfs, got error message of 'Library dependencies ... not met'. Turned out that gconf-2.0.pc was missing. Searched Gentoo forums, and found a suggestion to copy in existing gconf-2.0.pc; didn't exactly like that, as I wasn't sure how appropriate it was for my system.

So I untarred /usr/portage/distfiles/GConf-2.6.2.tar.bz2, and ran ./configure, which created a gconf-2.0.pc; copied that to /usr/lib/pkgconfig, and re-emerged gnome-vfs. No luck, got report that header file was missing. I examined gconf-2.0.pc, did a locate for missing header file, and hence saw what needed to be fixed in gconf-2.0.pc, (prefix was pointing to /usr/local, and should have pointed to /usr). Re-emerged gnome-vfs, which worked fine this time.

Still not sure why a) the wrong value was generated by configure, and b) the file wasn't placed where it should have been. But it works, and I can continue.

Monday, November 01, 2004

Started in on Netbeans; Eclipse Trouble

Got Netbeans 3.6 running, and started playing with it. Worked through the QuickStart and Using guide. It looks fine, but feels a little sluggish compared to what I remember Eclipse being. But A) I'm also doing emerges (compiles) at the same time, and B) I'm probably not on as fast a box as I was when I used Eclipse. I pulled down Eclipse 3.0.1, and will compare apples to apples tomorrow.

I do like Netbeans' Import Management Tool. Nice amount of control over how you specify and manage your imports. And I wish I'd had a GUI editor when I was doing that Swing stuff.

As a footnote, Eclipse was crashing on me, but again, I was mid-compile, and the .so's that Eclipse listed on the dump were on both sides of my compile, so I'll wait until I'm not messing with stuff before trying to troubleshoot.