Replacing BrowserLauncher with BrowserLauncher2 - java

I am starting on an enhancement to an existing Java applet where I let the user hit a link in a menu item, and open a page in his/her default browser. Some of our deployed code is in Java 1.4, while the majority of it is in Java 5. This prevents me from using the Desktop API in Java 6. It looks like the easiest way to solve the problem is to integrate BrowserLauncher2 into the application.
The wrinkle is that the existing code includes an early version of BrowserLauncher.java (version 1.4b1 (Released June 20, 2001)). Unlike the original, BrowserLauncher2 is more than just one class. It appears to have a ton of enhancements of which I'd like to take advantage.
I think I will use the newer release for my needs, and just drop the references to the old version in the legacy code. I have a pretty good suite of existing unit tests on the old code, and will do some functional testing on the code where I make the swap.
Does anyone who has already been down the upgrade path from older versions of BrowserLauncher have any advice on potential gotchas?

Well, that's what you get for asking such an obscure question. Instead of letting an unanswered question sit abandoned, I'll share what I've learned.
The BrowserLauncher class in BrowserLauncher2 has deprecated the old static openURL(String) method. In addition, while the old method threw an IOException, the new one throws a different set of exceptions.
It's therefore necessary to rewrite your catch blocks, and is probably a good idea to convert static calls to openURL(String) into calls to methods on an actual BrowserLauncher object.
Given the improvements in BrowserLauncher2, however, it's probably worth it.

Related

Run simultaneously multiple versions of same feature

Context
Running multiple version of the same library seems to be a usual need and there are many questions for this when dealing with versioned jar dependencies.
However, I have another constraint here: my code is part of a rolling-release MOAB where code has no version. I cannot depend on a older version of a library from the MOAB.
The use case of that question is being able to load different versions of the same code at runtime for compatibility.
Eg: GET /my/api/call?compat_version=42
I have to be able to provide several compatibility versions (ie code from version x that have not been changed). This must be the actual code that was running when version x was the current/latest version and not any kind of retrocompatibility trick.
Naive solution
The "obvious" way seems to duplicate the code for each version. For instance by having per-version packages:
com.me.thing.v1
com.me.thing.v2
com.me.thing.v3
...
and dynamically loading the code from the associate package upon the provided compat_version parameter by whatever technique. Let's suppose for know that all those versions share a common interface (API).
Challenge
I'd like to challenge that and maybe find a better option than the naive solution.
Since using the exact code from version x is a prerequisite, I don't believe I can get rid of the copy-paste (but please, tell me I'm wrong).
What technique would you suggest as a simple (but not necessarily easy) and robust implementation? Reflection? Dependency injection?
Is there a "good" pattern for doing such things? Is there any literature on that?
This was already an old problem when Java was developed, hence Sun's emphasis on binary compatibility (which existed for Solaris of course as well). This is the original guarantee offered by the platform- that you can upgrade the bits underneath and applications will continue to work, unmodified.
The way to run legacy code in the JVM world is to run the full legacy application.
Many segregation architectures have of course been developed over the years and reached various levels of maturity- like OSGI and many others before it- but there are edge cases upon edge cases and many failure modes.
Do not futz with multiple code versions within a single JVM. It was never a design goal and in environments where it matters only leads to pain.

Was SourceToHTMLConverter.class removed from java 7?

Attempting to build some javadocs using the com.sun.tools.doclets. Existing code is referencing a class file
SourceToHTMLConverter.class
Found it in an older JRE
JRE\160_38\lib\tools.jar\com\sun\tools\doclets\internal\toolkit\util\
However all of the JRE7 that I have does not seem to contain this class. Does anyone know why?
That class isn't part of Java's public API. It's no longer part of the Java distribution. In general it's a very bad idea to rely on anything in the package com.sun, especially if it also includes internal in the package name. This is because they're not part of the public, documented API, and the developers make absolutely no promises about how much these classes will change from version to version.
If you rely on such classes, your code isn't guaranteed to be portable from one JVM to another (it may or may not run on IBM's JMV or on Android), or ever from one version to the next of the same JVM. They don't even promise not to change these out from under you between minor revisions.
As for your question about why it was removed: because they didn't feel the need to keep it anymore, so they got rid of it. Simple as that.
Don't use those classes. Stick to the public, documented API.

