Java in the picture
The Java platform is in widespread use today. It was the first commercial language featuring JVM and byte-code with garbage collection, sandbox security, and networking capability to be adopted by business. Java's greatest strength is that businesses trust this platform to power enterprise applications in server-side computing. Since 1995, this strength in depth has grown to such a level that the platform is seen as very mature and mainstream. The disadvantage of being part of the main herd is that innovation takes a while to happen; as the steward of the platform, earlier Sun Microsystems and now Oracle Corporation, always guarantee backward compatibility and the maintenance of standards through the Java Community Process.
The JVM is the crown jewel of the platform. Java is the mother programming language that runs on the JVM. Other languages such as Scala, Groovy, and Clojure also run the JVM. These alternative JVM languages are popular, because they introduced many functional programming ideas to the mainstream developers. Functional programming primitives such as closures and comprehensions and languages such as Scala demonstrated a pure object-oriented model and mix-ins. These languages benefited from an easy interaction tool called REPL.
Tip
In fact, Java SE 9 will most likely have Read-Evaluate-Print-Loop (REPL). Keep an eye on the progression of the official OpenJDK project Kulla at http://openjdk.java.net/projects/kulla/.
Released in 2014, Java SE 8 features functional interfaces, otherwise known as Lambdas, which bring the benefits of closures and functional blocks to the main JVM language on the platform.
Whatever programming language you choose to develop your next enterprise application, Java or Scala or otherwise, I think you can bet on the JVM being around for a long time, at least for the next decade or so. The PermGen issue finally ended in Java SE 8, because there is no permanent generation in there. Before Java SE 8, PermGen was the source of many memory leaks (slow and steady memory hogs). This was also the dedicated space where the JVM would load classes into a piece of memory such as the Java Runtime (such as java.lang.String
, java.lang.System
, or java.util.collection.ConcurrentHashMap
). However, classes were rarely unloaded or compacted in size, especially during a very long execution of a JVM. If you are running websites 24/7 over a number of days or even weeks at a time with some degree of user interaction, then there is a good chance that your applications (and their application server) could run out of memory (java.lang.OutOfMemoryError: PermGen space
). The permanent generation was the storage area reserved for internal representation of Java classes in releases before JDK 8. For long running application servers and JVM processes, it was possible for references to metadata and classes to remain in permanent generation memory even after if WAR/EAR applications were undeployed and uninstalled. In Java SE 8, the reserved allocation of memory for the Java classes is adaptive. The JVM can now gracefully manage its own memory allocations and represents at least 10 percent efficiency improvement as compared to the previous versions.
In Java SE 8, we have a Garbage First Garbage collector known as G1, which is a parallel collector. Java SE 8 also includes new byte codes to improve the efficiency of dynamic languages such as JRuby and Clojure. The InvokeDynamic byte code from JDK 7 and the Method Handle API were particularly instrumented for the Nashorn, an implementation of JavaScript (ECMAScript Edition 6).
Tip
As of April 2015, Oracle stopped releasing updates to Java SE 7 to its public download sites. Please pass on this information to your CTO!
There is no doubt that the Java platform will continually serve digital engineers as a back-end technology. It may even occur to businesses to take advantage of the client-side technology in Java SE 8 that is now delivered with the platform. JavaFX is an interesting solution, but outside the scope of this book.
We should introduce some code now. The following is a Lambda function for Java SE 8:
public interface PaymentIssuer { public void allocate( int id ); } @ApplicationScoped public class CreditCardTicketTracker() { // Rely on CDI product factory to inject the correct type @Inject PaymentIssuer issuer; public void processTickets( List<Ticket> ticketBatch ) { final LocalDate dt = LocalDate.now().plusDays(2) ticketBatch.stream() .filter( t -> t.isAvailable() && t -> t.paymentType == PaymentType.CreditCard && dt.isBefore(DateUtils.asLocalDate( t.getConcertDate()))) .map(t -> t.getAllocation().allocateToTicket(t)) .forEach(allocation -> issuer.allocate(allocation)); } }
If this code looks very strange to you, then you are probably not yet familiar with Lambda expressions. We have a Context and Dependency Injection (CDI) bean, which is application scoped, called CreditCardTicketTracker
. It has a method called processTickets()
that accepts a list collection of Ticket objects. The exact type of Ticket is unimportant. What is important, however, is the PaymentIssuer
type that the CDI injects into a Plain Old Java Object (POJO). The method processTickets()
invokes the stream API of the Java SE 8 collection. Essentially, invoking the method parallelStream()
causes processing on each element in the Java collection with multiple threads working in a concurrent operation. The Lambda expressions are on the filter()
, map()
, and the forEach()
methods of the updated Collection API.
Moreover, the code reads close enough to written English. Let me now explain the method processTickets()
. An outside component is sending batches of concert tickets for processing to our component CreditCardTicketTracker
. For each ticket in the batch, we filter only those tickets that are marked as available, which have already been paid for using a credit card, and where the concert date is two or more days after the current date. By the way, we take advantage of java.time.LocalDate
, which is new in Java SE 8.
So, very briefly, a Lambda expression is an anonymous method and the syntax follows this format:
( [[Type1] param1 [, [Type2] param2 ....]] ) -> { /* * Do something here and return a result type * including void */ }
A lambda expression can be parameterless; therefore, the Java compiler can infer that an expression can be substituted for the java.lang.Runnable
type. If there are parameters, the compiler can infer the types of the arguments given enough information. Therefore, the Type1 and Type2 declarations are optional. A Lambda must return a single instance of a type or it may be void, which means the curly braces may be left off.
Lambda expressions are concise, timesaving, and allow functions to be passed to the libraries. For more information, consult the excellent Java Tutorial for Java SE 8 on Oracle's website (http://docs.oracle.com/javase/tutorial/java/index.html). As we have seen in the previous example, your application could use the parallel stream facility in the collection to achieve concurrency.
One immediate use of the Lambda expressions is to replace the inner classes that call the managed thread services, javax.enterprise.concurrent.ManagedExecutorService
in Java EE 7. We know that Java has multiple-thread support, networking, and security. Let us turn our attention to the client side.