It's a simple tip and is not mentioned in Spring reference docs:
2008/09/03
Simple tip: Inject the nested class in Spring context
2008/04/24
Java7 new features: Personal View
Ref: The incoming Java 7 new features
All about just one thing: Java is becoming a platform and heavier and heavier version by version.Losing its very authentic and original simple beauty purely from language perspective.
Actually all the ideas are not quite new or very original innovative, they have already appeared in various libraries, components, frameworks and products. Sun is just collecting and refurbishing those ideas in name of JSR process then put them in its own JDK's shoes. Afterwards, MS will borrow the ideas but make it much easier to use in its monolithic .NET tools than diverted java tools world.
However, it's still a good news that the new changes on the heavier new "JAVA platform" will definitely drive the success of simpler and straightforward emerging dynamic 2G languages on top of Java, such as Groovy, which is just copying the same story Java replacing C/C++/Delphi 10 years ago!
Let's see.
2008/04/22
Incoming new Java 7 Featuers
Alex Miller has an excellent summarize of the new Java 7 Featuers:
Improved Modularity Support (superpackages)
1. superpackage example.bar.lib {
2.
3. // member packages
4. member package example.bar.lib;
5.
6. // member superpackages
7. member superpackage example.bar.lib.net, example.bar.lib.xml;
8.
9. // list of exported types
10. export example.bar.lib.Table;
11.
12. export superpackage example.bar.lib.net;
13. }
Java Module System
A distribution format and a repository for collections of Java code and related resources. It also defines the discovery, loading, and integrity mechanisms at runtime. Defines a new deployment archive called a JAM (Java Module). The Java Module is a JAR file that contains other JARs, resources, and metadata. JAMs can specify which portions of the module are public and which are hidden. JAMs can specify dependencies on other modules.
Java Kernel
Implement Java as a small kernel, then load the rest of the platform and libraries as needed, with the goal of reducing startup time, memory footprint, installation, etc. In the past this has also been referred to as “Java Browser Edition”.
NIO2
APIs for filesystem access, scalable asynchronous I/O operations, socket-channel binding and configuration, and multicast datagrams.
Date and Time API
A new and improved date and time API for Java. The main goal is to build upon the lessons learned from the first two APIs (Date and Calendar) in Java SE, providing a more advanced and comprehensive model for date and time manipulation.
Units and Quantities
one or more Java packages for the programmatic handling of physical quantities and their expression as numbers of units.
JCache API
Standardizes in process caching of Java objects in a way that allows an efficient implementation, and removes from the programmer the burden of implementing cache expiration, mutual exclusion, spooling, and cache consistency.
Concurrency Utilities
New kind of BlockingQueue called TransferQueue and a fine-grained parallel computation framework based on divide-and-conquer and work-stealing.
XQuery API
An API for executing XQuery calls and working with results. XQJ is to XQuery what JDBC is to SQL. At a glance, the XQJ API intentionally shares many high-level concepts from JDBC (DataSource, Connection, etc) but supports XQuery specific concepts such as static and dynamic phases, XML-oriented retrieval, etc.
Resource Consumption Management API
Allow for partitioning resources (constraints, reservations) among Java applications and for querying about resource availability (notifications). It will also provide means of exposing various kinds of resources. Example resources are heap memory size, CPU time, open JDBC connections, etc. The goal is to allow resources to be managed so that multiple applications might run simultaneously in a JVM and be given finite amounts of memory, cpu, etc. This JSR will build on top of JSR 121 Isolates.
Swing Application Framework
A simple application framework for Swing applications. It will define infrastructure common to most desktop applications. In so doing, Swing applications will be easier to create.
Beans Binding
An API that allows two properties of two beans to stay in sync. Formalizes an API for connecting JavaBeans.
Beans Validation
Define a meta-data model and API for JavaBeanTM validation based on annotations, with overrides and extended meta-data through the use of XML validation descriptors.
Java Media Components
Support for video to Java. It will initially address playback and ultimately will also cover capture and streaming. Video playback will provide support for both native players and a pure Java player.
JMX 2.0
Updates the JMX and JMX Remote APIs to improve usability of existing features and add new functionality such as annotations for ease of development, federated JMX servers, etc.
Web Services Connector for JMX
A connector for the JMX Remote API that uses Web Services to make JMX instrumentation available remotely. Clients do not have to be Java applications, but can be.
Javadoc Technology Update
New tags and generated Javadoc document representation aimed to increase readability, information richness, and make the Javadoc more approachable to developers learning and using the APIs.
Reified Generics
Currently, generics are implemented using erasure, which means that the generic type information is not available at runtime, which makes some kind of code hard to write. Generics were implemented this way to support backwards compatibility with older non-generic code. Reified generics would make the generic type information available at runtime, which would break legacy non-generic code. However, Neal Gafter has proposed making types reifiable only if specified, so as to not break backward compatibility.
Type Literals
1. Type<List<String>> x = List<String>.class;
Annotations on Java Types
enriches the Java annotation system. For example, it permits annotations to appear in more places than Java 6 permits; one example is generic type arguments (List<@NonNull Object>). These enhancements to the annotation system require minor, backward-compatible changes to the Java language and classfile format.
Type Inference
Constructor invocation can be changed from:
1. Map<String, List<String>> anagrams = new HashMap<String, List<String>>();
2. to
3. Map<String, List<String>> anagrams = new HashMap<>();
and explicit type references can now be inferred changing:
# timeWaitsFor(Collections.<Man>emptySet());
# to
# timeWaitsFor(Collections.emptySet());
Closures
A closure is a function that captures the bindings of free variables in its lexical context. Closures support passing functions around and make many anonymous inner class use cases easier to use. In addition, they support additional high-level programming abstractions.
Automatic Resource Block Management
1. // Start a block using two resources, which will automatically
2. // be cleaned up when the block exits scope
3. do (BufferedInputStream bis = ...; BufferedOutputStream bos = ...) {
4. ... // Perform action with bis and bos
5. }
Language level XML support
1. elt.appendChild(
2. <muppet>
3. <name>Kermit</name>
4. </muppet>);
JavaBean Property Support
1. public property String foo;
2. a->Foo = b->Foo;
BigDecimal operator support
Support for manipulating BigDecimal objects with arithmetic operators (just like other numeric primitives) instead of via method calls.
Strings in switch statements
# static boolean booleanFromString(String s) {
# switch(s) {
# case "true":
# return true;
# case "false":
# return false;
# }
# throw new IllegalArgumentException(s);
# }
Comparisons for Enums
1. boolean isRoyalty(Rank r) {
2. return rank >= Rank.JACK && rank != Rank.ACE;
3. }
Chained Invocation
1. class Factory {
2. void setSomething(Something something) { ... }
3. void setOther(Other other) { ... }
4. Thing result() { ... }
5. }
6.
7. Thing thing = new Factory()
8. .setSomething(something)
9. .setOther(other)
10. .result();
Extension methods
1. import static java.util.Collections.sort;
2. List<String> list = ...;
3. list.sort(); // looks like call to List.sort(), but really call to static Collections.sort().
Improved Catch Clause
# try {
# return klass.newInstance();
# } catch (InstantiationException | IllegalAccessException e) {
# throw new AssertionError(e);
# }
invokedynamic
Introduces a new bytecode invokedynamic for support of dynamic languages.
Tiered compilation
Tiered compilation uses a mix of the client (JIT) and server hot spot compilers - the client engine improves startup time by using JIT over interpreted and the server hot spot compiler gives better optimization for hot spots over time.
G1 Garbage Collector
G1 (for “garbage first”) is a single collector that divides the entire space into regions and allows a set of regions to be collected, rather than split the space into an arbitrary young and old generation. Sun intends to make this new collector the default in Java 7. (This applies only to the Sun JDK.)
More Script Engine
additional language interpreters to JSE. The JavaScript Rhino engine was added in Java 6. Leading candidates for Java 7 are: JRuby, Jython, and Beanshell.
2008/04/09
Will it Compile?
This small sample project uses two libraries, apache-log4j-1.2.15 from www.apache.org and jpos-1.6.0-r2465 from www.jpos.org. Both are latest version as of the date I write this blog - freshly downloaded. The jpos library comes with no pre-packaged distribution jar file, thus we used ant to build the jar file from it's source files and the build.xml.
Besides that, we have a source file of our own, A.java:
import org.apache.log4j.Logger;It does nothing except log a message at trace level. The question here is, will this compile?
/**
* A.java
*/
public class A {
static Logger logger = Logger.getLogger(A.class);
public static void main(String[] args){
logger.trace("blah blah");
}
}
The answer? Yes and No. Depends how you compile it.
To demonstrate the problem, we'll just try to use the command line to compile it, instead of using apache-ant or any IDE. It helps us to identify the root of the problem. (Assume lib is where you put your libraries, also we have two version of j2sdk installed, 1.4.2_16 under c:\j2sdk1.4.2_16, 1.5.0_14 under c:\jdk1.5.0_14.)
c:\j2sdk1.4.2_16\bin\javac -classpath lib\apache-log4j-1.2.15\log4j-1.2.15.jar;lib\jpos-1.6.0-r2465\build\jpos.jar src\*.javaNow swap the classpath entries and try it again:
Result: Compile success.
c:\jdk1.5.0_14\bin\javac -classpath lib\apache-log4j-1.2.15\log4j-1.2.15.jar;lib\jpos-1.6.0-r2465\build\jpos.jar src\*.java
Result: Compile Success.
c:\j2sdk1.4.2_16\bin\javac -classpath lib\jpos-1.6.0-r2465\build\jpos.jar;lib\apache-log4j-1.2.15\log4j-1.2.15.jar src\*.javaSurprise, huh? Try it yourself.
Result: Compile success.
c:\jdk1.5.0_14\bin\javac -classpath lib\jpos-1.6.0-r2465\build\jpos.jar;lib\apache-log4j-1.2.15\log4j-1.2.15.jar src\*.java
Result:
src\A.java:12: cannot find symbol
symbol : method trace(java.lang.String)
location: class org.apache.log4j.Logger
logger.trace("blah blah");
^
1 error
Everything comes with a reason. Since jdk1.5, both java and javac recurse the manifest classpath of a jar on the java classpath. Looking into jpos.jar, we found that its manifest file says to use log4j-1.2.8.jar and the trace method wasn't supported till log4j-1.2.12 or above.
jpos.jar manifest file entry:
Class-Path: lib/bsh-2.0b4.jar lib/commons-cli.jar lib/jdbm-1.0.jar lib
/jdom-1.0.jar lib/log4j-1.2.8.jar lib/mx4j-impl.jar lib/mx4j-jmx.jar
lib/mx4j-tools.jar lib/classes
That's the reason why the compilation error happened - javac was instructed to used log4j-1.2.8.jar come with the jpos distribution, instead of the the 1.2.15 that we want it to use.
Conclusion? Well, I don't know what to say here, but this looks something similiar to the windows DLL hell problem. And it was called DLL 'Hell' for a reason.
Further reading: How classes are found?
2008/04/02
TypeSafe Enum and equals()
At first it seems a No Brainer Problem
If you assign the same pre-initialized instance of the same class to two variables, do they always equal to each other? Note that this is the typical pre-jdk1.5 typesafe enum pattern.
public class ReagentType implements Serializable{Sounds like a no brainer. The answer obviously should be yes. checkEquals() method will print out "true". Always. That is, in an ideal world.
private static final String PROTEIN_TYPE = "PROTEIN";
// more types here
public ReagentType PROTEIN = new ReagentType(PROTEIN_TYPE);
// more pre-initialized instance here
private String type;
public String getType(){
return this.type;
}
private ReagentType(String type){
this.type = type;
}
public void checkEquals(ReagentType a, ReagentType b){
System.out.println(a.equals(b));
}
public static void main(String[] args){
ReagentType a = ReagentType.PROTEIN;
ReagentType b = ReagentType.PROTEIN;
checkEquals(a,b);
}
}
However...
In real world, assuming a & b are both assigned to ReagentType.PROTEIN, in many cases we will see checkEquals() method prints out "false". The standard java equals() compares object identity, which is nothing but the memory location of the object instance, which will most certainly fail in a real world deployment environment.
- Consider Distributed Computing. Either a or b has travelled the wire before checkEquals() method gets it, a.equals(b) is false. They resides in two different memory location.
- Even in a single server, after serializable/deserialization, it's guranteed that an object will have a different memory location. a equals() the serialize/deserialized copy of itself, is false.
- Consider an EJB invoking a method in another EJB, if they're packaged in different deployment JARs and both contains the ReagentType class, depends how the class loading mechanism in app-server works, there might exists many pre-initialized instance of the REAGENT object and they have different memory location.
Oh yeah, there's always solutions. For one, implement the equals() method properly.
public boolean equals(Object obj){For two, for those who're not big fan of the typesafe enum pattern, they can simply fall back to the good old set-of-static-primitive-values enumeration.
if (obj!=null && obj instanceof ReagentType){
return getType().equals( ((ReagentType)obj).getType());
} else {
return false;
}
}
// hashcode() methods omitted here
A note is that while implementation of the RMI readResolve() method might seem to solve this problem, it actually will fail in scenario 3, since the container may decide not to perform serialize/deserialize if the EJBs resides in the same server. However the readResolve() solution should be safe in non-EJB situation where the class loading situation is simpler.
2008/03/31
Java Constructor Invocation and Instance Variable Initialization
This is a tricky one:
What the println in the main() method will output? null? "property"?
abstract public class BasePayment {
public BasePayment(){
setFakeValue();
}
abstract public void setFakeValue();
}
public final class Payment extends BasePayment{
private String property = null;
public Payment(){
super();
System.out.println("after super(): " + this.getProperty());
}
public String getProperty() {
return property;
}
public void setFakeValue() {
System.out.println("Calling setFakeValue()");
this.property = "property";
System.out.println("After setFakeValue(), property: " + this.getProperty());
}
public static void main(String[] args) throws Exception{
Payment p = new Payment();
System.out.println("'new'ed a Payment, property value: " + p.getProperty());
}
}
It has something to do whether java will initialize the instance variable first, or will invoke the constructor of the super class first. The behaviour is fully documented (it better be!) at http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.8.7.1
And yes, the output is 'null'.
2007/12/11
Watch out for java SimpleDateFormat
Look at this code, what it will come out?
import java.text.SimpleDateFormat; public class Test{ |
The result is:
247625706-07-03 |
Is this what you expected? You thought it would have thrown an exception of invalid format of text you passed in.
It's very common for a developer do date and time data conversion from text and vice versa in different format. Will it breach your boundary validation if you purely rely on this stupid SimpleDateFormat class?
Work around so far like:
import java.text.SimpleDateFormat; public class Test{ |
Ugly codes, but works.
How many online Web systems relying on Java and J2EE have those codes?
2007/10/25
Singleton vs. Multiton & Synchronization
1. The classic java singleton synchronization problem
public class Singleton{
private static Singleton instance;
/** Prevents instantiating by other classes. */
private Singleton(){}
public static synchronized Singleton getInstance()
if (instance == null){
instance = new Singleton();
}
return instance;
}
}
2. The traditional solution using a static variable
public class Singleton {
private final static Singleton instance = new Singleton();
/** Prevents instantiating by other classes. */
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
3. The Classic synchronized Multiton
public class Multiton{
private static final HashMap<Object, Multiton> instances = new HashMap<Object, Multiton>();
private Multiton(){}
public static Multiton getInstance(Object key){
synchronized (instances) {
// Our "per key" singleton
Multiton instance;
if ((instance = instances.get(key)) == null) {
// Lazily create instance and add it to the map
instance = new Multiton();
instances.put(key, instance);
}
return instance;
}
}
}
4. The double-checked locking solution
public class Multiton {
private static final HashMap<Object, Multiton> instances = new HashMap<Object, Multiton>();
public static Multiton getInstance(Object key) {
// Our "per key" singleton
Multiton instance;
if ((instance = instances.get(key)) == null){
synchronized(instances){
if ((instance = instances.get(key)) == null){
instance = new Multiton();
instances.put(key, instance);
}
}
}
return instance;
}
}
5. An alternative solution: Using the Java 5 ConcurrentMap
public class Multiton {
private static final ConcurrentMap<Object, Multiton> instances = new ConcurrentHashMap<Object, Multiton>();
public static Multiton getInstance(Object key) {
// Our "per key" singleton
if (instances.get(key) == null){
// Lazily create instance and try to add it to the map
Multiton instance = new Multiton();
instances.putIfAbsent(key, instance);
}
return instances.get(key);
}
}
6. Afterwords
Well well... why another J2EE blog? I benefited from other people's technical blogs, and guess what, it's a good idea to contribute some of my works too. Hope it's helpful and useful, to all of your folks.