Featured FREE Whitepapers

What's New Here?

software-development-2-logo

Books That Have Most Influenced My Software Development Career

I have read numerous books on software development and have learned valuable things from most of them, but a small subset of these books has significantly influenced me and how I develop software. Effective C++ and More Effective C++ Although I had written a lot of lines of code in BASIC, Pascal, C, and C++ before starting my career, it was C++ that was my first professional programming language. As such, it was the first programming language in which I started to get past the basic syntax and learn about more advanced issues and nuances of the programming languages. For the first time, I started considering performance issues, maintainability, readability, and issues other than just whether the code worked or not. Effective C++ and More Effective C++ helped me to see that there was more to programming than basic syntax and getting functionality to work. These books helped me to realize that there are general programming concepts that are wise to follow but that there are also language-specific concepts and tips one should learn and apply in the programming language of choice. General software development principles apply across many languages, but sometimes it is necessary to know language-specific features as well.Effective Java, Editions 1 and 2 After such good experiences with Effective C++ and More Effective C++, I was excited to learn about the book called Effective Java as I was transitioning from C++ to Java, a transition several years in the making. Effective Java did not disappoint. I started reading Effective Java sooner in my Java experience than I had started reading the Scott Meyer‘s C++ books in my C++ experience and it helped me tremendously. It helped me to see from the beginning that there were more considerations when developing with Java than just writing syntax and making things work.Java Cookbook Although I have purchased and read seemingly countless Java-themed books over the years, I’ve never had a book focused on the Java language basics. Instead, I’ve always had specialized books focusing on aspects of Java or Java EE. The way that I learned the basics of the Java programming language was via the Java Cookbook. It helped me realize that I like this recipe-based approach to reading about, learning, and applying a new programming language. I’ve liked recipe-oriented books ever since, especially for quickly learning and apply a new programming language or framework.Groovy Recipes: Greasing the Wheels of Java Groovy Recipes: Greasing the Wheels of Java was my introduction to Groovy. This excellent book provides a nice introduction to Groovy that not only quickly introduces its syntax and features but also introduces practical ways that Groovy can be applied in regular everyday situations. I was able to quickly see the value of learning Groovy and to realize that Groovy was more than just a trendy language fad. This book reaffirmed my realization that I learn programming languages best from recipe-oriented books that demonstrate the language used in practical situations. Groovy Recipes: Greasing the Wheels of Java and the Groovy language itself have dramatically influenced my overall approach to software development by giving me the tools and confidence to do significantly more scripting than I used to do. Being able to script and develop software in similar languages (Groovy and Java) and use the same Java libraries and frameworks has made scripting easier. Easier scripting has meant that I’ve done more of it and spent less time doing it.Holub on Patterns: Learning Design Patterns by Looking at Code I purchased Holub on Patterns after seeing Allen Holub speak at SD West 2005 (I wasn’t the only one). Holub, the author of Why Extends is Evil and Why Getters and Setters Are Evil, challenged my way of thinking (traditional and commonly accepted way of thinking at the time) about object-oriented programming. I definitely look at objects now more from a behavioral perspective than data perspective. Also, although willing to write get/set methods when necessary, my reluctance to write them until needed has been of great benefit as the era of multicores has helped us realize the dangers of mutable state. Although Holub on Patterns does provide in-depth coverage of some common design patterns implemented in Java, the far bigger influence it had on me was in how I think about object-oriented design.Expert One-on-One J2EE Design and Development At a time when developers of enterprise Java applications were being told to use heavyweight EJBs and like it, many of us were wondering what we were missing when it seemed overly complex to us. Rod Johnson‘s J2EE Design and Development stuck a chord with me; it was relieving to see that I wasn’t the only one who thought EJB 1.x was too difficult and cumbersome. More importantly, Johnson’s book provided examples and discussion text that helped to see what parts of J2EE were worth using and which parts needed improvement. The Spring Framework was born out of the examples covered in this book and Spring’s success inspired changes in Java EE that make it much more productive and useful. J2EE Design and Development influenced me personally and influenced an entire community. It also helped me to realize that one can be correct in thinking something isn’t all it’s said to be even if the so-called experts insist it is. This has helped me weather numerous fads (and their blindly adherent evangelists) in software development since then. The book also articulated better than I could my own thoughts and feelings on enterprise Java development.Agile Web Development with Rails During my brief infatuation with Ruby on Rails, I found Agile Web Development with Rails to be a great introduction to Ruby on Rails. Although I enjoyed my foray into Rails, I have never worked with it to the same degree as I have with Java. Agile Web Development with Rails introduced me to Ruby on Rails, but more importantly it influenced my career, which has mostly not been in Rails, by demonstrating in a practical way how agile development can be done if a client is readily available to provide feedback. Agile Web Development with Rails and the Ruby on Rails framework itself helped change my way of thinking to see the value of convention over configuration. Shortly thereafter, the Java-sphere began to see changes inspired by Ruby on Rails’s success. These included Java Persistence API (JPA) adopting “configuration by exception” approach and the Grails framework. Ruby on Rails influenced much of the web development community and Agile Web Development with Rails was the tool that allowed me to most easily experience this influence personally.The Practice of Programming The Practice of Programming does not waste time with extraneous pages. The 250 page book covers the most fundamental issues in programming such as debugging, testing, performance, and portability. I read this early in my software development career and find myself reading portions of it again from time to time. Many great books have come along since that deal with these subjects, but The Practice of Programming was the first to cover most of these for me.Software Craftsmanship: The New Imperative Software Craftsmanship: The New Imperative was published at almost the perfect time for me in my career. The book helped me articulate my own observations about what made a “software engineer” more complete. In addition, this relatively short and to-the-point book helped me discover other approaches that I would later use in efforts to make my code more than just functional.201 Principles of Software Development 201 Principles of Software Development features 201 short (typically one or two paragraphs) descriptions of 201 software development principles with a reference to a generally well-recognized expert source with further details on that principle. The text is comprehensive enough to understand the principle and the references to proven sources give the reader the ability to learn in more detail how to apply the covered principle. This book not only helped me to solidify these principles in my own mind, but helped me to understand the breadth of materials available to the software developer. During my software development career, I’ve repeatedly seen trends come and go. Sometimes I’ll hear a relatively new developer talking about some “new” thing that is really just a reincarnation of the same idea in different form that its previous incarnations. 201 Principles of Software Development helped me realize at a relatively early stage in my career that many concepts and principles that were “new” to me, were really not new to the greater software development industry. Most “innovative” concepts in our industry typically share common themes or are even grounded in one or more of the principles covered in this book.Conclusion The books covered in this post have had significant influence on my software development career and how I think about software development today. Numerous other books have had lesser degree of influence. In some cases, these other books might have had more influence had I encountered them at a different (often earlier) point in my career. In fact, that might be the point of this post: different books will have different impact on different developers depending on where those developers are in their careers. The books in this post have had particularly great influence on me, but I know that other developers have been significantly influenced by books such as Code Complete, Clean Code, and numerous other books. I was surprised at how many language-specific books were on this list as I compiled it, but each was really more about that language. These books are about how to apply the language to achieve more general software development ideals and that’s where they have been most influential to me.Reference: Books That Have Most Influenced My Software Development Career from our JCG partner Dustin Marx at the Inspired by Actual Events blog....
enterprise-java-logo

Java EE: Asynchronous constructs and capabilities

