Adventures With Java URL Handler
Have you ever wanted the native URL Java object to support your personal protocol? Well me neither, until I came across it, and then all I could think was a "bill://" protocol would be pretty neat. Not sure what it would do, but just nice seeing my name in a URL. Although honestly, I had a third party library that had limited options to fetch a resource and this one of them, so I needed to play with this.
Option 1 - Set the System Level URLStreamHandlerFactory
You create an instance of URLStreamHandlerFactory and then issue a static method call on the URL object to register it. However, you can do this only once. Thus, I don't recommend this option.
Moreover, I tinkered with it after running into an issue with option 2, and found it was already register in my small application. I didn't really dive into what already used it. It may have been Tomcat, spring boot, or something else. But even if I resolved that, maybe in the future, there'd be another library that I needed that took the short cut of registering this one way. And option 2 isn't really that much work for much more extensibility.
Option 2 - Add a Handler to the the URL Packages property
You create a class named Handler that extends URLStreamHandler. Put that in a package named after the protocol. Then add the parent package to java.protocol.handler.pkgs system property. The value is | separate to support multiple packages. There's a lot of good references out there, so I won't share code and just point to elsewhere. Here's a nice stackoverflow question that shows both ways. The property way even has a nice spiffy method for auto-appending to the property value. And here's a good in depth write up in the Learning Java book.
One tip I'll mention on the registering, you can define a spring bean in the package whose sole purpose is to register the Handler. Then you can auto scan that package. Kind of gives you that decoupling of not worrying about what all your utilities are doing in your main app code.
I was able to achieve my lifetime (ok maybe hour long) ambition of having a "bill://" protocol. However, this was a classic doesn't behave the same on the local computer as on the deployed server. I was doing a spring boot application with Tomcat. When you run local in Eclipse, all the class binaries are exploded and right there on the native classpath. Thus, any regular ClassLoader can get at them. But when you bundle it into the typical spring boot JAR, all the classes are in specially placed JARs and must load through the spring boot loader. The built-in URL handler searcher won't find those. However, I didn't pursue further to see if there was a way around this.
One work around is that spring boot maven plugin will let you exclude packages from the JAR, so you could exclude and add another way to the classpath. Of course, then you have to handle two JARs. Another thought - you may able to shade the JAR in somehow. As I said, I didn't pursue it further to see if there was a way to still hook, but just mentioning those thoughts if it is of help to anyone.
Option 3 - Don't Register and manually supply the Handler to the URL class
There is a streamlined option, depending on your need. As in the last option, still implement the Handler, but don't bother registering it. The URL has constructors that can take an explicit handler. Thus, even without doing option 1 or 2, you can still construct the URL with the Handler of your dreams. Of course, this only works if you can construct the URL and supply to whatever interface you need to give it too.