SO_KEEPALIVE on existing java application

I need to activate SO_KEEPALIVE on an existing commercial java application because my firewall drops the connections after some inactivity. I do not own the source code so i can't change it (it would be rather easy when i had the source, just adding socket.setKeepAlive(true) ). So i was looking for some alternatives:
first i tried to work with libkeepalive.so ( http://libkeepalive.sourceforge.net/ ), putting this in de LD_PRELOAD seems to work for things like telnet & nc, but when i use it with my jrockit jvm, this LD_PRELOAD is totally ignored and every socket object is still being created without SO_KEEPALIVE
then i tried to search on the OS level if there was an option to activate this SO_KEEPALIVE per default for all TCP connections: unfortunately on redhat 6 enterprise there isn't such an option, although i found one for freebsd (net.inet.tcp.always_keepalive)
patching the linux kernel for adding this feature was a big no for my sysadmin ;)
searching for any java command line argument was unsuccessful
so last option: patching the existing JVM's java.net.PlainSocketImpl by adding setOption(SocketOptions.SO_KEEPALIVE, Boolean.valueOf(true)); in the protected synchronized void create(boolean stream) method and putting it before rt.jar via -Xbootclasspath/p
This last option works so far, but i'am a bit frustrated because i had to change a JVM for this! Anyone knows other / better ways to deal with such a problem? Why isn't there another simple way to activate SO_KEEPALIVE per default on all (java) applications?
Last question: why doesn't the java API let you set the keepAlive on serverSockets objects? It's only possible on Socket objects but in fact it also works on serverSockets
I run over the same problem and wondered why libkeepalive does not work. After some investigation I found, that libkeepalive has some 'limitations' (maybe somebody would call them bugs).
Because of the strange license (it comes with GPL), I decided to start over. The result is the libdontdie.
You can find a small Java test program there that works with (at least) openjdk7.
It is possible to redefine existing bootstrap classes during runtime using a java agent (http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/package-summary.html) and ASM4 (http://asm.ow2.org/).
As you know the target class and method, all that is needed is to catch the return bytecode instruction of the relevant method and inject a method call before it.
This is one of the problems with commercial closed source software. If it doesn't work, your options are limited for fixing it. This is a COST of using closed source.
There is one obvious thing that you haven't tried yet.
Contact the support line for the product you are using and ask them to provide a solution for you. There may already be something in the product itself to solve this; e.g. some undocumented configuration option. Or they may be able to develop a custom workaround for your problem.
If customer support is unhelpful, you have a number of potential options:
You could attempt to reverse engineer the relevant part of the product (e.g. the place where it creates sockets), and figure out how to set "keepalive" by:
modifying one of their classes,
subclassing one of their classes, or
writing some kind of hook that uses reflection to dig out the socket objects from private variables, etcetera.
Reverse engineering could be a violation of your license agreement. However, if the reason you do it is to fix a problem in their code that makes it unusable for you, they would have a hard time convincing a court that what you were doing deserved to be punished. And the "court of public opinion" would most likely punish them if they tried that.
You could check your rights under your license agreement and relevant consumer protection law. Is the product "fit for use" if you can't get it to work for you?
You could threaten to cancel your support contract and stop using their product.
You could actually cancel your support contract and stop using their product. (And if you use a different product, prefer open source so that you don't get into the same bind all over again.)
The problems with your solution that "works" are:
You may have to repeat this every time you refresh your JVM.
It may interfere with other things in the application ... or other applications that use the patched JVM.
You can't redistribute this without violating your Oracle license ... unless you are using OpenJDK.
It is likely to make other folks who need to support your stuff nervous. (Understandably).
Last question: why doesn't the java API let you set the keepAlive on serverSockets objects?
You would need to ask the folks who designed the API. (Good luck with that!)
If you believe that this could and should be done, submit an RFE via the Java Bugs Database. Or better still, implement it yourself as patches to the latest OpenJDK codebase, and contribute the patch. Unlike your unnamed commercial product, Java is (basically) Open Source, and they welcome useful patches that improve the product.

Can I use runtime parameters to fix out of bad API calls in Java?

Not sure if this is the right spot to ask but I'm having a Java issue. I have some Java code that works in Java 6 but not in Java 7, the error is:
java.lang.IllegalStateException: This function should be called while holding treeLock
Using Java6 works but a few of our external users are running Java 7. I figured out the error was caused by a call to validateTree(), which works in java6 but in Java7 we need to call validate() . When I test it locally it works.
Here's my problem, I started working at a big corporate and they won't let us make any changes to the code until its been very throughly looked at(my working change is going to take affect in April 2013) but until then our users are getting annoyed. I'm not the best with Java and was wondering if there was a way I could pass a runtime parameters to have this changed? or is there anything I can do without touching the code base?
I'm embrassed to ask this question since it could be solved easily by just implementing the fix but any ideas or direction would be very helpful.
Update: I'm ideally looking for something that I can get support to put in the java runtime parameter that would change all validateTree() references to validate().
Can I use runtime parameters to fix out of bad API calls in Java?
As a general rule, no.
In a specific case, you could look at the source code of the relevant classes Java 7 version of the class library to see if there is a backwards compatibility property.
Assuming that you can't find a fix, you are kind of stuck. I'd suggest:
Recommend to your customers that they use Java 6 until a fix can be issued.
Discuss with your management whether they can make an exception to their policy to allow this problem to be fixed urgently.
If neither of those works, then the real problem is between your customers and your management. You've done as much as you can do. Leave it to "the higher ups" deal with it.
You might be interested in my Answer to a related SO Question which touches on the issue of why they made this "breaking" change. My take is that the change is to force people to fix a class of insidious, hard-to-reproduce application bugs that cause strange UI behaviour. And that is a good thing ... in the long term.
Based on that, you could make a stronger case for issuing an out-of-band fix. The fix to replace validateTree() calls with validate() calls is actually a necessary fix for all Java platforms, not just for Java 7.
I have some Java code that works in Java 6 but not in Java 7, ..
One 'workaround' (I can see this being unpopular) is:
Deploy the applet using JNLP and use a J2SE version attribute of 1.6*. See Java Web Start - Runtime Versioning for details.
Note it will only work embedded in a Plug-In 2 JRE (a sub-set of 1.6 JREs) & even then, the client will likely receive warnings about 'uses an earlier JRE'. If the applet can be launched free-floating using JWS, it will work (supposedly) with around 1.4.2+.
The fix it to change the applet code to be compatible with both JREs, as outlined by kleopatra's 2nd comment & the answer of Stephen C.
The object returned by Component#getTreeLock() is used as a thread sychronization monitor. The documented thread-safety of certain methods was deprecated in the transition from version 6 to 7; an example is seen here. In general, verify that Swing GUI objects are constructed and manipulated only on the event dispatch thread. One of the approaches cited here may be helpful in automating the search for violations.
if (System.getProperty("java.version").startsWith("1.6")) {
...
} else{
...
}

How to unit test for backward and forward compatibility?

I am working on developing an Plug-In API that uses Java serialization. The idea is similar to SmallTalk's system images. I was wondering how would to best to automate testing for whether changes I am making will break deserialization since some changes seem to be innocuous like adding a method to an interface that is implemented (as long as that is not called, otherwise it will result in a AbstractMethodException).
Yes, this is more for an experimental spike rather than production code so please do not suggest not using serialisation.
For backward compatibility of data, keep a lot of old messages in binary form, and see if you can still deserialize them with the new code.
For backward compatibility of code, you'll need some way of building your old code (e.g. one version per release) and testing that against data created from the newest version of the code. This is a slightly more challenging problem - you may want to build a small test jar on each appropriate release, and put that into source control at the same time to avoid having to build the same code again and again. Your tests would then try all the different jar files against the output of the new code.
To be honest, this all sounds like quite a lot of work for an experimental spike. For real work I'd just use protocol buffers of course :)

Categories