I never want to be a “corporate developer”

During a JavaOne session today, Linda DeMichiel, Sun's EJB specification lead, said the EJB 3.0 experts group wants to make writing EJBs easier so that even "corporate developers" could write EJBs.

Yesterday, I heard a Sun person say one of the goals of Java Studio Creator is to allow "corporate developers" to write Java web applications.

Do corporations just hire less-skilled developers? Or does something happen to a developer when he or she joins a big corporation?

Update: Since my attempt at irony didn't come across after three hours of sleep, I want to point out that corporate developer is an unfair term when what is meant is lesser-skilled developer.

JavaOne update: Faster, lighter Java with Barcelona

Can you run multiple Java applications in one virtual machine to boost speed and reduce memory requirements? Apparently, engineers at Sun are trying to find a way to do this. And from this first JavaOne session I attended this morning, it sounds like this could happen in the next year or so.

This research effort at Sun is called Project Barcelona, being led by Grzegorz Czajkowski, a senior staff engineer at Sun. Sun wants a JVM to run multiple applications in order to:

  • Improve application startup time
  • Boost performance
  • Lower the memory footprint for Java apps.

Some fruits of Barcelona will be available in the new HotSpot JVM in J2SE 1.5. Those improvements will allow classes running in different JVMs to share some read-only data. But Grzegorz Czajkowski stressed that Barcelona still is a project, not a product. The first real product to allow multiple Java applications to run in the same JVM should come this fall in the Connected Limited Device Configuration of J2ME, he said.

The Barcelona project has created a Multitasking Virtual Machine. MVM works using a daemon process on Solaris, called the mserver, and acts as a central point of contact for all Java applications that want to run. The Java startup command becomes a short-running application to contact the mserver daemon, which starts the Java app within its single JVM. Pretty neat.

The current MVM shares common classes, bytecodes and some of the runtime system, Grzegorz Czajkowski said. The MVM is in charge of isolating the different applications to ensure they don't collide with each other, and that security constraints are still handled on an application level and don't run with the security permissions of the MVM. Here's the great news:

  • Application startup time is reduced by about 96% for non-GUI applications, 33% for GUIs.
  • Memory requirements shrink 30% to 50% for each application.
  • Runtime performance suffers only slightly. I think he said the MVM creates a performance overhead of only about 1%.

If Sun can make the MVM part of Java, our Java applications should become less of the memory hogs they are, and start up much faster. Can you imagine the day when Eclipse launches in a few seconds rather than after you've returned from your coffee break?

What are friends for?

Scott McNealy, during his JaveOne keynote today, made sure everyone knew Sun Microsystems and Microsoft are partners moving forward. With a $2.4 billion check, MS and Sun will be working together for the next 10 years, getting the Liberty Alliance and Passport systems working together, getting LDAP and MS Directory Server to work together for an enterprise single-signon solution, integrating .NET and Java, and other joint ventures.

But even though Sun and MS will be working together, the Redmond relationship isn't all warm and fuzzy. First, he publicly invited Microsoft to get involved in the Java Community Process.

"Come to class and participate and contribute," he told the crowd. "This is my open letter."

Apparently, his private invitation for Microsoft to join the JCP hasn't worked, and a little public pressure was in order. Second, McNealy took a few digs at Windows. He referred to the Java Deskstop System as an "upgrade" to Windows, then blasted Windows for being a warm, moist and welcoming host for a plethora of computer viruses. Viruses cost companies $300 billion a year, he said.

"Where's the outrage against viruses? ... They're Microsoft viruses."

Some other notable remarks from McNealy:

  • Sun will continue running Java.
    "Someone's gotta be in charge." And that someone will be Sun in the foreseeable future, apparently.
  • 90% of all web visitors will hit a site running Java.
    "Java is everywhere," he said. "You can't get away from it."
  • Sun is healthy and isn't going anywhere.
    A little scary that McNealy felt he had to say this. But he pointed out that sales are up and the latest quarter's numbers that will be announced in a few weeks will reinforce this, he said.
  • Java.net has 41,000 members, with 1,000 open-source projects hosted.
  • Project Looking Glass is now open source under the GPL.
    This was announced yesterday, as coming soon. Soon turned out to be today.
  • Legislation to force companies to expense stock options will harm innovation.
    He said everyone with stock options will lose them if companies have to count them as expenses. Tell your representatives in Congress to stop the move toward the requirement for companies to consider options an expense. "We can't have this world run by accountants," he said.

Now, I'm off to the technical sessions. I'll update later today on what was interesting.

