|
|
|||||||||||
Graham Hamilton's BlogJ2EE ArchivesHurtling Towards JavaOne...Posted by kgh on May 05, 2006 at 09:13 AM | Permalink | Comments (3)I'm in my normal ten-days-to-JavaOne panic phase, but the various pieces are starting to come together. Bill Shannon are I are finalizing the slides for the JavaOne 2006 Technical General Session at 12:15 on Tuesday the 16th. This is the session where we provide the overall roadmaps for the Java SE and EE platforms, to try to give people a context for the many individual technical sessions and BOFs that follow. As usual we're panicking over having far too much material for the available time. We'll be covering Mustang and Java EE 5, but we'll also have a section towards the end looking forward to Dolphin and other new technologies. This year we're including a range of demos, so you can see the reality, both of the "Now and How" for Java EE 5 and for some of the future ideas. So grab your box lunch and bring it into the keynote room for our 12:15 start! The program of general sessions start with the Tuesday morning Sun executive keynote with Jonathan Schwartz and Jeff Jackson. The Thursday morning keynote from Erich Gamma and John Wiegand of IBM should be particularly interesting: it promises many insights from their Eclipse experiences. And on Friday, Scott and James will show us the latest, greatest, craziest, most fun Java innovations! There are, of course, a vast range of Technical Sessions and BOFs covering all kinds of key Java technologies. but, in addition to the sessions and BOFs, I wanted to plug a few associated community events:
Now I have to run - Chet has just got me some new benchmark data to expose (!) concrete numbers for the benefits of the famous Gray Rect UI fix...
AOP: Madness and SanityPosted by kgh on March 08, 2006 at 11:50 AM | Permalink | Comments (18)When people ask me "what do you think of AOP?", I tend to flinch, because the term AOP has come to be used to cover a very wide range of different uses, some of which I think are Totally Wonderful and some of which I think are Thoroughly Bad Ideas. Here's a brief survey of the range and of my reactions. Quick Overview of AOP The core concept of Aspect Oriented Programming is that there are common issues that apply across a range of otherwise unrelated classes. In AOP, these common issues are often referred to as "cross cutting" concerns because they cut across the normal inheritance class structure. The goal of AOP is to allow cross cutting concerns to be addressed by applying some common logic (or "aspects") to a set of classes, without having to individually modify the source code for each class. The idea of wrapping extra functionality around target classes will be very familiar to Java EE developers. Java EE containers typically add extra functionality and semantics to target classes by intercepting incoming calls to target objects. For example, an EJB container can add transactional semantics to a target class. (Yes, J2EE has been using AOP all along!) Java Language Principles The Java language has been designed and evolved with certain specific underlying principles in mind. We have put great emphasis on source code readability. As far as possible we have tried to follow the principle that "what you get is what you see". We have worked to maintain a clear and consistent base semantic model and to avoid language constructs that might undermine source code readability. People should be able to quickly read Java source code and then reliably understand what that Java source code does. That meaning should be independent of the particular compilers, tools, or runtime environments that are used. Now, we aren't ivory tower philosophers. We want a Java language that is productive for writing and maintaining large applications. So there will always be a trade-off between principles and pragmatics. However, in looking at the success and popularity of the Java language, much of it does seem to derive from these core principles. They seem to have worked well and to be worth maintaining and protecting. The Good: Container Based AOP One use of AOP is based on running objects within containers. These objects can only be accessed via their container. The container can intercept incoming calls and add additional semantics. An example of this approach is the way that Java EE containers can add transactional semantics to EJB components by intercepting incoming calls. In general this use of AOP seems fairly benign. The source code within the target objects is all behaving exactly as a developer should expect. Developers do need to be aware that they are accessing the objects indirectly and that the container may perform extra tasks. However the idea of operating through a level of indirection is a fairly normal Java concept. Now, within this general use case, there are probably a range of good and bad uses. Uses of container intervention such as adding transactional semantics in EJB, or adding logging, or adding extra security checks seem very reasonable. The Bad: Modifying Language Semantics Some uses of AOP rely on using runtime mechanisms to modify semantics that are specified by the Java Language Specification (JLS). For example, side files might specify that various modifications are to be made to target classes to invoke additional code when various operations are performed. Some uses of AOP allow extra code to be invoked when fields are accessed or when methods are called. The JLS carefully specifies the precise semantics of the Java language. For example, it precisely specifies the behavior that occurs when fields are accessed and it precisely specifies the rules by which one method may call another, including the cases when the call may proceed through other code as well as the cases when it must proceed directly from caller to callee. Developers should be able to rely on these semantics when they are reading source code. To take an extreme example, if a developer has written a statement "a = b;" then they should be able to rely on the value of the field "b" being assigned to the field "a", with no side effects. Some AOP toolkits allow arbitrary extra code to be executed when this statement runs, so that there can be arbitrary extra side effects as part of this assignment or even so that an arbitrary different value may be assigned to "a". Yikes! Similarly, some uses of AOP permit extra code to be inserted on a method call from one method to another, even when the JLS clearly specifies that that method call will occur directly. This enables arbitrary extra code to be executed, with potentially arbitrary side effects, in situations where a Java developer should expect there will be no side effects. This is the kind of arbitrary intervention that I think quickly races across the boundary line to insanity. (And I think most serious AOP proponents would agree.) I don't want the fundamental behavior of a chunk of source code being changed by someone magically reaching in and changing the code's meaning from the outside. That seems like a really bad idea! The core problem with these approaches is that if someone relies on techniques like these in writing their code, then other developers will no longer be able to understand that source code, because it has been developed to rely on side effects that are both at odds with the Java language definition and which are magically applied from somewhere outside the source file. You should not need to have global knowledge of a whole environment in order to understand some local fragments of code. Overall, using AOP to modify the meaning of the Java language seems like a really bad way to go. The New: Java Language Annotations In J2SE 5.0, the concept of annotations was added to the Java language. In many ways, annotations were designed to meet similar goals to AOP. The concept of annotations is that developers may apply special markers to target method, fields, or classes in order to designate that they should be processed specially by tools and/or runtime libraries. Now, annotations are not allowed to modify the behavior defined in the Java Language Specification. Within a source file that contains annotations, at runtime all the source code must execute exactly as defined by the JLS. That was a deliberate choice - we don't want annotations to become a way of defining arbitrary magic behavior within normal Java code. However, the annotations may cause changes to the overall behavior of the program, for example by directing a container to apply special behavior when forwarding calls into a target class. For me, one big benefit of annotations over classic AOP is that annotations are clearly visible in source code. So if you are reading an application you can clearly see which specific annotations are affecting the code. That readability advantage normally seems to outweigh the AOP advantage of being able to apply new semantics silently without modifying the affected class. My sense is that many use cases that were initially considered for use with AOP can now be better solved by the use of annotations. That is part of what is happening with the extensive use of annotations in Java EE 5. Conclusion The use of container based AOP seems to provide a reasonable mechanism for supporting AOP "cross cutting concerns" within Java environments, without breaking developers' expectations of how Java source code behaves. Similarly, Java language annotations appear to provide a convenient mechanism for supporting some of the use cases originally targeted by AOP. However, I think AOP quickly drifts from good to evil when it starts being used to mutate the meaning of source code or to otherwise modify what people can and should expect from Java source code. So, yes, I am a fan of AOP. But of a sane, restrained AOP!
Raving about Java EE 5Posted by kgh on February 21, 2006 at 09:52 AM | Permalink | Comments (6)Java EE 5 went into Beta today. I've been raving at people inside of Sun about how important this is. I think Java EE 5 will be by far the biggest developer event of 2006. I love what we've accomplished in Tiger and Mustang, but Java EE 5 brings a much deeper and more important set of changes:
If you've been tracking J2EE, then you probably know that J2EE has pretty consistently conquered the high ground on functionality, stability, scalability, performance, flexibility, deployment, support and many other topics. So given all this abundance of riches, why do we need to do a major upgrade? Well, in stepping back and surveying J2EE 1.4, we realized that the power, richness and flexibility had come with a significant price tag. You can do anything in J2EE, but doing common tasks can involve a lot of boilerplate and a lot of unnecessary concepts. We allow lots of options, which is good: but we often require you to specify lots of options for even simple cases, which is bad. My very favorite ugliness (of which I am one of the prime perpetrators!) is the boilerplate for getting an EJB reference: Context initial = new InitialContext();
Context myEnv = (Context)initial.lookup("java:comp/env");
Object objref = myEnv.lookup("ejb/SimpleConverter");
ConverterHome home = (ConverterHome) PortableRemoteObject.narrow(
objref, ConverterHome.class);
Converter currencyConverter = home.create();
Yikes! What is all that code doing? Two casts and a PortableRemoteObject.narrow ? So we realized that the big challenge was to greatly simplify the Java EE development model so that developers could use the power of Java EE, but avoid the complexity and the boilerplate. This was a key motivation behind a major Ease-of-Development initiative that we ran across J2SE 5.0 and Java EE 5. For Java EE 5 we had some wide ranging goals:
All of this while still offering full binary and source compatibility. And while also still allowing people to use all the fancy bells and whistles when they need them. Including the full glories of deployment descriptors! One of the key early decisions was to move to a more declarative programming model. Rather than requiring that people programmatically code up behavior, we wanted to allow people to specify behavior in some kind of declarative style, so that tools and libraries could recognize your intent and take care of the programmatic actions for you. But at the same time we wanted to ge away from complex XML side files or obscure naming patterns as the way of specifying behavior. We wanted to allow both simple declarative coding and also return to an emphasis on truth-in-source-code. These various factor led to the decision to develop a new Java language feature annotations that would allow API designers to create targeted annotation types and then allow developers to easily use those annotation types to declaratively specify behavior, which will then be implemented by tools and libraries. To illustrate this, let's look at how my earlier six lines of EJB reference code from J2EE 1.4 would appear in Java EE 5: @EJB Converter currencyConverter; That's it. We are now using the @EJB annotation to declaratively specify that the field "currencyConverter" should be initialized to contain a reference to a Converter EJB, obtained from the default provider. When the Java EE container initializes our object it will use this information to fill in the field for us. Ha! Annotations have been a big win. They are succeeding in allowing major simplifications of both the Web Services model (JAX-WS) and the core EJB model. To show that, let's start with a minimal Plain Old Java Object: public class Hello {
public String sayHello(String param) {
return “Hello “ + param;
}
}
Now let's turn it into a Web Service, by adding an @WebService annotation: import javax.jws.WebService;
@WebService
public class Hello {
public String sayHello(String param) {
return “Hello “ + param;
}
}
Gee, that was easy. Now let's make it into an EJB. In this case we'll make it a stateless session bean by using the @Stateless annotation: import javax.jws.WebService;
import javax.ejb.Stateless;
@WebService
@Stateless
public class Hello {
public String sayHello(String param) {
return “Hello “ + param;
}
}
I love annotations. They change everything. Yes, as Java developers we do need to learn the new annotation lifestyle. When we read code we need to watch out for use of annotations and understand what that will mean. But the annotations are there in the source code, they are readable, and they sure simplify a lot of tasks. As well as simplifying Web Service creation and EJBs, annotations also support the new and greatly simplified Java Persistence Model, which provides a lightweight Object-Relational Mapping for mapping between in-memory Java objects and on-disk database tables. (Java Persistence is being delivered as part of Java EE 5, but it will also be made available as an add-on for use with Java SE.) There is a lot more in Java EE 5, including JSP 2.1, Servlets 2.5, JSF 1.2, JAXB 2.0, JAX-WS 2.0, StAX, and many smaller spec updates. There has been a lot of great work here, based on cooperation from many individuals across a wide range of companies working together through the JCP. The official Java EE 5 Beta Bits are available at java.sun.com/javaee/5/downloads. However, bear in mind that the Reference Implementation for Java EE 5 is being developed in open source at the GlassFish Project and you can see the raw development and get the regular nightly builds there. And if you want, you can participate in building it! For more on the Java EE 5 Beta, check out some of the other Java EE 5 blogs an The Aquarium. 2006 looks like being a good year for Java. Mustang looks like being a great update for Java SE - we went to Mustang Beta last week and we've already had a lot of positive responses from the Mustang early access snapshots. But Java EE 5 looks like it is on track to be the really Big Winner.
My Favorite (Dead) Java BoilerplatePosted by kgh on November 13, 2005 at 04:03 PM | Permalink | Comments (31)In the Java platform we have tended to focus on adding lots of power and flexibility. That's great, but sometimes that power and flexibility can get in the way of doing common tasks. As part of the Ease-of-Development initiative we have been focusing on simplifying common tasks and getting rid of unnecessary boilerplate code. Here are my five of my favorite cleanups so far: #1: Opening a Text File In JDK 1.1 to 1.4, in order to open a simple text output file you needed to do: FileWriter fout = new FileWriter("fred.txt");
BufferedWriter bout = new BufferedWriter(fout);
PrintWriter pout = new PrintWriter(bout);
Say what? Why are we having to type three "new"s in order to do what should be a simple operation? In Tiger we have finally added direct support for the common case and now you can do: PrintWriter pout = new PrintWriter("fred.txt");
This is an interesting example of a common glitch in our thinking. In the Java platform we often like to provide lots of well designed, well separated components that can be plugged together in interesting ways. In fact some people might argue be that the design is cleaner if the PrintWriter class doesn't know anything about files. Well, personally, I don't think so. I think it is good to provide clean, well separated components, but we also need to provide simple shortcuts to support the most common use cases. #2: Avoiding the Content Pane Pain In JDK 1.1 to 1.4, if you wanted to add a Swing GUI component to a container you simply said container.add(component). Well, yes, except that if the container happened to be a JFrame you would get a helpful runtime exception saying that you ought to be saying frame.getContentPane().add(component); Umm, say what? Rather than raising the exception, couldn't the JFrame.add method itself call JFrame.getContentPane().add()? Yes it could. And in Tiger it does. Now you can just call add, as you would with any other container object. frame.add(component); This only saves a few keystrokes, so is this really a big deal? Yes. The real saving is that you can avoid having to learn a whole new unnecessary concept. The reason that the JFrame.add method originally threw an exception was because JFrames actually support three different panes (content, glass and root), and it was considered important to educate developers about those choices. Well, I've written various Swing applications over the years and I've never actually found the need to exploit the various different panes. The old behavior of JFrame.add forced me to go away and learn about panes. And that was distracting and unhelpful. The lesson here is that (once again) it is normally better to provide simple sensible defaults and to avoid forcing people to learn about complex options. #3: Self Registering JDBC Drivers Since JDK 1.1, in order to load a JDBC driver, you needed to do: Class.forName("com.fred.FredDriver");
Connection con = DriverManager.getConnection("jdbc:fred:fredsite.com");
Umm, what exactly is that Class.forName doing there?
This one is my fault. Back in the early days of JDBC, we needed a way
for the JDBC DriverManager to locate drivers. We arranged that newly
loaded driver classes would register with the
DriverManager. And then we asked that developers call
"Class.forName" to force the driver class to be loaded.
Sigh. This is an ugly wart. I'm happy to report that this one is going away as part of JDBC 4.0 in Mustang. The JSR-221 Expert Group is adding a new mechanism so that the JDBC DriverManager can locate and load driver classes without the need for developers to explicitly type Class.forName. So you will be able to just do the obvious: Connection con = DriverManager.getConnection("jdbc:fred:fredsite.com");
#4: Locating Resources in J2EE In J2EE 1.4, if you wanted to locate a reference to a remote EJB you needed to type: Context context = new InitialContext();
Object obj = context.lookup("fred");
FredHome fred = (FredHome) PortableRemoteObject.narrow(obj, FredHome.class);
Yikes. What on earth is going on with that PortableRemoteObject.narrow? I have to confess that I'm one of the prime culprits here and, given some of the constraints, it may have been unavoidable. But I think this one definitely does win "Ugly Boilerplate of the Year". As part of Java EE 5, there are now specific mechanisms for dependency injection, so you can now replace that code with a simple annotated field definition: @Resource FredHome fred; And then the Java EE runtimes will take care of locating the resource, doing the "narrow" for you and injecting the resource object into your field. By default the resource name is inferred from the field name and the type is inferred from the field type. This is an example of using JSR-175 annotations to restructure how we handle a common task so that it can become much simpler. I'm very excited with what is happening with annotations as part of Java EE 5 - I think it is allowing us to greatly simplify Java EE programming. And I'd like to find more ways to use annotations in Java SE, too. #5: Iterating over Collections My last example is from Tiger. We've all been used to typing some standard boilerplate for iterating over collections, such as: Vector<Wombat> v = getWombats();
Enumeration<Wombat> e = v.elements();
while (e.hasMoreElements()) {
Wombat w = e.nextElement();
...
}
Josh Bloch successfully argued for a language change to make it easier to iterate over both collections and arrays, so now in Tiger we can do: Vector<Wombat> v = getWombats();
for (Wombat w : v) {
...
}
We all knew this would be useful, but I have been really surprised by how much I have enjoyed using it, for both arrays and collections. This has turned into one of my favorite Tiger features. The resulting code is distinctly easier to read, partly because we have managed to eliminate an unnecessary local variable. This is an example of fixing a boilerplate problem we barely realized we had. I'd like to find a few more things like this! To be continued... I'll continue this topic in my next blog.
Slides for JavaOne Technical KeynotePosted by kgh on July 10, 2005 at 05:31 PM | Permalink | Comments (6)Here are the PDF slides for the JavaOne 2005 Technical Keynote (450 K). The Technical Keynote is our attempt to provide a high level overview of the roadmaps and big directions for the core Java platform. The rough agenda was:
The JavaTM ME roadmaps were covered in a special kickoff session for the Java ME track. (We had way too much material to fit into a single keynote session.) The Technical Keynote aims to provide a high level overview to help set direction at the start of the conference. But the real technical meat is, of course, in the individual technical sessions. The PDFs for all the technical sessions will be going on-line in a few weeks and those will provide much more detail on specific areas.
| |||||||||||
|
|