What's the rationale behind the javax package? What goes into java and what into javax?
I know a lot of enterprise-y packages are in javax, but so is Swing, the new date and time api (JSR-310) and other J2SE packages.
Originally javax was intended to be for extensions, and sometimes things would be promoted out of javax into java.
One issue was Netscape (and probably IE) limiting classes that could be in the java package.
When Swing was set to "graduate" to java from javax there was sort of a mini-blow up because people realized that they would have to modify all of their imports. Given that backwards compatibility is one of the primary goals of Java they changed their mind.
At that point in time, at least for the community (maybe not for Sun) the whole point of javax was lost. So now we have some things in javax that probably should be in java... but aside from the people that chose the package names I don't know if anyone can figure out what the rationale is on a case-by-case basis.
I think it's a historical thing - if a package is introduced as an addition to an existing JRE, it comes in as javax. If it's first introduced as part of a JRE (like NIO was, I believe) then it comes in as java. Not sure why the new date and time API will end up as javax following this logic though... unless it will also be available separately as a library to work with earlier versions (which would be useful). Note from many years later: it (date and time API) actually ended up being in java after all.
I believe there are restrictions on the java package - I think classloaders are set up to only allow classes within java.* to be loaded from rt.jar or something similar. (There's certainly a check in ClassLoader.preDefineClass.)
EDIT: While an official explanation (the search orbfish suggested didn't yield one in the first page or so) is no doubt about "core" vs "extension", I still suspect that in many cases the decision for any particular package has an historical reason behind it too. Is java.beans really that "core" to Java, for example?
java packages are base, and javax packages are extensions.
Swing was an extension because AWT was the original UI API. Swing came afterwards, in version 1.1.
The javax namespace is usually (that's a loaded word) used for standard extensions, currently known as optional packages. The standard extensions are a subset of the non-core APIs; the other segment of the non-core APIs obviously called the non-standard extensions, occupying the namespaces like com.sun.* or com.ibm.. The core APIs take up the java. namespace.
Not everything in the Java API world starts off in core, which is why extensions are usually born out of JSR requests. They are eventually promoted to core based on 'wise counsel'.
The interest in this nomenclature, came out of a faux pas on Sun's part - extensions could have been promoted to core, i.e. moved from javax.* to java.* breaking the backward compatibility promise. Programmers cried hoarse, and better sense prevailed. This is why, the Swing API although part of the core, continues to remain in the javax.* namespace. And that is also how packages get promoted from extensions to core - they are simply made available for download as part of the JDK and JRE.
Javax used to be only for extensions. Yet later sun added it to the java libary forgetting to remove the x. Developers started making code with javax. Yet later on in time suns decided to change it to java. Developers didn't like the idea because they're code would be ruined... so javax was kept.
java.* packages are the core Java language packages, meaning that programmers using the Java language had to use them in order to make any worthwhile use of the java language.
javax.* packages are optional packages, which provides a standard, scalable way to make custom APIs available to all applications running on the Java platform.
Some packages like javax.swing were not included in java standard library at first. Sun company decided to consider them official and included them into the early versions of java as standard libraries or standard extensions.
By convention, all the standard extensions start with an X while they can get promoted to first-class over time like what happened for javax.swing.
All the javax packages were aimed to be experimental packages. By the time Swing was stable enough and ready to be moved to the java package there was too much code out there that they decided to leave it as it is to keep their commitment with backwards compatibility. This is explained in the book Learn Java in 21 days from the Sams editorial, written by Laura Lemay and Rogers Candedhead.
Related
Ten years ago I created, and have maintained, some commons/library jar files of helper classes specifically for cryptography in Java 8. Our organizations are FINALLY starting to update to Java 11 LTS, in which similar functionality has been added natively.
These commons are used across many groups in my company but as individual groups upgrade to Java 11+ JRE/JVMs, I would like to encourage them to use the new native classes vs. my libraries.
Is there a way to annotate/Javadoc-tag my classes/methods such that they only warn as deprecated when built with a Java 11+ JRE/JVM?
My classes still work perfectly fine in Java 11+, but I'd really like to encourage using the now native classes/methods. If depreciation is not the way to go, are there other annotation/Javadoc methods to discourage use via warning when used beyond a specific version of JRE/JVM?
There is no way to do that out of the box. I suggest you just include the explanation in the JavaDoc text.
Deprecation is overkill because it sounds like you have no intention of actually removing it. You just want to encourage users targeting a later version to use something else.
You could always write your own annotation and annotation processor, of course.
The compiler display warnings if you use Sun's proprietary Java classes. I'm of the opinion that it's generally a bad idea to use these classes. I read this somewhere. However, aside from the warnings are there any fundamental reasons why you should not use them?
Because they are internal APIs: they are subject to change in a undocumented or unsupported way and they are bound to a specific JRE/JDK (Sun in your case), limiting portability of your programs.
Try to avoid uses of such APIs, always prefer a public documented and specified class.
The JDK 6 Documentation includes a link titled Note About sun.* Packages. This is a document from the Java 1.2 docs, so references to sun.* should be treated as if they said com.sun.*
The most important points from it are:
The classes that Sun includes with the
Java 2 SDK, Standard Edition, fall
into package groups java.*, javax.*,
org.* and sun.*. All but the sun.*
packages are a standard part of the
Java platform and will be supported
into the future. In general, packages
such as sun.*, that are outside of the
Java platform, can be different across
OS platforms (Solaris, Windows, Linux,
Macintosh, etc.) and can change at any
time without notice with SDK versions
(1.2, 1.2.1, 1.2.3, etc). Programs
that contain direct calls to the sun.*
packages are not 100% Pure Java.
and
Each company that implements the Java
platform will do so in their own
private way. The classes in sun.* are
present in the SDK to support the Sun
implementation of the Java platform:
the sun.* classes are what make the
Java platform classes work "under the
covers" for the Sun Java 2 SDK. These
classes will not in general be present
on another vendor's Java platform. If
your Java program asks for a class
"sun.package.Foo" by name, it may fail
with ClassNotFoundError, and you will
have lost a major advantage of
developing in Java.
Try running your code with a non-Sun JVM and see what happens...
(Your code will fail with a ClassNotFound exception)
Yes, because nobody guarantees that these classes or API will be the same with the next Java release and I bet it's not guaranteed that those classes are available in Java versions from other vendors.
So you couple your code to special Java version and loose at least portability.
Sun's proprietary Java classes are part of their Java implementation not part of the Java API their use is undocumented and unsupported. Since they are internal they can be changed at any time for any reason that the team working the Sun JVM decides.
Also Sun's Java implementation is not the only one out there! Your code would not be able portable to JVMs from other vendors like Oracle/BEA and IBM.
Here is Oracle's answer: Why Developers Should Not Write Programs That Call 'sun' Packages
I recently had a case that showed a real-world problem you can hit when you use these classes: we had code that would not compile because a method it was using on a sun.* class simply did not exist in OpenJDK on Ubuntu. So I guess when using these classes you can no longer say things like 'this works with Java 5', because it will only work on a certain Java implementation.
I have a Java application that runs on BlackBerry (JDE 4.5). I want to port this application to Android, and be able to maintain the 2 applications simultaneously. I may also want to port this application to other Java platforms (J2ME ?).
I understand that a good part of the code will have to be specific to each platform (UI and other stuff). But I also feel that a lot of the code could (should) be shared (domain related classes).
What is the best way to achieve this, and what are the pitfalls to avoid?
I have been able so far to create a JAR with all my shared classes, that I have been able to integrate into my BlackBerry application (using preverify and rapc). But:
The JAR is a J2SE library. How can I make sure that it will run (or even compile) on BlackBerry, Android or J2ME?
I am also using a JSON library targeting J2ME (https://github.com/upictec/org.json.me/). This library seems to make use of some kind of preprocessing directives (CLDC, see https://github.com/upictec/org.json.me/blob/master/src/main/java/org/json/me/JSONObject.java#L392). How can I use (or convert) this library using the right preprocessing definitions?
This is likely to be difficult:
As you have already identified, the UI code will have to be different for each platform.
There are major differences between Java SE / Android and Java ME-based platforms. For example, ME doesn't have the Collections framework, or the java.io or java.nio stacks.
It is hard to predict from the information you've provided, but there's a fair chance that you'll spend more time fighting the platform dependencies than you are saving by sharing the code-base.
These days, the biggest stumbling block to sharing code this way is that the BlackBerry VM and Android VM both support different versions of the Java language. BlackBerry uses a subset of Java 1.3, Android uses a subset of Java 1.5. (As an aside, neither platform implements a Java VM, both use their own VMs. Java is used as the programming language. Java bytecodes must be transformed to the appropriate native VM format before they can run on the platform.)
The biggest difference you will find as a library implementor is that the BlackBerry lacks the things that were introduced in 1.5, very important things like generics and enums. Even worse, the Collections classes are missing from the BlackBerry. It is unfortunate, but that is the way it has been for a long time now.
This means that to be truly portable you have to write to the lowest-common denominator, which means using (very) old-style classes like Hashtable and Vector, not having generics, rolling your own enums (as in the 1st edition of Effective Java) and so on.
Or you build two libraries, a modern version for Android and a stripped-down version (with just the bare stuff you need) for the BlackBerry.
Hard to say what`s right for you.
Rather than prepackage your shared library, I would consider sharing the library project and having it as a dependency in your mobile applications' build process. That would allow you to share the code base, but have it built by the appropriate builders for your target devices. With a bit of IDE magic and some attention to detail, you should be able to pick up errors before anything is shipped out.
Alternatively, set up your library project to use two separate builders to pick up errors. That would allow cleaner distribution, but you may run into problems trying to convince your IDE to treat the project as being device specific in order to identify problem areas.
It would be likely that you would end up supporting the lowest common denominator device (cough Blackberry), and forgoing the additional facilities of the more extensive Java implementation on Android.
Unfortunately the answer will be one of experimentation. Try it and see what happens.
The article Porting Android code to BlackBerry has some good detail on how to work with code shared between the two platforms.
it will be very difficult to create shared library for blackberry and android.
if you want simple method, create your application as web app.
using
phonegap with jQtouch
I want to ship an open source Java project with its own JRE so that it doesn't depend on whether one is installed or not.I will have everything in one directory and my program will be the sole user of that jvm and class library.
As Java is now open source, I think I can now legally strip down the class library (rt.jar) to only classes I need. For example I don't use any SQL so I don't want to burden the download with classes in the java.SQL package.
This would be somewhat analogous to a linking step when an executable is built from libraries using only methods in the call tree that starts with the programs main().
Does anyone know what tools I might use to do that. Is it possible?
I think this is pretty much already done in Java 6 update 10.
It was planned for Java 7 but it shipped before.
It is the Java Kernel here are the details, I'm not quite sure if is what you need.
Here are the links:
http://tech.puredanger.com/java7/#kernel
http://weblogs.java.net/blog/chet/archive/2007/05/consumer_jre_le.html#JavaKernel
Here is other:
http://java.sun.com/javase/6/6u10faq.jsp#JKernel
There is a commercial tool that can legally strip down the Java class library.
We are stuck with Java2SE v1.4 till the end of 2010. That's really nasty, but we can't help it. What options do we have to use some of the new features already now? I can think of several ways like
changing the bytecode, e.g. using Retrotranslator or Retroweaver.
backport of libraries, e.g. Concurrent Backport, but this does not help for generics.
emulation of Java 5 features, e.g. checked Collections, Varargs with helper methods, etc.
changing source code by precompilation, stripping all 1.5 stuff before final compilation, e.g. using Declawer can do this.
I am most interested in very positive experience with it in production environments using Weblogic and "real" stuff.
Thanks for your answers. Here is the summary of all relevant answers and my own research.
Changing the bytecode: The Retros
This is done by the "retro"-tools: Retrotranslator, Retroweaver and JBossRetro. Retrotranslator seems to be the most mature
and active of them tool. These tools scan all classes and change the bytecode to remove Java 5 and 6 features. Many Java5 features are supported, some
by using 3rd party backport libraries. This option is most popular and there is some positive feedback from users. Experiments showed that it's working as
expected. See a short overview on developerworks.
Pro: You can develop entirely in Java 5, build modules and all kind of JARs. In the end you just transform all classes to Java 1.4 and package your EAR.
This is easily done with Retrotranslator's Maven integration (org.codehaus.mojo:retrotranslator-maven-plugin).
Con: Conservative environments do not allow changed bytecode to be deployed. The result of the retro-step is not visible to any coder and can't be approved.
The second problem is fear: There might be some cryptic production problem and the retro-code is another step that might be blamed for that. App-server vendors
might refuse help due to changed bytecode. So nobody wants to take responsibility to use it in production. As this is rather a policital than a technical
problem, so I see no solution. It has happened to us, so I was looking for further options :-(
Compiling Java5 to Java 1.4: jsr14
There is an unsupported option, javac -source 1.5 and -target jsr14 which compiles the Java5 source to valid Java 1.4 bytecode. Most features like
varargs or extended for loop are translated by the compiler anyway. Generics and annotations are stripped. Enums are not supported and I don't know
about autoboxing, as the valueOf methods were mostly introduced in Java5.
Con: Only byte code is translated, library usage is not changed. So you have to be careful not to use Java5 specific APIs (but could use Backports).
Further you have to build all modules at the same time, because for development time you propably want Java5 code with generic and annotation information.
So you have to build the entire project from scratch for Java 1.4 production.
Changing Source back to Java 1.4: Declawer
As answered in a related question, there is Declawer, a compiler extension, that works for generics and varargs, but not for enhanced for loop or
autoboxing. The generated source "is a little funky, but not too bad".
Pro: The generated source is available and can be reviewed. In worst case fixes can be made in this source. There is no "magic", because the source
is valid Java. Some people even use JAD (Java decompiler) to get the Java 1.4 source again. The output of Jad readable is readable if you compile with debug
information and don't use inner classes.
Con: Similar to -target jsr14, you need an extra step in the deployment. Same problems with libraries, too.
Changing Source back to Java 1.4: by hand
Several answers suggested doing it by hand. For an automatic, repeating build process this is of course not useful, but for one-time changes it's
reasonable. Just automate what is possible. Maybe look at Antlr for creating a home-grown conversion tool.
Backported Libraries:
The problem is, that Java5 also ships new libraries, that are not available in older JREs, see related question. Fortunately there are several
backported libraries that give you some functionality of Java5, but can't simulate language features, like generics.
Annotations, discussed at TSS
Concurrent
com.sun.net.httpserver (Java 6 to 5)
Gif writing (Java 6 to 5)
Start your own backport project ;-)
You might copy classes you need from the JDK or other libraries, but most likely they are related to other classes.
Emulating Java5 features in Java 1.4 code:
I was thinking about some things you might do to make your life easier and still staying with Java 1.4. The most important features are typesafe collections,
here are some ideas:
Instead of using generics you can create your own typesafe containers with some template.
Add a typesafe Iterator (which is no Iterator any more).
Add asList methods that allows 1,2,...,n arguments and an array of them (to simulate varargs).
Methods for varargs (converting 1,...,n arguments to arrays) and valueOf can be put in some helper class.
sourcecode precompilation, stripping
all 1.5 stuff before final compilation
and deployment. Are there any tools
which can do this?
Yes. They're called Retrotranslator or Retroweaver. Apart from Generics (which only exist for the compiler's sake anyway), you cannot simply "strip 1.5 stuff". Enums (and maybe also some other features) have to be replaced with functionally equivalent code. Which is exactly what those tools do.
You can code with JDK 1.5 features and target JDK 1.4 at compile time. See available Javac options. However, most libraries are now using JDK 1.5 code, so you'll be stuck with old libs.
It worth noting that while Java 1.4 has been EOL for some time. Java 5.0 will be EOL Oct 8th, 2009. If anyone is promising you Java 5.0 by 2010, I would ask why?!
To simulate annotations in java 1.4 you can use http://xdoclet.sourceforge.net/xdoclet/index.html