JavaOne update: the new threading package in J2SE 5

My favorite technical session of the day was the new concurrency utility package scheduled for release this fall in J2SE 5. (the newly rebranded J2SE 1.5.) If you're writing multi-threading applications today and you're not using Doug Lea's package, get it. The new java.util.concurrent package is based on it.

The session was conducted by Brian Goetz and David Holmes, both on the JSR 166 experts group.

The new concurrent package offers higher performance for multi-threaded applications in a package that's easier to use than using synchronize blocks and calling wait() and notifyAll() in a while loop. As David Holmes said in the session, if you find yourself synchronizing a block of code, look at the new concurrent package for a better solution.

The new java.util.concurrent package offers:

  • Built in thread pools
  • A class to let you schedule a runnable
    The runnable may execute at a certain time from now, on a specific date, or run on a regular interval.
  • New concurrency-friendly Collections classes
    As Brian Goetz said, you can get thread-safe Collections objects in Java 1.2+, but those collections aren't concurrency friendly. I.e. they don't run efficiently in a multi-threaded environment.
  • Atomic variables
    These are thread-safe variables you can get and set in a multi-threaded environment without worrying about synchronizing access.

An example from the session: Instead of writing:

Runnable r = ...
new Thread(r).start();

and creating a new, and potentially unlimited number, of threads each time, you'd write:

Executor pool = Executors.newFixedThreadPool(10);
...
Runnable r = ...
pool.execute(r);

to ensure your runnables are executed in a maximum of 10 threads, that are reused and not left around as garbage upon each use.

The new threading package should make threading easier to use for those times when you must use threads, don't want to write a lot of synchronized blocks with notification loops, and want to use a standard Java package.

Supersize me

I just arrived at JavaOne on a sunny Sunday afternoon. I got side-tracked on my way over to the Moscone by the Gay Pride parade rolling down Market Street. At first, my goal was to cross Market to wend my way over to the conference center, but then the parade was fun to watch for a while.

Once I checked in and got my conference catalog, I noticed just about every session is marked Advanced. If the session is labeled a "round-table" or sounds like marketing, it gets the Introductory label. There seem to be about three "intermediate" sessions offered. I'm wondering if most of the content this week really will be advanced, or is the labeling more of a grade inflation in our supersized world.

I point out this "advanced" nature of the sessions because I think a lot of the excitement in the Java world right now -- a lot of what will make JavaOne hot this year -- is the trend toward simplicity.

In the Java language itself, we have new features in 1.5 that should make programming easier: autoboxing/unboxing, the enhanced for loop, generics, typesafe enums, and the new java.util.concurrent package J2SE 1.5 that should make threading easier.

On the application server side, we have products like the Spring Framework and Pico Container to make developing and testing applications easier. On the data persistence side, we have products like Hibernate, iBatis, and Cayenne to help turn our database data into Java objects without all that messy JDBC code. And we even have the coming features of EJB 3.0 itself, which holds out the promise to make enterprise computing easier by not having to worry about the container as much as we have to today.

So overall, I see the life of a Java developer getting easier, at least in the coding part.

What I do see getting more difficult, though, is the increase in what Java can do. AWT, JFC, SWT, EJB, JAXB, JAXP, CMP, CMT, JAX-RPC, SAAJ, JAXR, JAAS... We can't be experts in them all. Java is just too big and getting bigger all the time. But if your specialty is on the client tier, IDEs and plug-ins help create GUIs better today than a few years ago, including web GUIs with tools like Java Studio Creator. If your specialty is the web tier, you have easier abstractions over the servlet layer with Struts, Tapestry, JSF, Spring and the soon-to-be open-sourced Net-UI package from BEA. If your specialty is the application server tier, you have tools like Spring today to help you get past the EJB comlexity, and EJB 3.0 in the future to help do the same. And the above-mentioned data-persistence packages.

And that's why I'm at JavaOne this year. We can do more with Java, and doing it is getting easier. There is more excitement about Java today than there was in the past two years, when a malaise seem to set in after .NET grabbed not only the headlines, but the attentions of IT decision makers. Now that the reality of .NET is starting to spread, that it is not a magically "easier" solution, I can proudly say:

Java is back.

Windows dissing Mozilla

I upgraded to Mozilla Thunderbird 0.7 today. Since I used the Windows installer for version 0.6, the uninstall was easy by using the Windows Control Panel.

In the uninstall area, Windows told me I use Thunderbird -- an application I've used daily since installing it -- "rarely."

Unusual definition of rarely.

