By:
Tags: ,
Category:
Comments Off

Autogenerating META-INF/services

If you've ever tried to use SPI, you're familiar with the hassle of maintaining the meta files necessary for the system to work.  Especially early on when a system is under heavy flux, keeping everything in sync can be a frustrating, error-fraught experience.  Many just plow through it.  Others turn to automated solutions and here is where the trouble begins.

If you're smart you look for a library and if you're lucky you find one that fits your needs.  For one reason or another, some choose to write their own library.  I know I've written one.  Kohsuke of hudson fame has written one.  If i were to use one today, I'd probably end up using this one.  I don't see it on the home page, but I seem to remember Reinier Zwitserloot suggesting that lombok had one in the works.  There are probably a dozen more out if one cared to dig deep enough (I don't).  But it shouldn't be this way.

So we have a situation where using a built-in feature to the java runtime is so awkward that we have all these competing, divergent solutions.  It's time for the JDK team to provide a native apt plugin to handle this natively.  Any feature that drives so many to build work arounds for it clearly is missing something.  In my opinion, this should be done by the JDK team and included in Java 8 at the latest.  If it takes filing a JSR to get it into Java 8, great.  I'd even lead it if necessary.  Build an amalgam of the solutions out.  Bundle an existing implement.  Build one from scratch.  Anything.  But please, give us something native so we can stop inventing the wheel over and over again.

To take it even a step further, I'd push for building a type database by default when building a jar.  Fantom has very nice way to tell the system, "Give me everything of type X."  This kind of "database" would be trivial to build during either the compilation or jar bundling phase.  But to be able to ask the JVM, give me references to all the classes implementing the interface FooBar would be an amazingly useful facility to have.  It would eliminate the need for jar/classpath scanning at start up for everything from simple plugin systems to full blown EE stacks.

So what do you think?  Is it too late for something like this in Java 8?  Or Java 7 update mumblemuble?  It'd be an amazing addition.

Meet Sofia

I've just released a pet project of mine on to maven central (provided the sync succeeds...) called sofia.  I won't go into too much detail here since there's a readme on the project page but I did want to share a few "meta" details about the whys and the wherefores.  As I mention in the readme, glassfish/grizzly use something similar and I found myself missing it in various different projects.  I also have other, larger projects I'm trying to get into a releasable state and this smaller project served as a nice dry run for those others.  It's small enough to manage and niche enough, probably, that I can get away with some churn as I figure out the maven release stuff.  

Which leads me to some meta-meta-details. The new(ish) policy for maven central publishing requires that you own the domain name for the coordinates you want to publish under.  For some large groups (apache.org, oracle.com, etc.) this makes a certain sense.  But for your average "garage" developer who just has a github repo and a great idea, requiring a registered domain name just creates a large burden on the part of developers/projects.  Finding a good project name is hard enough.  Finding a good project name that can be converted in to an available .com/.net/.org/.whatever can be unbelievably frustrating.  I find this policy to be incredibly short-sighted and, dare I say, lazy on the part of the managers of maven central.  Yes it avoids groupId conflicts and the need for arbitration should some domain owner come along.  But I'm not sure it's worth the headaches up front of finding available domain names before publishing artifacts.  Oh, well.  Done is done.

Please give sofia a spin and let me know what you think.  Fork it, patch it, file pull requests/issues.

Port Unification in GlassFish 3 – Part 4

In what should be the last entry in this series, we'll cover a late addition to port unification.  As I mentioned earlier, GlassFish 3.1 isn't adding support for port unification, we're simply introducing commands to make it accessible to people beside GlassFish hackers.  As often happens, though, once these commands were revealed to the wider community, one of the first questions was "How can I redirect to a different port?"  The short answer used to be "you can't."  But thanks to Ryan Lubke, now you can and we'll see how below. The steps are pretty similar to what we've seen so far.  There are 4 different use cases covered here.  HTTP->HTTPS (and vice versa), and redirecting on the same or a different port.  In the steps listed below, I've tried to reuse existing elements of the config as much as possible to avoid polluting the configuration file with too much cruft.  However, in some cases it was simpler to just create new structures because of some validation checks asadmin performs to try to prevent invalid configurations from cratering your instance.