Introduction Java EE has a number of APIs and constructs to support Asynchronous execution. This is vital from a scalability and performance stand point. Let us assume 2 modules which are interacting with each other. When moduleA (the sender) sends a message to moduleB (the receiver) in a Synchronous fashion, the communication takes place in the context of a Single thread i.e. the thread which initiated the communication from moduleA is blocked until moduleB responds back. This was a generic statement but can be extended to the context of a simple Java methods interacting with each other – in this case, a synchronous call from methodA to methodB would execute in the same thread which would be blocked until methodB returns or throws an exception. Why do we need Asynchronous behavior in Java EE based applications? We can further extrapolate this point to the Java EE world – be it inter server communication e.g. between web tier and EJB tier (servlets and EJBs) or a typical client server interaction – a browser interacting with a RESTful end point, Servlets etc – the server thread which responds to a client request always blocks until the server component responds back. Here is where Asynchronous execution comes into play – if the server thread processing the client request can be released/suspended and the actual business logic is executed in a separate thread (different than that of the original one), performance and scalability can be improved immensely ! E.g. if a HTTP listener thread allocated to listen to client requests is released immediately, then it is free to attend to requests from other clients and the business logic can be executed in a separate container thread which can then return the response via appropriate methods such as java.util.concurrent.Future object or via call back handlers registered by the client. Think from an end user perspective – responsiveness matters a lot! Dive In: Async constructs and APIs in Java EE Let’s take a look at few of the Async related features (APIs) in Java EE. This is not an exhaustive list – but should be a good starting point. Different Java EE specs have their typical ways and APIs to facilitate Async capabilities. Let’s explore the below Java EE specificationsJAX-RS 2.0 (Java EE 7) Websocket 1.0 (Java EE 7) Concurrency Utilities 1.0 (Java EE 7) EJB 3.1 (Java EE 6) Servlet 3.0 (Java EE 6)Note: The code presented below is in a snippet form (for obvious reasons). The complete samples can be accessed here.  JAX-RS 2.0 Async processing of requests is a new feature in 2.0 edition of JAX-RS (new in Java EE 7). In order to execute an aysnc request using JAX-RS APIs, one needs to inject a reference to a javax.ws.rs.container.AsyncResponse interface in the JAX-RS resource method itself. This parameter puts the request execution in async mode and the method proceeds with its execution. The resume method on the AsynResponse object needs to be called from within a separate thread after the business logic execution is complete. One can leverage the Java EE concurrency utility features (discussed later) such as the javax.enterprise.concurrent.ManagedExecutorService in order to encapsulate the business logic as a Runnable object and submitting it to the container’s executor service which takes care of the rest. No need to spawn un-managed, isolated threads on your own. @Path("/{id}") @GET @Produces("application/xml") public void asyncMethod(@Suspended AsyncResponse resp, @PathParam("id") String input) {System.out.println("Entered MyAsyncRESTResource/asyncMethod() executing in thread: "+ Thread.currentThread().getName()); mes.execute( () -> { System.out.println("Entered Async zone executing in thread: "+ Thread.currentThread().getName()); System.out.println("Simulating long running op via Thread sleep() started on "+ new Date().toString()); try { Thread.sleep(5000); } catch (InterruptedException ex) { Logger.getLogger(MyAsyncRESTResource.class.getName()).log(Level.SEVERE, null, ex); } System.out.println("Completed Long running op on "+new Date().toString()); System.out.println("Exiting Async zone executing in thread: "+ Thread.currentThread().getName());//creating a dummy instance of our model class (Student)Student stud = new Student(input, "Abhishek", "Apr-08-1987"); resp.resume(Response.ok(stud).build()); } );System.out.println("Exit MyAsyncRESTResource/asyncMethod() and returned thread "+Thread.currentThread().getName()+" back to thread pool"); } The JAX-RS Client API also has asynchronous capabilities but they have not been discussed in the post. They are definitely worth a look! Websocket 1.0 The Websocket API is a brand new addition to the Java EE arsenal (introduced in Java EE 7). It facilitates bi-directional (both server and client initiated) communication which is also full duplex in nature (either the client or server can send messages to each other at any time). In order to send async messages using the Websocket API, one needs to use the getAsyncRemote method available on the javax.websocket.Session interface. Internally, this is nothing but an instance of the nested interface of the javax.websocket.RemoteEnpoint – javax.websocket.RemoteEnpoint.Async. Calling the regular sendXXX methods on this would result in the sending process being executed in a separate thread. This is particularly useful when you consider exchange of large messages or handling large numbers of websocket clients to whom the messages need to be sent. The method wither returns a java.util.concurrent.Future object or one can register a callback in the form of a javax.websocket.SendHandler interface implementation. public void sendMsg(@Observes Stock stock) { System.out.println("Message receieved by MessageObserver --> "+ stock); System.out.println("peers.size() --> "+ peers.size()); peers.stream().forEach((aPeer) -> { //stock.setPrice();aPeer.getAsyncRemote().sendText(stock.toString(), (result) -> { System.out.println("Message Sent? " + result.isOK()); System.out.println("Thread : " + Thread.currentThread().getName()); });}); } Concurrency Utilities 1.0 The Java EE Concurrency Utilities is another great addition to Java EE 7. It provides a standard way of spawning threads – the good part is that these are container managed and not just isolated/orphan threads about which the container has no contextual information. In general, the Concurrency Utilities 1.0 provide a few standard constructs for execution of asynchronous tasks in separate threads. These are as follows – javax.enterprise.concurrent.ManagedExecutorService  and javax.enterprise.concurrent.ManagedScheduledExecutorService. In order to start a new task in a separate thread, one can use the ManagedExecutorService interface to submit a Runnable. In addition to implementing the Runnable interface, a class can also implement the javax.enterprise.concurrent.ManagedTask interface and provide a  javax.enterprise.concurrent.ManagedTaskListener implementation in order to listen to life  cycle changes to the task submitted via the ManagedExecutorService. @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("Enter AConcurrencyUtilsExample/doGet executing in thread "+ Thread.currentThread().getName()); System.out.println("initiating task . . . "); mes.execute(new AManagedTask()); System.out.println("Exit AConcurrencyUtilsExample/doGet and returning thread "+ Thread.currentThread().getName() +" back to pool"); } Servlet 3.0 Asynchronous HTTP was introduced in Servlet 3.0 (part of Java EE 6) which basically provided the capability to execute the request in separate thread and suspend the original thread which handled the client invocation. The key player here is the javax.servlet.AsyncContext interface. In order to initiate asynchronous processing, the startAsync method of the java.servlet.ServletRequest interface is called. In order to execute the core logic, a java.lang.Runnable object needs to be submitted to the start method of the AsyncContext interface. One can choose to attach a listener by implementing the javax.servlet.AsyncListener in order to receive callback notifications during specific times of the Async task execution. @Overridepublic void doGet(HttpServletRequest req, HttpServletResponse resp) {PrintWriter writer = null; try { writer = resp.getWriter(); } catch (IOException ex) { Logger.getLogger(MyAsyncServlet.class.getName()).log(Level.SEVERE, null, ex); } //System.out.println("entered doGet()"); writer.println("ENTERING ... " + MyAsyncServlet.class.getSimpleName() + "/doGet()"); writer.println("Executing in Thread: " + Thread.currentThread().getName()); //step 1 final AsyncContext asyncContext = req.startAsync();//step 2 asyncContext.addListener(new CustomAsyncHandler(asyncContext));//step 3 asyncContext.start( () -> { PrintWriter logger = null; try { logger = asyncContext.getResponse().getWriter(); } catch (IOException ex) { Logger.getLogger(MyAsyncServlet.class.getName()).log(Level.SEVERE, null, ex); }logger.println("Long running Aync task execution started : " + new Date().toString());logger.println("Executing in Thread: " + Thread.currentThread().getName()); try { Thread.sleep(5000); } catch (InterruptedException e) { Logger.getLogger(MyAsyncServlet.class.getName()).log(Level.SEVERE, null, e); }logger.println("Long task execution complete : " + new Date().toString());logger.println("Calling complete() on AsyncContext");//step 4 asyncContext.complete(); } );writer.println("EXITING ... " + MyAsyncServlet.class.getSimpleName() + "/doGet() and returning initial thread back to the thread pool");} EJB 3.1 Typically, (prior to EJB 3.1) EJB Message Driven Beans were used to fulfill async related requirements. A MDB bean listens to messages sent to a javax.jms.Destination (a Queue or Topic) and executes the required business logic – this might be anything from sending an email to initiating an order processing task. The important thing to understand is that the client which sends the message to the Queue in the first place is unaware of the MDB (decoupled) and does not have to wait/remain blocked until the end of the job (email receipt or order processing confirmation). EJB 3.1 (part of Java EE 6) introduced the javax.ejb.Asynchronous annotation. This can be placed on a EJB Session bean (Stateless, Stateful or Singleton) class (makes all the methods Asynchronous) or at the method level itself – in case fine grained control is needed. A method with the @Asynchronous annotation can either return void (fire and forget) or an instance of java.util.concurrent.Future if the async method result needs to be tracked – this can be done by calling the Future.get() – the thing to note is that the get method itself is blocking in nature. @Asynchronous public Future<String> asyncEJB2(){System.out.println("Entered MyAsyncEJB/asyncEJB2()"); System.out.println("MyAsyncEJB/asyncEJB2() Executing in thread: "+ Thread.currentThread().getName()); System.out.println("Pretending as if MyAsyncEJB/asyncEJB2() is doing something !"); try { Thread.sleep(5000); } catch (InterruptedException ex) { java.util.logging.Logger.getLogger(MyAsyncEJB.class.getName()).log(Level.SEVERE, null, ex); }System.out.println("Exiting MyAsyncEJB/asyncEJB2()"); return new AsyncResult("Finished Executing on "+ new Date().toString());} This was a rather brief preview of Java EE capabilities. These APIs and specifications are functionally rich and it is hard cover all of them via a blog post! I hope this piques your interest and gives you a starting point to explore further. Cheers!Reference: Java EE: Asynchronous constructs and capabilities from our JCG partner Abhishek Gupta at the Object Oriented.. blog....
hawtio-logo

HawtIO on JBoss EAP (Part II)

I just posted an entry on running HawtIO on JBoss Wildfly 8.1 recently. From that post you know how awesome HawtIO is, and all of the cool plugins it has to make managing your JVM based technologies from a single dashboard… well… hawt….However, I wanted to dedicate a post to running HawtIO on JBoss EAP for the same reasons outlined in the previous post: As we at Red Hat roll out JBoss Fuse and JBoss Fuse Serviceworks, we’re getting better at integrating the individual components. For example, a Fuse Service Works subscription gives you full access to A-MQ, Fuse, and all of its components, including HawtIO. Unfortunately, HawtIO isn’t “officially” supported in EAP as of today, but that will be fixed in next releases. It’s not a limitation of the technology, it’s just there’s so much there and Red Hat has stringent testing/compatibility requirements so we need to have all of the testing/certification done before we “support it” fully. BUT… there’s really no reason to not use it anyway (at least Development and QA), while we wait for support. And there are lots of people already doing that. Just remember, it’s not officially supported yet! So the rest of this blog is a step-by-step guide with best practices for getting HawtIO deployed and secured on your JBoss EAP 6.x application server. I will use HawtIO 1.4.11 (latest release from the community) for this guide.HawtIO on JBoss EAP 6.1 This first section will discuss EAP 6.1 because it seems to work great following the similar directions as those for deploying HawtIO on Wildfly 8.1. Basically, if you follow the instructions from the blog post on running on Wildfly, you’ll get it working just fine. To be very specific do these pieces:Remove the log4j.properties file to use EAP logging subsystem Rename distro to hawtio.war Create users in ApplicationRealm with roles including “admin” Edit the standalone.xml file to account for the following settings:I’ve also added [these instructions to the HawtIO documentation][http://hawt.io/getstarted/index.html] (the website should update with those changes soon). After successfully deploying HawtIO to JBoss EAP 6.1, you should be greeted with a login page at this URL: http://localhost:8080/hawtioHawtIO on JBoss EAP 6.2 So unfortunately, getting HawtIO to run on JBoss EAP 6.2 has some issues with JAAS that I haven’t been able to figure out. If you’re a Wildfly 7/EAP 6.x wizard and wish to take a look have a peek at the github issue I have open. Thankfully, however, HawtIO is quite versatile and doesn’t have to be run as a web-app collocated on the container you want to manage. You can run it standalone as a Chrome extension or in a separate container that’s not JBoss EAP. Effectively, you can use HawtIO’s Connect page to remotely connect to the container you wish to manage. For example, download the standalone distribution of HawtIO which ends up just being an executable jar. Run it like this (make sure to add the params for the port change, because we don’t want to conflict with the EAP ports if running on the same machine): ceposta@postamachat(standalone) $ java -jar hawtio-app-1.4.11.jar --port 9091 This will bring up HawtIO running standalone (with an internal Jetty server! Woohoo!). Then click the “Connect” tab and you should see a page like this:Wait, what? Just connect? “How would this even work”” you ask? “How can we connect to EAP and have HawtIO just manage it?” Well, the magic is this totally awesome little library named Jolokia.Jolokia provides REST access to your JMX tree. So the way to get HawtIO to manage your JBoss EAP 6.2 container is to enable Jolokia on it and then use HawtIO’s Connect tab to log in. If you haven’t taken a look at Jolokia, you’re missing out!! No more complicated JMX API/clients and query/filter API. Just use REST endpoints and curl. Simple. Jolokia has a few options for deploying/enabling. The most straight forward is a web app, but you could also attach as a JVM agent at startup time. We’ll take the easy approach and deploy Jolokia as a webapp: Rename distro For this blog post, I’m using Jolokia 1.2.2. So when you download it, it has a name like this jolokia-1.2.2.war. Let’s rename the distro so we don’t take into account the version numbers to make it easier to get to the URL: ceposta@postamachat(rename) $ mv jolokia-war-1.2.2.war jolokia.war Enable security for Jolokia Next, we want to enable security for the jolokia web app. We’ll do that as described in the Jolokia documentation. We’ll need to edit the web.xml file that comes in the Jolokia jar and uncomment the section that’s blocked out for security: ceposta@postamachat(rename) $ vi jolokia.war Your config in WEB-INF/web.xml should have a security section like this: 163 <!-- 164 Example Configuration for switching on BASIC security. The role 'Jolokia' 165 must be mapped to real users with passwords on the Appserver side: 166 --> 167 <login-config> 168 <auth-method>BASIC</auth-method> 169 <realm-name>Jolokia</realm-name> 170 </login-config> 171 172 <security-constraint> 173 <web-resource-collection> 174 <web-resource-name>Jolokia-Agent Access</web-resource-name> 175 <url-pattern>/*</url-pattern> 176 </web-resource-collection> 177 <auth-constraint> 178 <role-name>Jolokia</role-name> 179 </auth-constraint> 180 </security-constraint> 181 182 <security-role> 183 <role-name>Jolokia</role-name> 184 </security-role> 185 186 </web-app> Now add a user like we did in the previous blog that has a role of “Jolokia”. Note, make sure this user is added to the ApplicationRealm. Connect to EAP 6.2 Now go back to your standalone HawtIO (we deployed it in the previous step at http://localhost:9091/hawtio) and enter the connect params (path as follows):Click “Connect to remote server” and viola! You’re conencted. Where to go from here You can also try to enable SSL over the http connection as well as maybe use DIGEST auth instead of the default BASIC auth. I’ll leave that as an exercise for the reader!Reference: HawtIO on JBoss EAP (Part II) from our JCG partner Christian Posta at the Christian Posta – Software Blog blog....
java-logo

Decorator Design Pattern Applied

Hi there! Today i’m gonna show the decorator design pattern in action. The decorator design pattern is a largelly used design pattern while dealing with grafics, trees and dynamic changes during runtime. It is also a greate choice if you are looking or trying to do recursion with. I love it. In this post we will implement a students decoration. We will decorate it with degrees and doctor titles. A nice example to see how it works in the real world. First of all, let’s take a look at the UML diagram of it in its simpliest variety. After that we will take the analogy for our example. The simpliest UML Pay close attention, because once you understand that, everything will become clear and simple to understand. That’s the reason I’m putting the simplest model here first.Understanding the Details The decorable will be every concrete implementation of the common interace Decorable. The decorators will be every implementation of the abstract class Decorator. Which defines the decorator’s contract holding an instance to decorables. Let’s dive into some code to fix it: // 1. COMMON INTERFACE FOR DECORABLES public interface Decorable { public String getDescription(); } // 2. THE ABSTRACT DECORADOR WHICH HOLDS A REFERENCE TO DECORABLES public abstract class Decorator implements Decorable { protected Decorable component; public Decorator(Decorable component){ super(); this.component=component; } } The Analogy to our Students example Let’s start again with the UML diagram first:The common decorable Girl Here we start with the analogies. The interface Girl is the decorable. GirlDecorator defines the abstract decorator’s contract with the concrete decorators bellow. // 1. COMMON INTERFACE FOR DECORABLES public interface Girl { public String getDescription(); } // 2. THE ABSTRACT DECORADOR WHICH HOLDS A REFERENCE TO DECORABLES public abstract class GirlDecorator implements Girl { protected Girl girl; public GirlDecorator(Girl girl){ super(); this.girl=girl; } } // 3. DEFINING CONCRETE DECORATORS public class Science extends GirlDecorator { public Science(Girl girl) {super(girl);} @Override public String getDescription() { // DECORATES WITH A SCIENCE'S DEGREE return girl.getDescription() + "+Like Science"; } public void caltulateStuff() { // ADDS NEW FEATURES (METHOD) TO IT System.out.println("scientific calculation!"); } } public class Art extends GirlDecorator { public Art(Girl girl) {super(girl);} @Override public String getDescription() {return girl.getDescription() + "+Like Art";} public void draw() {System.out.println("draw pictures!");} } public class Doctor extends GirlDecorator { public Doctor(Girl girl) {super(girl);} @Override public String getDescription() {return girl.getDescription() + "+Like Doctor";} public void calculateStuff() {System.out.println("doctor calculation!");} public void doctorTitle() {System.out.println("doctor title");} } The Decorables AmericanGirl and EuropeanGirl are the decorable that will be decorated with degrees and doctor tittles at runtime enhancing its curriculum and abilities. // 4. AN AMERICAN GIRL WILL BE DEFINED AS A DECORABLE public class AmericanGirl implements Girl { private String description=""; // NORMAL AMERICAN GIRL public AmericanGirl(){ super(); description = "+American"; } @Override public String getDescription() {return description;} } public class EuropeanGirl implements Girl { private String description=""; public EuropeanGirl() { super(); description = "+European"; } @Override public String getDescription() {return description;} } Testing it Now let’s see in practise how it looks like. How we can decorate and enhance its abilities at runtime: public class Client { public static void main(String[] args) { // COMMOM GIRL Girl girl; // CREATING NORMAL AMERICAN GIRL girl = new AmericanGirl(); System.out.println(girl.getDescription()); // DECORANTING AMERICANA GIRL WITH SCIENCE'S DEGREE girl = new Science(girl); System.out.println(girl.getDescription()); // DECORANTING AMERICANA GIRL WITH ART'S DEGREE girl = new Art(girl); System.out.println(girl.getDescription()); // EUROPEAN GIRL HAS ALREADY ALL DEGREES Girl europeia = new Science(new Art(new EuropeanGirl())); System.out.println(europeia.getDescription()); // DOCTOR HAS NEW FUNCTIONS girl = new Doctor(girl); System.out.println(girl.getDescription()); // BECAUSE DOCTOR EXTENDS FROM COMMON GIRL, IT CAN DO A DOWNCAST ((Doctor)girl).doctorTitle(); ((Doctor)girl).calculateStuff(); // PAY ATTENTION THAT WE USE THE SAME INSTANCE, BUT THEY BEHAVIOR DIFFERENT // AT DIFFERENT TIME SLOTS. THE CLIENT HAS THE IMPRESSION THAT WE HAVE // CHANGED THE IMPLEMENTATION, BUT IN FACT NOT. } } That’s all! Hope you like it!Reference: Decorator Design Pattern Applied from our JCG partner Ricardo Ferreira at the Clean Code Development – Quality Seal blog....
enterprise-java-logo

Writing Clean Tests – To Verify Or Not To Verify

When we write unit tests that use mock objects, we follow these steps:                    Configure the behavior of our mock objects. Invoke the tested method. Verify that the correct methods of our mock objects were invoked.The description of the third step is actually a bit misleading, because often we end up verifying that the correct methods were invoked AND that the other methods of our mock objects were not invoked. And everyone knows that if we want to write bug free software, we have to verify both of these things or bad things happen. Right? Let’s Verify Everything Let’s start by taking a look at the implementation of a service method that is used to add new user accounts to the database. The requirements of this service method are:If the email address of the registered user account is not unique, our service method must throw an exception. If the registered user account has a unique email address, our service method must add a new user account to the database. If the registered user account has a unique email address and it is created by using normal sign in, our service method must encode the user’s password before it is saved to the database. If the registered user account has a unique email address and it is created by using social sign in, our service method must save the used social sign in provider. A user account that was created by using social sign in must not have a password. Our service method must return the information of the created user account.If you want learn how you can specify the requirements of a service method, you should read the following blog posts:From Top to Bottom: TDD for Web Applications From Idea to Code: The Lifecycle of Agile SpecificationsThis service method is implemented by following these steps:The service method checks that the email address given by user is not found from the database. It does this by invoking the findByEmail() method of the UserRepository interface. If the User object is found, the service method method throws a DuplicateEmailException. It creates a new User object. If the registration is made by using a normal sign in (the signInProvider property of the RegistrationForm class is not set), the service method encodes the password provided by user, and sets the encoded password to the created User object. The service methods saves the information of the created User object to the database and returns the saved User object.The source code of the RepositoryUserService class looks as follows: import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional;@Service public class RepositoryUserService implements UserService {private PasswordEncoder passwordEncoder;private UserRepository repository;@Autowired public RepositoryUserService(PasswordEncoder passwordEncoder, UserRepository repository) { this.passwordEncoder = passwordEncoder; this.repository = repository; }@Transactional @Override public User registerNewUserAccount(RegistrationForm userAccountData) throws DuplicateEmailException { if (emailExist(userAccountData.getEmail())) { throw new DuplicateEmailException("The email address: " + userAccountData.getEmail() + " is already in use."); }String encodedPassword = encodePassword(userAccountData);User registered = User.getBuilder() .email(userAccountData.getEmail()) .firstName(userAccountData.getFirstName()) .lastName(userAccountData.getLastName()) .password(encodedPassword) .signInProvider(userAccountData.getSignInProvider()) .build();return repository.save(registered); }private boolean emailExist(String email) { User user = repository.findByEmail(email);if (user != null) { return true; }return false; }private String encodePassword(RegistrationForm dto) { String encodedPassword = null;if (dto.isNormalRegistration()) { encodedPassword = passwordEncoder.encode(dto.getPassword()); }return encodedPassword; } } If we want write unit tests which ensure that our service method is working correctly when the user is registering a new user account by using social sign in AND we want to verify every interaction between our service method and our mock objects, we have to write eight unit tests for it. We have to ensure that:The service methods checks that email address is unique when a duplicate email address is given. The DuplicateEmailException is thrown when a duplicate email address is given. The service method doesn’t save a new account to the database when a duplicate email address is given. Our service method doesn’t encode the user’s password if a duplicate email address is given. Our service method checks that the email address is unique when a unique email address is given. When a unique email address is given, our service method creates a new User object that contains the correct information and saves the information of the created User object to the database. When a unique email address is given, our service method returns the information of the created user account. When a unique email address is given and a social sign in is used, our service method must not set the password of the created user account (or encode it).The source code of our test class looks as follows: import net.petrikainulainen.spring.social.signinmvc.user.dto.RegistrationForm; import net.petrikainulainen.spring.social.signinmvc.user.dto.RegistrationFormBuilder; import net.petrikainulainen.spring.social.signinmvc.user.model.SocialMediaService; import net.petrikainulainen.spring.social.signinmvc.user.model.User; import net.petrikainulainen.spring.social.signinmvc.user.repository.UserRepository; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; import org.mockito.stubbing.Answer; import org.springframework.security.crypto.password.PasswordEncoder;import static com.googlecode.catchexception.CatchException.catchException; import static com.googlecode.catchexception.CatchException.caughtException; import static net.petrikainulainen.spring.social.signinmvc.user.model.UserAssert.assertThatUser; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.isA; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when;@RunWith(MockitoJUnitRunner.class) public class RepositoryUserServiceTest {private static final String REGISTRATION_EMAIL_ADDRESS = "john.smith@gmail.com"; private static final String REGISTRATION_FIRST_NAME = "John"; private static final String REGISTRATION_LAST_NAME = "Smith"; private static final SocialMediaService SOCIAL_SIGN_IN_PROVIDER = SocialMediaService.TWITTER;private RepositoryUserService registrationService;@Mock private PasswordEncoder passwordEncoder;@Mock private UserRepository repository;@Before public void setUp() { registrationService = new RepositoryUserService(passwordEncoder, repository); }@Test public void registerNewUserAccount_SocialSignInAndDuplicateEmail_ShouldCheckThatEmailIsUnique() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(new User());catchException(registrationService).registerNewUserAccount(registration);verify(repository, times(1)).findByEmail(REGISTRATION_EMAIL_ADDRESS); }@Test public void registerNewUserAccount_SocialSignInAndDuplicateEmail_ShouldThrowException() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(new User());catchException(registrationService).registerNewUserAccount(registration);assertThat(caughtException()).isExactlyInstanceOf(DuplicateEmailException.class); }@Test public void registerNewUserAccount_SocialSignInAndDuplicateEmail_ShouldNotSaveNewUserAccount() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(new User());catchException(registrationService).registerNewUserAccount(registration);verify(repository, never()).save(isA(User.class)); }@Test public void registerNewUserAccount_SocialSignInAndDuplicateEmail_ShouldNotCreateEncodedPasswordForUser() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(new User());catchException(registrationService).registerNewUserAccount(registration);verifyZeroInteractions(passwordEncoder); }@Test public void registerNewUserAccount_SocialSignInAndUniqueEmail_ShouldCheckThatEmailIsUnique() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(null);registrationService.registerNewUserAccount(registration);verify(repository, times(1)).findByEmail(REGISTRATION_EMAIL_ADDRESS); }@Test public void registerNewUserAccount_SocialSignInAndUniqueEmail_ShouldSaveNewUserAccountAndSetSignInProvider() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(null);registrationService.registerNewUserAccount(registration);ArgumentCaptor<User> userAccountArgument = ArgumentCaptor.forClass(User.class); verify(repository, times(1)).save(userAccountArgument.capture());User createdUserAccount = userAccountArgument.getValue();assertThatUser(createdUserAccount) .hasEmail(REGISTRATION_EMAIL_ADDRESS) .hasFirstName(REGISTRATION_FIRST_NAME) .hasLastName(REGISTRATION_LAST_NAME) .isRegisteredUser() .isRegisteredByUsingSignInProvider(SOCIAL_SIGN_IN_PROVIDER); }@Test public void registerNewUserAccount_SocialSignInAndUniqueEmail_ShouldReturnCreatedUserAccount() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(null);when(repository.save(isA(User.class))).thenAnswer(new Answer<User>() { @Override public User answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); return (User) arguments[0]; } });User createdUserAccount = registrationService.registerNewUserAccount(registration);assertThatUser(createdUserAccount) .hasEmail(REGISTRATION_EMAIL_ADDRESS) .hasFirstName(REGISTRATION_FIRST_NAME) .hasLastName(REGISTRATION_LAST_NAME) .isRegisteredUser() .isRegisteredByUsingSignInProvider(SOCIAL_SIGN_IN_PROVIDER); }@Test public void registerNewUserAccount_SocialSignInAnUniqueEmail_ShouldNotCreateEncodedPasswordForUser() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(null);registrationService.registerNewUserAccount(registration);verifyZeroInteractions(passwordEncoder); } } These unit tests are written by following the instructions given in the previous parts of this tutorial. That class has a lot of unit tests. Are we sure that every one of them is really necessary? Or Maybe Not The obvious problem is that we wrote two unit tests which both verify that our service method checks that the email address given by the user is unique. We could fix this by combining these tests into a single unit test. After all, one test should convince us that our service method verifies that the email address given by user is unique before it creates a new user account. However, if we do this, we won’t find an answer to a much more interesting question. This question is: Should we really verify every interaction between the tested code and our mock objects? A few months I ago I ran into an article titled: Why Most Unit Testing is Waste by James Coplien. This article makes several good points but one of them was suits very well in this situation. James Coplien argued that we should ask one question about every test in our test suite: If this test fails, what business requirement is compromised? He also explains why this is such an important question: Most of the time, the answer is, “I don’t know.” If you don’t know the value of the test, then the test theoretically could have zero business value. The test does have a cost: maintenance, computing time, administration, and so forth. That means the test could have net negative value. That is the fourth category of tests to remove. Let’s find out what happens when we evaluate our unit tests by using this question. Popping Up the Question When the ask the question: “If this test fails, what business requirement is compromised?” about every unit test of our test class, we get the following answers:The service method checks that email address is unique when a duplicate email address is given.User must have a unique email address.The DuplicateEmailException is thrown when a duplicate email address is given.User must have a unique email address.The service method doesn’t save a new account to the database when a duplicate email address is given.User must have a unique email address.Our service method doesn’t encode the user’s password if a duplicate email address is given.-Our service method checks that the email address is unique when a unique email address is given.User must have a unique email address.When a unique email address is given, our service method creates a new User object that contains the correct information and saves the information of the created User object to the used database.If the registered user account has unique email address, it must be saved to the database. If the registered user account is created by using social sign in, our service method must save the used social sign in provider.When a unique email address is given, our service method returns the information of the created user account.Our service method must return the information of the created user account.When a unique email address is given and a social sign in is used, our service method must not set the password of the created user account (or encode it).User account that is created by using social sign in has no password.At first it looks like our test class has only one unit test that has no business value (or which might have a negative net value). This unit test ensures that there are no interactions between our code and the PasswordEncoder mock when a user tries to create a new user account by using a duplicate email address. It is clear that we must delete this unit test, but this is not the only unit test that must be deleted. The Rabbit Hole Is Deeper than Expected Earlier we noticed that our test class contains two unit tests that both verify that the findByEmail() method of the UserRepository interface is called. When we take a closer look at the implementation of the tested service method, we notice that:Our service method throws a DuplicateEmailException when the findByEmail() method of the UserRepository interface returns a User object. Our service method creates a new user account when the findByEmail() method of the UserRepository interface returns null.The relevant part of the tested service method looks as follows: public User registerNewUserAccount(RegistrationForm userAccountData) throws DuplicateEmailException { if (emailExist(userAccountData.getEmail())) { //If the PersonRepository returns a Person object, an exception is thrown. throw new DuplicateEmailException("The email address: " + userAccountData.getEmail() + " is already in use."); }//If the PersonRepository returns null, the execution of this method continues. }private boolean emailExist(String email) { User user = repository.findByEmail(email);if (user != null) { return true; }return false; } I argue that we should remove both of these unit tests because of two reasons:As long as we have configured the PersonRepository mock correctly, we know that its findByEmail() method was called by using the correct method parameter. Although we can link these test cases to a business requirement (user’s email address must be unique), we don’t need them to verify that this business requirement isn’t compromised. These unit tests don’t document the API of our service method. They document its implementation. Tests like this are harmful because they litter our test suite with irrelevant tests and they make refactoring harder.If we don’t configure our mock objects, they return “nice” values. The Mockito FAQ states that: In order to be transparent and unobtrusive all Mockito mocks by default return ‘nice’ values. For example: zeros, falseys, empty collections or nulls. Refer to javadocs about stubbing to see exactly what values are returned by default. This why we should always configure the relevant mock objects! If we don’t do so, our tests might be useless. Let’s move on and clean up this mess. Cleaning Up the Mess After we have removed these unit tests from our test class, its source code looks as follows: import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; import org.mockito.stubbing.Answer; import org.springframework.security.crypto.password.PasswordEncoder;import static com.googlecode.catchexception.CatchException.catchException; import static com.googlecode.catchexception.CatchException.caughtException; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.isA; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when;@RunWith(MockitoJUnitRunner.class) public class RepositoryUserServiceTest {private static final String REGISTRATION_EMAIL_ADDRESS = "john.smith@gmail.com"; private static final String REGISTRATION_FIRST_NAME = "John"; private static final String REGISTRATION_LAST_NAME = "Smith"; private static final SocialMediaService SOCIAL_SIGN_IN_PROVIDER = SocialMediaService.TWITTER;private RepositoryUserService registrationService;@Mock private PasswordEncoder passwordEncoder;@Mock private UserRepository repository;@Before public void setUp() { registrationService = new RepositoryUserService(passwordEncoder, repository); }@Test public void registerNewUserAccount_SocialSignInAndDuplicateEmail_ShouldThrowException() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(new User());catchException(registrationService).registerNewUserAccount(registration);assertThat(caughtException()).isExactlyInstanceOf(DuplicateEmailException.class); }@Test public void registerNewUserAccount_SocialSignInAndDuplicateEmail_ShouldNotSaveNewUserAccount() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(new User());catchException(registrationService).registerNewUserAccount(registration);verify(repository, never()).save(isA(User.class)); }@Test public void registerNewUserAccount_SocialSignInAndUniqueEmail_ShouldSaveNewUserAccountAndSetSignInProvider() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(null);registrationService.registerNewUserAccount(registration);ArgumentCaptor<User> userAccountArgument = ArgumentCaptor.forClass(User.class); verify(repository, times(1)).save(userAccountArgument.capture());User createdUserAccount = userAccountArgument.getValue();assertThatUser(createdUserAccount) .hasEmail(REGISTRATION_EMAIL_ADDRESS) .hasFirstName(REGISTRATION_FIRST_NAME) .hasLastName(REGISTRATION_LAST_NAME) .isRegisteredUser() .isRegisteredByUsingSignInProvider(SOCIAL_SIGN_IN_PROVIDER); }@Test public void registerNewUserAccount_SocialSignInAndUniqueEmail_ShouldReturnCreatedUserAccount() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(null);when(repository.save(isA(User.class))).thenAnswer(new Answer<User>() { @Override public User answer(InvocationOnMock invocation) throws Throwable { Object[] arguments = invocation.getArguments(); return (User) arguments[0]; } });User createdUserAccount = registrationService.registerNewUserAccount(registration);assertThatUser(createdUserAccount) .hasEmail(REGISTRATION_EMAIL_ADDRESS) .hasFirstName(REGISTRATION_FIRST_NAME) .hasLastName(REGISTRATION_LAST_NAME) .isRegisteredUser() .isRegisteredByUsingSignInProvider(SOCIAL_SIGN_IN_PROVIDER); }@Test public void registerNewUserAccount_SocialSignInAnUniqueEmail_ShouldNotCreateEncodedPasswordForUser() throws DuplicateEmailException { RegistrationForm registration = new RegistrationFormBuilder() .email(REGISTRATION_EMAIL_ADDRESS) .firstName(REGISTRATION_FIRST_NAME) .lastName(REGISTRATION_LAST_NAME) .isSocialSignInViaSignInProvider(SOCIAL_SIGN_IN_PROVIDER) .build();when(repository.findByEmail(REGISTRATION_EMAIL_ADDRESS)).thenReturn(null);registrationService.registerNewUserAccount(registration);verifyZeroInteractions(passwordEncoder); } } We removed three unit tests from our test class, and as a result, we can enjoy the following benefits:Our test class has less unit unit tests. This might seem like a strange benefit because often we are advised to write as many unit tests as possible. However, if we think about this, having less unit tests makes sense because we have less tests to maintain. This and the fact that each unit tests only one thing makes our code easier to maintain and refactor. We have improved the quality of our documentation. The removed unit tests didn’t document the public API of the tested service method. They documented its implementation. Because these tests were removed, it is easier to figure out the requirements of the tested service method.Summary This blog post has taught us three things:If we cannot identify the business requirement that is compromised if a unit test fails, we shouldn’t write that test. We should not write unit tests that don’t document the public API of the tested method because these tests make our code (and tests) harder to maintain and refactor. If we find existing unit tests that break these two rules, we should delete them.We have achieved a lot during this tutorial. Do you think that it is possible to make these unit tests even better? If you want to learn more about writing clean tests, read all parts of my Writing Clean Tests tutorial.Reference: Writing Clean Tests – To Verify Or Not To Verify from our JCG partner Petri Kainulainen at the Petri Kainulainen blog....
apache-maven-logo

Maven Git Release

I need to start this post by stating that I’ve only started to work seriously with Git within the last year. Unfortunately, a lot of the projects that I work on are still using SVN or CVS, but I’m now finally starting in a few that use Git. During the last few years, I’ve done a lot of software releases using Maven Release Plugin. I still remember that I’ve took a full week just to setup the plugin in one of my projects. It worked well most of the times, but if something went wrong you could spend the next few hours fixing the problem. Oh boy, what a nightmare! Recently, I wanted to do the same operation with a Git project and I came across with the Maven JGit-Flow Plugin and I have to tell you that this is fantastic! Very easy to setup and worked flawlessly on the first try! This plugin is based on the development model described in the post A successful Git branching model by Vincent Driessen. Take your time to read it, since it’s very interesting. I’m going to show you how to perform a release using this plugin. I’ll use the project from my latest post about Spring Batch as Wildfly Module. Setup Setup is very easy, just add the following to your pom.xml: om-jgitflow-maven-plugin.xml <plugin> <groupId>external.atlassian.jgitflow</groupId> <artifactId>jgitflow-maven-plugin</artifactId> <version>1.0-m3</version> <configuration> <noDeploy>true</noDeploy> </configuration> </plugin> I’ve just added the noDeploy configuration, because I’m not releasing to a Maven repository. That’s it! Release Let’s look at my project branches and version: branches radcortez:wildfly-spring-batch radcortez$ git branch -avv * master 0b2364b [origin/master] Added documentation. remotes/origin/master 0b2364b Added documentation. radcortez:wildfly-spring-batch radcortez$ mvn help:evaluate -Dexpression=project.version [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building wildfly-spring-batch 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-help-plugin:2.2:evaluate (default-cli) @ wildfly-spring-batch --- [INFO] No artifact parameter specified, using 'com.cortez.wildfly.batch:wildfly-spring-batch:war:1.0-SNAPSHOT' as project. [INFO] 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ Now, just run mvn jgitflow:release-start: release-prepare radcortez:wildfly-spring-batch radcortez$ mvn jgitflow:release-start [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building wildfly-spring-batch 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- jgitflow-maven-plugin:1.0-m3:release-start (default-cli) @ wildfly-spring-batch --- [INFO] ensuring origin exists... [INFO] (develop) Checking for SNAPSHOT version in projects... [INFO] (develop) Checking dependencies and plugins for snapshots ... What is the release version for "wildfly-spring-batch"? (com.cortez.wildfly.batch:wildfly-spring-batch) [1.0]: [INFO] ensuring origin exists... [INFO] (release/1.0) adding snapshot to pom versions... [INFO] (release/1.0) updating poms for all projects... [INFO] turn on debug logging with -X to see exact changes [INFO] (release/1.0) updating pom for wildfly-spring-batch... What is the development version for "wildfly-spring-batch"? (com.cortez.wildfly.batch:wildfly-spring-batch) [1.1-SNAPSHOT]: [INFO] (develop) updating poms with next development version... [INFO] (develop) updating poms for all projects... [INFO] turn on debug logging with -X to see exact changes [INFO] (develop) updating pom for wildfly-spring-batch... [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ You get an interactive menu to pick the version numbers you want to release, the same way as Maven Release Plugin. I’m developing on the master branch, but during this process a release branch is created with the release versions and development branch with the new development versions. release-prepare-branches radcortez:wildfly-spring-batch radcortez$ git branch -avv develop 728856a [origin/develop] updating poms for 1.1-SNAPSHOT development master 0b2364b [origin/master] Added documentation. * release/1.0 9f88a42 updating poms for branch '1.0' with snapshot versions remotes/origin/master 0b2364b Added documentation. Now the cool thing about this, is that everything is still in your local environment! If you are not happy with the changes, you can get rid of the branches and start over. No build was performed at this point. If we want to release, just run mvn jgitflow:release-finish: release-finish radcortez:wildfly-spring-batch radcortez$ mvn jgitflow:release-finish [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building wildfly-spring-batch 1.0 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- jgitflow-maven-plugin:1.0-m3:release-finish (default-cli) @ wildfly-spring-batch --- [INFO] ensuring origin exists... [INFO] running jgitflow release finish... [INFO] ensuring origin exists... [INFO] (release/1.0) Updating poms for RELEASE [INFO] (release/1.0) removing snapshot from pom versions... [INFO] (release/1.0) updating poms for all projects... [INFO] turn on debug logging with -X to see exact changes [INFO] (release/1.0) updating pom for wildfly-spring-batch... [INFO] (release/1.0) Checking for RELEASE version in projects... [INFO] (release/1.0) Checking dependencies and plugins for snapshots ... [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building wildfly-spring-batch 1.0 In this step, the release branch is going to get merged as described in A successful Git branching model and create the tag. Remember, nothing has been pushed yet, so you can always revert the process. Let’s have a look into the branches and tags now: branch-tag radcortez:wildfly-spring-batch radcortez$ git branch -avv * develop a8e762b [origin/develop] Updating develop poms back to pre merge state master b6fbda0 [origin/master: ahead 3] Merge branch 'release/1.0' remotes/origin/master 0b2364b Added documentation. radcortez:wildfly-spring-batch radcortez$ git tag 1.0 Now you’re a push away to complete your release and ready to keep developing in your new updated development branch. How easy was that? Conclusion Looking into some differences between the original release plugin and jgitflow:You don’t have to worry about stage commits. Everything is local until you push. No more problems with other people changing pom.xml during the process. Your project is only built once, saving release time. Very easy to setup. Everything is picked from your Git configuration.When I was investigating / writing, I’ve found this very interesting post, about an alternative way to perform the release. It’s worth reading: http://axelfontaine.com/blog/final-nail.html by Axel Fontaine.Reference: Maven Git Release from our JCG partner Roberto Cortez at the Roberto Cortez Java Blog blog....
enterprise-java-logo

Compile-time checking JPA queries

JPA provides several alternatives for querying data. Such alternatives may be classified attending to a variety of criteria, eg, language used (SQL vs JPQL) or whether queries are static (compilation time) or dynamic (execution time). Static queries are defined using annotations @NamedQuery (javax.persistence.NamedQuery) and @NamedQueries (javax.persistence.NamedQueries) in the @Entity class definition itself:         @NamedQuery( name="findAllCustomersWithName", query="SELECT c FROM Customer c WHERE c.name LIKE :custName" ) On the other hand, EntityManager provides methods createQuery(…) y createNativeQuery(…) which take either a JPQL or a SQL query, respectively. Thus, queries can be defined both in compilation or execution time. (Note: It is advisable to always use parametrized queries using methods setParameter(…) from Query to avoid SQL Injection vulnerabilities.) Criteria API However, JPA provides an alternative approach to query objects: Criteria API. Indeed, one of the motivations to switch to JPA is to deal with objects rather than SQL dialects, isn’t it ? Let’s look a sample code. Entity definition: @Entity public class User {@Id private Integer userId;@Basic @Column(length=15, nullable=false) private String name;@Basic @Column(length=64, nullable=false) private String userDigestedPasswd;@Basic @Column(length=50, nullable=true) private String email;@Basic @Column(nullable=false) public Integer privilegeLevel;@Basic @Column(nullable=false) private Boolean active; } Let’s query db and check results (using JUnit): public class UserTest { @Test public void testUserCriteria(){ EntityManagerFactory emf = null; EntityManager em = null; try { emf = Persistence.createEntityManagerFactory("criteria"); em = emf.createEntityManager(); final CriteriaBuilder cb = em.getCriteriaBuilder(); final CriteriaQuery<User> q = cb.createQuery(User.class); final Root<User> users = q.from(User.class); final Predicate condition = cb.equal(users.get("privilegeLevel"), 5); q.select(users).where(condition).orderBy(cb.asc(users.get("userId"))); em.getTransaction().begin(); List<User> result = em.createQuery(q).getResultList(); em.getTransaction().commit();assertNotNull(result); assertEquals(2, result.size());assertEquals(1, (int)result.get(0).getUserId()); assertEquals("Pepe", result.get(0).getName());assertEquals(3, (int)result.get(1).getUserId()); assertEquals("Dolores", result.get(1).getName());} catch (Exception e) { fail("Unexpected Exception " + e.getMessage()); } finally { if (em != null) em.close(); if (emf != null) emf.close(); } } } Following lines show query creation: final CriteriaBuilder cb = em.getCriteriaBuilder(); final CriteriaQuery<User> q = cb.createQuery(User.class); final Root<User> users = q.from(User.class); final Predicate condition = cb.equal(users.get("privilegeLevel); q.select(users).where(condition).orderBy(cb.asc(users.get("userId First of all, get a CriteriaBuilder from an EntityManager. Then, get a CriteriaQuery instance, setting the class to hold results. In our case, User.class: final CriteriaBuilder cb = em.getCriteriaBuilder(); final CriteriaQuery<User> q = cb.createQuery(User.class); Following, the Entity to run the query against must be set: final Root<User> users = q.from(User.class); Now it’s time to set query matching conditions. In the sample code, the condition is just attribute privilegeLevel to be equals to 5: final Predicate condition = cb.equal(users.get("privilegeLevel"), 5); Finally, query is built adding conditions on Root. Grouping and sorting options may be set too (ie, ascending sorting is set on userId): q.select(users).where(condition).orderBy(cb.asc(users.get(“userId”))); Please have a look at CriteriaBuilder for different options. Grouping and sorting options may be found at CriteriaQuery. Using metamodel for compile-time checking Note the query we have just build requires to keep track of object attributes names. Eg, to build the query, the name of the attribute privilegeLevel is used. However, if attribute name were changed later, the code would compile and only fail at runtime: final CriteriaQuery<User> q = cb.createQuery(User.class); final Root<User> users = q.from(User.class); final Predicate condition = cb.equal(users.get("privilegeLevel"), 5); q.select(users).where(condition).orderBy(cb.asc(users.get("userId"))); That is no good. Fortunately, using metamodel, we will be able to build compile-time checked queries. A brief introduction can be found at The Java EE6 Tutorial. Using metamodel, the code will reference an SingularAttribute of the object rather than using a String holding the object attribute name. So, if object attribute were changed later, the compiler would flag it for us. First of all, the correspondent metamodel class (EntityType) must be created. Although it can achieved by several ways, probably the easiest one, for openJPA implementation, is to add a openJPA build flag:  -Aopenjpa.metamodel=true. So we have the class User_ created, which is the correspondent metamodel class for User: * Generated by OpenJPA MetaModel Generator Tool. **/ package com.wordpress.tododev.criteria.entities; import javax.persistence.metamodel.SingularAttribute; @javax.persistence.metamodel.StaticMetamodel (value=com.wordpress.tododev.criteria.entities.User.class) @javax.annotation.Generated (value="org.apache.openjpa.persistence.meta.AnnotationProcessor6",date="Mon Mar 04 16:47:46 CET 2013") public class User_ { public static volatile SingularAttribute<User,Boolean> active; public static volatile SingularAttribute<User,String> email; public static volatile SingularAttribute<User,String> name; public static volatile SingularAttribute<User,Integer> privilegeLevel; public static volatile SingularAttribute<User,String> userDigestedPasswd; public static volatile SingularAttribute<User,Integer> userId; } If such class were added to code repo, any later change to class User would remain unnoticeable. Moreover, it is not a good idea to add auto-generated items to code versioning systems. Using ant, maven or similar tools, a target could be added to create metamodel classes. Such target should be executed after any change to JPA Entities. Also possible to use IDE for that. Eg, for those using Eclipse, just need to add the already mentioned compilation flag to Properties->Java Compiler->Annotation Processor and the lib (jar) containing the Annotation Processor for the chosen JPA implementation to section Factory Path within Annotations Processor (could lead to compilation issues in auto mode, provided that metamodel class must be compiled before the code using it). Let us add another test to the suite. This one will not provide a String containing the attribute name, but use the metamodel class instead: @Test public void testUserCriteriaMetaModel(){ EntityManagerFactory emf = null; EntityManager em = null; try { emf = Persistence.createEntityManagerFactory("criteria"); em = emf.createEntityManager(); final CriteriaBuilder cb = em.getCriteriaBuilder(); final CriteriaQuery<User> q = cb.createQuery(User.class); final Metamodel m = em.getMetamodel(); final Root<User> user = q.from(m.entity(User.class)); final Predicate condition = cb.equal(user.get(User_.privilegeLevel), 5); q.select(user).where(condition).orderBy(cb.asc(user.get(User_.userId)));em.getTransaction().begin(); List<User> result = em.createQuery(q).getResultList(); em.getTransaction().commit();assertNotNull(result); assertEquals(2, result.size());assertEquals(1, (int)result.get(0).getUserId()); assertEquals("Pepe", result.get(0).getName());assertEquals(3, (int)result.get(1).getUserId()); assertEquals("Dolores", result.get(1).getName()); } catch (Exception e) { fail("Unexpected Exception " + e.getMessage()); } finally { if (em != null) em.close(); if (emf != null) emf.close(); } } More relevant changes are user.get(User_.privilegeLevel) instead of users.get(“privilegeLevel”) and  user.get(User_.userId) instead of  users.get(“userId”).Download source code from GitHub.Reference: Compile-time checking JPA queries from our JCG partner Sergio Molina at the TODOdev blog....
android-logo

Android Listview with multiple row layout

In many posts we talked extensively about ListView and how to handle it: creating custom adapter or handling user interactions. In this post, I will cover another aspect related to the ListView that was not covered in the past: ListView with multiple row layout. By now we have seen rows having the same layout, anyway it is possible to have rows with different layouts. We want to have something like the pic shown below:        In this app, we show a Contact list that has two different layouts one that uses an image and another one without image. Even if the example is quite simple, it is enough to understand how to use several ListView methods to get this result. How to have multiple layout Usually when we want to customize the ListView data we use a custom adapter. We know Android provides some basic adapter ready-to-use (i.e ArrayAdapter, SimpleAdapter and so on) . We know, already, that all these adapters have in a common a father class known as BaseAdapter. When we want to customize how the ListView display the data, we can use one of the adapter class provided by Android or implement our custom adapter, in this case we will create a custom adapter extending the BaseAdapter. The BaseAdapter has two methods that are very useful if we want to have multiple row layouts:public int getItemViewType(int position) public int getViewTypeCount()The method getViewTypeCount “returns the number of types of Views that will be created by getView(int, View, ViewGroup)“. In other words this method returns how many different layouts we have in our ListView. The getItemViewType returns the view type of the current row, if you look at the method signature we have the position as parameter. One thing we should notice is that this method must return an integer value between 0 and the getViewTypeCount() – 1. So if we want to have multiple row layout, we have to override these methods and returns the right values. Multiple row layout implementation As first thing, we have to create a custom adapter, that we call ContactAdapter: public class ContactAdapter extends BaseAdapter { ... } and to have two different layouts, we override: @Override public int getViewTypeCount() { return 2; } and then we have to implement the logic to select the type of layout to assign to the row according to the position value: @Override public int getItemViewType(int position) { return (contactList.get(position).getContactType() == ContactType.CONTACT_WITH_IMAGE) ? 0 : 1; } In this method we use getContactType to know which layout to use, as you can see we return 0 or 1. Now we have to implement two different layout: they are very similar: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"><ImageView android:layout_width="48dp" android:layout_height="48dp" android:id="@+id/img"/><TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/name" android:layout_toRightOf="@id/img" android:layout_marginTop="2dp"/><TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/surname" android:layout_toRightOf="@id/name" android:layout_marginLeft="4dp"/><TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/email" android:layout_below="@id/name" android:layout_alignStart="@id/name" android:layout_marginTop="4dp"/> </RelativeLayout> and the other one without image is: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"><TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/name"/><TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/surname" android:layout_toRightOf="@id/name" android:layout_marginLeft="4dp"/><TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/email" android:layout_below="@id/name" android:layout_alignStart="@id/name" android:layout_marginTop="4dp"/> </RelativeLayout> Now we have simply to override, in our custom adapter, the getView method: @Override public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; int type = getItemViewType(position); if (v == null) { // Inflate the layout according to the view type LayoutInflater inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); if (type == 0) { // Inflate the layout with image v = inflater.inflate(R.layout.image_contact_layout, parent, false); } else { v = inflater.inflate(R.layout.simple_contact_layout, parent, false); } } // Contact c = contactList.get(position);TextView surname = (TextView) v.findViewById(R.id.surname); TextView name = (TextView) v.findViewById(R.id.name); TextView email = (TextView) v.findViewById(R.id.email);if (type == 0) { ImageView img = (ImageView) v.findViewById(R.id.img); img.setImageResource(c.imageId); }surname.setText(c.surname); name.setText(c.name); email.setText(c.email);return v; } Finishing the app Now we have our custom adapter is very easy to use it and bind it to the ListView. In the main activity that holds the ListView: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); ContactAdapter ca = new ContactAdapter(createContact(20), this); ListView lv = (ListView) findViewById(R.id.contact_list); lv.setAdapter(ca); }Source code available soon.Reference: Android Listview with multiple row layout from our JCG partner Francesco Azzola at the Surviving w/ Android blog....
spring-logo

Spring MVC Integration Testing: Assert the given model attribute(s) have global errors

In order to report a global error in Spring MVC using Bean Validation we can create a custom class level constraint annotation. Global errors are not associated with any specific fields in the validated bean. In this article I will show how to write a test with Spring Test that verifies if the given model attribute has global validation errors.     Custom (Class Level) Constraint For the sake of this article, I created a relatively simple class level constraint called SamePassword, validated by SamePasswordValidator: @Target({TYPE, ANNOTATION_TYPE}) @Retention(RUNTIME) @Constraint(validatedBy = SamePasswordsValidator.class) @Documented public @interface SamePasswords { String message() default "passwords do not match"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; } As you can see below, the validator is really simple: public class SamePasswordsValidator implements ConstraintValidator<SamePasswords, PasswordForm> {@Override public void initialize(SamePasswords constraintAnnotation) {}@Override public boolean isValid(PasswordForm value, ConstraintValidatorContext context) { if(value.getConfirmedPassword() == null) { return true; } return value.getConfirmedPassword() .equals(value.getPassword()); } } The PasswordForm is just a POJO with some constraint annotations, inclduing the once I have just created: @SamePasswords public class PasswordForm { @NotBlank private String password; @NotBlank private String confirmedPassword;// getters and setters omitted for redability} @Controller The controller has two methods: to display the form and to handle the submission of the form: @Controller @RequestMapping("globalerrors") public class PasswordController {@RequestMapping(value = "password") public String password(Model model) { model.addAttribute(new PasswordForm()); return "globalerrors/password"; }@RequestMapping(value = "password", method = RequestMethod.POST) public String stepTwo(@Valid PasswordForm passwordForm, Errors errors) { if (errors.hasErrors()) { return "globalerrors/password"; } return "redirect:password"; } } When the password validation fails, a global error is registered in a BindingResult (Errors in the above example) object. We could then display this error on top of the form in a HTML page for example. In Thymeleaf this would be: <div th:if="${#fields.hasGlobalErrors()}"> <p th:each="err : ${#fields.globalErrors()}" th:text="${err}">...</p> </div> Integration Testing with Spring Test Let’s setup an integration test: @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration public class AccountValidationIntegrationTest {@Autowired private WebApplicationContext wac; private MockMvc mockMvc;@Before public void setUp() throws Exception { mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); } } The first test verifies that sending a form with empty password and confirmedPassword fails: @Test public void failsWhenEmptyPasswordsGiven() throws Exception { this.mockMvc.perform(post("/globalerrors/password") .param("password", "").param("confirmedPassword", "")) .andExpect( model().attributeHasFieldErrors( "passwordForm", "password", "confirmedPassword" ) ) .andExpect(status().isOk()) .andExpect(view().name("globalerrors/password")); } In the above example, the test verifies if there are field errors for both password and confirmedPassword fields. Similarly, I would like to verify that when given passwords do not match, I get a specific, global error. So I would expect something like this: .andExpect(model().hasGlobalError("passwordForm", "passwords do not match")). Unfortunately, ModelResultMatchers returned by MockMvcResultMatchers#model() does not provide methods to assert the given model attribute(s) have global errors. Since it is not there, I created my own matcher that extends from ModelResultMatchers. The Java 8 version of the code is below: public class GlobalErrorsMatchers extends ModelResultMatchers {private GlobalErrorsMatchers() { }public static GlobalErrorsMatchers globalErrors() { return new GlobalErrorsMatchers(); }public ResultMatcher hasGlobalError(String attribute, String expectedMessage) { return result -> { BindingResult bindingResult = getBindingResult( result.getModelAndView(), attribute ); bindingResult.getGlobalErrors() .stream() .filter(oe -> attribute.equals(oe.getObjectName())) .forEach(oe -> assertEquals( "Expected default message", expectedMessage, oe.getDefaultMessage()) ); }; }private BindingResult getBindingResult(ModelAndView mav, String name) { BindingResult result = (BindingResult) mav.getModel().get(BindingResult.MODEL_KEY_PREFIX + name); assertTrue( "No BindingResult for attribute: " + name, result != null ); assertTrue( "No global errors for attribute: " + name, result.getGlobalErrorCount() > 0 ); return result; } } With the above addition I am now able to verify global validation errors like here below: import static pl.codeleak.demo.globalerrors.GlobalErrorsMatchers.globalErrors;@Test public void failsWithGlobalErrorWhenDifferentPasswordsGiven() throws Exception { this.mockMvc.perform(post("/globalerrors/password") .param("password", "test").param("confirmedPassword", "other")) .andExpect(globalErrors().hasGlobalError( "passwordForm", "passwords do not match") ) .andExpect(status().isOk()) .andExpect(view().name("globalerrors/password")); } As you can see extending Spring Test’s matchers and providing you own is relatively easy and can be used to improve validation verification in an integration test. ResourcesThe source code for this article can be found here: https://github.com/kolorobot/spring-mvc-beanvalidation11-demo.Reference: Spring MVC Integration Testing: Assert the given model attribute(s) have global errors from our JCG partner Rafal Borowiec at the Codeleak.pl blog....
java-logo

Oracle’s Latest Java 8 Update Broke Your Tools — How Did it Happen?

If you’ve been keeping up with the news in the Java world lately, you’ve probably heard that the latest Java 8 build released by Oracle, Java 8u11 (and Java 7u65), introduced errors and broke some popular 3rd party tools such as ZeroTurnaround’s JRebel, Javassist, Google’s Guice, and even Groovy itself. The errors spewed by the JVM are long and verbose, but in essence they look something like this: Exception in thread "main" java.lang.VerifyError: Bad method call from inside of a branch Exception Details: Location: com/takipi/tests/dc/DepthCounter.()V @10: invokespecial … The reason these errors suddenly started appearing stems from the fact that the bytecode verifier in the latest updates is a bit more strict than that of previous versions. Unlike previous versions, it does not allow calls to super-constructors from within branched code. Let’s break it down. Java bytecode and the bytecode verifier Bytecode is the intermediate language the JVM actually executes, and in which compiled .class files are written. The JVM’s machine code, if you will. All JVM-based languages are compiled into bytecode, from Java, through Scala, Groovy, Clojure, and so on. The JVM doesn’t know and doesn’t care what the source language was — it only knows bytecode. I’m not going to go into how bytecode works, as it is a subject worthy of a post (or several posts) of its own, but just to get a feel for what bytecode looks like — take this simple Java method for example: int add(int x, int y) { int z = x + y; return z; } When compiled, its bytecode looks like this: ILOAD x ILOAD y IADD ISTORE z ILOAD z IRETURN When the JVM loads a class file from the classpath into memory, it must first make sure the bytecode is valid and that the code is structured correctly. It basically checks if the code that’s being loaded can actually be executed. If the bytecode is good, the class is successfully loaded into memory; otherwise, a VerifyError is thrown, just like the one at the beginning of the post. This process is called bytecode verification, and the part of the JVM that’s responsible for it is the bytecode verifier. Why did it break? In order for bytecode to pass verification, it must adhere to a set of rules defined in the class file format specification. As the JVM was originally designed with the Java programming language in mind, many of these rules are directly derived from Java rules and constraints. One such well-known constraint in the Java language, is that the very first thing you must do in a constructor, before doing anything else, is call either super(…) or this(…). Any piece of code before that — and your code won’t compile. Even when you don’t explicitly write super(), the compiler implicitly inserts it for you at the very beginning of the constructor. The same constraint exists, at least on paper, in the bytecode verification rules. However, it turns out that up until these recent JDK updates, this constraint had not been fully enforced. This means, that although no Java compiler would ever let you compile this code: public static class ClassyClass { public ClassyClass() { if (checkSomething()) { super(); } else { super(getSomething()); } } } … The equivalent bytecode would pass verification! ALOAD this INVOKESTATIC checkSomething() : boolean IFEQ L2 INVOKESPECIAL super() : void GOTO L2 L1: INVOKESTATIC getSomething() : int INVOKESPECIAL super(int) : void L2: RETURN You can see in the simplified bytecode above that there are both an invocation (INVOKESTATIC) and even a branch (IFEQ — “if equal”) taking place before the first call to the super-constructor (INVOKESPECIAL). Bear in mind that although the above code is not legal Java, and thus no Java compiler would ever produce the equivalent bytecode — there are plenty of other tools which potentially could, such as compilers of other JVM languages which do not follow Java’s constraints, and many other tools such as bytecode instrumentation libraries. The ability to execute code before the call to super can be pretty useful! However, Java 8 update 11 brought with it a stricter bytecode verifier, one which rejects classes that use such constructs in their bytecode, and causes verification errors to be thrown and JVMs to crash. On one hand, the new verifier is loyal to the spec, making sure our JVMs are safe from bad code. On the other hand, many tools which utilize bytecode instrumentation, such as debuggers and aspect weavers (AOP) often make use of constructs such as the above. How to solve it? A fix to the bytecode verifier has already been committed, but it hasn’t been released yet. However, many of the affected tools and projects are already releasing fixed versions and workarounds. In the meantime, if you happen to encounter one of these errors, you can try starting your JVM with the -noverify command line argument. This option instructs the JVM to skip bytecode verification when loading classes.Reference: Oracle’s Latest Java 8 Update Broke Your Tools — How Did it Happen? from our JCG partner Niv Steingarten at the Takipi blog....
Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close