JAR files XDoclet needs for Hibernate

Today I began refactoring some Hibernate data objects in order to use XDoclet to generate the mapping files. When creating the Ant taskdef:

<taskdef
name="hibernatedoclet"
classname="xdoclet.modules.hibernate.HibernateDocletTask"
classpathref="lib.class.path"
/>

Eclipse was kind enough to tell me all the XDoclet JARs I was missing -- except one. The missing one didn't turn up until I ran the Ant task and got:

[hibernatedoclet] - Running <hibernate/>
[hibernatedoclet] Generating mapping file for com.client.dataobjects.Portfolio.
[hibernatedoclet] com.client.dataobjects.Portfolio
[hibernatedoclet] - Could not find tag handler for prefix: 'XDtCollection'
[hibernatedoclet] - Error occured at/around line 166,
offending template tag: XDtCollection:create
[hibernatedoclet] xdoclet.template.TemplateException:
Could not find tag handler for prefix: 'XDtCollection'
[hibernatedoclet] at xdoclet.template.TemplateEngine.getTagHandlerFor
(TemplateEngine.java:207)
...
[hibernatedoclet] - Running XDoclet failed.
[hibernatedoclet] - <<Running XDoclet failed.>>

For my future reference, here are the XDoclet JAR files needed to generate the Hibernate mapping hbm files:

xdoclet-xdoclet-module-1.2.1.jar  <-- the one that fixes the above problem
xdoclet-1.2.1.jar
xdoclet-hibernate-module-1.2.1.jar
xjavadoc-1.0.3.jar

Update: From the xdoclet-user mailing list, the Hibernate ant task also needs the commons-collections-2.1.jar and commons-logging-1.0.3.jar. But since my project already had those in the Ant classpath, those didn't cause me any grief.

O-R mapping tools — a step backward?

First, some history on why I think the Java community missed a step in developing a standard way to use object-relational mapping tools for our data.

When most of us started coding Java, there was JDBC. We saw the API for what it was: a low-level, but standard way we could access databases from different vendors. We could use Oracle, DB2, MySQL, PostgreSQL, etc., and as long as we didn't use vendor-specific JDBC extensions, we could swap out underlying database technologies without having to rewrite out code.

Progress didn't stop with JDBC. It's low-level nature makes coding with it tedious. We have to manage our own transactions, and we have to manage translation between the relational database tables and the business objects we use in our applications.

With EJB 2.0, we got container-managed persistence for our business entities. Vendors provided tools to map relational database tables to EJB entities. The EJB container could be made responsible for reading and writing our Java objects to and from our database tables, freeing us from writing low-level database access code. I think EJB-CMP was the first standard O-R tool in Java.

Today, however, we mostly agree EJBs are too complex for most applications. EJBs have a cost in programmer expertise, project development time, and the cost of hardware and software to run EJB containers.

But if you aren't using EJBs for object-relational mapping, and you want to use a standard object-relational mapping API, what are your choices? The JDO specification came out last year seemingly as the answer. The goal of JDO seems to be to allow a database-neutral O-R mapping system to allow developers to code with objects and worry less about how the objects are stored. And it's supposed to be a standard you knew would be around in the future. A JDBC++.

But JDO seems never to have gained traction. I've never used it on a project, or seen a project with it being used. I'm sure JDO is being used out there. It just doesn't seem to be very common. Did the JDO spec scratch the wrong itch?

Instead of having a JCP standard Java OR-mapping API, we have open-source tools like Hibernate and Cayenne gaining market share as object-relational mapping tools of choice. These tools seem to be answering what developers need. But by using these tools, we're now back to coding to non-standard APIs.

Don't get me wrong. I'm not saying Hibernate or Cayenne are bad. Hibernate is a nice tool. I'm using Hibernate on my current project. And the beauty of tools like Hibernate is I can swap out Oracle and replace it with DB2 and still have most everything work. We haven't gone so far backwards that we're coding to vendor specific APIs. But something still seems wrong here.

Without a standard API, we've gone back to the days of coding to proprietary APIs that could disappear if the open-source developers lose interest. Yes, we still have the source code available (if we remember to download it and store it in our source-code repositories). But five years from now, I bet I could find a Java programmer who understands JDBC faster than I could find a Java programmer who understands Cayenne.

I'm unsure what the next step will be for Java and O-R mapping. Will the Java Community Process adopt a Hibernate-like O-R mapping API to replace JDO? Will JDO eventually capture the mind share of developers? Will the new, "lighter" EJB 3.0 spec provide an O-R mapping API that can be used outside of the EJB container?