###
### HttpToHttpsRedirectOnSamePort
###
asadmin create-protocol --securityenabled=false http-redirect
asadmin create-http-redirect --secure-redirect true http-redirect
asadmin create-protocol --securityenabled=false pu-protocol
asadmin create-protocol-finder --protocol pu-protocol --targetprotocol http-listener-2 --classname com.sun.grizzly.config.HttpProtocolFinder http-finder
asadmin create-protocol-finder --protocol pu-protocol --targetprotocol http-redirect --classname com.sun.grizzly.config.HttpProtocolFinder http-redirect
asadmin set configs.config.server-config.network-config.network-listeners.network-listener.http-listener-1.protocol=pu-protocol

###
### HttpToHttpsRedirectOnDifferentPort
###
asadmin create-protocol --securityenabled=false http-redirect
asadmin create-http-redirect --redirect-port 8181 --secure-redirect true http-redirect
asadmin create-protocol --securityenabled=false pu-protocol
asadmin create-protocol-finder --protocol pu-protocol --target-protocol http-listener-2 --classname com.sun.grizzly.config.HttpProtocolFinder http-finder
asadmin create-protocol-finder --protocol pu-protocol --target-protocol http-redirect --classname com.sun.grizzly.config.HttpProtocolFinder http-redirect
asadmin set configs.config.server-config.network-config.network-listeners.network-listener.http-listener-1.protocol=pu-protocol

###
### HttpsToHttpRedirectOnSamePort
###
asadmin create-protocol --securityenabled=true http-redirect
asadmin create-http-redirect --secure-redirect false http-redirect
asadmin create-ssl --certname s1as --type network-listener --ssl2enabled=false --ssl3enabled=false --tlsenabled=true --tlsrollbackenabled=true --clientauthenabled=false http-redirect
asadmin create-protocol --securityenabled=false pu-protocol
asadmin create-protocol-finder --protocol pu-protocol --targetprotocol http-listener-1 --classname com.sun.grizzly.config.HttpProtocolFinder http-finder
asadmin create-protocol-finder --protocol pu-protocol --targetprotocol http-redirect --classname com.sun.grizzly.config.HttpProtocolFinder http-redirect
asadmin set configs.config.server-config.network-config.network-listeners.network-listener.http-listener-2.protocol=pu-protocol
asadmin set configs.config.server-config.network-config.network-listeners.network-listener.http-listener-2.enabled=true

###
### HttpsToHttpRedirectOnDifferentPort
###
asadmin create-protocol --securityenabled=true http-redirect
asadmin create-http-redirect --redirect-port 8080 --secure-redirect false http-redirect
asadmin create-ssl --certname s1as --type network-listener --ssl2enabled=false --ssl3enabled=false --tlsenabled=true --tlsrollbackenabled=true --clientauthenabled=false http-redirect
asadmin create-protocol --securityenabled=false pu-protocol
asadmin create-protocol-finder --protocol pu-protocol --targetprotocol http-listener-1 --classname com.sun.grizzly.config.HttpProtocolFinder http-finder
asadmin create-protocol-finder --protocol pu-protocol --targetprotocol http-redirect --classname com.sun.grizzly.config.HttpProtocolFinder http-redirect
asadmin set configs.config.server-config.network-config.network-listeners.network-listener.http-listener-2.protocol=pu-protocol
asadmin set configs.config.server-config.network-config.network-listeners.network-listener.http-listener-2.enabled=true

A few of the options on the create-ssl commands you could probably remove if you'd like. I added them simply to make the created structures match the default ones to reduce any confusion and clutter while looking at the resulting domain.xml.

Pick the scenario you need and cut and paste the relevant part of the above script into your terminal window and let glassfish do the rest. You can verify your set up by using wget -S to request index.html at the end of whichever url you need and look at the header responses to make sure you're properly getting the relocation information. For example, if you're doing https -> http redirection on different ports, you'd do (and see) this:

wget -q -S --no-check-certificate https://localhost:8181

  HTTP/1.1 302 Moved Temporarily
  Location: http://localhost:8080/
  Connection:close
  Cache-control: private
  HTTP/1.1 200 OK
  Content-Type: text/html
  Content-Length: 5212
  Date: Mon, 30 Aug 2010 16:35:24 GMT
  Connection: Keep-Alive

There you go. Redirecting HTTPS on 8181 to HTTP on 8080. It's that easy. At this point I feel I should point out that redirect from secure to nonsecure connections is almost always a monumentally bad idea but I'm sure there are a handful of uses for it. Regardless, these 4 use cases should cover anything you might need. These steps require a nightly build of GlassFish 3.1 but if you're already using/experimenting with those builds, please try it out. Let us know if you have any issues on the users list and we'd be happy to help.