Until something like JDBC comes out for O-R mapping, gets widely adopted, and widely accepted by programmers, it seems we're back to the old days of coding to non-standard APIs, locking ourselves into specific technologies. Is this taking a small step backward in order to take a bigger step forward in a few months with a new spec? That's what I'm hoping.

Continuous Integration with Java

The client I'm working for wants to set up Cruise Control or another tool to assist with the continuous integration of their project code.

I heard Erik Hatcher say a year ago that he prefers Anthill over Cruise Control for its ease of use, and Franz Garsomke, a past advocate of Cruise Control, said last year he would use Anthill on his next project when he spoke at the Denver JUG.

Going with Antill sems a no-brainer, right?

Well, I started reading a comparison of the two people have posted on Ward Cunningham's wiki. From what the posters say, Cruise Control's 2.1 version has improved, and most of the cricisms are no longer valid. The biggest difference between Anthill and Cruise Control that matter to me is Anthill is a servlet application, so must be hosted on an app server. Cruise Control, apparently, is a program you also can run from a command line or run via cron(8) or even as a Windows service, with a free program to run a Java application as a service.

With what I've read so far, I'm leaning toward Anthill because it sounds like it will be easier to set up for our project, and provides more web-based feedback. The server that will run the CI tool at my client's site is a Windows server. I think I'll have more luck installing Tomcat on their box than trying to configure Cruise Control to be run as a Windows service at boot time.

I'll let you know how it goes.

Installing Roller

Not surprisingly, my first post to this blog is on the issues I encountered installing and getting the Roller webapp working with Tomcat and MySQL. I want to track these issues for my next installation.

The first minor issue involved deploying Roller 0.9.8.2 to Tomcat and starting the server. I got this in my catalina.out Tomcat log:

DBCP borrowObject failed: java.sql.SQLException:
Server connection failure during transaction.
Due to underlying exception: 'java.sql.SQLException:
Invalid authorization specification,
message from server: "Access denied for user: 'tomcat-user@blogserver'
(Using password: YES)"'.
** BEGIN NESTED EXCEPTION **
java.sql.SQLException
MESSAGE: Invalid authorization specification,  message from server:
"Access denied for user:
'tomcat-user@blogserver' (Using password: YES)"
STACKTRACE:
java.sql.SQLException: Invalid authorization specification,
message from server: "Access denied for user:
'tomcat-user@blogserver' (Using password: YES)"
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:1977)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:1900)
at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:950)
at com.mysql.jdbc.Connection.createNewIO(Connection.java:1887)
at com.mysql.jdbc.Connection.(Connection.java:440)
at com.mysql.jdbc.NonRegisteringDriver
.connect(NonRegisteringDriver.java:400)
at org.apache.commons.dbcp.DriverConnectionFactory
.createConnection(DriverConnectionFactory.java:83)
at org.apache.commons.dbcp.PoolableConnectionFactory
.makeObject(PoolableConnectionFactory.java:184)
at org.apache.commons.pool.impl.GenericObjectPool
.borrowObject(Unknown Source)
[long stack trace continues...]
** END NESTED EXCEPTION **
Attempted reconnect 3 times. Giving up.
ERROR 2004-06-13 15:34:40,841
| RollerFactory:setRoller | Error instantiating
org.roller.business.hibernate.RollerImpl

You can probably guess the source of this problem. The Roller installation guide mentions that you should grant access to the MySQL database to the user Tomcat uses for the data source:

mysql> create database roller;
mysql> grant all on roller.* to scott identified by 'tiger';
mysql> grant all on roller.* to scott@localhost identified by 'tiger';

But since my hostname name is blogserver, apparently that is used when logging into MySQL, not localhost.

I fixed the problem by going back to MySQL and adding:

mysql> grant all on roller.* to tomcat-user@blogserver
identified by '[password]';

That allowed Tomcat to start the Roller webapp.

The second problem is mentioned as a bug in the 0.9.8.2 installation guide. I configured the login servlet to use MD5 encryption, as the documentatin suggested. And as the documentation says, the implementation of encryption is incomplete.

When you create a new user in the Roller main screen, it creates the user with a cleartext password. When you try to log in with that password, that's when your entered password gets encrypted and tries to compare it against the plain text version in the rolleruser database table. Whoops.

The fix is mentioned in the installation guide: Go in and change the cleartext password in the rolleruser table to the MD5 version, using the MySQL md5() function. Pretty clear. Pretty easy. Nice documentation.