Professional JavaEE Design Pattern

515

Transcript of Professional JavaEE Design Pattern

CONTENTSFOREWORDINTRODUCTION

WHO THIS BOOK IS FORWHAT THIS BOOK COVERSHOW THIS BOOK IS STRUCTUREDWHAT YOU NEED TO USE THIS BOOKMOTIVATION FOR WRITINGCONVENTIONSSOURCE CODEERRATAP2P.WROX.COMCONTACT THE AUTHORSNOTES

PART I INTRODUCTION TO JAVA EEDESIGN PATTERNS

CHAPTER 1 A BRIEF OVERVIEW OFDESIGN PATTERNS

WHAT IS A DESIGN PATTERN?DESIGN PATTERN BASICSENTERPRISE PATTERNSSUMMARYNOTES

CHAPTER 2 THE BASICS OF JAVA EEMULTITIER ARCHITECTURE

2

THE CLIENT TIERTHE MIDDLE TIERTHE EIS TIERJAVA EE SERVERSTHE JAVA EE WEB PROFILECORE PRINCIPLES OF JAVA EECONVENTION OVERCONFIGURATIONCONTEXT AND DEPENDENCYINJECTIONINTERCEPTORSSUMMARYEXERCISES

PART II IMPLEMENTING DESIGNPATTERNS IN JAVA EE

CHAPTER 3 FAÇADE PATTERNWHAT IS A FAÇADE?IMPLEMENTING THE FAÇADEPATTERN IN PLAIN CODEIMPLEMENTING THE FAÇADEPATTERN IN JAVA EEWHERE AND WHEN TO USE THEFAÇADE PATTERNSUMMARYEXERCISESNOTES

CHAPTER 4 SINGLETON PATTERN

3

WHAT IS A SINGLETON?IMPLEMENTING THE SINGLETONPATTERN IN JAVA EEWHERE AND WHEN TO USE THESINGLETON PATTERNSUMMARYEXERCISESNOTES

CHAPTER 5 DEPENDENCYINJECTION AND CDI

WHAT IS DEPENDENCYINJECTION?IMPLEMENTING DI IN PLAINCODEIMPLEMENTING DI IN JAVA EESUMMARYEXERCISESNOTES

CHAPTER 6 FACTORY PATTERNWHAT IS A FACTORY?FACTORY METHODABSTRACT FACTORYIMPLEMENTING THE FACTORYPATTERN IN JAVA EEWHERE AND WHEN TO USE THEFACTORY PATTERNSSUMMARY

4

EXERCISESNOTES

CHAPTER 7 DECORATOR PATTERNWHAT IS A DECORATOR?IMPLEMENTING THEDECORATOR PATTERN IN PLAINCODEIMPLEMENTING THEDECORATOR PATTERN IN JAVAEEWHERE AND WHEN TO USE THEDECORATOR PATTERNSUMMARYEXERCISESNOTES

CHAPTER 8 ASPECT-ORIENTEDPROGRAMMING (INTERCEPTORS)

WHAT IS ASPECT-ORIENTEDPROGRAMMING?IMPLEMENTING AOP IN PLAINCODEASPECTS IN JAVA EE,INTERCEPTORSWHERE AND WHEN TO USEINTERCEPTORSSUMMARYNOTES

CHAPTER 9 ASYNCHRONOUS

5

WHAT IS ASYNCHRONOUSPROGRAMMING?IMPLEMENTING ASYNCHRONOUSPATTERN IN PLAIN CODEASYNCHRONOUS PROGRAMMINGIN JAVA EEWHERE AND WHEN TO USEASYNCHRONOUS PROGRAMMINGSUMMARYEXERCISESNOTES

CHAPTER 10 TIMER SERVICEWHAT IS THE TIMER SERVICE?IMPLEMENTING A TIMER IN JAVAEESUMMARYEXERCISESNOTES

CHAPTER 11 OBSERVER PATTERNWHAT IS AN OBSERVER?IMPLEMENTING THE OBSERVERPATTERN IN PLAIN CODEIMPLEMENTING THE OBSERVERPATTERN IN JAVA EEWHERE AND WHEN TO USE THEOBSERVER PATTERNSUMMARYEXERCISES

6

NOTESCHAPTER 12 DATA ACCESS PATTERN

WHAT IS A DATA ACCESSPATTERN?OVERVIEW OF THE DATA ACCESSPATTERNIMPLEMENTING THE DATAACCESS PATTERN IN JAVA EEWHERE AND WHEN TO USE THEDATA ACCESS PATTERNSUMMARYEXERCISESNOTES

CHAPTER 13 RESTFUL WEBSERVICES

WHAT IS REST?THE SIX CONSTRAINTS OF RESTRICHARDSON MATURITY MODELOF REST APIDESIGNING A RESTFUL APIREST IN ACTIONIMPLEMENTING REST IN JAVA EEHATEOASWHERE AND WHEN TO USE RESTSUMMARYEXERCISESNOTES

7

CHAPTER 14 MODEL VIEWCONTROLLER PATTERN

WHAT IS THE MVC DESIGNPATTERN?IMPLEMENTING THE MVCPATTERN IN PLAIN CODEIMPLEMENTING THE MVCPATTERN IN JAVA EETHE FACESSERVLETMVC USING THE FACESSERVLETWHERE AND WHEN TO USE THEMVC PATTERNSUMMARYEXERCISESNOTE

CHAPTER 15 OTHER PATTERNS INJAVA EE

WHAT ARE WEBSOCKETS?WHAT IS MESSAGE-ORIENTATEDMIDDLEWAREWHAT IS THE MICROSERVICEARCHITECTURE?FINALLY, SOME ANTI-PATTERNSNOTES

PART III SUMMARYCHAPTER 16 DESIGN PATTERNS: THEGOOD, THE BAD, AND THE UGLY

8

THE GOOD: PATTERNS FORSUCCESSTHE BAD: OVER AND MISUSE OFPATTERNS…AND THE UGLYSUMMARYNOTES

TITLEPAGECOPYRIGHTDEDICATIONABOUT THE AUTHORSABOUT THE TECHNICAL EDITORCREDITSACKNOWLEDGMENTSADVERTWILEY END USER LICENSE AGREEMENT

List of TablesChapter 10

Table 10.1

Table 10.2

Table 10.3

Table 10.4

List of IllustrationsChapter 1

9

Figure 1.1 A class diagram showinginheritance

Figure 1.2 The singleton pattern classdiagram

Chapter 2

Figure 2.1 Multitier architecture showingthe interaction between tiers

Figure 2.2 Technology used in the Weband Business layers

Chapter 3

Figure 3.1 Class diagram of the façadepattern

Chapter 4

Figure 4.1 The singleton pattern classdiagram

Chapter 6

Figure 6.1 The class diagram shows thestructure of the factory method pattern.You can see how the object creation isencapsulated in the subclasses.

Figure 6.2 As can be seen in the classdiagram, you can use the abstract factorypattern to group existing factories andencapsulate how you access them.

Chapter 7

Figure 7.1 Class diagram of the decoratorpattern

10

Chapter 9

Figure 9.1 Asynchronous flow diagram

Chapter 11

Figure 11.1 Class diagram of the observerpattern

Chapter 12

Figure 12.1 Class diagram of the dataaccess pattern

Chapter 14

Figure 14.1 Diagram of the model viewcontroller pattern

Figure 14.2 Diagram of Spring’s MVCimplementation

Chapter 15

Figure 15.1 Point-to-pointimplementation

Figure 15.2 Publish/subscribeimplementation

Figure 15.3 Monolithic architecture

Figure 15.4 The AKF cube should haveX-, Y-, and Z-axis scaling.

Figure 15.5 Y-axis decomposition

11

FOREWORDIgnorant men raise questions that wise menanswered a thousand years ago

—JOHANN WOLFGANG VON GOETHE

Design patterns are our link to the past and thefuture. They make up a foundational languagethat represents well understood solutions tocommon problems that talented engineersbefore us have added to our collectiveknowledge base. Design patterns or blueprintsexist in every engineering field in one way oranother. Software development is no different.Indeed, design patterns are probably our mosttangible link to engineering rather than themore organic and less regimented world of theartisan or craftsman. The art and science ofdesign patterns was brought to the world ofsoftware engineering—and more specifically toenterprise Java—by the seminal Gang of Four(GoF) book. They have been with us ever sincethrough our adventures in J2EE, Spring, andnow modern lightweight Java EE. This is forvery good reasons. Server-side Java developerstend to write the type of mission criticalapplications that need to stand the test of timeand hence benefit the most from the disciplinethat design patterns represent.

12

It really takes a special kind of person to write abook on design patterns, let alone a book onhow to utilize design patterns in Java EEapplications. You require not only basicknowledge of APIs and the patterns themselves,but deep insight that can only come withhard-earned experience, as well as an innateability to explain complex concepts elegantly. Iam glad Java EE now has Murat and Alex toaccomplish the mighty feat.

This book fulfills a much needed gap and fills itwell. It is also very good that the book is on thecutting edge and covers Java EE 7 and not justJava EE 6 or Java EE 5. In fact many of thedesign patterns covered, like Singleton, Factory,Model-View-Controller (MVC), Decorator, andObserver, are now incorporated right into theJava EE platform. Others like Facade, DataAccess Object (DAO), and Data Transfer Object(DTO) fit elegantly on top. Murat and Alextackle each pattern, explain its pragmaticmotivation, and discuss how it fits into Java EE.

It is an honor and a privilege to write a smallopening part of this very important book that Ihope will become a very useful part of everygood Java EE developer's bookshelf. I hope youenjoy the book, and that it helps you writebetter, more satisfying enterprise Javaapplications.

13

M. REZA RAHMANJava EE/GlassFish EvangelistOracle Corporation

14

INTRODUCTIONTHIS BOOK DISCUSSES THE CLASSICDESIGN PATTERNS that were first mentionedin the famous book by the GoF1 and updatesthem specifically for Java EE 6 and 7.

In every chapter we describe the traditionalimplementation of each pattern and then showhow to implement it using Java EE-specificsemantics.

We use full code examples to demonstrate boththe traditional and Java EE implementationsand color each chapter with real-life stories thatshow the use (or misuse) of the pattern.

We investigate the pros and cons of eachpattern and examine their usages. Each chapterfinishes with some exercises that challenge yourunderstanding of the pattern in Java EE.

WHO THIS BOOK IS FORThis book is for everyone with any level ofexperience. It covers almost everything about apattern, from how it is referred to in otherbooks, to code on basic Java implementation, toJava EE implementation, and finally real lifeexamples of how and when to use a specificpattern. It also has real life war stories that talkabout good and bad practices.

15

Having some basic knowledge of designpatterns and Java EE will aid you as you readthis book.

If you are already experienced with patternsand basic Java implementations, you mayprefer to jump into Java EE implementations.Refreshing your memory and knowledge ofdesign patterns could prove helpful.

WHAT THIS BOOK COVERSThis book covers all classical design patternsthat Java EE offers as part of standardimplementation, besides some new patterns.The coverage goes back to Java EE5 and is up todate for the latest version available, which isJava EE 7.

We hope this book will be a reference you willkeep on your shelf for a long time.

HOW THIS BOOK ISSTRUCTUREDEach chapter focuses on a design pattern. If thepattern is classical, a simple Javaimplementation is given after the explanation ofthe pattern. Each chapter offers war storiestelling a good or bad real life example about thepattern focused on/in the chapter. The warstory is followed by a Java EE implementation,example, and explanation. Each code sample

16

given can be run by itself. Finally, each chapterends with when and how to use the patterneffectively.

WHAT YOU NEED TO USE THISBOOKAny modern computer with an operatingsystem that has a Java Virtual Machine (JVM)implementation is sufficient to run the samplesgiven in this book. For ease of coding, you needan integrated development environment (IDE)of your own choice. The sample can run on anypopular modern IDEs including Eclipse,NetBeans, and IntelliJ.

You need the Java Development Kit (JDK) forJava EE7 to be able to compile and run the codesamples, but some of the code samples wouldalso work on previous Java EE JDKs.

You can use any Java EE7–compliantapplication server to run the samples. We ranall the code samples on Glassfish, which is thereference implementation server, and TomEE,which is the Java EE version of the popularJava web server Tomcat. You can use anyserver, but because Glassfish is the referenceimplementation, you might want to try it for thesamples.

To run the samples in this book, you need thefollowing:

17

An operating system that has a JDK for JavaEE7, such as Linux, Mac OS X, or Windows

Java EE 7 JDK

An IDE of your choice, such as Eclipse for JavaEE Developers, NetBeans, or IntelliJ

Java EE 7–compliant application server such asGlassFish or TomEE

The source code for the samples is available fordownload from the Wrox website at:

www.wrox.com/go/projavaeedesignpatterns

MOTIVATION FOR WRITINGIn November 2011, after having a debate onJava EE versus Spring for a project, I went backto my desk and wrote a blog post titled “JavaEE 6 and the Ewoks,”2 which became popularpretty quickly. The story was based on the TVshow How I Met Your Mother. In this show,Barney, who is the playboy character,introduced a theory that was focused on Ewoks,the teddy bear–like creatures introduced inEpisode VI of Star Wars. Fans have mixedfeelings on Ewoks.

According to Barney, those born before May 25,1973, when Return of the Jedi was released,think Ewoks are childish and simply hate them.

18

However, those born after that date find Ewokscute because they remind them of teddy bears.

Now back to my story. Engaging in a debatewith a customer about Java EE versus Springmade me realize that it’s similar to the Ewoktheory. Those who are old enough to have usedJ2EE 1.4 (EJB 1.0/2.0/2.1) in corporateprojects had a slow, unproductive developmentenvironment with RAM-eating and buggy IDEsand servers taking several minutes to boot. Thearchitecture was over engineered and probablyfailed, resulting in a migration to Spring. Thoseusers tended to hate Java EE with a passion, nomatter what version they used. The release ofJava EE 5 was underrated and did not reallyimpress anyone.

Java EE will never be J2EE again. It is nowopen, has a large community and reshapes itselfby assimilating good ideas from frameworkssuch as Spring and Hibernate. The first greatchange was the architecture and style of coding.Enterprise JavaBeans (EJB) followed thelightweight Plain Old Java Object (POJO)model, almost unusable entity beans werereplaced with Java Persistence API (JPA),REST and Web Services became standard andintegral parts of the run time, and annotationsreplaced XML configuration. Still, some mightargue that Java EE 5 was not ready for the hugeshift because it was not as mature as Spring,and the development environment was still not

19

responsive enough. Using Spring on Tomcatinstead of EJBs and Java EE 5 on anapplication server greatly increased thedevelopment productivity, but Java EE 5 wasstill a big step forward towards designing,leveraging, and architecting the Enterprise Javaplatform from scratch.

This shift was followed by Java EE 6 and 7,which used the same principles and ideas asJava EE 5. Java EE is a great choice fordevelopment, but the debate was not over,thanks to the Ewok theory.

It was a hot August day when I first got a callfrom Wrox/Wiley about whether I would beinterested in writing a Spring book. I wasexperienced and confident with implementingand developing in Spring, but there werealready tons of books written about it, whichmade it hard to see the value in writing a newone.

Besides, I was using Java EE more than eversince version 6 had been released. Consideringthe Spring versus Java EE debates, my blogposts, and the Ewoks, I felt like writing aboutJava EE. However, just like Spring, there weremany great Java EE books that I admired. Ialways had the feeling that some properties ofJava EE were underrated. Java EE has greatbuilt-in implementations of design patternswith simple use of annotations.

20

The classic patterns listed in the GoF book wereused extensively in almost all languages,frameworks, and platforms. J2EE was noexception and neither was Java EE. ActuallyJava EE took a bold step in providing defaultimplementations for many of those patterns,but still even most of the experienceddevelopers underestimated the value of thoseout of the box implementations.

I had been blogging about those patterns foralmost a year, so I decided to present acounteroffer to write a book on the “classic”design patterns in Java EE. As you are readingthis book now, you may guess the feedback waspositive.

This book fills the gap between the Java EEplatform with the classic design patterns fromthe GoF book as well as talking about newpatterns. This way we did not write just anotherJava EE book but a catalogue for designpatterns in Java EE.

I started blogging, writing and giving talks ondesign patterns in Java EE to extend myknowledge and experience on a platform I reallybelieved in, so the best thing about writing thisbook for me was that I had the chance to writeabout something I was really passionate about.Although my blog had simpler examples, I wasalready using it as a reference when I needed,so writing a book, which is more formally and

21

properly formatted while still following thesame idea was a great opportunity.

Every chapter that my coauthor Alex and Iwrote had the same goal: Write content that wewould like to read ourselves. The result is abook that we both want to keep as a reference.

We hope that you enjoy reading this book asmuch as we enjoyed writing it.

CONVENTIONSTo help you get the most from the text and keeptrack of what’s happening, we’ve used a numberof conventions throughout the book.

NOTE Notes indicates notes, tips, hints,tricks, or asides to the current discussion.

As for styles in the text:

We highlight new terms and important wordswhen we introduce them.

We show keyboard strokes like this: Ctrl+A.

We show file names, URLs, and code within thetext like so: persistence.properties.

We present code in two different ways:

We use a monofont type with no highlightingfor most code examples.

22

We use bold to emphasize code that isparticularly important in the presentcontext or to show changes from aprevious code snippet.

SOURCE CODEAs you work through the examples in this book,you may choose either to type in all the codemanually or to use the source code files thataccompany the book. All the source code usedin this book is available for download atwww.wrox.com. Specifically for this book, thecode download is on the Download Code tab at:

www.wrox.com/go/projavaeedesignpatterns

You can also search for the book atwww.wrox.com by ISBN (978-1-118-84341-3) tofind the code. A complete list of code downloadsfor all current Wrox books is available atwww.wrox.com/dynamic/books/download.aspx.

Each chapter starts with introducing a basicJava implementation of the pattern, if there isany. Next, the chapter lists a Java EEimplementation of the pattern that can onlycompile and run on the Java EE JDK and a JavaEE–compliant application server.

Most of the code on www.wrox.com iscompressed in .ZIP, .RAR, or a similar archive

23

format appropriate to the platform. Once youdownload the code, just decompress it with anappropriate compression tool.

ERRATAWe make every effort to ensure that there areno errors in the text or in the code. However, noone is perfect, and mistakes do occur. If youfind an error in one of our books, like a spellingmistake or a faulty piece of code, we would bevery grateful for your feedback. By sending inerrata, you may save another reader hours offrustration. At the same time, you will behelping us provide even higher qualityinformation.

To find the errata page for this book, go to:

www.wrox.com/go/projavaeedesignpatterns

Then click the Errata link. On this page, you canview all errata that has been submitted for thisbook and posted by Wrox editors.

If you don’t spot “your” error on the BookErrata page, go to www.wrox.com/contact/techsupport?.shtml andcomplete the form there to send us the erroryou have found. We’ll check the informationand, if appropriate, post a message to the book’serrata page and fix the problem in subsequenteditions of the book.

24

P2P.WROX.COMFor author and peer discussion, join the P2Pforums at http://p2p.wrox.com. Theforums are a web-based system for you to postmessages relating to Wrox books and relatedtechnologies and interact with other readersand technology users. The forums offer asubscription feature to e-mail you topics ofinterest of your choosing when new posts aremade. Wrox authors, editors, other industryexperts, and your fellow readers are present onthese forums.

At http://p2p.wrox.com, you will find anumber of different forums that will help you,not only as you read this book, but also as youdevelop your own applications. To join theforums, just follow these steps:

Go to http://p2p.wrox.com and clickthe Register link.

Read the terms of use and click Agree.

Complete the required information to join,as well as any optional information you wishto provide, and click Submit.

You will receive an e-mail with informationdescribing how to verify your account andcomplete the joining process.

25

NOTE You can read messages in the forumswithout joining P2P, but in order to post yourown messages, you must join.

Once you join, you can post new messages andrespond to messages that other users post. Youcan read messages at any time on the web. Ifyou would like to have new messages from aparticular forum e-mailed to you, click theSubscribe to This Forum icon by the forumname in the forum listing.

For more information about how to use theWrox P2P, be sure to read the P2P FAQs foranswers to questions about how the forumsoftware works, as well as many commonquestions specific to P2P and Wrox books. Toread the FAQs, click the FAQ link on any P2Ppage.

CONTACT THE AUTHORSIf you have any questions regarding thecontents of this book, the code, or any otherrelated matter you can contact the authorsdirectly on their blogs and via Twitter.

Murat Yener:

Blog—devchronicles.com

Twitter—@yenerm

Alex Theedom:

26

Blog—alextheedom.com

Twitter—@alextheedom

NOTES

1. Design Patterns: Elements of ReusableObject-Oriented Software (Addison-Wesley,1994): Erich Gamma, Richard Helm, RalphJohnson, John Vlissides.

2. Java EE 6 and theEwoks:?http://www.devchronicles.com/2011/11/javaee6-and-ewoks.html.

27

PART IIntroduction to Java EEDesign PatternsCHAPTER 1 : A Brief Overview of DesignPatterns

CHAPTER 2 : The Basics of Java EE

28

1A Brief Overview of DesignPatternsWHAT’S IN THIS CHAPTER?

An overview of design patterns

A short history about design patterns and whythey are important

The use of design patterns in the real world

The history and evolution of Java EnterpriseEdition

The emergence of enterprise patterns

How these design patterns have evolved in theenterprise environment

Why and how patterns become anti-patterns

This book is aimed at bridging the gap betweenthe traditional implementation of designpatterns in the Java SE environment and theirimplementation in Java EE.

If you are new to design patterns, this book willhelp you get up to speed quickly as each chapterintroduces the design pattern in asimple-to-understand way with plenty ofworking code examples.

29

If you are already familiar with design patternsand their implementation but are not familiarwith their implementation in the Java EEenvironment, this book is perfect for you. Eachchapter bridges the gap between the traditionalimplementation and the new, often easier,implementation in Java EE.

If you are an expert in Java, this book will act asa solid reference to Java EE and Java SEimplementations of the most common designpatterns.

This book focuses on the most common JavaEE design patterns and demonstrates how theyare implemented in the Java EE universe. Eachchapter introduces a different pattern byexplaining its purpose and discussing its use.Then it demonstrates how the pattern isimplemented in Java SE and gives a detaileddescription of how it works. From there, thebook demonstrates how the pattern is nowimplemented in Java EE and discusses its mostcommon usage, its benefits, and its pitfalls. Allexplanations are accompanied by detailed codeexamples, all of which can be downloaded fromthe website accompanying this book. At the endof each chapter, you’ll find a final discussionand summary that rounds up all you have readin the chapter. There are even some interestingand sometimes challenging exercises for you todo that will test your understanding of thepatterns covered in the chapter.

30

WHAT IS A DESIGN PATTERN?Design patterns are “descriptions ofcommunicating objects and classes that arecustomized to solve a general designproblem in a particular context.”

—GANG OF FOUR

Design patterns offer solutions to commonapplication design problems. In object-orientedprogramming, design patterns are normallytargeted at solving the problems associated withobject creation and interaction, rather than thelarge-scale problems faced by the overallsoftware architecture. They provide generalizedsolutions in the form of boilerplates that can beapplied to real-life problems.

Usually design patterns are visualized using aclass diagram, showing the behaviors andrelations between classes. A typical classdiagram looks like Figure 1.1.

Figure 1.1 A class diagram showinginheritance

31 Proudly sourced and uploaded by [StormRG]Kickass Torrents | TPB | ExtraTorrent | h33t

Figure 1.1 shows the inheritance relationshipbetween three classes. The subclassesCheckingAccount and SavingsAccountinherit from their abstract parent classBankAccount.

Such a diagram is followed by animplementation in Java showing the simplestimplementation. An example of the singletonpattern, which will be described in laterchapters, is shown in Figure 1.2.

Figure 1.2 The singleton pattern classdiagram

And here is an example of its simplestimplementation.

public enum MySingletonEnum {INSTANCE;public void

doSomethingInteresting(){}}

32

How Patterns Were Discovered and WhyWe Need ThemDesign patterns have been a hot topic since thefamous Gang of Four (GoF, made up of ErichGamma, Richard Helm, Ralph Johnson, andJohn Vlissides) wrote the book DesignPatterns: Elements of ReusableObject-Oriented Software,1 finally givingdevelopers around the world tried and testedsolutions to the commonest softwareengineering problems. This important bookdescribes various development techniques andtheir pitfalls and provides 23 object-orientedprogramming design patterns. These patternsare divided into three categories: creational,structural, and behavioral.

But why? Why did we suddenly realize weneeded design patterns so much?

The decision was not that sudden.Object-oriented programming emerged in the1980s, and several languages that built on thisnew idea shortly followed. Smalltalk, C++, andObjective C are some of the few languages thatare still prevalent today. They have broughttheir own problems, though, and unlike thedevelopment of procedural programming, thistime the shift was too fast to see what wasworking and what was not.

Although design patterns have solved manyissues (such as spaghetti code) that software

33

engineers have with procedural programminglanguages like C and COBOL, object-orientedlanguages have introduced their own set ofissues. C++ has advanced quickly, and becauseof its complexity, it has driven many developersinto fields of bugs such as memory leaks, poorobject design, unsafe use of memory, andunmaintainable legacy code.

However, most of the problems developers haveexperienced have followed the same patterns,and it’s not beyond reason to suggest thatsomeone somewhere has already solved theissues. Back when object-orientedprogramming emerged, it was still apre-Internet world, and it was hard to shareexperiences with the masses. That’s why it tooka while until the GoF formed a collection ofpatterns to well-known recurring problems.

Patterns in the Real WorldDesign patterns are infinitely useful and provensolutions to problems you will inevitably face.Not only do they impart years of collectiveknowledge and experience, design patternsoffer a good vocabulary between developers andshine a light on many problems.

However, design patterns are not a magicwand; they do not offer an out-of-the-boximplementation like a framework or a tool set.Unnecessary use of design patterns, justbecause they sound cool or you want to impress

34

your boss, can result in a sophisticated andoverly engineered system that doesn’t solve anyproblems but instead introduces bugs,inefficient design, low performance, andmaintenance issues. Most patterns can solveproblems in design, provide reliable solutionsto known problems, and allow developers tocommunicate in a common idiom acrosslanguages. Patterns really should only be usedwhen problems are likely to occur.

Design patterns were originally classified intothree groups:

Creational patterns—Patterns that controlobject creation, initialization, and classselection. Singleton (Chapter 4, “SingletonPattern”) and factory (Chapter 6, “FactoryPattern”) are examples from this group.

Behavioral patterns—Patterns that controlcommunication, messaging, and interactionbetween objects. The observer (Chapter 11,“Observer Pattern”) is an example from thisgroup.

Structural patterns—Patterns that organizerelationships between classes and objects,providing guidelines for combining and usingrelated objects together to achieve desiredbehaviors. The decorator pattern (Chapter 7,“Decorator Pattern”) is a good example of apattern from this group.

35

Design patterns offer a common dictionarybetween developers. Developers can use themto communicate in a much simpler way withouthaving to reinvent the wheel for every problem.Want to show your buddy how you are planningto add dynamic behavior at run time? No morestep-by-step drawings or misunderstandings.It’s plain and simple; you just utter a few words:“Let’s use a decorator pattern to address thisproblem!” Your friend will know what you aretalking about immediately, no furtherexplanation needed. If you already know what apattern is and use it in a right context, you arewell on your way to developing a durable andmaintainable application.

SUGGESTED READING

It’s strongly suggested that you read DesignPatterns: Elements of ReusableObject-Oriented Software by Erich Gamma,Richard Helm, Ralph Johnson, and JohnVlissides (Addison-Wesley, 1995) or HeadFirst Design Patterns by Eric Freeman,Elisabeth Robson, Bert Bates, and KathySierra (O’Reilly, 2004). Both are greatcompanions to this book and are invaluableguides for learning design patterns.

36

DESIGN PATTERN BASICSOne key point regarding design patterns is thatoveruse or unnecessary use can be troublesome.As soon as some developers learn new patterns,they show a great desire to use them wheneverthey can. However, doing so often results intheir project being bloated with singletons oroverwrapping via façades or unnecessarilycomplex decorators. Design patterns areanswers to problems, so unless there is aproblem or a chance for a problem to appear,there is no point implementing a pattern. Togive an example, using the decorator patternjust because there is a slim chance that anobject’s behavior might change in the featureintroduces development complexity today and amaintenance nightmare in the future.

ENTERPRISE PATTERNSJava 1.0 quickly became popular after it wasreleased in early 1996. The timing was perfectfor the introduction of a new language thatwould remove the complexity of memorymanagement, pointers, and the syntax ofC/C++. Java offered a gradual learning curvethat allowed many developers to adopt itquickly and to start programming in Java.However, there was something else thataccelerated the shift: applets. An applet is asmall application that runs in a website in aseparate process from the web browser and

37

adds functionality to the website that would notbe possible with HTML and CSS alone. Anexample would be an interactive graph orstreaming video feed.

With the rapid growth of the Internet, staticweb pages soon became archaic anduninteresting. The web user wanted a better,faster, and more beautiful surfing experience.Along came applets, which offered unbelievableinteractivity, effects, and action to thethen-static World Wide Web. Soon, dancingDuke (the symbol of Java) became the trendamong modern websites. However, nothingremains still for long on the Internet. Userswanted even more, yet applets failed miserablyat adapting to those wants, so they did notmaintain their popularity.

Nevertheless, applets were the driving forcebehind the Java platform’s fast adaptation andpopularity. Today (as this book is written) Javais still among the two most popularprogramming languages in the world.2

Java to Enterprise JavaFollowing the release of the Standard Edition ofJava, IBM introduced Enterprise JavaBeans(EJB) in 1997, which was adopted by Sun in1999 and formed part of the Enterprise JavaPlatform (J2EE) 1.2. In 1998 and prior to therelease of J2EE,3 Sun released a professional

38

version of Java labeled JPE. However, it wasn’tuntil after EJB was released that vendors anddevelopers became interested in adoptingenterprise Java. With the release of J2EE 1.3 in2001, Java became a key player in theenterprise world, and its position was sealedwith the release of J2EE 1.4 in 2003.

Version 1.4 was one of the greatest milestonesin Java’s history. It was widely adopted andmaintained its popularity for many years eventhough new versions were released. Vendorsand corporations were slow to adopt the newerversions, even though many had reasons tocomplain about J2EE1.4. Using it was likedriving a monster truck to the shops instead ofa family sedan. It was definitely powerful, but itwas simply too complicated and bloated withXML files, and neither the frameworks nor thecontainers were lightweight.

Yet J2EE became the most popular enterprisedevelopment platform. It had a set of featuresthat made it a great choice for enterprisedevelopment.

Portability—The JVM let Java code run onany operating system. Developers could developon Windows, test on Linux, but go intoproduction on a UNIX system.

Security—J2EE offered its own role-basedsecurity model.

39

Transactions—J2EE offered built-intransactions.

Language features from J2SE—J2SEoffered easy syntax, garbage collection, andgreat object-oriented programming features.

However, J2EE was not perfect. Soon enough,the complex structure of the platform with itsheavy use of XML configurations created theperfect problem-ridden environment.

The Emergence of Enterprise JavaPatternsThe complex programming models of J2EEsoon led many projects into deep waters.Applications developed with J2EE technologiestended to contain excessive amounts of“plumbing” code such as JNDI lookup code,XML configuration files, and try/catch blocksthat acquired and released JDBC resources.Writing and maintaining such code proved amajor drain on resources and was the source ofmany bugs and performance issues. The EJBcomponent model aimed to reduce complexitywhen implementing business logic, but it didnot succeed in this aim. The model was simplytoo complex and often overused.

After just a few years from the first release atthe JavaOne conference in 2000, Deepak Alur,John Crupi, and Dan Malks gave a talk titled“Prototyping Patterns for the J2EE Platform,”

40

which introduced several patterns targeted atcommon problems experienced in the design ofJ2EE applications. This talk would become abook. The following year, they published a bookcalled Core J2EE Patterns: Best Practices andDesign Strategies.4 In addition to the 15already well-known patterns, the authorsintroduced 6 new J2EE design patterns. Thenew patterns included Context Object andApplication Controller for the Presentation tier,Application Service and Business Object for theBusiness tier, and Domain Store and WebService Broker for the Integration tier.

Some of those patterns evolved from the“classic” GoF patterns, whereas others werenew and addressed the flaws of J2EE. In thefollowing years, several projects andframeworks such as Apache Camel werereleased that made the life of enterprisedevelopers easier. Even some, led by RodJohnson,5 made a bold step by moving awayfrom J2EE and releasing the SpringFramework. Spring soon became popular, andits popularity influenced great changes in thenew programming model behind Java EE.Today most of those patterns are still valid andin use. However, some are obsolete and nolonger required thanks to the simplifiedprogramming model of Java EE.

41

Design Patterns Versus EnterprisePatternsEnterprise patterns differ from design patternsin that enterprise patterns target enterprisesoftware and its problems, which greatly differfrom the problems of desktop applications. Anew approach, Service Oriented Architecture(SOA), introduced several principals to followwhen building well-organized, reusableenterprise software. Don Box’s6 four tenets ofSOA formed the basis of these fundamentalprinciples. That set of principles addressedcommon needs of enterprise projects.

DON BOX’S FOUR TENETS OFSOA

1. Boundaries are explicit. 2. Services areautonomous. 3. Services share schema andcontract, not class. 4. Service compatibility isdetermined based on policy.

However, “classical” patterns still havesomething to offer. With the release of Java EE5, Enterprise Java was back in the spotlight,something that third-party frameworks such asSpring and Struts had hogged for too long. Therelease of Java EE 6 was an even greater stepforward and made the platform morecompetitive.

42

Today in Java EE 7, most “classic” designpatterns described in the GoF book areembedded in the platform ready to be used “outof the box.” Unlike the J2EE era, most of thesepatterns can be implemented via annotationsand without the need for convoluted XMLconfiguration. This is a huge leap forward andoffers the developer a simplified programmingmodel.

Although there are several great books ondesign patterns and the new features of JavaEE, there seems to be a missing link on howthose patterns are implemented in Java EE.

Plain Old Design Patterns Meet Java EEEven from day zero, Java has been friendlytoward design patterns. Some of the patternshave a built-in implementation that is ready touse, such as the observer pattern in Java SE.Java itself also uses many design patterns; forexample, the singleton pattern is used in thesystem and runtime classes, and comparatorsare a great example of the implementation ofthe strategy pattern.

The tradition has continued with EnterpriseJava, but especially Java EE, which has built-inimplementations of many of the patternsdescribed in the GoF book. Most of thesepatterns can be enabled and used with simpleand easy-to-use annotations. So instead oflooking at class diagrams and writing boiler

43

plate code, any developer with experience canenable a pattern with just a few lines of code.Magical? Well, not quite. Because the Java EErun time has a more sophisticated design, it canoffer many capabilities, relying on the power ofthe underlying platform. Most of thefunctionality that those patterns need wouldnot be available without Java EE’s superset offeatures such as EJB and Context andDependency Injection (CDI). The Java EEcontainer does most of the work for you as itadds many embedded services and functionalityto the server. The drawback is that it hasresulted in a heavyweight server runtimeenvironment, especially compared to basic webservers such as Apache Tomcat. However, thishas improved, and the latest runtime builds onJava EE 7 are more lightweight.

Still, why do people continue to need designpatterns in enterprise applications? Well,patterns are needed now more than ever before.Most of the enterprise applications are built forcorporations by different teams of developers,and different parts need to be reused often.Unlike solving a common problem pattern onyour own or in a small team, your solutions arenow exposed to the whole corporation andbeyond to potentially the whole world (if yourproject is open source). It is easy to introduce apoorly designed application and let it become acorporate tradition or development strategy.Because libraries, utility classes, and

44

application programming interfaces (APIs) areexposed to more developers, it has become evenharder to break compatibility and make radicalchanges. Changing one return type or evenadding a new method to an interface may breakall projects relying on that piece of code.

It is clear that enterprise software developmentrequires a higher level of discipline andcoordination between developer teams. Designpatterns are a good way to approach thisproblem. However, most enterprise developersstill do not make good use of classical designpatterns even though they have been in Java EEsince version 5.0. Although enterprise patternscan solve many issues, the original designpatterns continue to have much to offer. Theyare well worn and proven solutions, they havestood the test of time, and they have beenimplemented in almost all object-orientedlanguages.

Finally, because most of those patterns arealready integrated in the Java EE platform,there is no need to write the fullimplementation code. Some may require a littleXML configuration, but most of the patternscan be implemented by applying an annotationto the class, method, or member variable. Wantto create a singleton? Just add the@Singleton annotation to the top of yourclass file. Need to implement the factorypattern? Just add the @Produces annotation,

45

and the method will become the factory of thegiven return type.

Java EE also sets the standards. The @Injectannotation serves as a default implementationand can be mixed and matched with almost anyother framework (the Spring Framework)because they use the same annotation.

When Patterns Become Anti-PatternsDesign patterns represent collected wisdom,but this doesn’t mean you have to use them allthe time. Just like the famous Americanpsychologist Abraham Maslow7 so aptly stated,“If the only tool you have is a hammer, you tendto see every problem as a nail.” If you try toaddress all problems with only the patterns youknow, they simply won’t fit, or worse, they’ll fitbadly and cause more problems. Even more,unnecessary use of patterns tends toovercomplicate the system and result in poorperformance. Just because you like thedecorator pattern does not mean you need toimplement the pattern on every object. Patternswork best when the conditions and theproblems require their use.

SUMMARYJava and design patterns have had a longjourney to arrive at where they are now. Oncethey were separate, with no knowledge of each

46

other, but now they are together, to be foreverintegrated in the Java Enterprise Edition. Tounderstand this intimate paring, you mustknow their history. Already you have discoveredthe roots of your favorite couple and how theyfound each other. You’ve read about J2EE’srocky beginnings and how the GoF gave light to23 design patterns. You’ve seen howframeworks like Spring came up behind Javaand took over and how the reinvented Java EEis now fighting back and gaining ground. Theknowledge contained in this book will prepareyou to tackle with confidence the majority ofthe design issue that you will face during yourdevelopment career. You can rest easy knowingthat the years of struggle the Java EnterpriseEdition has endured combined with theinherent wisdom of design patterns haveresulted in an endurably strong and flexibleprogramming language and environment.

Enjoy this invaluable guide to design patternsin Java EE, and use the wisdom gained here inevery project you’re involved in.

NOTES

1. Design Patterns: Elements of ReusableObject-Oriented Software (Addison-Wesley,1994): Erich Gamma, Richard Helm, RalphJohnson, John Vlissides.

47

2. According to the TIOBE index, Java appearsat number two after C:http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html.

3. Before version 5, Java EE used to be calledJ2EE. From this point J2EE will be used torefer to pre-Java EE 5.

4. Core J2EE Patterns: Best Practices andDesign Strategies (Prentice Hall 2003, 2ndEdition): Deepak Alur, Dan Malks, JohnCrupi.

5. Rod Johnson (@springrod) is an Australiancomputer specialist who created the SpringFramework and cofounded SpringSource.http://en.wikipedia.org/wiki/Rod_Johnson_(programmer).

6. Don Box (@donbox) is a distinguishedengineer: http://en.wikipedia.org/wiki/Don_Box.

7. Abraham Maslow (1908–1970) AmericanPsychologist.

48

2The Basics of Java EEWHAT’S IN THIS CHAPTER?

Introduction to the core concepts of Java EE

Discussion of the multitier structure of anenterprise application

Explanation of Java EE–compliant servers andthe web profile

Convention over configuration overview

Content Dependency Injection overview

Interceptor overview

WROX.COM CODE DOWNLOADS FORTHIS CHAPTER

The wrox.com code download for this chapter isfound at www.wrox.com/go/projavaeedesignpatterns on theDownload Code tab. The code is in the Chapter2 download and individually named accordingto the names throughout the chapter.

The Java EE programming model has beensimplified substantially since J2EE.Annotations have replaced the XML descriptorsfiles, convention over configuration havereplaced the tedious manual configuration, anddependency injection hides the creation and

49

lookup of resources. Developers need toreconsider their approach to design and coding.

The development of Java EE enterpriseapplications has gotten easier. All that you needis a POJO (Plain Old Java Object) annotatedwith some metadata and, depending on theannotation used, the POJO becomes anEnterprise JavaBeans (EJB, stateful orstateless), a servlet, a JSF backing bean, apersistence entity, a singleton, or a REST webservice. You can optionally declare many ofthese services using XML in a deploymentdescriptor.

Listing 2-1 shows how to make a POJO into asingleton bean that is instantiated andinitialized at start-up and then managed by thecontainer simply by adding the @Singletonand @Startup annotations to the class and@PostConstruct to the initializationmethod. See Chapter 4, “Singleton Pattern,” fora detailed explanation of the use of theseannotations.

LISTING 2-1: POJO becomes acontainer-managed singleton beanwith the addition of some annotations

packagecom.devchronicles.singleton;

50

import java.util.HashMap;import java.util.Map;importjavax.annotation.PostConstruct;import javax.ejb.Singleton;import javax.ejb.Startup;

@Startup@Singletonpublic classCacheSingletonBean {

private Map<Integer,String> myCache;

@PostConstructpublic void start(){

myCache = newHashMap<Integer, String>();

}

public voidaddUser(Integer id, Stringname){

myCache.put(id, name);}

public StringgetName(Integer id){

51

return myCache.get(id);}

}

The aim of Java EE has not changed; itcontinues to recognize the requirement thatdevelopers and enterprises have for distributedand transactional applications that harnessspeed, security, and reliability. The Java EEplatform is designed to make the production oflarge-scale, multitiered applications easier,more reliable, and more secure.

MULTITIER ARCHITECTUREThe architecture of a Java EE application isseparated into tiers: the Client tier, the Middletier (which consists of the Web layer and theBusiness layer), and the Enterprise InformationSystems (EIS) tier. Each tier has uniqueresponsibilities and utilizes different Java EEtechnologies. The segregation of an applicationinto distinct tiers brings greater flexibility andadaptability. You have the choice of adding ormodifying just a specific layer rather thanrefactoring the entire application. Each tier isphysically separate and located on differentmachines. And in the case of a web application,the Client tier is distributed globally.

52

Java EE works within the realm of the Middletier, although it touches both the Client and theEIS tiers. The Middle tier receives requestsfrom the Client tier application. The Middletier’s Web layer processes the request andprepares a response, which it sends back to theClient tier, whereas the Business layer appliesthe business logic before persisting it in the EIStier. Within the Middle tier, there is fluidcommunication between the layers and the EIStier, while preparing the response to the Clienttier. A multitier architecture can be representedvisually, as in Figure 2.1.

Figure 2.1 Multitier architecture showing theinteraction between tiers

THE CLIENT TIERThe Client tier is usually a browser thatconnects to the Java EE server via HypertextTransfer Protocol (HTTP), although it can be

53

any application on any machine as long as itbehaves as a client in a server-clientrelationship. The client application sends arequest to the server for a resource; the serverthen processes the request and returns aresponse. This is usually the extent of therelationship between the client and the server.

NOTE The Client tier is often referred to asthe Presentation tier.

THE MIDDLE TIERThe Java EE server sits on the Middle tier andprovides two logical containers: the webcontainer and the EJB container. Thesecontainers roughly correspond to the Web layerand the Business layer, respectively. Each layerhas distinct but sometimes overlappingresponsibilities.

The MVC pattern is commonly used to clearlyseparate the view generation responsibilities ofthe Web layer from the data modelingresponsibilities of the Business layer. Chapter14, “Model Viewer Controller Pattern,”discusses in detail how to implement thisseparation of concerns.

54

Web LayerThe Web layer manages the interactionsbetween the Client tier and the Business layer.

The Web layer receives a request for a resourcefrom the Client tier. The request may includedata that the user inputted, such as a usernameand password or sign-up information. Therequest is processed and, if necessary, aninteraction between the Web layer and theBusiness layer takes place. The response isdynamically prepared in one of several forms(usually in the form of a HyperText MarkupLanguage [HTML] web page for a responseoriginating from a browser) and sent to theclient.

The Web layer maintains the user’s states in asession and may even perform some businesslogic and temporarily persist data in memory.

The technologies that are typically used in theWeb layer relate to the management of theinteractions between the Client tier and theMiddle tier and the construction of theresponse. Serlvets control the web flow andmanage interactions while JavaServer Pages(JSP), Expression Language (EL), andJavaServer Pages Standard Tag Library (JSTL)prepare the response to the client. This is just asnapshot of the technologies that you can use inthe Web layer. For a complete list, see Figure2.2.

55

Figure 2.2 Technology used in the Web andBusiness layers

In Java EE 7, four new technologies were addedto the EE universe: WebSockets, ConcurrencyUtilities, Batch, and JSON-P. You can use allbut WebSockets in both layers.

Business LayerThe Business layer executes business logic thatresolves business problems or satisfies aparticular business need within the businessdomain.

Normally, this would involve data that has beenretrieved from the database in the EIS tier orcollected from the client. In a banking domain,a transaction fee might be applied to atransaction amount and sent to the client viathe Web layer for the client to confirm thetransaction. In an e-commerce domain, adifferent tax rate might be applied to a product

56

depending on the physical location of the clientbefore being passed to the Web layer, and theweb page would be rendered according to thisinfo.

The Business layer is where the core logic of thebusiness application resides. Business logic iswrapped up in the EJB, and the data used bythe business logic is retrieved from the EIS tiervia Java Persistence API (JPA), JavaTransaction API (JTA), and Java DatabaseConnectivity (JDBC). It is common to requestand modify data via web services that useJAX-RS and JAX-WS. (See Chapter 14, “REST,”for more on this topic.) This is just a snapshotof the technologies that you can use in the weblayer. For a complete list, see Figure 2.2.

NOTE The Middle tier is often referred to asthe Logic tier, Data Access tier, andApplication tier.

THE EIS TIERThe EIS tier consists of data storage units, oftenin the form of databases, but they can be anyresource that provides data. It may be anantiquated legacy system or a file system.

57

NOTE The EIS tier is often referred to as theData tier, Persistence tier, and Integrationtier.

JAVA EE SERVERSAs you have seen, the Middle tier hosts the JavaEE server, which provides the Java EEfunctionality needed for an enterpriseapplication.

Java EE is based on 30 standards, called JavaSpecification Requests (JSRs)(http://www.oracle?.com/technetwork/java/javaee/tech/index.html). These requests go through theJava Community Process (JCP) before they canbecome accepted as part of the Java EEuniverse. The JCP is an open process in whichanyone can participate and give feedback onJSRs or even submit their own JSR(https://www.jcp.org/en/home/index).

These specifications are bundled together andrepresent the technologies that a serverapplication must implement to be able to claimthat it is Java EE compliant.

Additionally, Oracle requires that the serverapplication passes the TechnologyCompatibility Kit (TCK). This is a nontrivial testsuite that checks that the application server

58

behaves as the specification requires. Thisensures that if you develop your applicationfollowing the Java EE specifications, you will beable to deploy and execute it on any Java EEapplication.

At the time of writing, three application servershave been certified fully compatible with JavaEE 7. They are GlassFish Server Open SourceEdition 4.0(http://glassfish.java.net), Wildfly8.0.0 (http://wildfly.org), and TMAXJEUS 8 (http://tmaxsoft.com/product/jeus/certification/).Eleven application servers are Java EE 6compatible(http://en.wikipedia?.org/wiki/Java_Platform,_Enterprise_Edition#Java_EE_6_certified).

THE JAVA EE WEB PROFILEThe Java EE web profile is a subset oftechnologies that comprise the mostappropriate technologies required for thedevelopment of web-based enterpriseapplications. The profile reduces the size andcomplexity of the platform to just thetechnologies required for the development of amodern web application. The web profile is acomplete stack comprising technologies relatedto workflow and core functionality (Servlet),presentation (JSF and JSP), business logic (EJBlite), transactions (JTA), persistence (JPA), the

59

new WebSocket, and much more. It omits a lotof enterprise-related technologies such as theConcurrency Utilities, Java Message Services,JAX-RPC, JAXR, and JAX-WS. See Figure 2.2for a complete rundown of the technologiesincluded in the web profile.

CORE PRINCIPLES OF JAVA EEThe core principles of Java EE include anumber of design paradigms and patterns thatare essential to the way you develop enterpriseapplications. At the center of Java EE is thedesign paradigm of convention overconfiguration: a way to simplify thedevelopment of enterprise applications withoutlosing flexibility and obscuring its code’spurpose. It is not a new idea and has been apart of other frameworks including Grails, Rubyon Rails, and Spring Boot for some time—insome cases for nearly a decade. Thankfully, ithas made its way into the heart of Java EE,where it helps others write beautiful code.

Java EE makes good use of its componentmodel, which includes the components Entities,JavaBeans, EJBs, Managed Beans, Servlets,SOAP, and RESTful web services. All thesecomponents can be “injectable” dependencies;the container manages, in some way, their lifecycle (from instantiation todestruction)—whether they are bound to acontext or not—and their decoupling from

60

dependent components via dependencyinjection.

A loosely coupled application allows forextensibility: Old classes can be swapped withnew ones with no requirement to change thedependent class. Dependency injectiondecouples an object from its dependencies,whereas interceptors decouple businessconcerns from technical and cross-cuttingconcerns. Such technological concerns would beperformance and logging, and a cross-cuttingconcern would be security.

CONVENTION OVERCONFIGURATIONAll class names should start with a capital letteras part of convention. It’s not obligatory; theclass will still compile if it starts with alowercase letter, but starting with a capitalletter makes the code easier to read andmaintain. When setting up a project in an IDE,you only need to specify the type of the projectand its name for the most appropriate directorystructure to be created; the most commonapplication programming interfaces (APIs) tobe imported; and the default files such asweb.xml, index.jsp, etc. to be created withappropriate default settings for ease ofdevelopment. You do all of this based on agreedconvention.

61

The amount of work you have to do and thedecisions you have to make as a developer aresubstantially reduced when you rely onconvention. You don’t specify any configurationthat is considered conventional; you arerequired to specify only the unconventional.This has a significant effect. With just a fewannotations on a POJO, you can do away with alot of your ugly XML deployment descriptorsand application configuration files. As you haveseen in Listing 2-1, you need to apply just threeannotations to make a POJO into a singletonbean that will be instantiated and initialized atstart-up and then managed by the container.

NOTE Convention over configuration is alsoknown as coding by convention.

CONTEXT AND DEPENDENCYINJECTIONDependency injection is a design pattern (seeChapter 5, “Dependency Injection and CDI”)that decouples the relationship between acomponent and its dependencies. It does this byinjecting the dependency into an object ratherthan the object creating the dependency byusing the new keyword. By removing thecreation of the dependency from the object anddelegating that responsibility to the container,

62

you can swap out the dependency for anothercompatible object at compile time and run time.

Beans that the container manages are calledContext and Dependency Injection(CDI)-managed beans and are instantiatedwhen the container starts up. All POJOs thathave a default constructor and are not createdusing the new keyword are CDI beans that areinjected into an object based on type matching.To be injected, the receiving object must declarea field, constructor, or method using the@Inject annotation. Then the type of thedeclared object is used to determine whichdependency to inject.

In Listing 2-2, you have a POJO that has adefault constructor and therefore will bemanaged as a CDI bean, and in Listing 2-3, youinject the managed bean. The container knowsto inject the Message bean based on its type.The container manages only one CDI bean oftype Message, so this is the bean it injects.

LISTING 2-2: Dependency injectionexample—Dependency

packagecom.devchronicles.basicsofjavaee;

public class Message {

63

public String getMessage(){return "Hello World!!";

}

}

LISTING 2-3: Dependency injectionexample—Receiver

packagecom.devchronicles.basicsofjavaee;

import javax.inject.Inject;

public class Service {

@Injectprivate Message message;

public void showMessage(){

System.out.println(message.getMessage());}

}

An inquiring mind might ask: What happens ifthe container is managing more than one bean

64

of type Message? For this to be true,Message would have to be an interface thathas more than one concrete implementation.This is where it becomes more interesting .There are several strategies that you can employto resolve these types of ambiguities. You willencounter several of these during the course ofthis book. If curiosity has gotten the better ofyou, skip to Chapter 5.

Context is the distinguishing feature betweenEJBs and CDI-managed beans. CDI beans existwithin a defined context; EJBs do not. CDIbeans are created within the context of a scope;they exist for the life of the scope and aredestroyed when the scope finishes. There arefour scopes that are annotated as follows:@ApplicationScope,@ConversationScope, @SessionScope,and @RequestScope. The CDI containercontrols the life of a bean based on the bean’sdefined scope. For example, a bean annotatedwith @SessionScope exists for as long as theHTTP session is alive; at the end the scope, thebean is destroyed and marked for garbagecollection. This behavior is in contrast to that ofEJBs, which are not bound to a scope. Thismeans that you must explicitly remove the beanby calling a method annotated by the @Removeannotation.

65

INTERCEPTORSMost applications have concerns that don’tcomfortably fit into the core concern of theapplication logic but cannot be cleanlyseparated from the application’s design orimplementation. These concerns arecross-cutting and affect different parts of theapplication. They are often responsible forduplicate code and interdependencies thatmake the system less extensible. Theimplementation of these noncore concerns asinterceptors allows them to be decoupled fromthe core concern. You do this by logicallyseparating their implementation andintercepting method calls to the core andinvoking the appropriate method.

You implement interceptors using theannotation @Interceptors followed by theclass name of the crossing-cutting concern. InListing 2-4, the setValue method isintercepted upon its invocation by theLoggerInterceptor.class.

LISTING 2-4: Core methodintercepted by logger interceptor

@Interceptors(LoggerInterceptor.class)public void setValues(Integervalue, String name) {

66

this.value = value;this.name = name;

}

The logger interceptor can access theintercepted method’s parameters and performthe cross-cutting logic before returning to fullyexecute the intercepted method.

In Listing 2-5, the logger interceptor accessesthe parameters of the setValues method andlogs them to the system logger.

LISTING 2-5: The logger interceptor

@AroundInvokepubliclogger(InvocationContext ic)throws Exception {

Object[] params =ic.getParameters();

logger.warning("Parameterspassed: " + params);}

You can define interceptors in the businesscode and in the deployment descriptor files.This aspect of interceptors and much more is

67

discussed in Chapter 8, “Aspect-OrientedProgramming (Interceptors).”

SUMMARYIn this chapter, you have seen a brief summaryof Java EE and the history of the currentprinciples of it.

You have discovered how the architectureshould be layered properly in a Java EE project.We also provide a long JSR compatibility list tohelp you determine which container best suitsyour project. Finally the chapter focused onCore Principles of Java EE by presentingconvention over configuration and giving a briefsummary of CDI.

Next, we will be ready to move on to eachpattern, focusing on their implementations andproviding specific examples.

EXERCISES

Think about a banking application whereyou need to integrate into the mainframeback end and provide services for web,mobile, and native desktop clients.

Think about implementing the webapplication for the project you designed inthe first step. Which layer should host theweb application?

68

After a long debate, the bank you areworking for decided to move away from themainframe, asking you to design asubstitute system. What parts of the currentproject will be impacted?

69

PART IIImplementing DesignPatterns in Java EECHAPTER 3: Façade Pattern

CHAPTER 4: Singleton Pattern

CHAPTER 5: Dependency Injection and CDI

CHAPTER 6: Factory Pattern

CHAPTER 7: Decorator Pattern

CHAPTER 8: Aspect-Oriented Programming(Interceptors)

CHAPTER 9: Asynchronous

CHAPTER 10: Timer Service

CHAPTER 11: Observer Pattern

CHAPTER 12: Data Access Pattern

CHAPTER 13: RESTful Web Services

CHAPTER 14: Model Viewer Controller Pattern

CHAPTER 15: Other Patterns in Java EE

70

3Façade PatternWHAT’S IN THIS CHAPTER?

An introduction to the intent of thefaçade pattern

A brief discussion of the benefits that thepattern brings

Three ways that the pattern can beimplemented: POJO, stateless, andstateful session bean façade

The important differences between thestateful and the stateless session beanfaçade

When and where to use this pattern

Warnings about its use and potentialpitfalls

WROX.COM CODE DOWNLOADS FORTHIS CHAPTER

The wrox.com code downloads for this chapterare found at www.wrox.com/go/projavaeedesignpatterns on theDownload Code tab. The code is in the Chapter3 download and individually named accordingto the names throughout the chapter.

71

The façade pattern is one of the structuraldesign patterns described in the GoF1 book. Theintent behind it is to encapsulate complicatedbusiness logic in a higher-level interface thatmakes access to a subsystem easier to use. Thisis often done by grouping related method callsand invoking them sequentially from onemethod.

From a higher-level view, every API can beconsidered an implementation of the façadepattern since they provide a simple interfacewhich hides its complexity. Any call to an API’smethod results in the invocation of many othermethods from a subsystem hidden behind it. Anexample of a façade would be thejavax.servlet.http.HttpSessioninterface. This hides the complicated logicassociated with maintaining the session whileexposing its functionality via a handful ofsimple-to-use methods.

WHAT IS A FAÇADE?The GoF1 book describes this pattern as“providing a unified interface to a set ofinterfaces in a subsystem.” Head First DesignPatterns2 gives the same explanation andpoints out that, while hiding the complexity ofthe subsystem, the façade pattern offers the fullpower of the subsystem via an easier-to-useinterface.

72

To give a basic real-world example of how thefaçade pattern works, imagine a washingmachine with only two wash modes: heavilysoiled and lightly soiled. For each mode, thewashing machine must execute a predefined setof operations: set water temperature, heatwater, set duration of wash cycle, set durationof spin cycle, add detergent, add bleach, addfabric softener, and so on. Each mode requiresa different set of washing instructions (differentamounts of detergent, higher or lowertemperature, longer or shorter spin durations,and so on).

The simple interface provides two wash modesthat hide the complicated logic of selecting theappropriate water temperature, the duration ofthe spin and wash cycle, and the differentmethods for adding detergent, bleach, or fabricsoftener. The user of the washing machine doesnot have to think about the complicated logic ofhow to wash the clothes (decide thetemperature, cycle duration, and so on). Theonly decision the user must make is whether theclothes are heavily soiled or lightly soiled. Thisis in essence the façade pattern applied to awashing machine design. Later on in thischapter, you will see an implementation of thisuse case.

The façade pattern is commonly implementedfor the following purposes and situations:

73

Provide a simple and unified access to a legacyback-end system.

Create a public API to classes, such as a driver.

Offer coarse-grained access to availableservices. Services are combined, such as in thewashing machine example.

Reduce network calls. The façade makes manycalls to the subsystem, while the remote clientmakes only one call to the façade.

To encapsulate flow and inner details of an appfor security and simplicity.

NOTE Façades are sometimes implementedas singleton abstract factories.

WAR STORY

In the early dark days of J2EE, I was workingas a junior developer for a huge bankingapplication where we implemented almost allthe J2EE design patterns. All EnterpriseJavaBeans (EJB) were wrapped by a façade,and every service EJB using that façade waswrapped with another façade. We also hadinterfaces for the façades to ensure we didn’t

74

break the API. In J2EE, EJB needs a localand remote interface, so writing one EJBmeant writing four interfaces and twoclasses. We didn’t have spaghetti code, butwe had more layers than a meat lasagna. Wewere quite happy in our little world—thatwas, until other teams started to use our coreservices. Very soon, both the performance ofthe system and our ability to handle changerequests started to suffer.

We contracted a famous and expensiveconsultant from one of our server vendors toanalyze our system. He had a few meetings,spent some time browsing our code base, andconcluded that some refactoring was inorder, so he deleted all façades and relatedinterfaces. The result was that we had lesscode to maintain and much betterperformance, so everyone was happy. Themoral of this story is to use patterns—eventhe simple ones—sparingly and only whenyou need them, and definitely don’t show offyour knowledge of patterns.

Façade Class DiagramAs can be seen in the class diagram in Figure3.1, the façade pattern provides a simpleinterface to an underlying system. Itencapsulates the complicated granular logic.

75

Figure 3.1 Class diagram of the façade pattern

IMPLEMENTING THE FAÇADEPATTERN IN PLAIN CODEImplementing the façade pattern isn’tcomplicated. It doesn’t enforce a strict structureor rule set. Any method that provides easyaccess to a complicated flow could beconsidered an implementation of the façadepattern.

Now you’ll implement the washing machineexample given in the introduction as shown inListing 3-1. You need twomethods—heavilySoiled andlightlySoiled—that represent the twowashing modes. All complicated work (theselection of water temperature, spin cycleduration, decision to add bleach or not) isperformed in methods invoked from within thefaçade.

76

LISTING 3-1: Implementation of thewashing machine analogy

public class WashingMachine {

public voidheavilySoiled() {

setWaterTemperature(100);

setWashCycleDuration(90);

setSpinCycleDuration(10);addDetergent();addBleach();addFabricSoftener();heatWater();startWash();

}

public voidlightlySoiled() {

setWaterTemperature(40);

setWashCycleDuration(20);

setSpinCycleDuration(10);addDetergent();heatWater();

77

startWash();}

}

// to use the façadenewWashingMachine().lightlySoiled();

If you want to use this functionality, just invokethe façade’s lightlySoilded orheavilySoilded method and let it do thecomplicated logic of washing the clothes. Allcomplicated logic is kept hidden by the façadeand exposed via its two methods.

The implementation of the methods isdecoupled from the client. This decouplingallows the implementation to change withoutaffecting any change in the way the clientaccesses the washing services. The client knowsnothing about the implementation of thesemethods, and it doesn’t care. All that it isinterested in is obtaining the service it requires.

This example demonstrates one of many of thebenefits of the façade pattern. This book doesnot go into detail about the benefits of thefaçade pattern, so what follows is a briefsummary of the most important ones:

A reduction in coupling because the clientknows nothing about the subsystem

78

Increased maintainability and manageabilitywhen changes are required

Reuse of functionality because it encourages thereuse of controls and fine-grained logic

Consistency of service execution by invokingthe same method consistently from oneinvocation to the next

Reduction in business logic complexity bygrouping related methods and invoking themfrom one method invocation

Centralization of security and transactioncontrol management

Testable and mockable patternimplementations

NOTE You may see this implementationreferred to as the POJO façade to distinguishit from the stateful and statelessimplementations that you will see later inthis chapter.

IMPLEMENTING THE FAÇADEPATTERN IN JAVA EEUnlike many other patterns described in thisbook, Java EE does not offer a built-inimplementation of this method. Nevertheless, it

79

is straightforward to implement using statefulor stateless EJB. Using EJB offers theadvantage of easy access to other EJB that thefaçade might require.

Façade with Stateless BeansTo demonstrate this implementation, assumethat you have three EJBs as shown in Listing3-2 with distinct but related functionality:CustomerService, LoanService, andAccountService.

LISTING 3-2: Code for three EJBs thatform the subsystem to the façade

packagecom.devchronicles.facade;

import javax.ejb.Stateless;

@Statelesspublic class CustomerService {

public longgetCustomer(int sessionID) {

// get logged incustomer id

return 100005L;}

80

public booleancheckId(long x) {

// check if customerid is valid

return true;}

}

packagecom.devchronicles.facade;

import javax.ejb.Stateless;

@Statelesspublic class LoanService {

public booleancheckCreditRating(long id,double amount) {

// check if customeris eligible for the amount

return true;}

}

packagecom.devchronicles.facade;

import javax.ejb.Stateless;

@Stateless

81

public class AccountService {

public booleangetLoan(double amount) {

// check if bank vaulthas enough

return true;}

public booleansetCustomerBalance(long id,double amount) {

// set new customerbalance

return true;}

}

You can group these service EJB in a logicalcollection of related functionality to form animplementation of the façade pattern, such asin Listing 3-3.

82

LISTING 3-3: Implementation of thestateless façade

packagecom.devchronicles.facade;

import javax.ejb.Stateless;import javax.inject.Inject;

@Statelesspublic class BankServiceFacade{

@InjectCustomerService

customerService;

@InjectLoanService loanService;

@InjectAccountService

accountService;

public boolean getLoan(intsessionId, double amount) {

boolean result = false;long id =

customerService.getCustomer(sessionId);

83

if(customerService.checkId(id)){

if(loanService.checkCreditRating(id,amount)){

if(accountService.getLoan(amount)){result =

accountService.setCustomerBalance(id,amount);

}}

}return result;

}}

A façade can invoke other façades in othersubsystems, which in turn encapsulate theirown logic and flow. This shows one of thebenefits of using façades: a simplified hierarchyof method calls. There’s one façade for eachsubsystem, and these subsystems communicatewith each other via the façades.

Façade with Stateful BeanThe same bean can be implemented as astateful session bean or even as a singletonbean as long as it hides some complicated logicand exposes an easy-to-use interface to the

84

client. The only change is the addition of the@Stateful annotation, which marks the beana stateful EJB.

In J2EE (pre 5.0), the use of the façade patternwas encouraged in the implementation of thesession façade pattern. However, even in thesimplified approach of Java EE, façades stillhave their place when control andencapsulation of the workflow are required.

WHERE AND WHEN TO USE THEFAÇADE PATTERNThe façade pattern should be used toencapsulate complicated (business) logic at ahigh level and provide a cleaner single point ofaccess via an API.

Whenever you are in the position to provide aninterface or an API to someone, think firstabout the complexity of the logic and thechanges that might occur. The façade patterndoes a good job of providing a clean API whilehiding the parts subject to change.

However, unnecessarily wrapping methods in afaçade is bad practice and adds unnecessarylayers. Premature encapsulation could result intoo many invocations and layers that don’t addvalue.

When implementing the session façade, youmust determine if the use case requires state to

85

be maintained. A use case that invokes only onemethod of the façade to receive the service thatit needs is considered nonconversational, sothere is no need to save the conversational statebetween one method invocation and the next.You should implement this façade as a statelesssession bean.

On the other hand, if the conversational statemust be maintained between methodinvocations, the most appropriate way toimplement the façade is as a stateful sessionbean.

You must be careful in the use of the statefulsession façade because it ties up serverresources until the client that provoked theconversation releases them or times out. Thiscould mean that, for the majority of the timethe stateful session bean façade is bound to theclient, it is doing nothing; it’s just maintainingstate and using resources. And, unlike statelesssession bean façades, it cannot be reused andshared between other clients because eachrequest creates a new instance of the statelessfaçade, maintaining the state for that client’ssession.

So take care when using this pattern. Analyzethe use case and make appropriate decisions.

86

SUMMARYYou can implement the façade pattern as aPOJO, a stateless session bean, or a statefulsession bean. The various ways to implementthe façade pattern solve different problems fordifferent use case scenarios. But the variety ofimplementations does not distract from itsprinciple intent: providing a high-level simpleinterface to a more complicated subsystem.

Take care when deciding to implement thefaçade as a stateful session bean to ensure thatit will not cause resource consumption issues.

A well-designed application makes good use ofthe façade pattern to encapsulate complicatedlogic and decouple subsystems from clients;however, the premature and overuse of thefaçade pattern can lead to a more complicatedsystem with multiple layers.

The session façade pattern is akin to theboundary in the entity-control-boundaryarchitectural pattern, and it is related to theadapter and wrapper patterns.

EXERCISES

List some public API implementations of thefaçade pattern and explain how they hidethe complicated logic of the subsystem.

87

Develop a façade that hides the complicatedlogic of an order and payment system.

Encapsulate method invocations to the twosubsystems—payment and order—in justtwo methods.

Develop the façade as a singleton.

NOTES

1. Design Patterns: Elements of ReusableObject-Oriented Software (Addison-Wesley,1994): Erich Gamma, Richard Helm, RalphJohnson, John Vlissides.

2. Head First Design Patterns (O’Reilly, 2004):Eric Freeman, Elisabeth Robson, Bert Bates,Kathy Sierra.

88

4Singleton PatternWHAT’S IN THIS CHAPTER?

The different ways that a developer canimplement the singleton design pattern, besidesits common usage and pitfalls

The problems that using static members andmethods causes in multithreaded environments

The advances that were made in Java 5 SE withthe introduction of the enum type and how itcan be used to create thread-safe singletons

The use of the @Singleton annotation in JavaEE and how this has radically changed the waythe singleton pattern is implemented in sessionbeans

The use of BEAN- and CONTAINER-managedconcurrency and how the @LockTypeannotation controls access to business methods

The main issues that have dogged the singletonpattern and why it is considered an anti-patternthat has fallen out of favor

WROX.COM CODE DOWNLOADS FORTHIS CHAPTER

The wrox.com code download for this chapter isfound at www.wrox.com/go/

89

projavaeedesignpatterns on theDownload Code tab. The code is in the Chapter4 download and individually named accordingto the names throughout the chapter.

The singleton pattern is one of the easiest, mostwell-known design patterns, but it has fallenout of fashion. Some even consider it as ananti-pattern, which will be discussed later inthis chapter. However, enterprise frameworkssuch as Spring make heavy use of it, and JavaEE offers an elegant and easy-to-useimplementation. In this chapter, you will seewhy singletons are needed, why they fell out offashion, how they can be useful in Java EEapplications, and how you can implement them.

The singleton pattern is one of the creationalpatterns described in the GoF1 book. Asingleton class guarantees the production ofonly one instance of its own type. Having onlyone instance can be useful in several cases, suchas with global access and when cachingexpensive resources; however, it may introducesome problems of race conditions if thesingleton is used in a multithread environment.Because most programming languages do notprovide a built-in mechanism to createsingletons, developers must code their ownimplementations.

However, Java EE has a built-in mechanismthat gives the developer a simple way to create a

90

singleton via the addition of an annotation tothe class.

WHAT IS A SINGLETON?According to GoF, the singleton pattern is usedto “ensure a class only has one instance, andprovide a global point of access to it.” HeadFirst Design Patterns2 offers the sameexplanation and points. Singletons are oftenused in combination with factory patterns(discussed in Chapter 6, “Factory Pattern”).

Singletons are commonly used for the followingpurposes and situations:

To access shared data across the wholeapplication domain, such as configuration data

To load and cache expensive resources onlyonce, allowing global shared access andimprove performance

To create an application logger instance,because normally only one is required

To manage objects within a class implementingthe factory pattern

To create a façade object, because normally onlyone is necessary

To lazily create static classes, since singletonscan be lazily instantiated

Spring uses singletons when creating beans (bydefault, Spring beans are singletons), and Java

91

EE uses singletons internally, such as in theservice locator. Java SE also uses the singletonpattern in the implementation of the runtimeclass. So singletons are definitely helpful if youuse them in the right context.

Nevertheless, the aggressive use of the singletonpattern may mean unnecessarily cachingresources and not letting the garbage collectorreclaim objects and free valuable memoryresources. It also may mean you do not reallyuse the advantages of object creation andinheritance. An unusually high usage ofsingletons is considered a sign of poorobject-oriented design, which may causememory and performance issues. Anotherproblem is that singletons are not great when itcomes to unit testing. Later, this chapterdiscusses in more detail the issues surroundingthe use of the singleton pattern.

Singleton Class DiagramAs you can see from the class diagram in Figure4.1, the singleton pattern is based on a singleclass that holds a reference to the only instanceof itself while controlling its creation and itsaccess via the single getter method.

92

Figure 4.1 The singleton pattern class diagram

Implementing the Singleton Pattern inPlain CodeBecause you need to guarantee that singletonsserve only one instance, the first thing to do iscontrol the object’s creation. You can do thiseasily by making the constructor invisible to theouter world.

packagecom.devchronicles.singleton;public class MySingleton {

private MySingleton() {// Implemetation code

here.}

}

Next, you need a method that creates theinstance or returns it if the instance was alreadycreated. Because an instance of MySingletondoes not yet exist, you must mark the creationmethod as static to allow access via the classname; for example:MySingleton.getInstance().

93

At comment 1 in Listing 4-1, you test thecreation of the singleton and create it if it doesnot exist; otherwise, you return the instancethat was created in a previous call to thegetInstance() method. Each subsequentcalls returns the previously createdMySingleton object instance. The code mightappear to be functioning, but it is actuallybuggy and not complete. Because the objectcreation method is not atomic, it is prone toerror in race conditions. It allows more thanone instance of the singleton to be created in amultithreaded environment.

LISTING 4-1: Simple implementationof the singleton pattern

packagecom.devchronicles.singleton;

public class MySingleton {private static MySingleton

instance;

private MySingleton(){}

public staticMySingleton getInstance() {

if

94

(instance==null){ // 1instance=new

MySingleton();}return instance;

}}

To fix the race condition problem, you need toacquire a lock and not release it until theinstance is returned. In Java, you canimplement the locking mechanism via thesynchronized keyword, as shown in Listing4-2.

LISTING 4-2: Synchronizing thesingleton for thread safety

packagecom.devchronicles.singleton;

public class MySingleton {

private static MySingletoninstance;

private MySingleton() {}

95

public static synchronizedMySingleton getInstance() {

if (instance==null){instance=new

MySingleton();}return instance;

}}

Another approach is to create the singletoninstance at the same time you load the class, asshown in Listing 4-3. This prevents needing tosynchronize the creation of the singletoninstance and creates the singleton object oncethe JVM has loaded all the classes (andtherefore before a class can call thegetInstance() method). This occursbecause static members and blocks areexecuted when the class is loaded.

LISTING 4-3: Creating the singletonobject at the time of class loading

packagecom.devchronicles.singleton;

public class MySingleton {

96

private final staticMySingleton instance=newMySingleton();

private MySingleton() {}

public static MySingletongetInstance() {

return instance;}

}

Another approach is to use a static block, asshown in Listing 4-4. However, this leads tolazy initialization because the static block isinvoked before the constructor is called.

LISTING 4-4: Creating the singletonobject in a static block

packagecom.devchronicles.singleton;

public class MySingleton {

private static MySingletoninstance=null;

97

static {instance=new

MySingleton();}

private MySingleton() {}

public static MySingletongetInstance() {

return instance;}

}

Double-checked locking is another highlypopular mechanism to create singletons. It isconsidered more secure than other methodsbecause it checks the instance of the singletononce before locking on the singleton class andagain before the creation of the object. Listing4-5 shows this method.

LISTING 4-5: Implementing thedouble-checked locking

packagecom.devchronicles.singleton;

98

public class MySingleton {

private volatileMySingleton instance;

private MySingleton() {}

public MySingletongetInstance() {

if (instance ==null) { // 1

synchronized(MySingleton.class) {

if(instance == null) { // 2

instance = new MySingleton();}

}}return instance;

}}

The getInstance() method checks theprivate MySingleton instance member twice(once at comment 1 and then again at comment2) for being null before creating and assigninga MySingleton instance.

99

However, none of those approaches is 100percent safe. For example, the Java ReflectionAPI allows developers to change the accessmodifier of the constructor to Public, thusexposing the singleton to the possibility ofre-creation.

The best way to create singletons in Java is byusing the enum type, which was introduced inJava 5 and is shown in Listing 4-6. Thisapproach is also heavily advocated by JoshuaBloch in his book Effective Java.3 Enum typesare singletons by nature, so JVM handles mostof the work required to create a singleton. Thus,by using an enum type, you free yourself fromthe task of synchronizing object creation andprovision and avoid problems associated withinitialization.

LISTING 4-6: Enum typeimplementation of the singletonpattern

packagecom.devchronicles.singleton;

public enum MySingletonEnum {INSTANCE;public void

100

doSomethingInteresting(){}}

In this example, a reference to the instance ofthe singleton object is obtained by thefollowing:

MySingletonEnum mse =MySingletonEnum.INSTANCE;

Once you have the singleton’s reference, youcan call any of its methods like so:mse.doSomethingInteresting();.

WAR STORY

Several years ago, a close friend of mine whoowned a small software company asked myhelp to interview a candidate. Because Ialways find software job interviews greatengineer-to-engineer experience, I didn’thesitate to jump at the opportunity. Thecandidate had only a few years of jobexperience but graduated from a gooduniversity and was definitely sharp. We had along chat about Java, JPA, Spring, and otherwell-known Java frameworks. He was eagerto learn and try new stuff and handled allquestions calmly.

101

After about an hour, the interview wasfinished, but we continued to talk casually. Iasked him about the books he had recentlyread, and his reply was Head First DesignPatterns. I inquired about which pattern hefound most interesting or simply wanted totalk about. Not surprisingly, it was thesingleton pattern. This made my spidersenses tingle. The candidate thought thesingleton pattern was simple and easy toimplement, so it would be a safe topic. Thetruth was, it wasn’t. If he had chosen anotherpattern such as the decorator, I would nothave had the opportunity to dive into themore advanced topics of this seeminglysimple pattern.

I then asked the candidate how he wouldimplement a singleton. He responded withthe classic private constructor method, whichclearly showed he hadn’t read Effective Javaand had no clue about the enum typesingleton. Later I asked, “What if I usedreflection to change the access level of theconstructor back to public?” He wassurprised, but I could clearly see from hiseyes that he was more interested in goingback home and trying this out. He couldn’tcome up with a solution, but he also didn’tmake up a nonsense response. He was busier

102

digesting and thinking about the reflectionidea.

This job candidate may have missed the rightanswer, but he showed he was passionate andeager to learn. He was hired and became oneof the best developers I have ever workedwith.

IMPLEMENTING THE SINGLETONPATTERN IN JAVA EEAll the code examples so far have demonstratedthe use of singletons within the context of JavaSE. Although you can use them in Java EE,there is a more elegant and easy-to-useapproach: singleton beans.

Singleton BeansIn Chapter 2, “The Basics of Java EE,” you sawthe use of stateless and stateful session beansvia a simple annotation configuration. Luckily,singletons offer a similar approach. Just byadding the @Singleton annotation to a class,you can turn it into a singleton bean as shownin Listing 4-7.

103

LISTING 4-7: The implementations ofthe singleton pattern using@singleton

packagecom.devchronicles.singleton;

import java.util.HashMap;import java.util.Map;importjavax.annotation.PostConstruct;import javax.ejb.Singleton;importjava.util.logging.Logger;

@Singletonpublic classCacheSingletonBean {

private Map<Integer,String> myCache;

@PostConstructpublic void start(){

Logger.getLogger("MyGlobalLogger").info("Started!");myCache = new

HashMap<Integer, String>();}

104

public voidaddUser(Integer id, Stringname){

myCache.put(id, name);}

public StringgetName(Integer id){

return myCache.get(id);}

}

With the simple use of annotations, Java EEdoes not need a configuration XML file. Youmay see a beans.xml file in the project, butmost of the time it remains empty. You onlyneed it for starting the Context and DependencyInjection (CDI) container. The @Singletonannotation marks the class as a singleton EJB,and the container handles creation and usage ofthe single instance.

If you execute this bean code on your server,you will not see logger output from thesingleton because the method annotated with@PostConstruct has not been invoked. Whyis that?

105

Using Singletons at StartupSingletons in Java EE are initialized lazily bydefault. This might suit most situations:allowing the instance to be created only when itis needed and accessed for the first time.However, you may want to create the instanceat startup to allow access to the singletonwithout delay, especially if it’s expensive tocreate the instance or it’s guaranteed that youwill need the bean from the start of theapplication. To ensure that the instance iscreated at startup, use the @Startupannotation on the class as shown in Listing 4-8.

LISTING 4-8: Invoking the singleton atstartup

packagecom.devchronicles.singleton;

import java.util.HashMap;import java.util.Map;importjavax.annotation.PostConstruct;import javax.ejb.Singleton;import javax.ejb.Startup;importjava.util.logging.Logger;

@Startup

106

@Singletonpublic classCacheSingletonBean {

private Map<Integer,String> myCache;

@PostConstructpublic void start(){

Logger.getLogger("MyGlobalLogger").info("Started!");myCache = new

HashMap<Integer, String>();}

public voidaddUser(Integer id, Stringname){

myCache.put(id, name);}

public StringgetName(Integer id){

return myCache.get(id);}

}

If you relaunch your server, the post constructmethod is invoked because the singleton is now

107

created at server startup. The logger shouldnow receive the message Started!.

Determining Startup OrderThis may bring up another question. What ifthe singleton you have just created depends onanother resource? How do you wait for theother resource to be ready? Although this maylook like a corner case, it definitely is not. Thinkabout a singleton, which loads and caches somemessages from the database. This may looktrivial, but even basic read-only database accessmay be dependent on other services. What ifthe connection pool is created by anothersingleton or, better yet, what if the loggingdepends on another singleton? Java EE offers asimple annotation to fix this situation. You canuse the @DependsOn annotation and pass itthe name of the bean on which the classdepends (see Listing 4-9). Now you can easilydetermine the starting order of the singletons.

LISTING 4-9: Specifying startup orderusing @depends annotation

packagecom.devchronicles.singleton;

import java.util.HashMap;import java.util.Map;

108

importjavax.annotation.PostConstruct;import javax.ejb.Singleton;import javax.ejb.Startup;import javax.ejb.DependsOn;import javax.ejb.EJB;

@Startup@DependsOn("MyLoggingBean")@Singletonpublic classCacheSingletonBean {

private Map<Integer,String> myCache;

@EJBMyLoggingBean loggingBean;

@PostConstructpublic void start(){

loggingBean.logInfo("Started!");myCache = new

HashMap<Integer, String>();}

public voidaddUser(Integer id, Stringname){

109

myCache.put(id, name);}

public StringgetName(Integer id){

return myCache.get(id);}

}

Next let’s create another singleton bean (Listing4-10), which the previous bean alreadyreferenced.

LISTING 4-10: Specifying startuporder

packagecom.devchronicles.singleton;

importjavax.annotation.PostConstruct;import javax.ejb.Singleton;import javax.ejb.Startup;importjava.util.logging.Logger;

@Startup@Singleton

110

public class MyLoggingBean {

private Logger logger;

@PostConstructpublic void start(){

logger =Logger.getLogger("MyGlobalLogger");

logger.info("Well, Istarted first!!!");

}

public void logInfo(Stringmsg){

logger.info(msg);}

}

Here you can also use the @PostConstructannotation to test that your bean has beencreated and its life cycle has begun. Methodsannotated with @PostConstruct are invokedon newly constructed beans after alldependency injection has been done and beforethe first business method is invoked. Of course,in real life, you need to use singleton beansinside other beans. Later chapters will focusmore on integration and access of EJB andwhether they should be singletons.

111

The preceding example beans run when theserver is started. CacheSingletonBeanwaits to run because it depends onMyLoggingBean initialization. The loggeroutput is similar to the following:

> Well, I started first!!!> Started!

Your singleton bean might depend on theinitialization of a sequence of other beans. Inthis case, you can specify multiple beans in the@DependsOn. The following singleton beandepends on MyLoggingBean andMyInitializationBean:

@Startup@DependsOn({"MyLoggingBean","MyInitializationBean"})@Singletonpublic class CacheSingletonBean {

// Implementation code here.}

The order in which MyLoggingBean andMyInitializationBean are initialized isdetermined by their own @DependsOnannotations. If neither bean explicitly dependson the other, the beans are initialized by thecontainer in an unspecified order.

112

Managing ConcurrencyThe most important problem you’ll face isconcurrency. With the Java EEimplementation, you no longer need to worryabout the creation of the bean, but you may stillneed to be careful about method access becauseyour singleton will be exposed in a concurrentenvironment. Java EE, again, solves this issuewith annotations.

Java EE offers two types of concurrencymanagement: container-managed concurrencyand bean-managed concurrency. Incontainer-managed concurrency, the containeris responsible for handling anything related toread and write access, whereas bean-managedconcurrency expects the developer to handleconcurrency using traditional Java methodssuch as synchronization. You can enablebean-managed concurrency via theConcurrencyManagementType.BEANannotation.

Java EE uses container-managed concurrencyby default, but you can explicitly declare it withtheConcurrencyManagementType.CONTAINERannotation:

@Startup@DependsOn("MyLoggingBean")@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)@Singleton

113

public class CacheSingletonBean {// Implementation code here.

}

Now you’ll get back to the example and use the@Lock annotations to control the access. SeeListing 4-11.

LISTING 4-11: Managing concurrencyusing @locktype

packagecom.devchronicles.singleton;

import java.util.HashMap;import java.util.Map;importjavax.annotation.PostConstruct;importjavax.ejb.ConcurrencyManagement;importjavax.ejb.ConcurrencyManagementType;import javax.ejb.DependsOn;import javax.ejb.EJB;import javax.ejb.Lock;import javax.ejb.LockType;import javax.ejb.Singleton;import javax.ejb.Startup;

@Startup

114

@DependsOn("MyLoggingBean")@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)@Singletonpublic classCacheSingletonBean {

private Map<Integer,String> myCache;

@EJBMyLoggingBean loggingBean;

@PostConstructpublic void start(){

loggingBean.logInfo("Started!");myCache = new

HashMap<Integer, String>();}

@Lock(LockType.WRITE)public void

addUser(Integer id, Stringname){

myCache.put(id, name);}

@Lock(LockType.READ)public String

getName(Integer id){

115

return myCache.get(id);}

}

Two lock types control access to the bean’sbusiness methods:@Lock(LockType.WRITE), which locks thebean to other clients while the method is beinginvoked, and @Lock(LockType.READ),which allows concurrent access to the methodand does not lock the bean to other clients.Methods that affect change to data are usuallyannotated with WRITE access to prevent accessto the data as it updates. In this example, theaddUser() method is annotated with theWRITE lock type so that if any client calls thegetName() method, it has to wait until theaddUser() method returns before it cancomplete its call. This may result in thecontainer throwing aConcurrentAccessTimeoutException ifthe addUser() method does not complete inthe specified timeout period. You can configurethe timeout period via an annotation, which youwill see an example of in Listing 4-12.

You can set the LockType annotation at theclass level. It applies to all business methodsthat don’t explicitly configure their ownLockType. Because the default LockType is

116

WRITE, it is normally sufficient to configurejust the methods that require concurrent access.

LISTING 4-12: Defining the singleton’sconcurrent timeout access

importjava.util.logging.Logger;importjavax.annotation.PostConstruct;import javax.ejb.Singleton;import javax.ejb.Startup;import javax.ejb.DependsOn;importjavax.ejb.ConcurrencyManagement;importjavax.ejb.ConcurrencyManagementType;import javax.ejb.AccessTimeout;import java.util.Map;import javax.ejb.EJB;import java.util.HashMap;import javax.ejb.Lock;import javax.ejb.LockType;importjava.util.concurrent.TimeUnit;

@Startup@DependsOn("MyLoggingBean")@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)@Singleton

117

@AccessTimeout(value=120000) //default in millisecondspublic classCacheSingletonBean {

private Map<Integer,String> myCache;

@EJBMyLoggingBean loggingBean;

@PostConstructpublic void start(){

loggingBean.logInfo("Started!");myCache = new

HashMap<Integer, String>();}

@AccessTimeout(value=30,unit=TimeUnit.SECONDS)

@Lock(LockType.WRITE)public void

addUser(Integer id, Stringname){

myCache.put(id, name);}

@Lock(LockType.READ)public String

118

getName(Integer id){return myCache.get(id);

}}

The @AccessTimeout annotation can havedifferent TimeUnit constants, such asNANOSECONDS, MICROSECONDS,MILLISECONDS, and SECONDS. If noTimeUnit value is given, the value isinterpreted as milliseconds by default. You canalso place this annotation at the class level andapply it to all methods that don’t explicitlydefine an access timeout annotation.

WHERE AND WHEN TO USE THESINGLETON PATTERNAs a rule of thumb, heavy use of singletons maybe a sign of misuse. You should use singletonswhere it makes sense, such as cachingfrequently accessed but expensive-to-load data,sharing data for global access, or using singlepoint of contact purposes (such as logging).

Creating and caching unnecessary resourceshas a negative impact on memory, CPUresources, and initial startup, so handlesingletons with care when using them forcaching data. However, singletons can be quite

119

handy and can be configured easily in a Java EEcontainer. For serious caching solutions,consider a framework such as the widely usedEhcache (http://www.ehcache?.org/) orApache’s distributed caching system JavaCaching System(http://commons.apache?.org/proper/commons-jcs/).

You can use a singleton to control access toback-end systems that are not thread safe orhave licensing issues. Using theLockType.WRITE annotation on methodsallows sequential access to such systems inwhich multiple concurrent access would causeproblems with performance or licensing.

SUMMARYIt has been briefly mentioned that the singletonpattern has fallen out of favor to the point inwhich many developers and architects nowconsider it an anti-pattern. The singletonpattern’s unpopularity extends from problemscaused by its overuse and abuse and its evidentshortcomings in multithreaded applications.

Programmers have overused and abused thesingleton pattern because it is a simple patternto implement. So every class becomes asingleton. This has presented a nightmare fordevelopers who must maintain the code, and ithas become an even greater challenge for those

120

who have to refactor the singletons intoobject-orientated code when it is discoveredthat more than one instance of a singleton classis required.

The use of singleton classes has made testabilitymore complicated because global states need tobe instantiated to run a simple unit test.Furthermore, singletons have made tests lessdeterministic because these states mightchange, affecting the outcome of the tests.

You have seen in the code examples thenumerous difficulties that singletons pose inmultithread environments. It was difficult tocreate a singleton that was guaranteed threadsafe before Java SE 5 and the introduction ofthe enum type.

However, with the advances made in Java EE,the problem of thread-safe singletons haslargely been resolved with the @Singletonannotation and container control concurrency.

The container controls the creation of thesingleton and ensures that no business methodis called before the @PostContrustcompletes. The container also controls theconcurrency of access to the bean via the@ConcurrencyManagement annotation,and its associated @LockType annotationallows fine-grain access control over eachmethod.

121

By no means has every problem of the singletonbeen resolved. There could still be problems inmultinode environments if the bean is used toaccess back-end non-thread-safe resources.Bottlenecks and tight coupling of classes couldbe additional problems.

Even though the singleton pattern has sufferedfrom abuse and overuse by developers, leadingto its eventual relegation to an anti-pattern, ithas nevertheless matured substantially since itwas introduced by GoF and should bereconsidered as a valuable and viable designpattern.

EXERCISES

Design a web page hit counter with twomethods: one method that increments thecount, and one method that gets the latestcount. Ensure that it is thread safe bydefining the appropriate lock types.

Design a simple cache that stores a list ofbooks for a library management application.The data should be loaded into the cache onapplication startup. Add methods to retrievebooks based on different criteria, such asISBN, author, and genre.

Design a complex cache that reads data froma database at startup. The data retrievalmethods should query the cache first, and ifthe requested data is not found, the bean

122

should query the database. If the datarequested is found in the database, it shouldbe stored in the cache.

Add to exercise 3 a mechanism that deletesinfrequently accessed data from the cacheand updates out-of-date data. Ensure thatthe entire life cycle of the cache isappropriately managed.

NOTES

1. Design Patterns: Elements of ReusableObject-Oriented Software (Addison-Wesley,1994): Erich Gamma, Richard Helm, RalphJohnson, John Vlissides.

2. Head First Design Patterns (O’Reilly, 2004):Eric Freeman, Elisabeth Robson, Bert Bates,Kathy Sierra.

3. Effective Java (Addison-Wesley, 2008):Joshua Bloch.

123

5Dependency Injection andCDIWHAT’S IN THIS CHAPTER?

Introduction to dependency injection

Why DI is important in Java EE

How to implement DI in plain code

How DI is implemented in Java EE

Introduction to Content Dependency Injection

Key differences between CDI and EJBcontainers

WROX.COM CODE DOWNLOADSFOR THIS CHAPTERThe wrox.com code download for this chapter isfound at www.wrox.com/go/projavaeedesignpatterns on theDownload Code tab. The code is in the Chapter5 download and individually named accordingto the names throughout the chapter.

Dependency injection (DI) is one of the fewwell-known and accepted design patterns thatwas not listed in the book by the Gang of Four.1

Today, it has been used widely in modern

124

programming languages both internally and asa best practice to promote loose coupling.

J2EE was designed to handle the most complexsystems but failed miserably byovercomplicating the development of even thesimpler systems. The original design of J2EErelied on heavyweight complexity and tightcoupling, which led to the popularity offrameworks such as Spring and Pico container.In 2004, Martin Fowler published an article onthe inversion of control containers and thedependency of the injection pattern.2 Mostvendors did not support and encouragedevelopers to use the J2EE container. However,soon the lightweight containers took over, theybecame officially supported and, even more,Spring became the unofficial de facto standardand led to the redesign of Enterprise Java fromscratch.

WHAT IS DEPENDENCYINJECTION?The dependency injection pattern is based onthe idea of inverting the control. Instead ofcreating hard dependencies and creating newobjects either with the new keyword or lookups,you inject the needed resource into thedestination object. This approach has manybenefits:

125

The client does need not to be aware of thedifferent implementations of the injectedresources, making design changes easier.

Unit testing using mock objects is much easierto implement.

Configuration can be externalized, reducing theimpact of changes.

A loosely coupled architecture allows pluggablestructures.

The basic idea behind DI is to change the placewhere objects are created and to use an injectorto inject the specific implementations to thedestination objects at the right moment. Thismay sound like an implementation of thefactory pattern (see Chapter 6, “FactoryPattern”), but the whole concept is much morethan simple object creation. Inversion ofControl (IoC) changes the whole wiringbetween objects and lets the injector do thework (most of the time magically). Instead ofcalling a factory to provide an implementationto the caller, the injector works proactively todetermine when a destination object needs thetarget object and performs the injection in theappropriate way.

IMPLEMENTING DI IN PLAINCODEJava did not offer a standard DIimplementation out of the Enterprise

126

JavaBeans (EJB) container until theintroduction of Context and DependencyInjection (CDI). Although there are various DIframeworks, such as Spring and Guice, it is notdifficult to code a basic implementation.

The simplest implementation of DI is a factorythat creates the dependency on request via agetInstance() method. Now you’llimplement an example that shows how to dothis in plain code.

The simple DI implementation should separatethe resolution of dependencies from thebehavior of the class. This means a class shouldhave specific functionality without defining howit obtains a reference to the classes it dependson. This decouples object creation from wherethe object is used: the essence of DI.

You will start by looking at an example inListings 5-1, 5-2, 5-3 and 5-4 that is highlycoupled, and refactor it to use yourhome-grown DI.

LISTING 5-1: UserService class thatcreates a new dependency in theconstructor

package com.devchronicale.di;

class UserService {

127

private UserDataRepositoryudr;

UserService() {this.udr = new

UserDataRepositoryImpl();}

public voidpersistUser(User user) {

udr.save(user);}

}

LISTING 5-2: UserDataRepositoryinterface

package com.devchronicale.di;

public interfaceUserDataRepository {

public void save(Useruser);}

128

LISTING 5-3: Concreteimplementation of theUserDataRepository

package com.devchronicale.di;

public classUserDataRepositoryImplimplements UserDataRepository {

@Overridepublic void save(User

user) {// Persistence code

here}

}

LISTING 5-4: User class

package com.devchronicale.di;

public class User {// User Specific Code Here

}

In Listing 5-1, the UserService classprovides business logic services for usermanagement, such as persisting the user to the

129

database. In this example, the object creation isdone in the constructor. This couples thebusiness logic (the class’s behavior) to theobject creation.

You’ll refactor this example by taking the objectcreation out of your class and putting it in afactory.

In Listing 5-5, an implementation of theUserDataRepository is created and passedto the constructor of the UserService class.You change the constructor of theUserService class to accept this newparameter.

LISTING 5-5: UserServiceFactory thatcreates UserService objects

package com.devchronicale.di;

public classUserServiceFactory {

public UserServicegetInstance(){

return newUserService(newUserDataRepositoryImpl());

}}

130

In Listing 5-6, the UserService constructorasks for an instance of theUserDataRepository to be “injected” intothe constructor. The UserService class isdecoupled from theUserDataReposityImpl class. The factoryis now responsible for the creation of the objectand “injects” the implementation into theconstructor of the UserService. You havesuccessfully separated the business logic fromobject creation.

LISTING 5-6: The refactoredUserService class

package com.devchronicale.di;

class UserService {

private UserDataRepositoryudr;

UserService(UserDataRepositoryudr) {

this.udr = udr;}

public voidpersistUser(User user) {

131

udr.save(user);}

}

WAR STORY

When I was given the task of writing anAndroid application, I decided to researchDependency Injection Frameworks formobiles. As a software developer withEnterprise Development experience, thisseemed like the right route to take. TheAndroid user interface (UI) system wasalready reliant on a DI-like structure thatbound XML-based UI components to Javacode, so it seemed wise to implement a fullyfunctioning DI framework to achieve blownfunctionality.

I worked on a beautiful architecture in whichall objects and resources were wired together.The injection worked like a charm; however,the application did not. The app start-up tookmuch longer than similar apps, and thenavigation was not so smooth either. We allbelieved DI was a must-have to achieve loosecoupling and well-organized code, so welooked for problems in other areas. Wemastered sleek, lightweight UI and

132

asynchronous background tasks so wewouldn’t lock the app and to minimize thework done on start-up, but nothing reallyworked.

It soon dawned on us that the root of theproblem was the DI framework. It wassearching for all injection resources andreferences, while the app was starting andtrying to perform all the wiring at thebeginning of the app’s life cycle. This mightbe a good idea on a server start-up, which hasmany users, few restarts, and huge amountsof memory. But it wasn’t a good idea on amobile device, where we had a single user,many restarts, and limited memory.

Our solution was to hard-wire the resources.Even though this gave us an “uglier” app, theapp started up in lightning speed, solving ourperformance issue.

The moral of this story is not that DI is a badpattern to implement on mobile devices butthat a poor implementation of DI (whetheron a mobile device or not) in the wrongcontext can cause huge problems.

IMPLEMENTING DI IN JAVA EEJ2EE did not offer DI out of the box until JavaEE 5. Instead, in J2EE, beans and resources

133

were accessed using Java Naming and DirectoryInterface (JNDI) context lookups. Thisapproach caused hard-wiring and relied on aheavyweight server-based container, whichmade testing almost harder than writing theactual code.

With the release of Java EE 5 and EJB 3, DIbecame an integral part of the Enterprise Javaplatform. To get rid of XML-basedconfiguration, several annotations wereintroduced to perform injection:

@Resource (JSR250) is for injecting datasources, Java Message Service (JMS), URL,mail, and environment variables.

@EJB (JSR220) is for injecting EJB.

@WebServiceRef is for injecting webservices.

With the release of Java EE 6, CDI, and EJB 3.1,DI became a much more capable, and thusmore interesting, topic in Java EE.

In EJB 3.1, an interface was no longermandatory for EJBs. Also, a new EJB webprofile was introduced that offers a simplifiedlighter EJB container. A new and improvedinjection annotation @Inject was introduced(JSR229 and JSR330), which also provided acommon interface for injection between otherDI frameworks in the Java realm.

134

The @Inject annotation DI is type safebecause it injects a dependency based on thetype of the object reference. If you were torefactor the code in Listing 5-1, you wouldremove the constructor and add an @Injectannotation to the UserDataRepositoryfield. The code would look something likeListing 5-7.

LISTING 5-7: The refactoredUserService class using @Inject

package com.devchronicale.di;

import javax.inject.Inject;

class UserService {

@Inject

private UserDataRepositoryudr;

public voidpersistUser(User user) {

udr.save(user);}

}

The CDI container constructs a singleUserDataRepositoryImpl instance as a

135

container managed bean and injects itanywhere it finds @Inject annotating a fieldof type UserDataRepository.

You can inject a container-managed bean intoconstructors, methods, and fields, regardless ofthe access modifier, although fields must not befinal, and the method must not be abstract.

Some important questions arise. What happensif there is more than one implementation of theUserDataRepository interface? How doesthe CDI container identify the correctimplementation to inject? To disambiguate theconcrete implementations of theUserDataRepository interface, you canannotate the concrete class using adeveloper-defined qualifier.

Imagine having two implementations of theUserDataRepository interface: one for aMongo DB collection (a document baseddatabase) and another for a MySQL database(relational database). You would have to createtwo qualifiers (one for the Mongoimplementation and another for the MySQLimplementation), the concrete class would beannotated at the class level with the relevantqualifier, and in the class in which theUserDataRepository is to be injected, afield would be annotated with the samequalifier.

136

If you refactor the UserService class inListing 5-7 to use the Mongo implementation ofthe UserDataRepository, you would add@Mongo to the udr field as follows:

@Inject @Mongoprivate UserDataRepository udr;

The use of qualifiers is discussed in more depthbelow and in Chapter 6.

The @Named AnnotationAnother great achievement was theintroduction of the @Named annotation insteadof String qualifiers. Ambiguities in EJBdependencies were resolved by using a String inthe beanName attribute of the @EJBannotation that specified the implementation tobe injected:?@EJB(beanName="UserDataRepository").The @Name annotation also supportsdisambiguation with the use of a Stringattribute. In Listing 5-8, the Mongoimplementation of theUserDataRepository is injected into theudr field.

137

LISTING 5-8: The @Namedannotation used to disambiguate

package com.devchronicale.di;

import javax.inject.Inject;

import javax.inject.Named;

class UserService {

@Inject

@Named("UserDataRepositoryMongo")private UserDataRepository

udr;

public voidpersistUser(User user) {

udr.save(user);}

}

An explicit annotation of the Mongoimplementation is required by a corresponding@Named annotation appropriately named. InListing 5-9, the Mongo implementation of theUserDataRepository interface isannotated with the same String name as that

138

used to disambiguate the injectedimplementation in Listing 5-8.

LISTING 5-9: The concreteimplementation requires an @Namedannotation

package com.devchronicale.di;

import javax.inject.Named;

@Named("UserDataRepositoryMongo")public classUserDataRepositoryMongoimplements UserDataRepository {

@Overridepublic void save(User

user) {// Persistence code

here}

}

The use of Strings to identify dependencies islegacy because it is not type safe and isdiscouraged in the CDI specification JSR-299.However, there is a use of the @Namedannotation that avoids the need to use Stringidentifiers at the point of injection.

139

@Inject @Namedprivate UserDataRepository

UserDataRepositoryMongo;

In Listing 5-9, the name of the implementationto inject is inferred from the name of the fieldUserDataRepositoryMongo. What iseffectively happening is that @Named is beingreplaced by@Named("UserDataRepositoryMongo").

Context and Dependency Injection (CDI)Context and Dependency Injection (CDI)brought full-fledged dependency injection andcontext support to the Java EE platform, whichused to be EJB specific and far more limited.After EJB 3 was introduced, JBoss introducedSeam (a web application framework), whichhad become quite popular, by supporting directinteraction between JavaServer Faces (JSF) andJavaBeans as well as EJB. The success of Seamled to the design of JSR299, WebBeans. Just asHibernate, a famous Java PersistanceFramework, inspired Java Persistence API(JPA) standardization, Seam inspired andformed the core implementation of CDI.

CDI can work with any Plain Old Java Object(POJO) by instantiating and injecting objectsinto each other. The following types of objectsare injectable:

POJOs

140

Enterprise resources such as data source andqueues

Remote EJB references

Session beans

EntityManager objects

Web services references

Producer fields and objects returned byproducer methods

CDI Versus EJBAlthough CDI and EJB seem to be rivals, theywork in harmony. CDI can work alone withoutan EJB container. Actually, CDI can power adesktop application or any web application thatdoesn’t rely on the EJB container. CDI providesthe factory and injection to any JavaBean.

However, EJBs still require the EJB container.Even the simplified architecture of EJBs ismore complex than POJOs, so EJBs still needthe EJB container. The EJB container providesadditional services such as security,transactions, and concurrency that EJBs need.

Simply put, the CDI container is a lighter,powerful, but less functional container forPOJOs. Still, both containers are so wellintegrated that CDI annotations can act as agateway and standard interface to interact withthe EJB container. For example, the @Injectannotation can work with either POJOs or EJBs

141

and can inject any combination of each byinvoking the right container to handle the job.

CDI BeansA container managed bean is little more than aPOJO that conforms to some simple rules:

It must have a no-argument constructor, or theconstructor must declare an @Injectannotation.

The class must be a top-level concrete class ormust be annotated with @Decorate; it cannotbe a nonstatic inner class.

It cannot be defined as an EJB.

If the bean is defined as a managed bean byanother Java EE technology, such as the JSFtechnology, it will also be managed by thecontainer.

Any class conforming to these requirements willbe instantiated and managed by the containerand is injectable. No special annotation isrequired to define the class as a managed bean.

The container looks for bean-inside-beanarchives. There are two types of bean archives:explicit and implicit. An explicit archivecontains a bean.xml deployment descriptor,which is normally empty. The CDI scans theclasses in the archive looking for any class thatconforms to the bean requirements detailedearlier and manages and injects any such class

142

that is not annotated with @Vetoed. Thisannotation excludes that class from beingmanaged by the container.

In some cases, it may not be desirable to allowthe container to manage any conformant bean itfinds. If you want to restrict what the CDIcontainer considers to be a managed bean, youcan define the bean-discovery-modeproperty in the bean.xml deploymentdescriptor. Listing 5-10 shows a snippet of thebean.xml file that defines thebean-discovery-mode property as ALL.

LISTING 5-10: The bean discoverymode is set in the bean.xml

<?xml version="1.0"encoding="UTF-8"?><beansxmlns="http://xmlns.jcp.org/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee

http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"

143

version="1.1"bean-discovery-mode="all">

...</beans>

The bean-discovery-mode property cantake one of three values: ALL, NONE, orANNOTATED. The ALL property instructs theCDI container to manage all beans that it findsin the archive. This is the default. The NONEproperty means that the CDI container willmanage no beans, and the ANNOTATEDproperty makes the archive behave like animplicit archive. In this case, the containerscans for beans with annotated scope types.

An implicit bean archive does not contain abean.xml deployment descriptor. This signalsto the CDI container that the container shouldonly manage beans with a scope. Further detailsabout scoped beans are discussed later in thesection, “Contexts and Scope.”

The @Inject AnnotationThe @Inject annotation and its capabilitieshave already been covered. Before CDI in JavaEE was introduced, each DI framework offeredits own way of injecting resources. When theJava EE CDI container was released to workalongside the EJB container, @Inject

144

annotation became a unique and abstractinterface for almost all inject operations. The@Inject annotation lets you use anyappropriate container or DI frameworkreferenced for the case.

Contexts and ScopeContext is the difference between EJBs and CDIcontainers. Each CDI bean’s life cycle is boundto a context scope. The CDI offers four differentscopes:

@RequestScoped—Duration is a user’s HTTPrequest.

@SessionScoped—Duration is a user’s HTTPsession.

@ApplicationScoped—State is sharedacross all users for the duration of theapplication.

@ConversationScoped—Scope duration iscontrolled by the developer.

A bean annotated with a scope holds state forthe duration of the scope and shares that statewith any client that runs in the same scope. Forexample, a bean in the request scope holds statefor the lifetime of the HTTP request, and a beanwith session scope holds state for the lifetime ofthe HTTP session. The scoped bean isautomatically created when it is needed anddestroyed when the context in which it takespart finishes.

145

The scope annotations are often used to givescope to beans that are used via ExpressionLanguage (EL) in Facelet pages.

Naming and ELA bean annotated with @Named is accessiblethrough EL. By default, the name used in theexpression is the name of the class with the firstletter in lowercase. To refer to gettermethods that start with get or is, omit theget or is part of the method name. Listing5-11 shows an example.

LISTING 5-11: The @Namedannotation makes a bean visible to EL

package com.devchronicale.di;

importjavax.enterprise.context.RequestScoped;import javax.inject.Named;

@Named // Defining that this isa managed bean@RequestScoped // Defines thescopepublic class User {

private String fullName;

146

public String getFullName(){return this.fullName;

}

// some methods not included forbrevity}

This is a simple implementation of a namedbean that returns a String when thegetFullName() method is called. In aFacelets page, you would refer to this method asuser.fullname.

<h:form id="user"><p><h:outputText

value="#{user.fullname}"/></p></h:form>

CDI Beans for Backing JSFAs in the previous example, CDI Beans canserve as backing beans for JSF pages. You canaccess named beans via the name of the beanwith a lowercased first letter. You can accessGetter/Setter fields and methods within JSFpages using Java conventions. Details of JSF gobeyond the scope of this book, but Listing 5-11demonstrates a basic usage of CDI Beans withJSF.

147

QualifiersThis section looks at how you would constructthe qualifier classes.

In Listing 5-12, you create a qualifier namedMongo that you can use to annotate fields. Ifyou want to use this annotation on a METHOD, aPARAMETER, or a class/interface (TYPE), youcan add it to the @Target annotation.

LISTING 5-12: Create a customqualifier named @Mongo

package com.devchronicale.di;

import staticjava.lang.annotation.ElementType.FIELD;import staticjava.lang.annotation.RetentionPolicy.RUNTIME;

importjava.lang.annotation.Retention;importjava.lang.annotation.Target;

import javax.inject.Qualifier;

@Qualifier@Retention(RUNTIME)

148

@Target({FIELD})public @interface Mongo {}

The discussion regarding the varied use ofannotations continues in more depth in Chapter6.

AlternativesIn the examples so far, you learned how you candisambiguate between two distinctimplementations of theUserDataRepository interface by usingqualifiers. You normally make this choice ofimplementation at development time bychanging the source code. However, you canalso make this choice at deployment time byusing the @Alternative annotation andsome configuration in the bean.xmldeployment descriptor.

Adapting the examples so far, you annotate thetwo implementations of theUserDataRepository interface with@Alternative and add some configurationXML to the bean.xml file. This is where youdecide which implementation to inject.

@Alternativepublic classUserDataRepositoryMongo

149

implements UserDataRepository{...}

@Alternativepublic classUserDataRepositoryMySQLimplements UserDataRepository{...}

The implementation that you use in theapplication is declared in the bean.xml file:

<beans ...><alternatives>

<class>com.devchronicale.di.UserDataRepositoryMongo</class></alternatives>

</beans>

Alternatives are often used during the testingphase of development to create mock ?objects.

StereotypesYou can think of stereotypes as templates thatdefine the characteristics of a specificfunctionality of a bean type. For example, abean that is used at the model layer of an ModelView Controller (MVC) application requirescertain annotations to perform its function.These would include the following:

@Named@RequestScoped

150

@Stereotype@Target({TYPE, METHOD, FIELD})@Retention(RUNTIME)

Only @Named and @RequestScoped areenough to define a Model bean. Others arerequired to create an annotation called@Model.

You could apply these annotations on everybean that requires them, or you could define astereotype called @Model and apply only thatto the beans. The latter makes your code mucheasier to read and maintain.

To create a stereotype, you define a newannotation and apply the required annotationsas in Listing 5-13.

LISTING 5-13: Stereotype annotation

@Named@RequestScoped@Stereotype@Target({TYPE, METHOD, FIELD})@Retention(RUNTIME)public @interface Model {}

Any bean annotated with @Model has a requestscope (@RequestScoped) and is visible to EL(@Named). Luckily, the CDI container that

151

comes with this stereotype has already beendefined.

A typical use of the stereotype annotation is tocombine with alternative annotation so youhave a way to annotate mock objects.

Other Patterns via CDICDI unleashed a great power to Java EEdevelopers. CDI goes beyond being just asimple DI framework by making theimplementation of all those patterns possiblewith minimal code.

The chapters that follow dive deep into detailsof these patterns; however, to whet yourappetite, here’s a brief introduction to theseCDI-powered patterns.

Chapter 7, “Decorator Pattern,” covers thedecorator pattern. Decorators wrap a targetobject to dynamically add new responsibilitiesat run time. Each decorator can be wrapped byanother, which allows for a theoreticallyunlimited number of decorated target objects atrun time. The decorator pattern uses the@Decorator and the @Delegateannotations. You must specify the decorationorder in beans.xml.

The factory pattern is covered in Chapter 6.Factories minimize the usage of the newkeyword and can encapsulate the initializationprocess and different concrete

152

implementations. The factory pattern uses the@Produces annotation to mark producermethods. Target object can inject or observe theproduced objects.

The observer pattern and events are addressedin Chapter 11, “Observer Pattern.” The observerpattern changes the direction of a message, thusthe order of caller and the callee. With the helpof the observer pattern, instead of aggressivelychecking a resource, an object can subscribe tothe changes on the resource. The observerpattern in Java EE uses the @Observesannotation and events. The target observer(s)can observe any fired event.

Aspects and interceptors are the focus ofChapter 8, “Aspect-Oriented Programming(Interceptors).” They let you change executionflow at run time. Any aspect or interceptor canbe marked to cut the execution and kick in atthe given point. This approach enables dynamicchanges even on a large code base.

SUMMARYIn this chapter, you have seen the concept ofdependency injection in Java EE. Thedependency injection concept lets us buildloosely coupled systems easier than one canever imagine. We have seen how dependencyinjection allows us to eliminate the use of a newkeyword, thus, manual object creation.

153

We also focused on CDI, which unleashes ahuge potential by leveraging a whole newcontainer. With the help of CDI, dependencyinjection can be applied to any object and manypatterns that are discussed in this book are easyto implement.

EXERCISESDesign a service class which will returnsome string to the client.

Implement a file reader and inject it to theservice you developed before.

This time implement an object which readsthe html content as a string from a fixedURL.

Think about what you need to refactor in theservice class to be able to inject both dataproviders with the same reference.

Is there a way to dynamically inject eachimplementation depending on differentcircumstances? For example can you makesure the file reader is injected duringdevelopment but the http reader is usedduring production?

NOTES

1. Design Patterns: Elements of ReusableObject-Oriented Software (Addison-Wesley,

154

1994): Erich Gamma, Richard Helm, RalphJohnson, John Vlissides.

2. Inversion of Control Containers and theDependency Injection Pattern (MartinFowler, 2004):http://martinfowler.com/articles/injection.html.

155

6Factory PatternWHAT’S IN THIS CHAPTER?

What the factory pattern is and why you need it

How to implement the various flavors of thefactory pattern: the factory method and theabstract factory

How to implement the factory pattern in JavaEE using the @Producers and @Injectannotations

How to create custom annotations and the@Qualifier to disambiguate concreteimplementations

WROX.COM CODE DOWNLOADS FORTHIS CHAPTER

The wrox.com code download for this chapter isfound at www.wrox.com/go/projavaeedesignpatterns on theDownload Code tab. The code is in the Chapter6 download and individually named accordingto the names throughout the chapter.

The factory design pattern is one of the widelyused core design patterns in modernprogramming languages. It is used not only byweb and application developers, but by the

156

developers of run times and frameworks suchas Java and Spring.

The factory pattern has two variations: thefactory method and the abstract factory. Theintent of these patterns is the same: to providean interface for creating families of related ordependent objects without specifying theirconcrete classes. This chapter introduces you toboth of these variations and shows youexamples of how to implement them.

You will see how the factory pattern has beenimplemented in Java SE, how that differs fromits implementation in Java EE, and how it takesadvantage of context dependency injection.

WHAT IS A FACTORY?As one of the creational patterns, the factory’spurpose is to create objects. The creational logicis encapsulated within the factory and eitherprovides a method that returns a newly createdobject (factory method pattern) or delegates thecreation of the object to a subclass (abstractfactory pattern). In both cases, the creation ofthe object is abstracted away from where it willbe used.

The client need not be aware of the differentimplementations of the interface or class. Theclient only needs to know the factory (factorymethod or abstract factory) to use to get aninstance of one of the implementations of the

157

interface. Clients are decoupled from thecreation of the objects.

The decoupling occurs as the result of applyingthe dependency inversion principle and bringsmany practical advantages, of which the mostimportant is the decoupling of higher-levelclasses from lower-level classes. Thisdecoupling allows the implementation of theconcrete classes to be changed without affectingthe client, thus reducing coupling betweenclasses and increasing flexibility.

The factory pattern gives us the opportunity todecouple object creation from the underlyingsystem by encapsulating the code responsiblefor creating the objects. This approachsimplifies our life when it comes to refactoringas we now have a single point where therefactoring changes happen.

Often the factory itself is implemented as asingleton or as a static class because normallyonly one instance of the factory is required. Thiscentralizes factory object creation, allowing forgreater organization and maintainability ofsource code and the reduction of errors whenchanges and updates are made.

NOTE Dependency Inversion Principle:

High-level modules should not depend onlow-level modules. Both should dependon abstractions.

158

Abstractions should not depend ondetails. Details should depend onabstractions.1

In Java EE, dependency injection is employedto deliver the decoupling of higher-level classesfrom lower-level classes when implementingthe factory pattern. The combined use of the@Producers and @Inject annotationsmakes their implementation relatively simple.

FACTORY METHODThe GoF2 book describes the factory methodpattern as such: “Defines an interface forcreating an object, but lets subclasses decidewhich class to instantiate.” Head First DesignPatterns3 adds that the “factory method lets aclass defer instantiation to subclasses.”

Factories minimize the usage of the newkeyword and can encapsulate the initializationprocess and the different concreteimplementations. The ability to centralize thoseneeds minimizes the effect of adding orremoving concrete classes to the system and theeffects of concrete class dependencies.

The factory method class diagram is shown inFigure 6.1.

159

Figure 6.1 The class diagram shows thestructure of the factory method pattern. Youcan see how the object creation is encapsulatedin the subclasses.

WAR STORY

At one time, I was developing a desktopapplication with a friend. At the beginning,we were not sure if we needed a full-blowndatabase or not. This was long before no-SQLand document-based data stores, so our onlyoption was to use XML. Nevertheless, wewere not sure if XML files would be sufficientto store the data. Meanwhile, we had alreadystarted developing the application andneeded a concrete persistenceimplementation to save data. Because wewanted the flexibility to change the systemfrom using XML to using SQL, we decided tocreate all the data access objects (DAOs) viathe implementation of the factory pattern.This way we could easily switch from XML to

160

SQL or vice versa. Within a few weeks, werealized that we really underestimated thedata needs of the system. XML was definitelyan adequate solution and was now out ofquestion, so we were stuck with anSQL-based database for the rest of theproject. In the end, we didn’t really use ourDAO factory.

However, as we were completing theapplication, our clients asked for a demoplatform. It was not enough to demonstratethe capabilities of the application and letthem play for a day or two. They wantedmore time to evaluate the application. Thismeant we needed to install a functioningapplication on the network to allow theclients time to properly evaluate theapplication and see that it rocked. We didn’twant to install the full application becausethere was no way to ensure that the clientwouldn’t make a copy, and we definitelydidn’t want to build a demo application fromscratch. Suddenly, I came up with a brilliantidea. The demo application needed to persistthe data in order to function sufficiently, sothat the client could evaluate it, but notenough that the client could make a piratecopy of the application. The idea was totemporarily store the data in memory. If wecould easily change our DAOs to an

161

in-memory data store instead of persistingthe data in a database, we could leave theclients to try the demo version for as long asthey wanted. (Without a persistent datastore, the application would make no sense atall!) Because we already had the DAO factory,we only needed to implement the in-memoryDAO classes and tweak the factory code toreturn them when our database was notpresent.

The result was so successful that Iimplemented another factory to control printjobs to print to a nonformatted text fileinstead of the real printer for the demoversion. These changes that took advantageof the factory pattern meant that we couldeasily leave clients to evaluate our applicationfor as long as they wanted and, because theclients could not print formatted copies andpersist financial data, the application wasuseless in production.

Designing the system using factories was nota huge win at first but was a life saver in theend. Design patterns tend to address futureproblems if they are used in the right context.

162

Implementing the Factory Method inPlain CodeThe factory method does not have boilerplatecode for its implementation. Listings 6-1 to 6-6show implementations of the factory patternusing a DrinksMachine that dispensesdifferent types of drinks depending on theimplementation of its subclasses.

LISTING 6-1: DrinksMachine abstractclass extended by concreteimplementations

public abstract classDrinksMachine {

public abstract DrinkdispenseDrink();

public StringdisplayMessage(){

return "Thank for yourcustom.";

}}

163

LISTING 6-2: CoffeeMachineimplementation of the DrinksMachineabstract class

public class CoffeeMachineextends DrinksMachine {

public DrinkdispenseDrink() {

return new Coffee();}

}

LISTING 6-3: SoftDrinksMachineimplementation of the DrinksMachineabstract class

public class SoftDrinksMachineextends DrinksMachine {

public DrinkdispenseDrink() {

return new SoftDrink();}

}

164

LISTING 6-4: The Drink interface

public interface Drink {}

LISTING 6-5: SoftDrinkimplementation of the Drink interface

public class SoftDrinkimplements Drink {

SoftDrink() {

System.out.println("Softdrink");

}}

LISTING 6-6: Coffee implementationof the Drink interface

public class Coffee implementsDrink {

Coffee() {

System.out.println("Coffee");

165

}}

This implementation shows how the subclassesof the DrinksMachine abstract classdetermine the drink that is dispensed. Thisallows any implementation of theDrinksMachine class to dispense any objectof the Drink type. Each subclass of theDrinksMachine’s abstract class determineswhich drinks are dispensed.

This is a simple implementation in which thedispenseDrink method dispenses only onetype of drink. A more illustrative examplewould show the dispenseDrink methodreceiving the name of a drink and thenconstructing and returning the requested drinkobject. Listing 6-7 shows how to achieve this.

LISTING 6-7: CoffeeType enum

public enum CoffeeType{EXPRESSO, LATTE}

public DrinkdispenseDrink(CoffeeType type)

166

{

Drink coffee = null;

switch (type) {

case EXPRESSO: coffee= new Expresso();

case LATTE: coffee= new Latte();

}

return coffee;}

For brevity, this chapter shows only a codesnippet of the enum type CoffeeType thatdefines the type of coffee and thedispenseDrink method of the concreteCoffee class.

ABSTRACT FACTORYThe factory method pattern is straightforwardand useful to implement, but in more complexsystems, you need to organize it. This problemleads you to a new pattern called the abstractfactory pattern.

The abstract factory pattern is described in boththe GoF book and Head First Design Patterns

167

as “provides an interface for creating families ofrelated or dependent objects without specifyingtheir concrete classes.”

What abstract factories offer is theencapsulation of a group of factories andcontrol over how the client accesses them. Thischapter does not go into all the details of how toimplement abstract factories but instead offersa brief introduction for basic understanding.

The abstract factory class diagram is shown inFigure 6.2.

Figure 6.2 As can be seen in the class diagram,you can use the abstract factory pattern togroup existing factories and encapsulate howyou access them.

Implementing the Abstract Factory inPlain CodeTo demonstrate the abstract factory designpattern, this chapter extends the drinksmachine example by adding a factory thatproduces two different types of drinks machine:basic and gourmet.

168

The “families of related or dependent objects”that the abstract factory creates are the coffeemachine and the soft drinks machine. You mustcreate an interface for the factories toimplement. In Listing 6-8, you create theAbstractDrinksMachineFactoryinterface.

LISTING 6-8: Interface for the abstractfactory

public interfaceAbstractDrinksMachineFactory {

public DrinksMachinecreateCoffeeMachine();

public DrinksMachinecreateSoftDrinksMachine();}

The concrete implementations of this interfaceare the GourmetDrinksMachineFactoryand the BasicDrinksMachineFactoryclasses. For brevity, only theGourmetDrinksMachineFactory isshown in Listing 6-9.

169

LISTING 6-9: Implementation of theAbstractDrinksMachineFactory

public classGourmetDrinksMachineFactoryimplementsAbstractDrinksMachineFactory{

public DrinksMachinecreateCoffeeMachine() {

return newGourmetCoffeeMachine();

}

public DrinksMachinecreateSoftDrinksMachine() {

return newGourmetSoftDrinksMachine();

}

}

Each factory implements the abstract factory’screate method in a different way and,depending on which factory is instantiated, adifferent implementation of a coffee and softdrinks machine is created.

AbstractDrinksMachineFactoryfactory = new

170

GourmetDrinksMachineFactory();DrinksMachine CoffeeMachine =factory.createCoffeeMachine();CoffeeMachine.dispenseDrink(CoffeeType.EXPRESSO);

This shows aGourmetDrinksMachineFactory beinginstantiated. Its coffee machine’s creationmethod is invoked to create the coffee machineobject that this implementation requires.

The full code for this implementation is in theChapter 6 download.

IMPLEMENTING THE FACTORYPATTERN IN JAVA EEThe factory pattern is not tricky to implement,as you have seen in the preceding examples.Java EE offers a simple and elegant way toimplement the factory pattern via annotationsand dependency injection. In the Java EEworld, you use the @Produces annotation tocreate an object, and you use @Inject to injectthe created object (or resource) where it’srequired. The simplest implementation in JavaEE of the factory method follows in Listing6-10.

171

LISTING 6-10: Simple implementationof the factory method using producermethods

packagecom.devchronicles.producer;importjavax.enterprise.inject.Produces;

public class EventProducer {

@Producespublic String getMessage(){

return "Hello World";}

}

The getMessage method is annotated with@Produces and results in String objectscontaining the text Hello World. Althoughthe type produced in this example is a string,you can produce anything you need, includinginterfaces, classes, primitive data types, Javaarray types, and core Java types.

To use the produced object, you need to injectthe same type into the class where you are goingto use it, as demonstrated in Listing 6-11.

172

LISTING 6-11: Injecting a stringcreated by the factory

packagecom.devchronicles.factory;

import javax.ejb.Stateless;importjavax.ejb.TransactionAttribute;importjavax.ejb.TransactionAttributeType;import javax.inject.Inject;

@Stateless@TransactionAttribute(TransactionAttributeType.REQUIRED)public class EventService {

@Injectprivate String message;

public void startService(){

System.out.println("Startservice call " + message);

}}

When you run and invoke the startServicemethod, the string value in the producermethod is injected into the message member

173

of EventService and printed to the console.This is the simplest possible implementation ofthe factory pattern in Java EE. However, itraises one important question: How does theContext Dependency Injection (CDI) containerknow that it must inject the string produced bythe getMessage method into the messagemember of EventService?

The answer: The CDI container relies on typesto determine where to inject the produced type.In this example, the produced type is a string,as is the injected type. So it matches theproduced type with the inject type and injects it.

You might argue that in a real system, you needto produce and inject different instances of thesame object type. How does the CDI containerknow where to inject each produced type? Itdoes this by using an annotation configurationcalled a qualifier.

In real-world projects, you probably want toreturn different object types instead of a simplestring so that you can create different objects bytype.

LISTING 6-12: MessageA bean

packagecom.devchronicles.factory;

174

@Alternativepublic class MessageA {

private String message;

public String getMessage(){return message;

}

public voidsetMessage(String message){

this.message = message;}

}

LISTING 6-13: MessageB bean

packagecom.devchronicles.factory;

@Alternativepublic class MessageB {

private String message;

public String getMessage(){return message;

}

175

public voidsetMessage(String message){

this.message = message;}

}

LISTING 6-14: Factoryimplementation that creates messagebeans

packagecom.devchronicles.factory;

importjavax.enterprise.inject.Produces;

public class EventProducer {

@Producespublic MessageA

messageAFactory(){return new MessageA();

}

@Producespublic MessageB

messageBFactory(){

176

return new MessageB();}

}

In this example, you have created two beans:MessageA in Listing 6-12 and MessageB inListing 6-13. You have annotated them with@Alternative, which disables them so thatthe container does not attempt to inject theirinstances when it finds a matching injectionpoint. You annotate them so the factory inListing 6-14 will produce the instances. If youdidn’t annotate, the container would throw anexception while loading the application. Itwould read something like this: ?CDIdeployment failure:WELD-001409Ambiguous dependencies for type[MessageA]. The ambiguity is caused by thetwo instances of MessageA that are created:one by the container and the other by the@Produces method. The container doesn’tknow which instance to inject into themessage member of the EventService.You will see a way to resolve this ambiguitylater in the chapter.

177

LISTING 6-15: Injecting the beanscreated by the factory using the@Inject annotation

packagecom.devchronicles.factory;

import javax.ejb.Stateless;importjavax.ejb.TransactionAttribute;importjavax.ejb.TransactionAttributeType;importjavax.enterprise.event.Event;import javax.inject.Inject;

@Stateless@TransactionAttribute(TransactionAttributeType.REQUIRED)public class EventService {

@Injectprivate MessageA messageA;

@Injectprivate MessageB messageB;

public void startService(){

messageA.setMessage("This is

178

message A");

messageB.setMessage("This ismessage B");

System.out.println("Startservice call " +messageA.getMessage());

System.out.println("Startservice call " +messageB.getMessage());

}}

In the EventService class shown in Listing6-15, the containers inject the two beansproduced by the factory into the messageAand messageB member variables of theEventService class. You can use theseobjects as you would normally.

An alternative implementation is to use the@Qualifier and @interface annotationsto mark the type you want to inject. Theexample that follows uses custom annotationsto create two qualifiers: @LongMessage in

179

Listing 6-16 and @ShortMessage in Listing6-17.

LISTING 6-16: ShortMessage qualifier

@Qualifier@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD,ElementType.FIELD})public @interface ShortMessage{}

LISTING 6-17: LongMessage qualifier

@Qualifier@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD,ElementType.FIELD})public @interface LongMessage {}

You use these qualifiers to annotate theproducer methods as shown in Listing 6-18 andtheir matching injection points as shown inListing 6-19.

180

LISTING 6-18: Using the qualifiers todisambiguate the beans

public class EventProducer {

@Produces @ShortMessageprivate MessageA

messageAFactory(){return new MessageA();

}

@Produces @LongMessageprivate MessageB

messageBFactory(){return new MessageB();

}

}

LISTING 6-19: Injecting the createdbeans using qualifiers todisambiguate

@TransactionAttribute(TransactionAttributeType.REQUIRED)public class ClientMessage {

@Inject @ShortMessageprivate MessageA messageA;

181

@Inject @LongMessageprivate MessageB messageB;

public void doEvent(){

messageA.setMessage("This is along email message.");

messageB.setMessage("This is ashort SMS message.");

System.out.println(messageA.getMessage());

System.out.println(messageB.getMessage());}

}

The @Target annotation specified on thequalifier interface determines where you canuse the qualifier. The values can be one or all ofthe following—TYPE, METHOD, FIELD, andPARAMETER—and their meanings areself-explanatory.

Alternatively, you can achieve the sameimplementation via the use of an enum typedefined in the @interface class, Listing 6-20shows this implementation.

182

LISTING 6-20: Custom annotationtype

@Qualifier@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})public @interface MyEvent {

Type value();enum Type{ LOGGING, MESSAGE

}}

With the help of this custom annotation, youcan use different methods to create stringobjects marked with your annotation. In Listing6-21 strings are produced by themessageAFactory and the messageBFactorymethods.

LISTING 6-21: Using the customannotations to disambiguate thebeans

public class EventProducer {

@Produces

@MyEvent(MyEvent.Type.LOGGING)

183

public StringmessageAFactory(){

return "A message";}

@Produces

@MyEvent(MyEvent.Type.MESSAGE)public String

messageBFactory(){return "Another

message";}

}

You use these annotations to annotate theproducer methods and their matching injectionpoints as shown in Listing 6-22.

LISTING 6-22: Injecting the createdbeans using custom annotations todisambiguate

packagecom.devchronicles.observer;

import javax.ejb.Stateless;

184

importjavax.ejb.TransactionAttribute;importjavax.ejb.TransactionAttributeType;importjavax.enterprise.event.Event;import javax.inject.Inject;

@Stateless@TransactionAttribute(TransactionAttributeType.REQUIRED)public class EventService {

@Inject

@MyEvent(MyEvent.Type.LOGGING)private String messageA;

@Inject

@MyEvent(MyEvent.Type.MESSAGE)private String messageB;

public void startService(){

System.out.println("Startservice call " + messageA);

System.out.println("Startservice call " + messageB);

}

185

}

A simpler approach would be to use the@Named annotation rather than creating yourown annotation type. This is implemented as inListing 6-23.

LISTING 6-23: Using @Namedannotations to disambiguate

packagecom.devchronicles.factory;importjavax.enterprise.inject.Produces;

public class EventProducer {

@Produces@Named("Logging")public String

messageAFactory(){return "A message";

}

@Produces@Named("Message")public String

186

messageBFactory(){return "Another

message";}

}

You use @Name to annotate the producermethods and their matching injection points, asshown in Listing 6-24.

LISTING 6-24: Injecting using@Named annotations

@Stateless@TransactionAttribute(TransactionAttributeType.REQUIRED)public class EventServiceName {

@Inject@Named("Logging")private String messageA;

@Inject@Named("Message")private String messageB;

public void startService(){

187

System.out.println("Startservice call " + messageA);

System.out.println("Startservice call " + messageB);

}

}

Although this appears simpler than creatingyour own annotation type, in complicatedsystems, it may not be a wise or a type-safechoice. The named annotation works with theString provided in quotes and is far from beingtype safe. The compiler can’t warn you ofpotential bugs.

Harness the Power of CDIIf your application has multipleimplementations of an interface and you wantto implement a factory pattern to produce therequired instances of these objects, you aregoing to have a factory class with multiplemethods annotated with the @Producesannotation. This will become verbose anddifficult to maintain. Fortunately, Java EEprovides a solution in the form of the @Anyannotation and the imaginative use of enumtypes, annotation literals, and the Instanceclass.

188

What would take many tens if not hundreds oflines of code to produce each instance, you canaccomplish in just four lines of code. You canachieve this by collecting all instances of aparticular interface implementation andselecting the one you want to use by using the@Any annotation.

The @Any annotation instructs the containerthat all beans implementing the given interfaceshould be injected at that injection point. In thelisting below the code privateInstance<MessageType>,messagesinjects instances of all dependencies thatimplement the MessageType interface intothe member variable messages.

Once all dependencies have been injected, youneed a way to distinguish between them andselect the one you want to use. This is where theuse of annotation literals and enum typescomes into play. In the listings that follow, youdefine an @Message qualifier and the enumliterals SHORT and LONG. These distinguishbetween the implementations of theMessageType interface.

To select the dependency, compare it with theenum type of the qualifier of eachimplementation by creating anAnnotationLiteral of the type you aresearching for, retrieve it, and return it to theclient.

189

Now you’ll see how this is implemented in code.You will use the example of a factory thatproduces ShortMessage and LongMessageobjects, each implementing the Messageinterface annotated as either SHORT or LONG.

LISTING 6-25: MessageType interface

public interface MessageType {public String getMessage();public void

setMessage(String message);}

LISTING 6-26: ShortMessageimplementation of message interface

@Message(Message.Type.SHORT)@Dependentpublic class ShortMessageimplements MessageType{

private String message;

@Overridepublic String getMessage()

{return message;

190

}

@Overridepublic void

setMessage(String message) {this.message = message;

}}

LISTING 6-27: LongMessageimplementation of message interface

@Message(Message.Type.LONG)@Dependentpublic class LongMessageimplements MessageType {

private String message;

@Overridepublic String getMessage()

{return message;

}

@Overridepublic void

setMessage(String message) {

191

this.message = message;}

}

Each concrete implementation of theMessageType interface, as shown in Listing6-25, is annotated with an @Message qualifierdenoting the message type as eitherMessage.Type.SHORT orMessage?.Type.LONG as implemented inListing 6-26 and Listing 6-27 respectively. The@Message qualifier is implemented in thesame manner, as can be seen is Listing 6-28, asthe qualifier used in the Custom AnnotationType example shown earlier.

LISTING 6-28: Custom messageannotation

@Qualifier@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.FIELD,ElementType.TYPE})public @interface Message {

Type value();enum Type{ SHORT, LONG }

}

192

To create the annotation literal that you use tomake the comparison between the type youwant and the type of the dependency, youextend the abstract classAnnotationLiteral and implementMessage as the custom message qualifier.Listing 6-29 shows how this is done.

LISTING 6-29: Annotation literal usedto retrieve required message type

public class MessageLiteralextendsAnnotationLiteral<Message>implements Message {

private static final longserialVersionUID = 1L;

private Type type;

public MessageLiteral(Typetype) {

this.type = type;}

public Type value() {return type;

}

193

}

Now that you have all the parts of the puzzle,you can put it together in theMessageFactory class shown in Listing6-30.

LISTING 6-30: The Factoryimplementation

@Dependentpublic class MessageFactory {

@Inject@Anyprivate

Instance<MessageType> messages;

public MessageTypegetMessage(Message.Type type) {

MessageLiteral literal= new MessageLiteral(type);

Instance<MessageType>typeMessages =messages.select(literal);

returntypeMessages.get();

194

}

}

In the factory class, all dependencies thatimplement the MessageType interface areinjected into the member variable messages.Then, from the method getMessage, you usethe Message.Type parameter to create a newMessageLiteral that you use to select theMessageType implementation that you wantfrom messages, which in turn is returned tothe client.

The client injects the factory and calls thegetMessage method passing in theMessage.Type that it requires, as can be seenin Listing 6-31.

LISTING 6-31: Client using theFactory implementation

@TransactionAttribute(TransactionAttributeType.REQUIRED)@ApplicationScopedpublic class Client {

@InjectMessageFactory mf;

195

public void doMessage(){MessageType m =

mf.getMessage(Message.Type.SHORT);m.setMessage("This is

a short message");

System.out.println(m.getMessage());

m =mf.getMessage(Message.Type.LONG);

m.setMessage("This isa long message");

System.out.println(m.getMessage());}

}

This chapter has deviated quite substantiallyfrom the original GoF implementation of thefactory pattern. In fact, you could argue thatthis is not really a true factory patternimplementation but rather a select and injectpattern. Nevertheless, the new and dynamicfunctionality of CDI allows you to be creative inthe way you implement traditional patterns andimprove on classic design.

196

WHERE AND WHEN TO USE THEFACTORY PATTERNSThe traditional implementation of the factorypattern has changed substantially since the GoFfirst espoused its usage.

Abstract factories are considered an effectiveway to hide object creation, especially if thecreation is complex. And the more complex theobject creation, the more justifiable is the use ofa factory to create the object. If it is importantthat objects are created in a consistent mannerand their creation is strictly controlled, youshould consider an implementation of thefactory pattern.

However, in the brave new world of the CDIenvironment, where the container instantiatesmanaged objects, the use of an abstract factoryis arguably moot. Your best attempt toimplement the factory pattern uses the@Produce annotation that still allows you tohide complicated creational logic in theproducer method and inject the resulting objectinto the client.

Alternatively, you can harness the power of theCDI environment and let the container createthe objects and then select the instantiation youwant to use from a pool of similar objects.However, you are limited to simple objects thatcan be instantiated satisfactorily by calling thedefault constructor.

197

SUMMARYIn this chapter, you have seen how toimplement the various flavors of the factorypattern in a non-CDI environment. And in aCDI environment, you have seen how producermethods and the @Inject annotation haveradically changed the way you implement anduse the factory pattern in Java EE.

You have discovered how to harness the powerof the container’s automatic instantiation ofbean objects and how to select and use them inyour code.

Hopefully, you have no doubt that theimplementation of the factory pattern in a JavaEE is substantially more elegant and by far thesimpler and cleaner way to generate objects.

EXERCISES

Create a vehicle factory that producesdifferent types of cars and vans by using theabstract factory pattern.

Implement that same vehicle factory as inthe previous exercise but use @Produce,qualifiers, and enum types.

By harnessing the power of the CDIcontainer, implement a way to have multipleobjects of the same type and to select thetype you require based on type-safe logic.

198

NOTES

1. Wikipedia.org:http://en.wikipedia.org/wiki/Dependency_inversion_principle.

2. Design Patterns: Elements of ReusableObject-Oriented Software (Addison-Wesley,1994): Erich Gamma, Richard Helm, RalphJohnson, John Vlissides.

3. Head First Design Patterns (O’Reilly, 2004):Eric Freeman, Elisabeth Robson, Bert Bates,Kathy Sierra.

199

7Decorator PatternWHAT’S IN THIS CHAPTER?

How to implement the decorator pattern inplain code

How the decorator pattern solved a real-lifedilemma

How to implement the decorator pattern usingthe @Decorator and @Delegate annotations

How to make the decorator pattern pluggablevia the deployment descriptors

How to use qualifiers to gain fine-grain controlover how decorators are used

WROX.COM CODE DOWNLOAD FORTHIS CHAPTER

The wrox.com code download for this chapter isfound at www.wrox.com/go/projavaeedesignpatterns on theDownload Code tab. The code is in the Chapter7 download and individually named accordingto the names throughout the chapter.

The GoF1 book describes the decorator patternas “Attach additional responsibilities to anobject dynamically” and gives a Graphical UserInterface Toolkit as an example. This is an

200

excellent real-world example because addingnew styles or behaviors to a user interface (UI)toolkit is the perfect job for the decoratorpattern.

The Head First Design Patterns2 book gives acoffee shop as an example of different optionssuch as whip cream being added to the product.The addition of each new condiment wraps thebeverage object and adds new behavior to thedescription and price. This example has beenthe best-fit solution since the authors had asimilar real-life experience. See the next WarStory.

The decorator pattern relies on component anddecorator objects, which implement the sameinterface. The decorator has an instancevariable that implements the same interface soit can wrap either a component object oranother decorator. Sharing the same interfaceallows decorators to decorate the basecomponent or another decorator. With a properimplementation, it is simple to call all relevantfunction implementations in order from the lastdecorator to the inner target component object.In most cases, it should not be difficult to adaptan existing system to use the decorator pattern.

WHAT IS A DECORATOR?The decorator pattern is one of the structuralpatterns described in the book of GoF. Its

201

purpose is to wrap a target object so that youcan dynamically add new responsibilities at runtime. Each decorator can wrap another one,which allows for a theoretically unlimitednumber of decorating of target objects.

Although this runtime behavior is much moreflexible than inheritance via subclassing, itintroduces a level of complexity to concretesubclassing as it makes it more difficult todetermine the types and behaviors of objectsprior to executing the application.

Decorators are used in almost all languages andall platforms, from the UI to the back end. Mostframeworks and run times use the decoratorpattern to add flexibility and runtime–specificbehavior.

In Java EE, you implement the decoratorpattern without boilerplate code. However,unlike the majority of the patterns in this book,you often add XML configuration to thebean.xml.

WAR STORY

Several years ago, we won a contract tocomplete a food and drinks ordering andpayment system for a company that thenprovided it as a point of sale (POS) service toits clients.3 These clients were restaurants,

202

cafés, and bars. We had no knowledge of thedomain, so we made some reasonableassumptions based on the limited knowledgeand information we had at the time. Luckily,most assumptions worked out well.

One of our design rules was that if an add-onoption changes the price of a product, itshould be added as a new product. So if therestaurant serves extra portions for anadditional price, a new item should be addedto the menu. However, if an option like extracheese was free, that information could beadded as a side note to the order.

This rule had worked well for every clientuntil one day we met with a café owner whosebusiness operated slightly differently. Thecafé was focused on selling deserts, but it alsooffered pizza as a savory option. Pizza wasthe only meal item on the whole menu.Because the café didn’t specialize in pizza, itdid not offer set pizzas but instead let itscustomers create their own pizzas from along list of toppings, and it charged for eachtopping. This was quite a sensible way for thecafé to offer its customers pizza because onlya few of its customers would want to eatpizza. However, it was catastrophic for oursystem because of our design rule: If anadd-on option changes the price of a product,

203

it should be added as a new product. Becauseeach topping had a different price, we neededto calculate all the combinations of toppingsand enter a new pizza to the menu for eachcombination.

As you know, n! algorithms grow largequickly, which in this case would haveresulted in a long list of pizzas after only afew combinations. Because this was notacceptable, we suggested to the client that heenter several pizzas with a fixed number oftoppings (1 topping, 2 topping, 3 topping),and he could add a note to the order torecord the customer’s choice of topping. Withthis solution, we could shorten the list fromn! to n.

Still, this solution was not really reasonable.Because the system was already up andrunning, we needed to find a way to fix itwithout breaking other parts. We needed away to add functionality at run time. Weneeded to “decorate” the existing pizza objectwith toppings. Clearly, the answer was toimplement the decorator pattern. And that iswhat we did. Each topping the customerchose wrapped the pizza object in a similarway to the example used in the Head FirstDesign Patterns book.

204

Decorator Class DiagramAs is seen in the class diagram in Figure 7.1, thedecorator pattern introduces some boilerplatecode to an existing class hierarchy. The patternintroduces a shared interface between thetarget class and the decorator. The decoratormust have a reference to an instance of thisinterface.

Figure 7.1 Class diagram of the decoratorpattern

IMPLEMENTING THEDECORATOR PATTERN IN PLAINCODEIf the classes are in the design stage, theaddition of decorators shouldn’t be too much ofan issue. However, if the decorator is to beimplemented in an existing system, you mightneed to refactor some classes. For example, the

205

target class should implement the sameinterface that the decorator implements.

This chapter demonstrates the use of thedecorator pattern using a simplified POSsystem for a pizza restaurant. Each pizza can be“decorated” with extra toppings, such as doublecheese and free chili.

First, you will create the Order interface,which is implemented by the Pizza class andby the decorator’s Extra abstract class. TheExtra class is extended by the extra toppingsclasses: DoubleExtra, NoCostExtra, andRegularExtra.

You’ll start by creating the Order interface inListing 7-1.

LISTING: 7-1: The Order interface

public interface Order {public double getPrice();public String getLabel();

}

In Listing 7-2, you’ll create the class thatrepresents a pizza (Four Seasons, Margarita,Hawaiian, and so on) on the menu. This is thetarget object to be decorated.

206

LISTING: 7-2: The class to bedecorated implements the Orderinterface

public class Pizza implementsOrder {

private String label;private double price;

public Pizza(String label,double price){

this.label=label;this.price=price;

}

public double getPrice(){return this.price;

}

public String getLabel(){return this.label;

}}

The following code creates a Four Seasonspizza.

Order fourSeasonsPizza = newPizza("Four Seasons Pizza", 10);

207

Next, you need to create the decorators that willdecorate the pizza with extra toppings. Use anabstract class so that the concrete classes do nothave to implement all the business methods ofan interface. An abstract decorator will create ablueprint that other decorators can extend.

Perhaps you have different topping types(cheese, chili, pineapple, and so on). Imaginethat the customer wants to order the meal alittle spicier, and the restaurant will not chargefor that extra topping. So you need a decoratorthat does not add to the price of the pizza butprovides proper labeling (that extra chili hasbeen requested). Also, the customer may ask fortwo extra portions of cheese, and if the systemprints “cheese” twice, the chef may think it is abug and add only one portion of cheese. So youneed another concrete decorator to allow forproper labeling of double toppings. Listing 7-3accomplishes your goals.

LISTING 7-3: The abstract decoratorthat adds extra toppings

public abstract class Extraimplements Order {

protected Order order;protected String label;protected double price;

208

public Extra(String label,double price, Order order) {

this.label=label;this.price=price;this.order=order;

}

// Price can be a bigissue, so delegate this toconcrete implementation

public abstract doublegetPrice();

// Should be okay toprovide standard labeling

public String getLabel() {return

order.getLabel()+","+this.label;

}}

Now that you have the abstract decorator, youcan add specific behaviors and create concretedecorators. You’ll start with theRegularExtra decorator, which adds acharge and a label to the target object (thepizza). Because the labeling function is alreadyprovided by the abstract decorator and

209

inherited by all subclasses that extend it, youonly need to implement the pricingfunctionality. Listing 7-4 takes care of that.

LISTING 7-4: The decorator that addsextra toppings

public class RegularExtraextends Extra {

public RegularExtra(Stringlabel, double price, Orderorder) {

super(label, price,order);

}

public Double getPrice() {return

this.price+order.getPrice();}

}

Next, you need to create theNoCostDecorator, which modifies thelabel string but does not add to the cost of thepizza. See Listing 7-5.

210

LISTING 7-5: The decorator that addsextra toppings at no cost

public class NoCostExtraextends Extra {

public NoCostExtra(Stringlabel, double price, Orderorder) {

super(label, price,order);

}

public Double getPrice() {return

order.getPrice();}

}

Finally, in Listing 7-6, you implement theDoubleExtra decorator to avoid printing thetopping twice on the label. The decoratordoubles the price and adds the keyworddouble in front of the target label.

211

LISTING 7-6: The decorator that addsdouble toppings

public class DoubleExtraextends Extra {

public DoubleExtra(Stringlabel, double price, Orderorder) {

super(label, price,order);

}

public Double getPrice() {return

(this.price*2)+order.getPrice();}

public String getLabel() {return

order.getLabel()+ ", Double "+ this.label;

}}

Now that the decorator pattern has beenimplemented to add extra toppings to yourpizza, you can test your implementation.

212

Order fourSeasonsPizza = newPizza("Four Seasons Pizza", 10);fourSeasonsPizza = newRegularExtra("Pepperoni", 4,fourSeasonsPizza );fourSeasonsPizza = newDoubleExtra("Mozzarella", 2,fourSeasonsPizza );fourSeasonsPizza = newNoCostExtra("Chili", 2,fourSeasonsPizza );

System.out.println(fourSeasonsPizza.getPrice());System.out.println(fourSeasonsPizza.getLabel());

The output in the console will be as follows:

18.0Pizza, Pepperoni, DoubleMozzarella, Chili

But wait! There is a potential bug! Chili is notfree if you order it as a side dish, but the chef ishappy to offer it free on a pizza. You need tomake sure the system accounts for thosedifferences. Just imagine that these values andlabels come from a database. What would youdo to create different behaviors for chili? Oneoption might be to create two chili objects: onelabeled as “with pizza.” Clearly, this would be ahack, leaving a backdoor open for any waiter toorder free chili for his friends. Another optionwould be to create an additional constructor

213

method in the abstract class that does not take aprice parameter. Any decorator that does notcharge for extras could implement this.

IMPLEMENTING THEDECORATOR PATTERN IN JAVAEEUnlike most other patterns described in thisbook, you implement the decorator pattern bydeclaring the decorator classes in thebean.xml deployment descriptor (exceptwhen annotated with @Priority; see thefollowing section“Decorators Without XMLConfiguration”). Luckily, this configuration issimple and gives you the advantage ofpluggability and control over the order in whichthe decorators are invoked.

The decorator implementation in Java EEintroduces two new annotations: @Decoratorand ?@Delegate. @Decorator annotates thedecorator class, and @Delegate annotates thedelegate injection point where the class to bedecorated is injected.

You will use the example of a shop that wants todiscount some of its products. It will use adecorator to apply this discount to the regularretail price. In Listing 7-7, you start by creatingthe interface that you will use to connect thedecorator with the object you want to decorate.

214

LISTING 7-7: The Product interface

public interface Product {public void

setLabel(String label);public void

setPrice(double price);public String getLabel();public double getPrice();public String

generateLabel();}

The interface introduces the generateLabelmethod, which the decorator implements toadd its discounting behavior. In Listing 7-8, youcreate the Table class. It is the product thatyou want to be decorated; therefore, itimplements the Product interface.

LISTING 7-8: The class to bedecorated implements the Productinterface

public class Table implementsProduct {

private String label =

215

"Dining Table";private double price =

100.00;

public voidsetLabel(String label) {

this.label = label;}

public voidsetPrice(double price) {

this.price = price;}

public String getLabel() {return label;

}

public double getPrice() {return price;

}

public StringgenerateLabel() {

return price + ", " +label;

}

}

216

You create the PriceDiscountDecoratordecorator by implementing the Productinterface. This class implements thegenerateLabel method and adds itsdiscounting behavior. The decorator reducesthe price of a product by 50 percent and addsthe text “(Discounted)” to the product’s label.

To enable the container to identify this class asa decorator, you must annotate it with@Decorator. The delegate injection point (theinstance that will be decorated) is annotatedwith @Delegate and must be an injected field,an initializer method parameter, or a beanconstructor method parameter. The delegatetype must be the interface implemented by theclasses that you want to be decorated—in thiscase, Product. The CDI container injects anyavailable instance of the Product interfaceinto the product member variable as shownin Listing 7-9.

LISTING 7-9: ThePriceDiscountDecorator decorator

@Decoratorpublic classPriceDiscountDecoratorimplements Product {

217

@Any@Inject@Delegateprivate Product product;

public StringgenerateLabel() {

product.setPrice(product.getPrice()* 0.5);

product.setLabel(product.getLabel()+ " (Discounted)");

returnproduct.generateLabel();

}

// Not all methods shown}

Finally, you must declare the decorator inbean.xml. Although most of the configurationhas already been done via annotations, you stillneed to add some XML configuration to makethe decorator work. The configuration mightseem disappointing because you have alreadyannotated your decorator; nevertheless, theconfiguration is simple and necessary so thatyou can define the order of execution of the

218

decorators (if more than one). Add thefollowing lines to beans.xml:

<decorators>

<class>com.devchronicles.decorator.PriceDiscountDecorator</class></decorators>

Your work is done. You can now use yourdecorator.

@Any@InjectProduct product;

public void createPriceList(){System.out.println("Label: "

+ product.generateLabel());}

An instance of Table is injected into theProduct member variable, and thegenerateLabel method is called. The outputto the console will be as follows:

Label: 12.5, Dining Table(Discounted)

When a call is made to the generateLabelmethod of any Product instance, thecontainer intercepts it. The call is delegated tothe appropriate method of thePriceDiscountDecorator decorator,

219

where it discounts the product’s price andpasses the call onto the original destination bycalling the generateLabel method of theTable object.

A call chain is set up that includes all thedecorators that are declared to decorate classesthat implement the Product interface. Theorder in which the decorators are called isdetermined by the order in which they aredeclared in the bean.xml deploymentdescriptor.

You are going to see this in action in Listing7-10, where you define another decorator. Youcreate theBlackFridayDiscountDecoratordecorator, implement the Product interface,and add the @Decorator and @Delegateannotations.

LISTING 7-10: TheBlackFridayDecorator decorator

@Decoratorpublic classBlackFridayDiscountDecoratorextendsAbstractDiscountDecorator {

@Any

220

@Inject@Delegateprivate Product product;

public StringgenerateLabel() {

product.setPrice(product.getPrice()* 0.25);

product.setLabel(product.getLabel());return

product.generateLabel();}

// Not all methods shown

}

You must add the decorators to the bean.xmlarchive in the order that you want them to beinvoked. Here, you declare that thePriceDiscountDecorator decoratorshould be invoked before theBlackFridayDiscountDecoratordecorator.

<decorators>

<class>com.devchronicles.decorator.PriceDiscountDecorator</class>

221

<class>com.devchronicles.decorator.BlackFridayDiscountDecorator</class></decorators>

When the generateLabel method isinvoked, a call chain is set up that includes thetwo decorators. The call to generateLabel isintercepted and delegated to thegenerateLabel method of thePriceDiscountDecorator. It callsgetPrice, which will be intercepted anddelegated to the getPrice method ofBlackFridayDiscountDecorator,which in turn calls the getPrice method of itsinjected Product object. (This is the sameinstance that you injected into thePriceDiscountDecorator decorator.)This invocation is not intercepted because thereare no more decorators declared for thisinterface, and it calls the getPrice method inthe Table object. Once this call has finished, itreturns down the call stack to the firstgetPrice method. This is called returning theprice of the Table. The decorator reduces theprice by 50 percent and calls the setPricemethod. This call is delegated up the call chainuntil it reaches the Table object, where thenew price is set. Then the call returns down thecall chain.

222

The getLabel method is called and creates acall chain similar to that of the getPricemethod.

Finally, the generateLabel method isinvoked and intercepted by theBlackFridayDiscountDecoratordecorator. The price is discounted by a further25 percent, and a call chain similar to that setup by the PriceDiscountDecoratordecorator is initiated.

The output to the console follows:

Label: 6.25, Dining Table(Discounted)

For the chain to continue unbroken, thegenerateLabel method must delegate to thegenerateLabel method of the delegateinjected instance; otherwise, the chain isbroken and only the first decorator is invoked.

All classes that implement the same interface asthe one implemented by the delegate injectionpoint are decorated, but only if those decoratorsare declared in bean.xml. This has two majorimplications:

Decorators can be enabled and disabled atdeployment time by editing the bean.xml file.This gives great flexibility over when and whichdecorators are invoked. For example, you canimplement a price discount decorator only for

223

the duration of the sales period and disable itwhen the period comes to an end. The flexibilityof the deployment descriptor declaration meansthat this decorator can be easily enabled again ifdebugging information is later required.

A decorator is automatically applied to classesthat implement the same interface. This isefficient at the time of adding new classesbecause they are decorated with no additionalcoding. However, this could prove inconvenientif there is a requirement that not all classes ofthe same type are decorated. Luckily, there is asolution to this situation that involves usingqualifiers to annotate only those classes thatshould be decorated.

To not decorate all classes of the same type, youneed to create a custom qualifier and annotatethe delegate injection point and the classes thatyou want decorated. You’ll create a Plateproduct that implements the Productinterface. Only this product must bediscounted. To implement this requirement,you annotate it with a custom qualifier, thusexcluding the other product from beingdecorated.

You create a custom qualifier and call it@ClearanceSale.

@Qualifier@Retention(RUNTIME)

224

@Target({FIELD, PARAMETER, TYPE})public @interface ClearanceSale {}

In Listing 7-11, you create the newimplementation of the Product interface andannotate it with your custom qualifier.

LISTING 7-11: Class to be decoratedis annotated with custom qualifier

@ClearanceSalepublic class Plate implementsProduct {

private String label ="Plate";

private double price =50.00;

public voidsetLabel(String label) {

this.label = label;}

public voidsetPrice(double price) {

this.price = price;}

public String getLabel() {

225

return label;}

public double getPrice() {return price;

}

public StringgenerateLabel() {

return price + ", " +label;

}}

Finally, you annotate the delegate injectionpoint in the decorator that you want to invoke.In this case, choose thePriceDiscountDecorator decorator.

@ClearanceSale@Any@Inject@Delegateprivate Product product;

Only classes that are annotated with@ClearanceSale and implement theProduct interface are injected into thedelegate injection point of thePriceDiscountDecorator decorator;

226

therefore, only your Plate class will bedecorated. A delegate injection point can haveas many qualifiers as is required, and it willonly be bound to beans with the same qualifier.

Decorators Without XML ConfigurationAt deployment time, the CDI container scans allthe JAR and WAR files in the applicationlooking for bean.xml deployment descriptors.For those that it finds, it processes each one inturn, making the appropriate configurations.When it meets the <decorator/> descriptor,it enables the decorators for the archive inwhich the bean.xml file was found. It doesnot enable them for the whole application. Thisis a problem for developers who want thedecorators to apply to all classes thatimplement the same interface regardless ofwhere they are in the application. Since CDI1.1,4 it has been possible to enable decoratorsfor the entire application by annotating thedecorator class with @Priority and anInterceptor.Priority value. Here is anexample of how to enable your two decoratorsfor the whole application.

@Priority(Interceptor.Priority.APPLICATION)@Decoratorpublic classPriceDiscountDecorator extendsAbstractDiscountDecorator

227

@Priority(Interceptor.Priority.APPLICATION+10)@Decoratorpublic classBlackFridayDiscountDecoratorextends AbstractDiscountDecorator

Decorators annotated with a lower valuepriority are called first. In the precedingexample, PriceDiscountDecorator isinvoked beforeBlackFridayDiscountDecorator.

Decorators annotated with @Priority arecalled before decorators in the deploymentdescriptor. If a decorator is enabled in both, it iscalled twice. This may lead to undesirableresults, so you need to ensure that decoratorsare enabled in only one way.

WHERE AND WHEN TO USE THEDECORATOR PATTERNThe decorator pattern dynamically addsbehavior to an object at run time or when it isnot possible or advisable to use subclassing(perhaps because it would create multiplesubclasses). The pizza restaurant exampleshows how to add behavior to a pizza object atrun time based on choices the customer made.

The functionality of an applicationprogramming interface (API) can be extendedand ?improved by wrapping it in a decorator.

228

Data streams are often decorated in this way.java?.io.BufferedInputStream is agood example of a decorator wrapping alower-level API and adding functionality tobuffer an input stream.

In Java EE, decorators are implemented viaContext Dependency Injection (CDI). You canuse decorators to add new business behavior orany other functionality that can be wrappedaround the original object. However, this designshould be well documented and clearlyimplemented to allow for bettermaintainability.

The pluggability of decorators declared in thedeployment descriptor makes it easy to enableand disable decorators without recompiling andredeploying. In a hot deployment environment,the server does not need to be restarted for thechanges to the bean.xml to take effect. Thismakes it extremely easy to change the behaviorof an application in a production environmentwith no interruption to service.

Qualifier use provides a finer grain of controlover the execution of decorators than enabling/disabling them in the bean.xml deploymentdescriptor. You can use qualifiers to excludecertain implementations of an interface frombeing decorated or to apply different decoratorsto implementations of the same interface.

229

A decorator intercepts calls only to certain Javatypes. It is aware of all the semantics of thatinterface and can implement business logic.This makes it perfect for modeling businessconcerns that are identifiable for a certaininterface type.

Decorators are often contrasted withinterceptors. Interceptors intercept invocationsof any Java type, but they are not semanticallyaware and therefore are not a suitable tool formodeling business concerns. Interceptors areused to implement cross-cutting concerns suchas logging, security, and auditing that are notrelated to business logic.

The heavy use of decorators may introduceruntime bugs, a harder-to-understand codebase, and a loss to the advantage of stronglytyped static polymorphism. It may alsointroduce additional test cases. However,decorators can provide almost unlimitedextensibility and a great interface for futureimplementations without breaking old code.

SUMMARYIn this chapter, you have seen how theimplementation of the decorator pattern inJava EE is almost unrecognizable from itspre-Java EE ancestor. The object to bedecorated is instantiated and injected by thecontainer, and the decorators to be applied aredetermined by declarations made in the

230

bean.xml deployment descriptor or via thestrategic use of custom qualifiers.

The use of annotations and dependencyinjection has reduced the number of lines ofcode you must produce to implement adecorator solution and made it easier tointroduce additional new classes, which areautomatically decorated by virtue of theinterface they implement.

You have seen how the decorator pattern hasevolved into what is effectively a pluggablepattern that can be enabled and disabled whilethe application is in production with no loss toservice. However, it maintains its originaldesign principle of adding behavior orresponsibilities to the objects it decorates.

EXERCISES

Extend the shop example given earlier byadding more discount decorators andintroducing more qualifiers to gain finercontrol over which decorators are invokedfor which concrete implementations.

Implement the decorator pattern on anexisting API to add new functionality. Forexample: java.io.FileInputStream.

Create a decorator that adds behavior to abank account system such that when theclient withdraws more than a certain

231

amount of cash, an SMS text message is sentto the client advising of the withdrawal.

NOTES

1. Design Patterns: Elements of ReusableObject-Oriented Software (Addison-Wesley,1994): Erich Gamma, Richard Helm, RalphJohnson, John Vlissides.

2. Head First Design Patterns (O’Reilly, 2004):Eric Freeman, Elisabeth Robson, Bert Bates,Kathy Sierra.

3. Pyro: http://muse.com.tr/pyro.html.

4. CDI Specifications 1.1:http://docs.jboss.org/cdi/spec/1.1/cdi-spec?.html#decorators.

232

8Aspect-OrientedProgramming (Interceptors)WHAT’S IN THIS CHAPTER?

Introduction to aspect-oriented programming

Aspects in Java

Using servlet filters as aspects

Aspects in Java EE, interceptors

EJB interceptors versus CDI interceptors

WROX.COM CODE DOWNLOADS FORTHIS CHAPTER

The wrox.com code download for this chapter isfound at www.wrox.com/go/projavaeedesignpatterns on theDownload Code tab. The code is in the Chapter8 download and individually named accordingto the names throughout the chapter.

Aspect-oriented programming (AOP) is not anew concept. Its place in Java and third-partyframeworks was secured from the early days ofenterprise development. Despite this, it was notone of the classical design patterns listed in theGOF1 book.

233

AOP introduced a new concept and paradigm toprogramming. The idea relies on basing thecode execution order on aspects. Each aspectintercepts the program’s execution and adds itsown behavior before continuing with the call.

Aspects act like magic, adding further logic andbehavior to the code at run time. However, thisalso brings an ambiguous and hard-to-followcode execution order that can often result inalmost undebuggable code. AOP has manyfollowers and fans, besides many haters.

Luckily, Java EE has a nice and cleanimplementation that can be helpful if it’s usedin the right way and context.

WHAT IS ASPECT-ORIENTEDPROGRAMMING?Aspect-oriented programming (AOP) aims toadd behavior to existing code or applications tosolve common concerns. It is fairly normal toreceive a new logging or security request in themiddle of the development cycle. Such requestsmay consume a huge amount of time inrefactoring existing code even though thelogging code is a bunch of repetitive lines. Suchcommon concerns, whether they appear in themiddle of the development cycle or in thedesign phase of the project, are calledcross-cutting concerns and can be addressedwith AOP.

234

AOP became a popular programming paradigmduring the past decade. Although Java did notoffer a full-fledged out-of-the-box solution,some well-implemented third-partyframeworks offered AOP. AspectJ and Springare widely accepted and have been used for along time in Java-based projects. Java also hada similar but more basic approach with servletfilters, although it is limited to web requests.With servlet filters, any request or response canbe intercepted, and any additional behavior canbe added.

Java EE adopted AOP and introduced theinterceptor concept. Each update to Java EEbrought new functionalities and unleashed thefull potential of AOP to the Java EE platform.

AOP is not classified as a design pattern but isaccepted as a programming paradigm. Neitherthe GOF book nor Head First Design Patterns2

discusses aspects. However, if either one did, anappropriate description would be “Provides away to change execution behavior at run time(or compile time) to address cross-cuttingconcerns in the existing code base.”

AOP relies on code injection during compiletime or run time to add the desired behavior orfunctionality to each point of an existing codebase that matches the given injection criteria.Frameworks that perform compile-timeinjection usually out-perform, but they produceclass files that do not match the source code

235

line by line because of the injected code.Runtime injection does not modify the sourceor class files and performs injection byintercepting calls and executing the desiredcode before or after the original executionorder.

AOP can prove to be useful if it is necessary toadd a repetitive action, such as logging orsecurity, to a code base. The aspects can beturned on or off depending on the environmentor phase of the project. Aspects can dynamicallyadd the desired behavior to running code. Theydynamically decorate the method calls just asthe decorator pattern decorates objects.

WAR STORY

We had just finished development of a webapplication and were completing the finalphase before going live. After completingfunctionality and user acceptance tests, weneeded to submit the application to securitytrials. A team of security experts was hired totest our system for vulnerabilities. Becausethe application before ours was hacked andleaked important data, the security testingwas taken very seriously.

We were pretty confident about ourapplication, so we all grabbed some popcornand watched the test phases. After a huge set

236

of successful tests, one finally failed. Thesecurity guys had managed to capture theHypertext Transfer Protocol (HTTP) requestand change some parameters to get aresponse from the application. The issue wasnot huge because the middle tier had its ownauthorization system. Nevertheless, thetweaked request could access an authorizedresponse.

To summarize, the client should call severalservices to access a resource. Let’s say serviceA returns some IDs and Service B could becalled with the IDs returned from Service A.Similarly, Service C could be called with oneof the IDs returned from Service B. Thismeans that an intruder could capture andinsert a random B ID, which the user wasauthorized to query but didn’t. In such a case,the client would bypass the standard call flowand access a resource.

Because the accessed information was aresource that the user authorized, the issuewas not huge. Still, it was reported as asecurity flaw that bypassed regular flow; thisgot attention.

The application was already completed andtested, and we didn’t really want to refactorthe application. Instead, we came up with abrilliant idea: Because in each request the

237

client needs to use an ID from the previousresponse, we could capture all returned IDs.If the requested ID was from the list ofqueried IDs, we could easily let it go orinvalidate the session and force the user tolog in again.

The idea was simple but effective, yet wedidn’t know how to implement it withminimal change. Because everything wewanted to do related to web requests,intercepting and validating them seemed likea good idea. Luckily, Java already offered abuilt-in solution, and we didn’t need to use afancy third-party framework.

The solution was to implement a servletfilter. This would cache the requested IDs inthe response and check whether the nextrequest had a valid ID from the list. We onlyneeded to add a class file that acted as theservlet filter and an XML definition to put theservlet filter into action. The solution waspluggable and could be integrated with noproblem. Also, it came with an option to turnit off in development environments.

The system not only passed all security tests,but it went beyond expectations. We couldeasily log and extract statistical data fromrequest/response pairs. Best of all, thesolution did not have an impact on the

238

overall architecture and complexity of thesystem.

AOP can be a great tool to encapsulate commonnonbusiness concerns. However, AOP can alsobe confusing if it adds behavior to businesslogic. Such implementations causedecentralized, distributed, andhard-to-test-and-debug business logic. Theresulting code would be hard to maintain.

IMPLEMENTING AOP IN PLAINCODEJava SE does not offer out-of-the-box supportfor AOP. You can achieve plain AOP by usingthird-party frameworks such as AspectJ orSpring. Such frameworks used to depend onXML-only configuration; however, you can nowachieve AOP through the use of annotations.Implementation and configuration of bothframeworks are beyond the scope of this book,but they have a proven record and can easily beimplemented. They both provide a validalternative to the Java EE implementation.

However, Java web applications have theadvantage of using servlets to intercept therequest or the response, which works similarlyto aspects. To implement a servlet filter, createa new class file and implement the servlet filter

239

interface. Then provide an implementation ofthe doFilter() method, as shown in Listing8-1.

LISTING 8-1: Simple implementationof a servlet filter

packagecom.devchronicles.interceptor.filter;

import java.io.IOException;import java.util.ArrayList;import java.util.List;

import javax.servlet.Filter;importjavax.servlet.FilterChain;importjavax.servlet.FilterConfig;importjavax.servlet.ServletException;importjavax.servlet.ServletRequest;importjavax.servlet.ServletResponse;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;

240

public class SecurityFilterimplements Filter {

@SuppressWarnings("unused")private FilterConfig

filterConfig = null;

@Overridepublic void

doFilter(ServletRequest request,ServletResponse response,

FilterChainfilterChain) throws IOException,ServletException {

Log.info(((HttpServletRequest)request).getRemoteAddr());

//perform somesecurity check

}

@Overridepublic void

init(FilterConfigfilterConfig) throwsServletException {

this.filterConfig =filterConfig;

}

241

}

The web container needs the configurationshown in Listing 8-2 to activate the servlet filteron given uniform resource locators (URLs).This is placed in the web application’sweb.xml file.

LISTING 8-2: Define the Servlet Filter

<?xml version="1.0"encoding="UTF-8"?>

<web-appxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/

xml/ns/javaee"

xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/

javaee/web-app_2_5.xsd"version="2.5">

242

<filter>

<filter-name>LineSsoFilter</filter-name>

<filter-class>com.devchronicles.interceptor.filter</filter-class></filter>

<filter-mapping>

<filter-name>SecurityFilter</filter-name><url-pattern>/

*</url-pattern></filter-mapping>

</web-app>

It is even easier to implement filters usingServlet 3.0 like in Listing 8-3 because it usesannotations and does not need XMLconfiguration.

LISTING 8-3: Simple implementationof a servlet filter in Servlet 3.0

packagecom.devchronicles.interceptor.filter;

243

import java.io.IOException;import java.util.ArrayList;import java.util.List;

importjavax.servlet.ServletException;importjavax.servlet.ServletRequest;importjavax.servlet.ServletResponse;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;

import javax.servlet.Filter;importjavax.servlet.annotation.WebFilter;importjavax.servlet.annotation.WebInitParam;

@WebFilter(filterName ="TimeOfDayFilter", urlPatterns ={"/*"})public class SecurityFilterimplements Filter {

@Overridepublic voiddoFilter(ServletRequest

244

request, ServletResponseresponse, FilterChainfilterChain) throwsIOException, ServletException {

Log.info(((HttpServletRequest)request).getRemoteAddr());

//perform some securitycheck}

}

Servlet filters are easy-to-implement tools, butthey’re also powerful. However, thefunctionality is still limited to client server webrequests. To intercept other method calls or tofine-tune the interception, you need a muchmore sophisticated approach.

ASPECTS IN JAVA EE,INTERCEPTORSJ2EE did not offer an out-of-the-box AOPsolution but worked in harmony withthird-party frameworks. Java EE 5 introducedinterceptors, which resulted in an easy-to-usebuilt-in aspect approach. However, theinterceptor concept was limited to Enterprise

245

JavaBeans (EJB) until Context and DependencyInjection (CDI) was introduced.

Interceptors in Java EE work in a similar way toaspects. Each interceptor addresses the concernand hosts the code block that contains thefunctionality to be added. The target to bedecorated is called an advice. Each call to anadvice within the scope of the interceptor isintercepted. The exact location of the aspect tobe executed is called the pointcut.

Basic Java EE interceptors can only work onEJBs. Imagine an application consisting ofhundreds of EJBs. The whole application can beconfigured to log all EJB calls by deploying aninterceptor targeting all those EJBs.

Implementing interceptors in Java EE isstraightforward. The first step is to create a newinterceptor class and annotate it with the@Interceptor annotation. This class hoststhe advice code. Any method annotated with@AroundInvoke is executed at the pointcut.However, there are some syntax rules regardingthe pointcut method signature:

Any pointcut method must return an object oftype Object and have a parameter of typeInvocationContext.

Throw an exception.

246

You can use the InvocationContextparameter to access information about thecurrent context as seen in Listing 8-4.

LISTING 8-4: Simple implementationof an interceptor

packagecom.devchronicles.interceptor;

importjavax.interceptor.AroundInvoke;importjavax.interceptor.InvocationContext;

@Interceptorpublic classSecurityInterceptor {

@AroundInvoke

public Object doSecurityCheck(InvocationContextcontext) throws Exception{

//Do some securitychecks!

Logger.getLogger("SecurityLog").info(context.getMethod().getName()+

247

"is accessed!");

returncontext.proceed();

}}

To put the interceptor class into action, youmust annotate the target advice with the?@Interceptors annotation as in Listing8-5. The @Interceptors annotation wouldonly be used in an EJB or MDB (MessageDriven Bean).

LISTING 8-5: Simple implementationof target advice

packagecom.devchronicles.interceptor;

import javax.ejb.Stateless;importjavax.ejb.TransactionAttribute;importjavax.ejb.TransactionAttributeType;importjavax.enterprise.event.Event;import javax.inject.Inject;

248

importjavax.interceptor.Interceptors;

@Interceptors(SecurityInterceptor.class)@Stateless@TransactionAttribute(TransactionAttributeType.REQUIRED)public classSomeBusinessService {

public void startService(){//Complex business logic

Logger.getLogger("AppLog").info("done...");}

public voidstartAnotherService(){

//Complex business logic

Logger.getLogger("AppLog").info("doneagain...");

}}

The Interceptors annotation is flexible. You canalso use it at both the class and the methodlevels. The Interceptors annotation alsosupports multiple interceptor inputs, whichenable multiple interceptors on the targetadvice. Listing 8-5 uses class-level interceptors,

249

which means that the Security interceptor willintercept either of the service calls. If you donot want the interceptor to cover all methodcalls in the class, you can use method-levelannotations, as shown in Listing 8-6.

LISTING 8-6: Implementation ofclass-level interceptors

packagecom.devchronicles.interceptor;

import javax.ejb.Stateless;importjavax.ejb.TransactionAttribute;importjavax.ejb.TransactionAttributeType;importjavax.enterprise.event.Event;import javax.inject.Inject;importjavax.interceptor.Interceptors;

@Stateless@TransactionAttribute(TransactionAttributeType.REQUIRED)public classSomeBusinessService {

@Interceptors(SecurityInterceptor.class)

250

public void startService(){//Complex business

logic

Logger.getLogger("AppLog").info("done...");}

public voidstartAnotherService(){

//Complex businesslogic

Logger.getLogger("AppLog").info("doneagain...");

}}

This time only calls to the startService()method are intercepted, unlike in Listing 8-5, inwhich all methods of the class were intercepted.You should annotate each method separately.

Using @Interceptor, @Interceptorswith @AroundInvoke unleashes a powerfultool that solves cross-cutting concerns in anAOP approach. Yet interceptors offer easyannotation-based implementation with noboilerplate code.

251

You can use the InvocationContextinterface to extract information about thecontext or interact with the advice context.Following are some of the more usefulmethods:

METHOD DESCRIPTION

public Object getTarget(); Return to thetarget advice.

public Method getMethod(); Return theexecuted methodfrom the advice.

public Object[]getParameters();

Access targetadvice method’sparameters.

public voidsetParameters(Object[]);

Set target advicemethod’sparameters.

publicjava.util.Map<String,Object>getContextData();

Access contextdata.

public Object proceed()throws Exception;

Continueexecution.

In Listing 8-7, you can access the method name.Also, you can check whether the interceptor hadauthorized the access before; if it has not, youcan authorize the user for that method.

252

LISTING 8-7: Accessing informationin the InvocationContext

packagecom.devchronicles.interceptor;

importjavax.interceptor.AroundInvoke;importjavax.interceptor.InvocationContext;

@Interceptorpublic classSecurityInterceptor {

@AroundInvoke

public Object doSecurityCheck(InvocationContextcontext) throws Exception{

//Do some security checks!

Logger.getLogger("SecurityLog").info(context.getMethod()

?.getName()+ "is accessed!");String user =

context.getContextData.get("user");

if (user==null){user=(String)context.getParameters()[0];

253

context.getContextData.put("user",user)'

}

return context.proceed();}

}

Interceptor Life CycleYou can capture the interceptor’s life-cyclephases easily with the help of life-cycleannotations. Unlike extending and overriding,using life-cycle annotations hooks any functionto the appropriate phase. The availablelife-cycle annotations are @PostConstruct,@PrePassivate, @PostActivate, and@PreDestroy. Listing 8-8 shows how to hookup using interceptor life-cycle methods.

LISTING 8-8: Hooking theinterceptor’s life-cycle phases

packagecom.devchronicles.interceptor;

254

importjavax.interceptor.AroundInvoke;importjavax.interceptor.InvocationContext;

@Interceptorpublic classSecurityInterceptor {

@AroundInvoke

public Object doSecurityCheck(InvocationContextcontext)

throws Exception{//Do some security

checks!

Logger.getLogger("SecurityLog").info(context.getMethod()

.getName()+ "is accessed!");

String user =context.getContextData.get("user");

if (user==null){

user=(String)context.getParameters()[0];

context.getContextData.put("user",user)'

255

}

returncontext.proceed();

}

@PostConstructpublic void onStart(){

Logger.getLogger("SecurityLog").info("Activating");}

@PreDestroypublic void onShutdown(){

Logger.getLogger("SecurityLog").info("Deactivating");}

}

Because the hooks rely on annotations, methodnames do not make a difference; you can useany name.

Default-Level InterceptorsMarking the target advice with Interceptorsannotation provides an easy implementationand setup, but the nature of AOP usually asksfor more. Most scenarios require theinterceptor to perform its operation targetingall advices. Imagine adding interceptors for

256

logging or security—targeting only a subset ofEJB wouldn’t work. Also, annotating each EJBcan become cumbersome and can easily lead tohuman error.

Java EE offers default-level interceptors totarget all or subsets of EJB matching thenaming scheme provided. Unlike in theprevious example, to implement default-levelinterceptors, you need XML configuration:

<ejb-jar...><interceptors>

<interceptor><interceptor-class>

com.devchronicles.SecurityInterceptor</interceptor-class>

</interceptor></interceptors><assembly-descriptor>

<interceptor-binding><ejb-name>*</ejb-name><interceptor-class>

<interceptor-class>

com.devchronicles.SecurityInterceptor</interceptor-class>

</interceptor-class></interceptor-binding>

</assembly-descriptor></ejb-jar>

257

The first part of the XML file lists theinterceptors; then the interceptor bindings needto be declared. This is done in the assemblydescription part, which can accept a wildcard(*) that applies to all or a specific name tocreate the binding between the interceptors andthe EJB. The order of the interceptors listedalso determines the execution order. Theinterceptors listed in the EJB-JAR file applyonly to EJB in the same module.

Interceptor OrderIf more than one interceptor has been definedfor an advice, the order of the execution will befrom the most general to the most specific case.This means that default-level interceptors willbe executed before class-level interceptors,which will be followed by method-levelinterceptors.

This behavior is expected; nevertheless, theorder of same-level interceptors can be a bitmore confusing. If there is more than onedefault-level interceptor, the order in theEJB-JAR file determines the order of theexecution of the interceptors.

<ejb-jar...><interceptors>

<interceptor><interceptor-class>

com.devchronicles.SecurityInterceptor

258

</interceptor-class><interceptor-class>

com.devchronicles.AnotherInterceptor</interceptor-class>

</interceptor></interceptors><assembly-descriptor>

<interceptor-binding>

<ejb-name>OrderBean</ejb-name><interceptor-order>

<interceptor-class>

com.devchronicles.SecurityInterceptor

</interceptor-class></interceptor-order><interceptor-class>

com.devchronicles.AnotherInterceptor</interceptor-class>

</interceptor-binding></assembly-descriptor>

</ejb-jar>

When there is more than one class-levelinterceptor, the interceptors follow the order inwhich they are listed in the @Interceptorsannotation:

@Interceptors(SecurityInterceptor.class,AnotherInterceptor.class)

259

@Stateless@TransactionAttribute(TransactionAttributeType.REQUIRED)publicclass SomeBusinessService {

public voidstartService(){

// ...

Finally, if more than one method-levelinterceptor is present, again, the interceptorsfollow the order they are listed in the@Interceptors annotation:

@Stateless@TransactionAttribute(TransactionAttributeType.REQUIRED)public class SomeBusinessService{

@Interceptors(SecurityInterceptor.class,AnotherInterceptor.class)

public void startService(){// ...

If you need to tweak the default ordering, youcan do so by custom configuration within theEJB-JAR XML. The following overrides theinterceptor order and provides a customordering:

<ejb-jar...><interceptors>

<interceptor><interceptor-class>

260

com.devchronicles.SecurityInterceptor</interceptor-class>

</interceptor></interceptors><assembly-descriptor>

<interceptor-binding>

<ejb-name>OrderBean</ejb-name><interceptor-order>

<interceptor-class>

com.devchronicles.SecurityInterceptor

</interceptor-class></interceptor-order><interceptor-class>

com.devchronicles.AnotherInterceptor</interceptor-class><method>

<method-name>startService</method-name></method>

</interceptor-binding></assembly-descriptor>

>/ejb-jar<

There might be exceptional cases in which theinterceptors need to be disabled. You candisable interceptors with annotations as seen inListing 8-9. Java EE offers two different

261

annotations to disable default and class-levelinterceptors separately.

LISTING 8-9: Disabling theinterceptors

packagecom.devchronicles.interceptor;

import javax.ejb.Stateless;importjavax.ejb.TransactionAttribute;importjavax.ejb.TransactionAttributeType;importjavax.enterprise.event.Event;import javax.inject.Inject;importjavax.interceptor.Interceptors;

@ExcludeDefaultInterceptors@ExcludeClassInterceptors@Stateless@TransactionAttribute(TransactionAttributeType.REQUIRED)public classSomeBusinessService {

public void startService(){//Complex business

logic

262

Logger.getLogger("AppLog").info("done...");}

public voidstartAnotherService(){

//Complex businesslogic

Logger.getLogger("AppLog").info("doneagain...");

}}

Still, the example given is only valid in EJB andMDBs, which may not be enough for all cases.Thanks to CDI, it is not hard to achieve more.

CDI InterceptorsBefore CDI, interceptors were applicable onlyfor EJB and MDBs. CDI unleashed a hugepower and transformed interceptors into anAOP-capable feature that works on any object.

Implementing CDI interceptors isstraightforward and quite flexible. First, youneed to specify a binding. A binding is a customannotation annotated with@InterceptorBinding.

263

@InterceptorBinding@Target({TYPE, METHOD})@Retention(RUNTIME)public @interface Secure {}

The @InterceptorBinding is used to bindinterceptors with the target code. Next, you canimplement and annotate the interceptor withthe custom binding. CDI interceptors areimplemented the same way as the EJBinterceptors, the only significant differencebeing the use of the binding annotation whichcan be seen in Listing 8-10

LISTING 8-10: Binding an Interceptorwith @Secure

packagecom.devchronicles.interceptor;

importjavax.interceptor.AroundInvoke;importjavax.interceptor.InvocationContext;

@Secure@Interceptorpublic classSecurityInterceptor {

264

@AroundInvoke

public Object doSecurityCheck(InvocationContextcontext) throws Exception{

//Do some securitychecks!

Logger.getLogger("SecurityLog").info(context.getMethod().getName()+ "is

accessed!");

String user =context.getContextData.get("user");

if (user == null){user =

(String)context.getParameters()[0];

context.getContextData.put("user",user)'

}

returncontext.proceed();

}@PostConstructpublic void onStart(){

Logger.getLogger("SecurityLog").info("Activating");}

265

@PreDestroypublic void onShutdown(){

Logger.getLogger("SecurityLog").info("Deactivating");}

}

Just like the EJB interceptors, the@Interceptor annotation needs to be usedto promote the class file to an interceptor. The@Secure annotation binds the interceptor.Finally, the @AroundInvoke annotationmarks the method to be executed duringintercepted calls.

The next step is to implement the annotation onan advice, as shown in Listing 8-11.

LISTING 8-11: Implementing the@Secure on an advice

packagecom.devchronicles.interceptor;

importjavax.interceptor.Interceptors;

@Secure

266

public class SomeBusinessBean {

public void startService(){//Complex business

logic

Logger.getLogger("AppLog").info("done...");}

public voidstartAnotherService(){

//Complex businesslogic

Logger.getLogger("AppLog").info("doneagain...");

}}

CDI interceptors require one additional step ofdeclaring the interceptors in the beans.xmlfile. This is one of the rare cases in which youneed to use XML configuration; it’s used todetermine the execution order of theinterceptors.

Interceptor bindings can include otherinterceptor bindings that wrap multiplebindings together. The CDI container is notstarted if the beans.xml file is missing:

267

<beansxmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/beans_1_0.xsd">

<interceptors><class>

com.devchronicles.interceptor.SecurityInterceptor</class><class>

com.devchronicles.interceptor.SomeOtherInterceptor</class></interceptors>

</beans>

Although the declaration order of the bindingannotations may imply a sense of executionorder, in reality it has no effect. The executionorder of the interceptor depends on thedeclaration order in the beans.xml file.

Mixing CDI and EJB interceptors may createambiguity in the ordering. As a rule, EJBinterceptors execute before CDI interceptorsdo.

Intercepting methods creates complexity, butcreating multiple bindings and mixing CDI andEBJ interceptors brings this complexity to thenext level. Complex interceptor structures mayexpose a complex application architecture fordevelopers who are not familiar with the code.

268

WHERE AND WHEN TO USEINTERCEPTORSAOP is a popular programming paradigm thatcan help to implement and encapsulatecross-cutting concerns. In many cases, AOP canreally shine. Logging, auditing, security, andother repeating nonbusiness behavior are goodcandidates.

Interceptors in Java EE are powerful tools thatallow you to implement AOP without the needfor a third-party framework. With theintroduction of CDI interceptors, Java EE hasbecome more complete and capable.Implementing an interceptor may require someXML configuration, unlike other patterns listedin this book. However, the configuration is onlylimited to provide ordering, which otherpatterns such as decorators may also require.

Interceptors can address many cross-cuttingconcerns. They provide a clean implementationwhile encapsulating the common concern.However, interceptors can be troublesome ifthey change business behavior. If this happens,the business logic is distributed between theclass and the interceptor. The business methodbecomes unreadable and misleading because itdoesn’t expose the whole logic. Additionally, itunnecessarily complicates the architecture andapplication flow. Besides, debugging is almostimpossible and complicated.

269

Readability and self-documenting code is animportant aim, and misuse of interceptors cancause great harm if it consists of business logic.However, using interceptors for nonbusinessand repeating behavior can simplify thebusiness methods and help greatly.

As a general rule, avoid using interceptors forinjecting business logic or changing theexecution behavior. Interceptors are great whenyou need repetitive work that covers somemethods or classes.

SUMMARYAOP is a popular subject that has manysupporters but also many enemies. As expected,it is not a panacea that solves all problems.Aspects can greatly reduce code readability andcomplicate the overall application flow if notused properly.

However, aspects can be magical tools thatimplement additional behavior to the existingcode base with minimal effort. You can easilyturn them on or off depending on the runningtime environment. For example, you can turnoff a logging aspect during development andput it into action in the test environment.

Java EE offers simple interceptors that supportannotations and need little XML configuration,except in special cases. You can use interceptorsboth in EJB and MDB contexts either at the

270

class or the method levels. You can also declareinterceptors at a default level, which targets allEJBs matching the given criteria. The defaultlevel and ordering needs some configuration tobe done in the EJB-JAR XML file.

CDI adds great extensibility and functionality tointerceptors. You can easily customize CDIinterceptors and use them in a cleaner way withthe @InterceptorBinding annotation. Youcan use interceptor bindings to wrap otherinterceptor bindings, forming a chain ofinterceptors to execute. CDI interceptors doneed minimal XML configuration to help theCDI container determine the execution order.

EJB and CDI interceptors work alone ortogether in harmony. They offer all thefunctionality needed to implement AOP withouta third-party framework.

The proper use of interceptors createsbeautifully crafted applications with magicalexecution flow. When it is time to decide toimplement interceptors, make sure they don’tchange business flow and contain applicationlogic.

NOTES

1. Design Patterns: Elements of ReusableObject-Oriented Software (Addison-Wesley,1994): Erich Gamma, Richard Helm, RalphJohnson, John Vlissides.

271

2. Head First Design Patterns (O’Reilly, 2004):Eric Freeman, Elisabeth Robson, Bert Bates,Kathy Sierra.

272

9AsynchronousWHAT’S IN THIS CHAPTER?

Introduction to asynchronous programming

What is asynchronous programming

Asynchronous programming using threads

Using asynchronous programming in beans

Asynchronous programming in servlets

When and where to best use asynchronoustechniques

WROX.COM CODE DOWNLOADS FORTHIS CHAPTER

The wrox.com code download for this chapter isfound at www.wrox.com/go/projavaeedesignpatterns on theDownload Code tab. The code is in the Chapter9 download and individually named accordingto the names throughout the chapter.

Although asynchronous programming is notalways listed as a design pattern, it has been apopular and important programming model forthe past decade. The asynchronousprogramming model relies on multithreadingand executing the given functionality in aseparate thread. Not only do multithreaded

273

environments and programming languages takeadvantage of asynchronous programmingtechniques, but single-threaded platforms, suchas the popular server-side JavaScript platformNodeJS, make good use of asynchronousprogramming principles.

NOTE The asynchronous pattern is alsoreferred to as nonblocking method executionbecause the invoked method does not blockthe caller.

Java was designed to support multiple threadsfrom its start. However, it failed to provide asimple approach to making asynchronous calls.The Future<T> interface, which wasintroduced in Java 5, was Java’s first attempt atimplementing asynchronous programming, butit was cumbersome and tricky to use.Subsequent versions of Java introduced the@Asynchronous annotation. Theasynchronous servlet provided a much betterset of tools to aid in asynchronousprogramming.

WHAT IS ASYNCHRONOUSPROGRAMMING?The asynchronous programming pattern is aspecial and well-integrated case of multiplethreads. Due to the nature of threads,

274

multithreading models tend to need notificationsystems and depend on boilerplate code toinitiate threads.

Asynchronous calls are used even insingle-threaded environments like Node.JS.Almost all user interface (UI) frameworks useasynchronous execution to keep UI active andresponsive. The first “A” of AJAX,1 whichpowered the Web 2.0 movement, stands forasynchronous.

However, asynchronous programming can beuseful in places other than user interfaces,typically on the sever side. Neither J2SE norJ2EE offered a built-in easy implementation forasynchronous programming. With Java 5, theConcurrency Framework, based on JSR166, wasreleased. JSR166 included many utilities thatmade asynchronous programming possible,easier, and better controlled. The Future<V>interface also provided a way to help developersto implement asynchronous method execution.

Meanwhile, Spring offered asynchronousmethod calls, which are enabled withannotations. Java EE did not include such aconvenient solution until version 6.0. The@Asynchronous annotation was introducedwith Java EE 6 and offered an easy way toimplement asynchronous method execution.

275

Asynchronous PatternAsynchronous programming is not listed as adesign pattern in either the GoF2 book or in theHead First Design Patterns3 book. If it was, itsdescription might be “Provides a way to invokea method without blocking the invoker.”

The nature of method execution is to block thecaller until the called method finishes itsexecution. This behavior is straightforward andexpected but may not be desired in all cases.Almost all UI frameworks and web platformsrely on nonblocking requests.

WAR STORY

I was given the task of developing thecustomer services web portal for atelecommunications company. We hadimplemented a detailed logginginfrastructure while developing the portal.We did not log to a database to ensure thatthe logging was fast and failsafe in momentswhen the database was not available. Wewere successful in developing a system thathad fast response times and was reliable. Wewere pleased with what we had achieved.

Then we were asked to log each user’s actionsto a database table along with some specific

276

user-related data. The database we wereasked to use had a reputation for being slowand for regularly crashing and restarting.This was bad news for our fast and reliablelogging system. We now had to refactor oursystem, taking into consideration theunreliability of the database. Imagine whatwould happen if a user interaction was beinglogged at the same time the database wentdown. The synchronous call to the loggingsystem would block the response to the useruntil it either regained connection or timedout. The user would have to wait, which wasunacceptable.

We did not want the user to wait for thedatabase to respond and expose a databaseerror to the front end, especially consideringthat we were only logging statistics. Afterimplementing and testing all the DAOclasses, we added the @Asynchronousannotation and prepared to go live.

As usual, we were confident in ourwell-tested deployment package, so wedecided to go home to sleep rather thanspending the night with the serveradministrators who were doing thedeployment. The next morning we receivedan e-mail advising us that the application waslive.

277

Soon we discovered that our server’s log fileswere full of errors, showing that the databaseconnection had been unavailable. Wecontacted the server administrators andquickly discovered that the database adminshad forgotten to create the log tables in thelive database. The tables were quicklycreated, and all was well until the databasestarted to suffer from performance-relatedissues and had frequent server restarts (aswas expected given its reputation).

Our application had failed to persist somenoncritical logs but never faltered in itsperformance. Every time there was a problemwith the database and the logging failed, theuser had already finished what he was doingand didn’t notice that the logging had failed,thanks to the use of asynchronously callingthe logging functionality.

Asynchronous programming is a great tool touse when separating tasks that do not need tointeract with each other.

The asynchronous pattern relies on the fire andforget approach where an operation is done inparallel or in a way not blocking the executorthread, and the result is checked when it isready. Usually the asynchronous approachmakes use of parallel execution. It may not beaccurately reflected with a class diagram but

278

may be better shown with a flow diagram.Figure 9.1 demonstrates several asynchronousexecution flows.

Figure 9.1 Asynchronous flow diagram

IMPLEMENTINGASYNCHRONOUS PATTERN ?INPLAIN CODEJava has supported threads that you can easilyuse for asynchronous code execution from itsinitial design:

public class AsyncRunnableimplements Runnable {

public void run() {

System.out.println("Running!");}

}

To execute the Runnable class, initialize it in athread and invoke the run method by calling

279

the start() method on the newly createdthread:

(new Thread(newAsyncRunnable())).start();

Although the preceding example is thepreferred way to start a thread process, anotherapproach is to extend the thread class andoverride the run() method:

public class AsyncThread extendsThread {

public void run() {

System.out.println("Running!");}

}

To execute the class, instantiate it and then callthe start() method:

(new HelloThread()).start();

Two essential operations are commonly usedwhen dealing with threads: sleep() andjoin(). Both operations throw anInterruptedException.

The sleep() method lets the thread sleep fora specified period, given in milliseconds. The

280

following code snippet puts the current threadinto the sleep state for one second:

Thread.sleep(1000);

The join() method makes one thread wait foranother thread’s execution to finish. Consider athread, t1, that needs a resource from anotherthread, t2. To make t1 wait for t2 to finish, joint1 to t2, as shown in the following code snippet:

t2.join();

One of the most well-known and widely usedapproaches to programming asynchronously inJava is using the Future<V> interface. Thisinterface enables the use of a proxy object,which offers a reference for the future object.Because the concurrency framework does notoffer annotation-based support forasynchronous execution, the Future interfaceis mostly coupled with anExecutorService, which is part of theconcurrency framework.

The following example uses an executor serviceto complete a task while it returns a reference tothe Future interface with the appropriategeneric type:

ExecutorService executor =Executors.newSingleThreadExecutor();

281

Future<String> reference =executor.submit(

new Callable<String>() {public String call() {

return "Hello!!";}

});//..if (reference.isDone())

System.out.println(reference.get());

The FutureTask class is an implementationof the Future<T> interface, whichimplements the runnable interface and can beexecuted directly:

FutureTask<String> reference =new FutureTask<String>(

new Callable<String>() {public String call() {

return "Hello!!";}

});

executor.execute(reference);

You can cancel this execution by calling thecancel(booleanmayInterruptIfRunning) method. If themayInterruptIfRunning parameter is set

282

to true, calls to themethod SessionContext?.wasCancelled()return true. Otherwise, a call to theSessionContext.wasCancelled()method returns false. To check the status ofcancelation, you can use the isCancelled()method, which returns true if a cancelation issuccessful.

The concurrency framework JSR-133 offersgreat tools for threads and concurrentprogramming, such as BlockingQueues.These topics are beyond the scope of thischapter. See the book Java Concurrency inPractice4 for further reading. The Fork/JoinFramework, which was introduced in Java 7,also offers a huge change in favor ofasynchronous and parallel programming inJava.

ASYNCHRONOUSPROGRAMMING IN JAVA EEBecause J2EE failed to offer built-in support forthe asynchronous programming paradigms(except for Timer), third-party frameworks,such as Spring and Quartz, stepped in to fill thisgap. This deficit was corrected in Java EE 5; itwas the first Java version to support theasynchronous programming pattern out of thebox.

283

Asynchronous BeansJava EE supports asynchronous programmingin several ways. The simplest way to implementthe asynchronous pattern in Java EE is, notsurprisingly, via the application of anannotation. Annotating a method with@Asynchronous is enough to advise the JavaEE container to asynchronously execute theinvoked method in a separate thread. To see theasynchronous annotation in action, go back tothe singleton logging bean example in Chapter4, “Singleton Pattern” and add theasynchronous annotation to change its defaultbehavior. Listing 9-1 shows an example of anasynchronous bean.

LISTING 9-1: An example of anasynchronous bean

packagecom.devchronicles.asynchronous;

importjavax.annotation.PostConstruct;import javax.ejb.Singleton;import javax.ejb.Startup;importjava.util.logging.Logger;import javax.ejb.Asynchronous;

284

@Startup@Singletonpublic class MyLoggingBean {

private Logger logger;

@PostConstructpublic void start(){

logger =Logger.getLogger("MyGlobalLogger");

logger.info("Well, Istarted first!!!");

}

public void logInfo(Stringmsg){

logger.info(msg);}

@Asynchronouspublic void

logAsync(String msg){logger.info(msg);

}}

285

The logAsync() method, unlike itslogInfo() counterpart, is executedasynchronously. To observe asynchronousbehavior, add Thread.sleep() calls:

public void logInfo(String msg) {logger.info("Entering sync

log");

try {Thread.sleep(1000);

} catch (InterruptedExceptione) {}

logger.info(msg);}

@Asynchronouspublic void logAsync(String msg {

logger.info("Entering asynclog");

try {Thread.sleep(13000);

} catch (InterruptedExceptione) {}

logger.info(msg);}

Finally, create a new bean to call both functionsin order, as shown in Listing 9-2.

286

LISTING 9-2: Refactor of Listing 9.1 toinclude both functions

packagecom.devchronicles.asynchronous;

importjavax.annotation.PostConstruct;import javax.ejb.Singleton;import javax.ejb.Startup;

@Startup@Singletonpublic class TestLogging {

@EJBMyLoggingBean logBean;

@PostConstructpublic void testLoggers(){

System.out.println("callasync");

logBean.logAsync("LogAsync");

System.out.println("call

287

sync");logBean.logInfo("Log

Sync");

System.out.println("finished");

}}

A typical console output would be as follows:

> call async

> Entering async log

> call sync

> Entering sync log

> Log Sync

> finished

> Log Async

After you execute the testLoggers()method, call the logAsync() andlogSync() methods. Both methods let theirexecution thread sleep for the given length oftime. As can be seen from the console output,

288

the async() method was called and went intoa long sleep but did not lock the execution ofthe sync() method. The sync() methodsleeps for a while but returns control to thecaller method and prints finished. Finally,the async() method wakes up and finisheslogging by printing Log Async to the console.

This example clearly shows that theasynchronous call does not stop the callerthread, nor does it stop the sync() method.However, when the sync() method goes intothe sleep state, the caller method waits until thesleep ends. The @Asynchronous annotationis an easy way to implement asynchronousbehavior and can be added to almost anymethod at any time during and afterdevelopment.

Asynchronous ServletsSo far, you have seen that you can convert anymethod of a bean to an asynchronous method.Now you’ll look at how to make a servlet actasynchronously. Without asynchronous supportin servlets, it is hard to respond to theasynchronous web challenge.

The Servlet 3.0 specification (JSR 315) madehuge improvements to the Java web applicationprogramming interfaces (APIs). With JSR 315,the servlet specification was updated (after along wait) to support an asynchronous

289

execution model, easy configuration,pluggability, and other minor enhancements.

Asynchronous servlets rely on a basicimprovement in Hypertext Transfer Protocol(HTTP) 1.1, which enabled persistentconnections. In HTTP 1.0, each connection isused to send and receive only a single requestand response couple; however, HTTP 1.1allowed web applications to keep theconnection alive and to send multiple requests.On a standard implementation, the Java backend would need a separate thread constantlyattached to the HTTP connection. However,Java nonblocking I/O (NIO) APIs recyclethreads between active requests, thanks to thenew NIO capability. Today all web serverscompatible with the Servlet 3.0 specificationhave built-in support for Java NIO. Why do youneed such behavior from servlets? The nature ofback-end systems involves lengthy operationssuch as connecting to other servers, performingcomplex calculations, and making transactionaldatabase operations. However, the nature ofweb pages requires quite the opposite. Webusers expect fast response times and afunctional UI even if back-end operations arecompleted. AJAX addressed this issue for thebrowser and started the Web 2.0 revolution.

Servlet 3.0 introduced the startAsync()method, which enabled asynchronousoperations. Listing 9-3 shows an example.

290

LISTING 9-3: An example of thestartAsync() method

packagecom.devchronicles.asynchronous;

import java.io.*;import javax.servlet.*;importjavax.servlet.annotation.*;import javax.servlet.http.*;

@WebServlet(urlPatterns={"/async"}, asyncSupported=true)public class AsyncServletextends HttpServlet {

@Overrideprotected voiddoGet(HttpServletRequest req,HttpServletResponse res)

throwsIOException, ServletException {

final AsyncContextasyncContext =req.startAsync();

final String data;

291

asyncContext.addListener(newAsyncListener() {

@Overridepublic void

onComplete(AsyncEvent event)throws IOException {

AsyncContextasyncContext =event.getAsyncContext();

asyncContext().getWriter().println(data);}

@Overridepublic void

onTimeout(AsyncEvent event)throws IOException {

// Code not shownfor brevity

}

@Overridepublic void

onError(AsyncEvent event)throws IOException {

// Code not shownfor brevity

}

292

@Overridepublic void

onStartAsync(AsyncEvent event)throws IOException {

// Code not shownfor brevity

}

});

new Thread() {@Overridepublic void run() {

asyncContext.complete();}

}.start();

res.getWriter().write("Results:");//Read data from databasedata = "Queried data...";//sleep thread for some

time...}

}

293

This servlet prints Results: and later printsretrieved data from the database, which is asimple string in this scenario. You need toinitialize a separate thread. AsyncListener’sonComplete method is executed only whenthe execution completes. Several other life cyclemethods exist in the AsyncListener:

onStartAsync—executes when theasynchronous context starts

onTimeOut—executes only if a timeout occurs

onError—executes only if an error is received

The Servlet 3.1 specification provided an easierway to implement asynchronous servlets byusing managed thread pools and the executorservice. The example in Listing 9-4 uses aManagedThreadFactory to create a newthread.

LISTING 9-4: An example that usesManagedThreadFactory

packagecom.devchronicles.asynchronous;

import java.io.*;import javax.servlet.*;importjavax.servlet.annotation.*;

294

import javax.servlet.http.*;

@WebServlet(urlPatterns="/async", asyncSupported=true)public class AsyncServletextends HttpServlet {

@Resourceprivate

ManagedThreadFactory factory;

@Overrideprotected void

doGet(HttpServletRequest req,HttpServletResponse res)

throws ServletException,IOException {

final AsyncContextasyncContext =req.startAsync();

final PrintWriterwriter = res.getWriter();

Thread thread =factory.newThread(newRunnable() {

295

@Overridepublic void run() {

writer.println("Complete!");

asyncContext.complete();}

});

thread.start();}}

This example creates a new thread that hoststhe time-consuming process and finally calls acomplete function from asyncContext.ManagedThreadFactory serves as anavailable thread from the pool that you need tostart explicitly.

Another approach is to submit theasynchronous runnable toManagedExecutorService instead ofcreating and starting the thread in the servlet.Delegating threading issues toExecutorService provides cleaner code, asyou’ll see in Listing 9-5.

296

LISTING 9-5: An example thatdelegates to the ExecutorService

packagecom.devchronicles.asynchronous;

import java.io.*;import javax.servlet.*;importjavax.servlet.annotation.*;import javax.servlet.http.*;

@WebServlet(urlPatterns="/async", asyncSupported=true)public class AsyncServletextends HttpServlet {

@Resourceprivate

ManagedExecutorServiceexecutor;

@Overrideprotected void

doGet(HttpServletRequest req,HttpServletResponse res)

throws ServletException,IOException {

final AsyncContext

297

asyncContext =req.startAsync();

final PrintWriterwriter = res.getWriter();

executor.submit(newRunnable() {

@Overridepublic void run() {

writer.println("Complete!");

asyncContext.complete();}

});}

}

Although it’s just one line less than the previouslisting, Listing 9-5 delegates the creation andstarting of the thread to theExecutorService and only deals withservlet-specific code.

Asynchronous servlets are easier to understandand code and have an immediate effect onruntime behavior because it directly switches tothe asynchronous execution model.Asynchronous servlets provide a clean

298

implementation without a lot of boilerplatecode.

WHERE AND WHEN TO USEASYNCHRONOUS?PROGRAMMINGYou can use the asynchronous pattern almostanywhere where it is required to return aresponse before all the execution is complete.This approach can vary from executing the lessimportant functions of the applicationasynchronously, such as logging or keeping theuser informed about a time-consumingoperation. Asynchronous programming makesthe critical execution path shorter whiledelegating subtasks to other threads. The resultis better response times.

Asynchronous annotation is a simple way toimplement asynchronous methods or convertexisting ones. Each method marked with theasynchronous annotation runs in a separatethread without locking the current thread’sexecution. This behavior is a perfect match forconditions that do not affect the main executioncycle but need to be performed on the back end.Examples include logging and maintenanceresources.

You can use asynchronous servlets in almost allmodern web apps. Asynchronous servletsprovide nonblocking asynchronous behavior

299

without a special need for AJAX. Asynchronousservlets can help when a server-based pushoperation is needed, such as updatinginformation or delivering a message.

Because each asynchronous execution requiresa new thread, the Java Virtual Machine (JVM)needs to perform more context switches asmore asynchronous methods are implemented.A large number of context switches causethread starvation and result in poorerperformance than a synchronousimplementation.

Imagine that you are reading one book.Between reads, you must remember the story,the characters, and the last page you’ve read. Ifyou’re reading two books at the same time, youmay finish the second shorter book withoutneeding to finish the longer one you started.The time spent changing context from one bookto the other is acceptable.

Reading six books in parallel would bechallenging. It may require so many contextchanges that you may not be able to finish anyof the books in the expected time and end upchanging from one book to the other withoutmaking much progress in any of them.

Asynchronous programming radically modifiesthe execution order and therefore debugging.Because debugging relies on suspending theexecution and then stepping line by line

300

through it, it is more difficult to understand theexecution behavior and to mimic what is reallyhappening. The JVM determines the executionorder of threads at run time. It is almostimpossible to simulate the same behaviorbecause of very different available resources ontest and development environments. If youdon’t need it, asynchronous execution addsundesired complexity.

Threading and asynchronous execution can be agreat tool only if used properly without starvingresources. It is a good idea to run nonblockingparts asynchronously, but not on every method.

SUMMARYIn the age of multicores and web 2.0,asynchronous programming uses computingresources, delegates nonblocking tasks, andresults in faster and more responsive userinterfaces. Even if your application does notimplement the asynchronous pattern, mostapplication servers and JVMs use asynchronousexecution internally via thread pools for manyoperations. Using those available threads andresources greatly affects your application’sefficiency and responsiveness.

Threading has been a first-class citizen from theearly days of Java, but using threads to runasynchronous tasks was complicated and wasn’talways safe in server-managed containers. Withthe release of the Concurrency Framework,

301

Java unleashed a huge set of tools into thehands of Java developers.

Java EE followed this trend by providing aneasy-to-use and implement annotation-basedasynchronous programming model. Adding the@Asynchronous annotation tells thecontainer to execute the functionasynchronously.

The servlet API introduced important changesin release 3.0 and further improvements inrelease 3.1. The new servlet API uses the newnonblocking Java I/O to support asynchronousweb programming in an efficient way. Althoughprevious approaches needed a request/responsecouple to be bound to a thread, the new modelcan use or release threads using the internalthread pool that the container provides.

Today Java EE offers all the needed tools to runasynchronous code without the need for athird-party framework such as Spring orQuartz. This makes the asynchronous pattern agreat tool to implement if you want to executenonblocking code asynchronously with almostno boilerplate code.

EXERCISES

Create an implementation of a session beanthat has an asynchronous method.

302

Develop simple functionality that usesasynchronous methodology to persistapplication log data to a database.

Use the asynchronous feature of Servlet 3.0to design an asynchronous web service.

NOTES

1. “AJAX (Asynchronous JavaScript and XML):A New Approach to Web Applications.”Jessie James Garret.http://www.adaptivepath.com/ideas/ajax-new-approach-web-applications/.

2. Design Patterns: Elements of ReusableObject-Oriented Software (Addison-Wesley,1994): Erich Gamma, Richard Helm, RalphJohnson, John Vlissides.

3. Head First Design Patterns (O’Reilly, 2004):Eric Freeman, Elisabeth Robson, Bert Bates,Kathy Sierra.

4. Java Concurrency in Practice(Addison-Wesley Professional, 2006): BrianGoetz, David Holmes, Doug Lea, Tim Peierls,Joshua Bloch.

303

10Timer ServiceWHAT’S IN THIS CHAPTER?

Advancements made in the timer service

Automatic timers

Programmatic timers

Setting the schedule with schedule expressions

Timers and transactions

WROX.COM CODE DOWNLOAD FORTHIS CHAPTER

The wrox.com code download for this chapter isfound at www.wrox.com/go/projavaeedesignpatterns on theDownload Code tab. The code is in the Chapter10 download and individually named accordingto the names throughout the chapter.

Business applications need to perform tasksbased on either calendar events or a timedschedule, whether it is to generate weekly useractivity reports, repopulate a cache, or send aclient a reminder e-mail. There are many usecase scenarios. The timer service enables you toprogram timer events at specific times orregular intervals.

304

This chapter shows you how to configure thetimer service using both automatic andprogrammatic techniques and how to scheduletasks using the cron-like schedule expressions.

WHAT IS THE TIMER SERVICE?Can you imagine needing to wake up everymorning to check the clock to see if it is time toget up? Probably not. Even before the inventionof the alarm clock, people used sunlight orroosters to wake up. But roosters and the sunare not customizable. This lack of customizationled to the invention of one of the mostimportant devices of modern life: the alarmclock. Today even basic cell phones and fitnesstrackers offer alarms that you can adjust todifferent times and different days and evenoffer snooze options.

For a long time, neither Java SE nor Java EEoffered a built-in solution for time-basedoperations. This lack of support was filled withcommunity-led open source.

Traditionally, timer-based tasks would havebeen scheduled using a third-party tool such asQuartz,1 but such a tool tends to be tricky touse. Third-party tools require you to downloadand install a library, implement interfaces, andconfigure XML files. They’re anything butstraightforward.

305

Fortunately for you and partly because of thedifficulty faced by developers trying to usethird-party libraries, a scheduling facility wasintroduced into the EJB 2.1 specification. Thistimer service satisfied the simplest use casescenarios. And for those complicated cases,there was still Quartz. Indeed, Quartz almostbecame the de facto standard of time-basedoperations in Java.

There is no default implementation for timersin Java SE. You can use Quartz in both Java SEand Java EE, but Quartz usage is a separatetopic beyond this book. So this chapter skipsthe Java implementation and moves on to JavaEE.

Advancements were made in the EJB 3.2specification (the latest release) to the timerservice. Introduced were the @Schedule and@Schedules annotations and cron-likecalendar expressions. Now all but the mostexceptional use case scenarios are satisfied. Thetimer service runs in the container as a serviceand registers Enterprise JavaBeans (EJB) forcallbacks. It tracks the timers that exist andtheir schedules, and it even takes care ofpersisting the timer in case a server shuts downor crashes. The only thing the developer needsto do now is schedule the timer.

The timer service has been through a longdevelopment cycle. An overview of theadvancements is summarized in Table 10.1.

306

Table 10.1 Timer Service Development

EJB ANDJAVAVERSION

DEVELOPMENT

EJB 2.1Java 1.4(November2003)

The ejbTimer implements theTimedObject interface.The TimerService is accessedthrough the EJBContextmethod.The business logic must be in theejbTimeout method.

EJB 3.0Java 5(May2006)

The TimerService object isinjected via direct injection usingthe annotation @Resource.The business logic must be placedin a method annotated [email protected] set by specifying a date,duration, orScheduleExpression objector an XML configuration file.Referred to as programmatictimers in Java EE 6.

EJB 3.1Java 6(December2009)

The container sets theTimerService objectautomatically; no injection isrequired.The business logic must be placedin a method annotated with@Schedule or @Schedules.

307

EJB ANDJAVAVERSION

DEVELOPMENT

The schedule is set in theannotations attributes andbycalendar-based EJB timerexpressions.

EJB 3.2Java 7(June2013)

This extended the EJB Lite groupto include the nonpersistent EJBtimer service.Includes enhancements to theTimerService API that allowsaccess to all active timers in theEJB module.Restrictions on Timer andTimerHandle that obligedreferences to be used only inside abean have been removed.

WAR STORY

Recently, I was brought in to consult on aweb project that was suffering fromintermittent performance issues. Theseissues had only appeared recently—just asthe site’s visitor numbers started toaccelerate.

The developers had chosen to use a No-SQLdatabase to persist GPS data regarding the

308

location of the site’s visitors. This was a gooddecision because this particular No-SQL datastore was adept at geospatial queries.

Queries were regularly run against thedatabase, which collated data from thelocation collection and aggregated it togenerate reports. These reports generateddaily visitor statistics and were executedevery day by a junior staff member.

After some investigating, I discovered thatthe performance issues the application washaving coincided with the time the reportswere being run. The extra hit to the databasecaused by running the reports wasresponsible for the deterioration inperformance.

The solution was quite simple. Run thereports when the database was experiencinglower use. After reviewing the database usagereports, I determined that the optimal time torun the reports was 03:00 GMT. Clearly, Icouldn't ask the junior member of the staff tostart work at 3:00 in the morning, so Idecided to automate the generation of thereports and configured the timerserviceto launch the report generation.

Many tasks are best run in off hours for thesame reason as spelled out here.

309

Repopulating data caches is a commonexample of a heavy process that should berun when the effect on site performance isminimal.

IMPLEMENTING A TIMER IN JAVAEEThere are two types of timers in Java EE 7:automatic and programmatic. Automatic timersare set upon the deployment of an enterpriseJava bean (EJB) that contains a methodannotated with either @Schedule(...) or@Schedule(...). The annotated method isinvoked by the container’s scheduler at thespecified times, or time intervals defined withinthe arguments of the annotations. Suchmethods are referred to as callback methods.The timer starts ticking as soon as the EJB isdeployed. A programmatic timer is set at runtime by a method called from within thebusiness logic. The time can be configured onthe fly and invoked at anytime (or not at all).The timer start ticking when the programminglogic determines that it should start.

TIMER SERVICEIMPLEMENTATION

310

The EJB container implements the timerservice. An enterprise bean can access thisservice in three ways: by means ofdependency injection, through theEJBContext interface, or through lookup inthe Java Naming and Directory Interface(JNDI) namespace. This book only examinesthe way by means of dependency injection,because it's the newest and most efficient.

Automatic TimersThe container invokes any methodappropriately annotated with @Schedule andapplies the schedule configuration specified inthe annotation’s attributes. The attributes of theannotation are set following the calendar-basedtimer attributes in the “Timer Expression”section that follows. Here is a simple example:

@Schedule(second="*/1",minute="*", hour="*")public void executeTask(){

System.out.println("Taskperformed");}

In this code snippet, the methodexecuteTask is annotated @Schedule; thisindicates to the container to set a timer upondeployment based on the time values specified

311

in the annotations attributes. In this examplethe container invokes the executeTaskmethod once every second.

By default, all timers are persisted and restoredafter a server shutdown or crash. If you set theoptional attribute persistent to false, thetimer is reset on server restart. You can set twoadditional attributes: info and timezone. If youset timezone, that time zone is respected whenexecuting the timer; otherwise, the server timezone is used. The info attribute allows adeveloper to provide a description of the timethat you can retrieve by calling the getInfomethod of the Timer interface.

@Schedule(hour = "23", minute ="59", timezone = "CET",

info = "Generatesnightly report")public void executeTask(){

System.out.println("Taskperformed");}

In the preceding code snippet, theexecuteTask method is invoked at 23:59Central European time regardless of the timezone of the server on which it is deployed. A callto the method getInfo returns the textGenerates nightly report.

312

You can configure more complex timers using@Schedules (note the pluralization) withmultiple timer expressions.

@Schedules({@Schedule(dayOfMonth = "1"),@Schedule(dayOfWeek =

"Mon,Tue,Wed,Thu,Fri", hour ="8")})public void executeTask() {

System.out.println("Taskperformed");}

This timer fires on the first of every month andevery work day at 08:00. Listing 10-1 shows acomplete example of an automatic timer.

LISTING 10-1: The simplestimplementation of an automatic timer

packagecom.devchronicles.timer;

import javax.ejb.Schedule;import javax.ejb.Schedules;

public class PeriodicTimer {

313

@Schedules({@Schedule(dayOfMonth =

"1"),@Schedule(dayOfWeek =

"Mon,Tue,Wed,Thu,Fri", hour ="8")

})public void executeTask() {

System.out.println("Taskperformed");

}

}

One drawback of the automatic timer is that itsschedule is set at deployment time and cannotbe changed while the application is executing.Fortunately, there is a solution to this situationin the form of the programmatic timer, whichyou can set at any moment during run time.

Programmatic TimersProgrammatic timers are created at run time byinvoking one of the create methods of theTimerService interface. Here is a simpleexample:

public void setTimer(){

314

timerService.createTimer(30000,"New timer");}

When the application code invokes thesetTimer method, it creates a single-actiontimer that calls a “timeout” method in the samebean after the specified duration of 30,000milliseconds. A “timeout” method is identifiedby the annotation @Timeout and mustconform to certain requirements. It must notthrow exceptions or return a value. It’s alsoexempt from needing to take a parameter, but ifit does, it must be of type javax.ejb.Time.There can be only one “timeout” method.

@Timeoutpublic void performTask() {

System.out.println("SimpleTask performed");}

The Context Dependency Injection (CDI)container injects a reference to theTimerService into an instance variableannotated @Resource. Here the containerinjects the instance variable timerService.

@ResourceTimerService timerService;

If you put together the previous three codesnippets into a single bean and the application

315

code calls the setTimer method, you create atimer that, after 30 seconds, calls the “timeout”method performTask. Listing 10-2 shows thesimplest possible implementation of theprogrammatic timer in Java EE 7.

LISTING 10-2: The simplestimplementation of a programmatictimer

packagecom.devchronicles.timer;

importjavax.annotation.Resource;import javax.ejb.Timeout;import javax.ejb.TimerService;

public classSimpleProgrammaticTimer {

@ResourceTimerService timerService;

public void setTimer(){

timerService.createTimer(30000,"New timer");

}

316

@Timeoutpublic void performTask() {

System.out.println("SimpleTask performed");

}}

There are four timer creation methods in theTimerService interface with ten signatures.Table 10.2 shows an example of each one:

Table 10.2 Examples of the Four TimerCreation Methods

METHOD EXAMPLE

createIntervalTimer(new Date(),10000, new TimerConfig());

This createsa timer thatfires at thegiven dateand thenevery tensecondsthereafter.

createSingleActionTimer(1000, newTimerConfig());

This createsa timer thatfires afterone second.

createTimer(30000, "Created newprogrammatic timer");

This createsa timer that

317

METHOD EXAMPLE

fires after30 seconds.

createCalendarTimer(newScheduleExpression().second("*/10").minute("*").hour("*"));

This createsa timer thatfires everytenseconds.

All methods apart from thecreateCalendarTimer method can take asthe first parameter either duration inmilliseconds or a date. This sets up the point atwhich the timer is triggered. Here is anexample:

SimpleDateFormat formatter = newSimpleDateFormat("dd/MM/yyyy'at' HH:mm");Date date = formatter.parse("26/01/2015 at 17:56");timerService.createSingleActionTimer(date,new TimerConfig());

In this code snippet, the “timeout” method istriggered at 17:56 on January 26, 2015.

If a scheduled timer is required, you can use thecreateCalendarTimer method. Thismethod takes a ScheduleExpressionobject in which a schedule is set using the

318

values described in the “Timer Expression”section that follows.

ScheduleExpression expression =new ScheduleExpression();expression.second("*/10").minute("*").hour("*");timerService.createCalendarTimer(expression);

In this code snippet, the schedule is set totrigger every ten seconds of every minute ofevery hour.

All the creation methods return a Timer objectthat represents the timer. This object has themethod getHandle, which returns aserializable handle to the timer. The handleobject can be persisted in a database ormemory.

Later you can retrieve the handle object andreturn a reference to the timer by invoking thegetTimer method. With this object in hand,you can retrieve useful information about thetimer.

It’s easy to obtain information about thebehavior of the timer. You can retrieve detailsregarding the timer’s schedule by calling themethod getSchedule. This returns aScheduleExpression object that has agetter method for each attribute. Forexample, getMinute() returns the value setfor the minute attribute. The

319

getNextTimeout method gets the pointwhen the timer fires next, whereas the methodgetTimeRemaining returns the millisecondsbefore the timer expires.

The isCalendarTimer method returnstrue if the timer was set by constructing aScheduleExpression object. You must callit before the getSchedule method todetermine if the timer was set this way;otherwise, isCalendarTimer throws anIllegalStateException exception.

You can determine information about thetimer’s persistent state by using theisPersistent method. Similarly, you canobtain information about the time by calling thegetInfo method.

Timers are automatically cancelled when theyexpire. The container cancels the single-eventtimers, and you can cancel scheduled timers bycalling the cancel method on the Timerobject.

Timer ExpressionBoth programmatic and automatic timers canuse calendar-based timer attributes. Table 10.3shows the range of timer attributes that areused to set the timers. For automaticcalendar-based timers, you set the calendarattributes in the annotation, whereasprogrammatic calendar-based timers use

320

methods of the ScheduleExpression classto set the calendar attribute values.

Table 10.3 Calendar-Based Expressions

ATTRIBUTE DESCRIPTION PERMITTEDVALUES

second One or moreseconds within aminute

0 through 59

minute One or moreminutes withinan hour

0 through 59

hour One or morehours within aday

0 through 23

dayOfWeek One or moredays within aweek

0 through 7 (0and 7 refer toSunday)Sun throughSat

dayOfMonth One or moredays within amonth

1 through 31–7 through –1(days fromend of month)Last1st, 2nd, 3rd -nthSun throughSat

321

ATTRIBUTE DESCRIPTION PERMITTEDVALUES

month One or moremonths within ayear

1 through 12Jan throughDec

year A particularcalendar year

2014, 2015,etc.

It’s worth noting that the default value for thetime attributes is 0 (zero) and for thenon-numerical values it is * (asterisk).

This table has been appropriated from theOracle’s Java EE 7 tutorial.2 The syntax iscron-like and should be familiar to mostprogrammers. There are a few interestingcharacteristics worth pointing out.

The asterisk character is a placeholder for allpossible values for the given attribute. Forexample, to set a schedule to trigger every hour,you would use the expression hour="*" forannotation-configured timers. Forprogrammatic timers, you would invoke themethod hour("*")on an instance of theScheduleExpression class.

You can express values for each attribute as alist or a range. For example, the expressiondayOfMonth="1, 15, last" sets thetimer to trigger on the first, fifteenth, and lastday of every month, whereas the expression

322

hour="8-18" represents every hour from08:00 until 18:00.

You can specify intervals and augment themwith a starting point. The expressionhour="8/1" triggers every hour startingfrom 08:00, whereas the expressionhour="*/12" triggers every 12 hours.However, you can only set intervals for seconds,minutes, and hour attributes.

Table 10.4 offers a few examples of thecalendar-based schedule in action.

Table 10.4 Examples of Expressions in Action

EXPRESSION ACTION

Second="10" Every ten seconds

hour = "2", Every two hours

minute = "15" Every 15 minutes

dayOfWeek="Mon,Fri"

Every Monday andFriday at midnight

dayOfWeek="0-7",hour="8"

Every day at 8 a.m.

dayOfMonth="-7" Five days before theend of every month atmidnight

dayOfMonth="1stMon", hour="22"

First Monday of everymonth at 10 p.m.

323

EXPRESSION ACTION

Month="Mar",dayOfMonth="15"

The 15th of thefollowing March

year="2015",month="May"

May 1, 2015 atmidnight

New in the EJB 3.2 implementation is anenhancement to the timer service API thatallows access to all active timers in the EJBmodule. These include both programmaticallyand automatically created timers.

LISTING 10-3: All timers can beretrieved and manipulated

packagecom.devchronicles.timer;

import java.util.Collection;importjavax.annotation.PostConstruct;importjavax.annotation.Resource;import javax.ejb.Singleton;import javax.ejb.Startup;import javax.ejb.Timer;import javax.ejb.TimerService;

@Singleton

324

@Startuppublic class AllTimers {

@ResourceTimerService

timerService;

@PostConstructpublic void manageTimer(){

Collection<Timer>timers =timerService.getAllTimers();

for(Timer t : timers){

System.out.println("TimerInfo: " + t.getInfo());

System.out.println("TimeRemaining: " +t.getTimeRemaining());

t.cancel();}

}}

In Listing 10-3, the bean is instantiated atstart-up, and the manageTimer method iscalled. You retrieve a collection of all the active

325

timers and iterate over the collection, printingout the timer info and the number ofmilliseconds that will elapse before the nextscheduled timer expiration. Finally, you cancelthe timer.

TransactionsBeans create timers within a transaction thatthe container manages. If this transaction isrolled back, so is the timer. If this transaction isrolled back then the timer is also rolled back.This means that its creation is rolled back and ifit were canceled the cancellation would beundone and the timer reinstated. In listing 10-4we show an example of a timer method markedwith a transaction annotation.

LISTING 10-4: A timer can set atransaction attribute

packagecom.devchronicles.timer;

importjavax.annotation.Resource;import javax.ejb.Timeout;import javax.ejb.TimerService;

public classSimpleProgramaticTimer {

326

@ResourceTimerService timerService;

public void setTimer(){ScheduleExpression

expression = newScheduleExpression();

expression.second("*/10").minute("*").hour("*");

timer =timerService.createCalendarTimer(

newScheduleExpression().second("*/10").minute("*").hour("*"));

}

@Timeout

@TransactionAttribute(TransactionAttributeType.REQUIRED)public void performTask() {System.out.println("Simple

Task performed");}

}

Beans that use container-managed transactionsset the transitions attribute on the methodannotated @Timeout. Transactions aredesignated Required or RequiresNew. The

327

transaction is started before the method iscalled. If the transaction is rolled back, the@Timeout method is called again.

SUMMARYIn this chapter, you have seen how to createautomatic and programmatic timers and howthey behave within a transaction. Timers can bequite useful when a cron-like job needs to runwithout disturbing the main business logic. Youcan see examples of timers in many projectsand in almost all programming languages. Theautomatic timer is created by annotating amethod with either @Schedule or@Schedules and hard-coding timer values asattributes of the annotations by declaring themin the ejb-jar.xml deployment descriptor.Programmatic timers are created by theapplication code and can change their values atrun time.

The timer type you choose to solve yourproblem will depend largely on whether thefrequency of the event will change based onbusiness logic (client services) or technicalrequirements (repopulating a cache). The latterwould best be served with a programmatictimer, whereas the former would benefit mostfrom an automatic timer.

Timers are persisted by default to guard againstserver shutdowns and crashes and can be

328

serialized in a database and later retrieved.Timers take part in a transaction and are fullyrolled back with the transaction. It became alittle easier to manage timers in EJB 3.2; youcan retrieve all active timers in a collection andcall timer methods on each instance.

With the new achievements on Java EE, timersbecame solid and capable, leaving mostthird-party frameworks obsolete.

EXERCISES

Write a cache that repopulates a map from adatabase. Set the timer service to fire at 3a.m., calling the repopulate method of thecache.

Develop a programmatic timer that sends anotification to a client when his subscriptionis up for renewal.

NOTES

1. Quartz Job Scheduler:http://www.quartz-scheduler.org/.

2. Oracle’s Java EE 7 tutorial:http://docs.oracle.com/javaee/7/tutorial/doc/ejb-basicexamples004.htm#GIQLY.

329

11Observer PatternWHAT’S IN THIS CHAPTER?

How to implement the observer pattern in plaincode

How the observer pattern works in the realworld

How to implement the observer pattern using@Observes and Event firing

How to use qualifiers to gain fine-grain controlover observers

How to implement transaction-sensitiveobservers and rollbacks

WROX.COM CODE DOWNLOAD FORTHIS CHAPTER

The wrox.com code download for this chapter isfound at www.wrox.com/go/projavaeedesignpatterns on theDownload Code tab. The code is in the Chapter11 download and individually named accordingto the names throughout the chapter.

The observer pattern is one of the most widelyused and accepted design patterns in modernprogramming languages, software, and userinterface (UI) frameworks. Most programming

330

languages use observers within their internalapplication programming interfaces (APIs), andJava is no exception. But Java EE goes furtherthan most and provides a defaultimplementation of the observer pattern, sodevelopers can use this pattern withoutimplementing it from scratch. This chapterfocuses on Java’s default implementation of theobserver pattern: where it is used, howobservers are implemented via annotations inJava EE, and how observers can be madetransaction sensitive.

WHAT IS AN OBSERVER?The idea behind the observer pattern is that anobject that changes its state can inform otherobjects that a change has occurred. In thelanguage of the design pattern, the object thatchanges its state is called the subject, whereasthose objects that receive notification of thechange are called the observers. Therelationship is one to many, with the subjecthaving many observers.

Imagine a chat application that automaticallyrefreshes every second so it can check for newmessages. Also imagine that it has a chat roomfeature allowing many people to chat together.Each of these chat clients regularly checks withthe server to see if there has been a newmessage posted by one of the other clients. Asyou can imagine, this is not very performance

331

friendly. Would it not make much more sense ifthe newly sent message was “pushed” to allsubscribed clients? It would certainly be moreefficient. The observer pattern can solve thisproblem. Here, the observer would be the chatserver, and each client would be a subject. Theserver would be registered with each client, andwhen the client posts a new message (a changein state of the subject), the subject would call amethod on the server to notify it of the newmessage. Then the server would call a methodon all its registered clients and send themessage to each one.

NOTE The observer pattern is also referredto as the Hollywood principle, whose mottois “don’t call us; we’ll call you.” This is notsurprising; most Hollywood agents wouldprefer to call clients for a new role ratherthan being hounded by clients calling them.This system works well because there’s nevera perfect time to call an agent to check aboutan available job. You’ll likely either miss outon a job if jobs arrive more frequently thanyou’re calling, or you’ll be seen as obnoxiousif you’re calling more often than jobs arrive.

With the help of the observer pattern, anagent calls appropriate clients just as a newjob opens, without losing time or wastingresources.

332

Description

The GoF1 book states that the observer pattern“defines a one-to-many dependency betweenobjects so that when one object changes state,all its dependents are notified and updatedautomatically.” The Head First DesignPatterns2 book gives the example of a weathermonitoring application that sends a noticewhen temperatures change. The observerpattern is based on the principle of inheritanceand is one of the behavioral design patterns.

To be an observer, each concrete observerimplementation needs to share a similarinterface. The subject lets each observer additself to a registry. When the subject changes,the observer calls each subject’s registeredimplementation to notify the observer about thechanges.

This is an efficient implementation becauseonly one call happens for each observer at thetime of the change. A naive solution such asregularly checking the subject may produce anunlimited number of calls from differentobservers even though there had been nochange to the object observed.

The observer pattern is not that different from anews subscription. Objects that want tosubscribe to changes on another object registerthemselves to receive news of those changes.

333

Rather than checking the target object, theseobjects are called when there is a change.

UI Frameworks are another place whereobservers are heavily used, although this ismore related to desktop applications, notenterprise applications. In the context of UIframeworks, the observer pattern is oftenreferred to as the listener pattern. Essentially,these patterns are the same. Button clicklisteners, drag drop handlers, and value changelisteners all rely on an implementation of theobserver pattern.

Almost all web frameworks are built on themodel-view-controller pattern, which also usesthe observer pattern internally. See Chapter 15,“Model View Controller Pattern,” for moredetails.

WAR STORY

For a long time, part of my daily job has beento mentor interns and fresh graduates. Thiswar story goes back to a talented intern I hadthe chance to work with. This brightelectronics graduate had more experiencewith hardware and structural programmingthan object-oriented languages; therefore,she had little knowledge of design patterns.

334

She had just completed a successfulArduino-based project.3

We started developing an Androidapplication that used Android’s built-in facedetection feature to detect whether the userwas in front of the device. Coming from anArduino project, the intern’s first approachwas to create a loop to query the camera andsee if it had detected a new face. This loopwas running in the main application thread,so it was blocking on the application.

After realizing that she had locked the UIthread, she decided to create a separatethread to perform the face detection job. Shewas using the “if the only tool you have is ahammer, every problem looks like a nail”approach.4 We chatted for a while about howthe Arduino application was structured. Onthe Arduino, the whole application was a loopthat we wanted to keep running until westopped it, and all program features werehandled in that loop. However, our Androidapplication had a different structure. Theapplication needed to be informed of whenthere was a face detected rather thanquerying the camera to see if a face had beendetected. Once this graduate understood howobservers work, she didn’t have muchdifficulty implementing the pattern because

335

the Android system was already built on theobserver pattern. All she needed to do wasadd the appropriate listener class andperform whatever function she needed whena face was detected.

Observer Class DiagramAs can be seen from Figure 11.1, the observerpattern introduces an Observer interface thatall concrete observers must implement. Thisinterface has just one method that is called bythe subject to notify the observers that there hasbeen a change in state. Each subject holds a listof registered observers and calls thenotifyObservers method to inform theregistered observers about any updates orchanges in the subject. It has methods forregistering and unregistering observers.

Figure 11.1 Class diagram of the observerpattern

336

IMPLEMENTING THE OBSERVERPATTERN IN PLAIN CODEJava provides an out-of-the-boximplementation of the observer pattern. Byimplementing the Observer interface andextending the Observable class, developerscan easily implement the observer pattern.

The first thing you need to do is create a classthat extends the Observable class. In Listing11-1, a news agency informs several types ofsubscribers when a new story is published. Thesubscriber may introduce its own behavior afterreceiving an update. Listing 11-2 provides aninterface for publishing the observable class.

LISTING: 11-1: The news agencyimplementing the observable interface

packagecom.devchronicles.observer;

import java.util.ArrayList;import java.util.List;import java.util.Observable;import java.util.Observer;

public class NewsAgencyextends Observable implements

337

Publisher {

private List<Observer>channels = new ArrayList<>();

public void addNews(StringnewsItem) {

notifyObservers(newsItem);}

public voidnotifyObservers(StringnewsItem) {

for (Observer outlet :this.channels) {

outlet.update(this, newsItem);}

}

public voidregister(Observer outlet) {

channels.add(outlet);}

}

338

LISTING: 11-2: The Publisherinterface

packagecom.devchronicles.observer;

public interface Publisher {}

Next, you need to create the class that observesthe NewsAgency for changes. This observermust implement the Observer interface as inListing 11-3.

LISTING: 11-3: Concrete observer

packagecom.devchronicles.observer;

import java.util.Observable;import java.util.Observer;

public class RadioChannelimplements Observer {

@Overridepublic void

update(Observable agency,Object newsItem) {

339

if (agency instanceofPublisher) {

System.out.println((String)newsItem);}

}}

Finally, you must register the RadioChannelobserver with the NewsAgency observable andcreate some news.

// Create the observer andsubjectNewsAgency newsAgency = newNewsAgency();RadioChannel radioChannel = newRadioChannel();

// Register the observer withthe subjectnewsAgency.register(radioChannel);

// Now add some news headlinesnewsAgency.addNews("Breakingnews: Life found on Mars");newsAgency.addNews("Update:Earth invasion imminent");newsAgency.addNews("Just in:

340

Hail to our new Martianoverlords");

The output in the console should be as follows:

Breaking news: Life found on MarsUpdate: Earth invasion imminentJust in: Hail to our new Martianoverlords

Notice that you can register many observerswith the NewsAgency and receive updates.Perhaps a TVChannel observer or anInternetNewsChannel observer canregister to receive updates from theNewsAgency. In addition, you can have otherPublishers (or any other type of object thatimplements Observable) issue updates toany observer that wants to register itself toreceive news. These observers can check thetype of the Observable and process theupdate according to its source.

One significant drawback of implementing theobserver pattern in this way is that you have toextend the Observable class. This forces theuse of a class hierarchy that might not bedesirable. Because you cannot extend morethan one class in the single-inheritance world ofJava, this way of implementing the observerpattern restricts the inheritance design. Youcan’t add the Observable behavior to an

341

existing class that already extends anothersuperclass, thus restricting its reuse potential.

But don’t despair. You can also implement theobserver pattern by “hand,” without using theinternal Observer and Observableinterfaces, by following the given class diagram.However, because this book is focused on JavaEE, this implementation is left for you to playwith.

IMPLEMENTING THE OBSERVERPATTERN IN JAVA EEAlthough Java had built-in support for theobserver pattern from inception, Java EE offersan easier implementation via the @Observesannotation andjavax.enterprise.event.Event<T>interface. Any method annotated with@Observes listens for events of a certain type.When it “hears” such an event, the parameter ofthe observer method receives an instance of thetype and then executes the method.

The @Observes annotation lets any methodlisten for any event to be fired with the markedobject type. Listing 11-4 is a simple example of abean that fires an event of type String andanother bean that listens for events of that typefrom our bean.

342

LISTING 11-4: The observable servicebean

packagecom.devchronicles.observer;

import javax.ejb.Stateless;importjavax.ejb.TransactionAttribute;importjavax.ejb.TransactionAttributeType;importjavax.enterprise.event.Event;import javax.inject.Inject;

@Stateless@TransactionAttribute(TransactionAttributeType.REQUIRED)public class EventService {

@Injectprivate String message;

@InjectEvent<String> event;

public void startService(){event.fire("Starting

service " + message);}

}

343

The container injects an Event object of typeString into the event instance variable ofthe EventService class. This forms part ofthe message when the to fire Stringobject is fired. This instance variable Messageobject is a String which may be produced by afactory. (See Chapter 6, “Factory Pattern,” formore information about the factory designpattern injected to the EventService class.) Tomake this example work without creating afactory even simpler, you can just define anyString constant to the variable called messageand remove the @Inject annotation asfollows.

private String message ="produced message";

Now the observable part is completed, so it istime to create an observer that listens for yourString events. The addition of the@Observes annotation to the methodsignature marks the method as an observer ofevents of the type it precedes. In this case, the@Observes annotation precedes the typeString and thus listens for events of that type.The @Observes annotation followed by anobject type does the magic and lets theannotated method observe the fired event of thegiven type.

344

In Listing 11-5, the @Observes annotation hasbeen added to the serviceTrace methodsignature, which marks the method as anobserver for String events. When an event oftype String occurs, the serviceTracemethod receives the object that the eventproduced via its parameter. serviceTracecan then manipulate the String object as itwants. In this case, it prints the message to theconsole.

LISTING 11-5: The observer bean

packagecom.devchronicles.observer;

import javax.ejb.Stateless;importjavax.enterprise.event.Observes;

@Statelesspublic class TraceObserver {

public voidserviceTrace(@Observes Stringmessage){

System.out.println("Servicemessage: " + message);

345

}}

If you run the server and invoke the startservice method, you will realize howmagically a string will be injected to theEventService class, and then a String event isfired “where it will be coughed (observed)” bythe serviceTrace method of theTraceObserver class, and a message isprinted to the console. Surprisingly, this is allthat you need to implement the observerpattern in Java EE without furtherconfiguration.

Although in real-world scenarios you probablywouldn’t be firing and observing plain stringsbut rather your own objects that would beobserved by their type, it is still quite easy todifferentiate between the same object types ofobjects and set up different observers to listenfor them.

You are now going to look at an example inwhich you use Qualifiers to disambiguateString objects. You have seen how this can beeffective when implementing a factory patternthat produces different implementations of thesame type of object.

346

In Listing 11-6, you start with the code thatdisambiguates your Strings.

LISTING 11-6: The annotationQualifier interface

packagecom.devchronicles.observer;

importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;import javax.inject.Qualifier;

@Qualifier@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.FIELD,ElementType.PARAMETER})public @interface MessageEvent{

Type value();

enum Type{ SERVICE,PARAMETER }

347

The interface preceding class defines aMessageEvent qualifier and two enum types(SERVICE and PARAMETER) that you will useto act as annotation to mark the strings to befired by the event instances.

importcom.devchronicles.observer.MessageEvent.Type;

@Stateless@TransactionAttribute(TransactionAttributeType.REQUIRED)public class EventService {

@Injectprivate String message;

@Inject@MessageEvent(Type.SERVICE)

Event<String> serviceEvent;

@Inject@MessageEvent(Type.PARAMETER)

Event<String> parameterEvent;

public void startService(){

serviceEvent.fire("Startingservice "+message);

parameterEvent.fire("-d-p");

}

348

To use the Qualifiers, you just add theMyEvent annotation to the relevant injectedinstance with the desired enum type inparenthesis. Then you later fire the events fromwithin the startService method, just as youdid before in the previous example. The boldparts code lines are all you have added to theprevious example in the previous listing.

Now you’ll add the annotations to the observerpart. As you did before, you just have to add theQualifiers to the relevant @Observesannotation.

importcom.devchronicles.observer.javaee.MessageEvent.Type;

@Statelesspublic class TraceObserver {

public void serviceTrace(@Observes

@MessageEvent(Type.SERVICE)String message) {

System.out.println("Servicemessage: " + message);

}

public void parameterTrace(?@Observes

@MessageEvent(Type.PARAMETER)String message) {

349

System.out.println("withparameters: " + message);

}

Firing and observing your own object types iseven simpler. The object type is unique, and it’snot necessary to create your own annotationqualifiers; you can use the object instead.

Observable events are transactional and aredelivered in the transactional phase that youdefine for that event. That may be before orafter the transaction has completed or after asuccessful or unsuccessful transaction.

Now you’ll see this in action. In Listing 11-7, youdefine three observer methods that specify atransaction phase during which the observerslisten for events of type String.

LISTING 11-7: The Transaction eventobserver

packagecom.devchronicles.observer;

importjavax.enterprise.event.Observes;importjavax.enterprise.event.TransactionPhase;

350

public classTransactionEventObserver {

public voidonInProgress(@Observes Stringmessage) {

System.out.println("Inprogress message: " + message);

}

public void onSuccess(@Observes(during =

TransactionPhase.AFTER_SUCCESS)String message) {

System.out.println("Aftersuccess message: " + message);

}

public void onFailure(@Observes(during =

TransactionPhase.AFTER_FAILURE)String message) {

System.out.println("Afterfailure message: " + message);

}

public void onCompletion(@Observes(during =

351

TransactionPhase.AFTER_COMPLETION)String message) {

System.out.println("Aftercompletion message: " +message);

}

}

There are five transitional phases:BEFORE_COMPLETION,AFTER_COMPLETION, AFTER_SUCCESS,AFTER_FAILURE, and the defaultIN_PROGRESS. In Listing 11-7, we have notimplemented BEFORE_COMPLETION. InListing 11-8 we implement a class thatdemonstrates event firing in successful andfailure scenarios.

LISTING 11-8: Provoke success andfailure scenarios

packagecom.devchronicles.observer;

importjavax.annotation.Resource;

352

importjavax.ejb.SessionContext;import javax.ejb.Stateless;importjavax.ejb.TransactionAttribute;importjavax.ejb.TransactionAttributeType;importjavax.enterprise.event.Event;import javax.inject.Inject;

@Stateless@TransactionAttribute(TransactionAttributeType.REQUIRED)public class Children {

@ResourceSessionContext sc;

@InjectEvent<String> message;

int[] children = newint[3];

public voidgetSixthChild() {

try {int sixthChild =

children[5]; // Throws anIndexOutOfBounds Exception

353

} catch (Exception e) {

message.fire("Rollback eventoccurred.");

System.out.println("Exceptioncaught.");

sc.setRollbackOnly();}

}

public voidgetThirdChild() {

int thirdChild =children[2]; // Succeeds

message.fire("Successfulevent");

}

}

The Children class simulates a successfultransaction in the getThirdChild methodand an unsuccessful transaction in thegetSixthChild method by causing anIndexOutOfBoundsException.

You’ll examine each method to see how theevents are observed. The getThirdChild

354

method fires a String event, passes it themessage Successful event, and thenfinishes successfully. The output from callingthis method follows:

In progress: Successful eventAfter completion message:Successful eventAfter success message:Successful event

The onInProgress method is invokedimmediately when the event is fired and whilethe transaction is still in flight. The other twomethods—onCompletion andonSuccess—must wait until the transactionreaches the AFTER_COMPLETION andAFTER_SUCCESS phases, respectively, beforethey can execute.

Next you’ll look at the getSixthChildmethod, which fails by causing anIndexOutOfBoundsException. Theoutput that results from calling this methodfollows:

In progress: Rollback eventoccurred.Exception caught.After completion message:Rollback event occurred.After failure message: Rollbackevent occurred.

355

As before, the onInProgress method isinvoked immediately, and the onCompletionand onFailure methods must wait until themethod completes. Once the onInProgressmethod outputs the message Exceptioncaught and the transaction is marked forrollback by calling the SessionContextmethod setRollbackOnly, theonInProgress method completes, and youcan execute your observers. TheonCompletion method is executed, followedby the OnFailure method.

The setRollbackOnly method marks thecurrent transaction for rollback, so it can neverbe committed. This action triggers thetransaction into the AFTER_FAILURE phaseand invokes the onFailure method.

Observers can also be given conditionalbehavior, although it’s limited to being notifiedif an instance of the bean that defines theobserver method already exists in the currentcontext. The observer method is called only ifan instance exists. To define an observermethod as conditional, add notifyObserver= Reception.IF_EXISTS as an argumentto the @Observes annotation.

importjavax.enterprise.event.Reception;

356

public void addMember (@Observes(notifyObserver =

Reception.IF_EXISTS) Stringmessage){

// Implementation code.}

The default behavior is to create an instance if itdoes not exist.

WHERE AND WHEN TO USE THEOBSERVER PATTERNThe observer pattern, which can unleash hugeperformance gains, is an effective way topromote loose coupling and change thedirection of calling/listening.

When designing your application or refactoringanother’s code, watch out for unnecessary andtime interval-based method executions, whichcan be good candidates for implementing theobserver pattern.

In the Java EE realm, you can migrate existingcode to the observer pattern without too muchhassle. Java EE observers are usuallyaccompanied by dependency injection, whichuses @inject, and factories, which use@produces.

The observer pattern’s greatest strength, thedecoupling of classes, is also its greatestweakness. As control of the observable moves to

357

the observer, you lose track of the application’sworkflow. Vision becomes obscured as oneevent triggers another. A complicatedimplementation of the observer pattern can be anightmare to debug, so it is recommended thatyou keep the implementation simple. Avoidmultiple layers of observers; using just onelayer (or a few) is ideal.

To help future and present developersdetermine the purpose of your code, the nameof an observer should reflect its purpose. Inaddition, you should incorporate the reason forthe observation into the name of its methods,expressing the purpose of the class.

In the Java EE realm, existing code can bemigrated to the observer pattern without muchhassle. Java EE observers are usuallyaccompanied by dependency injection (@inject)and factories ?(@produces). The heavy andunnecessary use of observers may introducehard to follow and debug systems. However,since most developers are used to observersfrom UI or web frameworks, they usually havean instinct to use in the right context most ofthe time.

Whenever you see a resource subject to changeand callers trying to capture the data fromsubject, never hesitate to use the observerpattern. Transaction-sensitive observers offerfunctionality that was not easily available inearlier versions. In the BEFORE_COMPLETION

358

phase, you can cancel the current transaction byinvoking the setRollbackOnly method,thus allowing nontransactional operations to beperformed within a transactional phase. If anexception is thrown, the entire transaction canbe rolled back.

During the IN_PROCESS phase, which spansthe entire transaction, observable events can befired and observed immediately. This can beimplemented as a type of progress monitor orlogger.

A call to an observer method blocks the eventemitter and is synchronous but can be madeasynchronous by annotating the observermethod @Asynchronous. (See Chapter 9,“Asynchronous,” for more information abouthow to use this annotation.) You should takecare when making observers of theBEFORE_COMPLETION phase asynchronousbecause the setRollbackOnly method isineffective, and the transaction will not berolled back. The asynchronous method occursin a new transaction.

SUMMARYYou have seen how Java’s core observerpattern’s implementation has advanced in JavaEE 7 and how it can be made sensitive to thetransactional phase of the events that itobserves. Its implementation completely

359

decouples business logic from the observer,leaving only the event type and qualifier toconnect them. This has raised the concern thatvision over the relationship is lost, although thiscan be mitigated by appropriately naming theclass and methods and illustrating therelationship in the class’s documentation.

The transactional phase sensitivity has addedanother dimension to the observer pattern. Itprovides integration between the observermethods and the transaction, allowing rollbacksto be invoked.

EXERCISES

List as many implementations of theobserver pattern as you can that you wouldfind in the Java language.

Create an example that usesnotifyObserver =Reception.IF_EXISTS as an argumentto the @Observes annotation.

Use the observers transitional sensitivity tomonitor the progress of a transaction andlog the result of the transaction (success orfailure).

360

NOTES

1. Design Patterns: Elements of ReusableObject-Oriented Software (Addison-Wesley,1994): Erich Gamma, Richard Helm, RalphJohnson, John Vlissides.

2. Head First Design Patterns (O’Reilly, 2004):Eric Freeman, Elisabeth Robson, Bert Bates,Kathy Sierra.

3. A small hardware board for maker projects:http://www.arduino.cc.

4. Abraham Maslow (1908–1970) AmericanPsychologist.

361

12Data Access PatternWHAT’S IN THIS CHAPTER?

Discussion regarding the origins of the dataaccess pattern

Examination of the related data transfer object

How the DAO and factory pattern worktogether

An introduction to the JPA and ORM

A simple implementation of the DAO

An improved implementation using generics

A discussion regarding the role of DAO inmodern Java EE

WROX.COM CODE DOWNLOADS FORTHIS CHAPTER

The wrox.com code download for this chapter isfound at www.wrox.com/go/?projavaeedesignpatterns on theDownload Code tab. The code is in the Chapter12 download and individually named accordingto the names throughout the chapter.

It is unimaginable to think of an enterpriseapplication that does not in some way interactwith a data source. The data source may be a

362

relational, object-oriented or NoSQL database,a Lightweight Directory Access Protocol (LDAP)repository, a file system, a web service, or anexternal system. From whatever source the datacomes, the enterprise application must interactwith it and perform basic create, retrieve,update, and delete (CRUD) operations. Almostall servers use such data sources to persistsessions or long-running processes seamlessly.

The way in which you use data sources can varysubstantially, and their implementation candiffer widely. There are different SQL dialects,such as Postgre SQL and Oracle. The simpleobjective of the data access object (DAO)pattern is to encapsulate access to the datasource by providing an interface via which thevarious layers can communicate with the datasource.

This chapter discusses the original problem thatthe DAO solved and its relevance in modernJava EE applications. Also examined are therole of the related data transfer object (DTO)and how it and the factory pattern fit togetherwith the DAO. In addition, this chapter coversthe use of the JPA and ORM in the context ofthe DAO. You’ll see an implementation of theDAO and how to improve it by using generics.Finally, you will read about the changed role ofthe pattern and why it is still a valid designpattern.

363

WHAT IS A DATA ACCESSPATTERN?The original solution that the DAO patternproposed was defined in the book Core J2EEPatterns: Best Practices and Design Strategies1

as follows:

Use a data access object (DAO) to abstractand encapsulate all access to the datasource. The DAO manages the connectionwith the data source to obtain and storedata.

The problem that was solved with theabstraction and encapsulation of the datasource was to guard against the applicationbeing dependent on the data sourceimplementation. This decoupled the businesslayer from the data source. It was thought thatif the data source changed, the decouplingwould reduce or negate any impact. However,in reality, the data source rarely changed—noteven between vendors of the same source typesuch as between Postgre and MS SQL. It is hardto imagine that a decision would be made tomigrate an SQL data source to an XML flat filesystem, LDAP repository, or web service. Thissimply didn’t happen. So what value does theDAO pattern have in modern Java EE? Do youreally need this pattern?

The DAO pattern is still a valuable pattern, andits original solution is still valid, although the

364

motivation for its implementation has changedin its emphasis. Rather than guarding againstthe impact of an unlikely change in the datasource type, the value is in its mockability andtestability and its use in structuring the codeand keeping it clean of data access code. Thereis still value in using it as a way to encapsulatelegacy data storage systems and to simplifyaccess to complex implementations of datasources. However, these are more likely to becorner and exceptional cases.

The DAO pattern encapsulates CRUDoperations in an interface that is implementedby a concrete class. This interface can bemocked and therefore easily tested, avoiding aconnection to the database. Testing is improvedbecause writing tests using mocks is easier thanintegrating tests with a live database. TheDAO’s concrete implement uses low-level APIssuch as JPA and Hibernate to perform theCRUD operations.

Data Access Class DiagramFigure 12.1 shows the class diagram of the DAO,demonstrating the interaction between theclient and the DAO and the DTO. Not shown isthe optional factory that produces the DAOinstance.

365

Figure 12.1 Class diagram of the data accesspattern

OVERVIEW OF THE DATAACCESS PATTERNThe implementation of the DAO patterninvolves several components:

The DAO interface

The concrete implementation of the DAOinterface

The DAO factory

The DTO

The factory, interface, and DTO are optionalcomponents, not required components, but youwill see these two patterns used with the DAOpattern. The factory pattern is discussed infurther detail in Chapter 6, “Factory Pattern.”

Data Transfer Object PatternThe DTO carries the data retrieved from orpersisted to the database across logical layers.For example, to transfer a list of User objects

366

retrieved from the data access layer to the weblayer, the service layer would be responsible fortransferring from a DAO to a DTO.

NOTE The DTO is also referred to as theValue Object.

The solution that the DTO pattern proposes isdefined in Core J2EE Patterns: Best Practicesand Design Strategies as follows:

Use a Transfer Object to carry multiple dataelements across a tier.

The DTO reduces remote requests across thenetwork in applications that make manymethod calls to enterprise beans, resulting inimproved performance. Sometimes not all thedata retrieved from the database is required onthe web layer or whatever other layer requiresthe use of data. So the DTO reduces to just theessential data that the layer requests, therebyoptimizing the transfer of data across tiers. Thischapter does not go into detail regarding theDTO. It’s recommended that you read the DTOchapter in the Core J2EE Patterns: BestPractices and Design Strategies book.

Java Persistence Architecture API andObject ?Relational MappingThe Java Persistence API (JPA) manages theapplication’s interactions with the data source.

367

It specifies how to access, persist, and managedata between the application’s objects and thedata source. JPA itself cannot perform CRUD orother data-related operations; it’s just a set ofinterfaces and implementation requirements.However, a compliant Java EE applicationserver must provide support for its use.

The JPA specification replaces the EJB 2.0Container-Managed Persistence (CMP) entitybeans specification, which was heavyweight andcomplex. CMP received an adverse reactionfrom many in the developer community thatresulted in the wide adoption of proprietarysolutions such as Hibernate and TopLink. Thisprompted the development of JPA (releasedwith EJB 3.0), which aimed to bring togetherCMP, Hibernate, and TopLink and seems tohave been largely successful.

At the heart of JPA is the concept of an entity.For those of you familiar with CMP, this is whatwas referred to as an entity bean. An entity is ashort-lived object that is capable of beingpersisted in a database—not as a serializedobject but as data. It is a Plain Old Java Object(POJO) whose members are annotated andmapped to a field in the data source. To betterunderstand how this is represented in code,you’ll go through a code snippet.

In the following snippet, you represent aMovie entity class as a POJO that’sappropriately annotated:

368

@Entitypublic class Movie {

@Id @GeneratedValueprivate Long id;private String title;private String description;private Float price;public Movie(){}// For brevity, the getters

and setters have been left out.

}

As you can see, this is a simple class with justthree annotations. The @Entity class levelannotations indicate that this class should betreated as an entity class, and the @Id and@Generated annotations mark the idmember as an auto-generated identificationfield. This means that when the entity ispersisted, the id field is automaticallygenerated according to the rules ofauto-generated fields laid down by the datasource. If the data source is a database, then allfields in this entity are persisted to a tablecalled Movie. No other annotations arenecessary to indicate which fields are persisted.It is convention over configuration that allfields are persisted unless otherwise annotated.This mapping is referred to as Object RelationalMapping (ORM). It is beyond the scope of this

369

chapter to discuss in detail JPA and ORM, so itis recommended that you read The Java EE 7Tutorial: Part VIII Persistence.2

IMPLEMENTING THE DATAACCESS PATTERN IN JAVA EENow you’ll go through an example to see how toimplement the DAO in Java EE. You are goingto use the movie rental domain and a relationaldatabase as the data source. You’ll start bycreating a movie entity class and annotating itwith appropriate JPA annotations, as shown inListing 12-1.

LISTING 12-1: The movie entity class

packagecom.devchronicles.dataaccessobject;

import java.io.Serializable;importjavax.persistence.Entity;import javax.persistence.Id;importjavax.persistence.NamedQuery;

@Entitypublic class Movie implementsSerializable {

370

private static final longserialVersionUID =-6580012241620579129L;

@Id @GeneratedValueprivate int id;private String title;private String description;private int price;//Some runtime value which//does not need to be

persisted@Transientprivate int runtimeId;

public Movie() {}

public int getId() {return this.id;

}

public void setId(int id) {this.id = id;

}

public String getTitle() {return this.title;

}

public void

371

setTitle(String title) {this.title = title;

}

public StringgetDescription() {

returnthis.description;

}

public voidsetDescription(Stringdescription) {

this.description =description;

}

public int getPrice() {return this.price;

}

public void setPrice(intprice) {

this.price = price;}public int getRuntimeId() {

return this.runtimeId;}

public void

372

setRuntimeId(int runtimeId) {this.runtimeId =

runtimeId;}

}

The class in Listing 12-1 is a simple POJO withappropriate JPA annotations. As brieflymentioned earlier, the @Entity class levelannotation indicates that this class should betreated as an entity class and should bemanaged by the persistence provider. Theentity class must have a no-arg constructor thathas to be public or protected, although it mayhave other constructors. It must be a top-levelclass, which means that it cannot be an enum oran interface, and it must not be final. Also, noneof the persistent instance variables or setter/getter methods of the entity class can be final.The entity class must implement theSerializable interface.

You have annotated the id member with @Idand @GeneratedValue, which marks the idmember as an auto-generated primary key. Allentities must have a primary key, which can bea single member or a combination of members.

The primary key can be one of the followingtypes:

373

Primitive Java types—byte, char, short,int, long

Wrapper classes of primitive Java types—Byte,Character, Short, Integer, Long

Arrays of primitive or wrapper types—long[],Long[], and so on

Java types—String, BigInteger, Date

All members of the entity class areautomatically mapped to fields of the samename in the movie table unless they’reannotated with @Transient. This means thatthe id member maps to the id field in themovie table, the title member maps to thetitle field in the movie table, and so on.

Next, in Listing 12-2, you create the DAOinterface. This should define the basic CRUDmethods and any other methods that mightprove useful.

LISTING 12-2: The DAO interface

packagecom.devchronicles.dataaccessobject;

import java.util.List;

public interface MovieDAO {

374

public void addMovie(Moviemovie);

public Movie getMovie(intid);

public voiddeleteMovie(int id);

public voidupdateMovie(Movie movie);

public List<Movie>getAllMovies();}

Now for the concrete implementation of theDAO interface shown in Listing 12-3. Here youimplement the CRUD operations. Notice thatthe constructor accepts an instance of theEntityManager. This instance is associatedwith a persistence context that is defined inpersistence.xml. The EntityManagerAPI provides create, remove, and persistencefunctionality as well as the ability to createqueries. Any transient field would not be savedor retrieved from the database so expect thedata on the transient field to be reset each timethe object is re-created.

375

LISTING 12-3: The implementation ofthe DAO interface

packagecom.devchronicles.dataaccessobject;

import java.util.List;importjavax.persistence.EntityManager;

public class MovieDAOImplimplements MovieDAO{

private EntityManager em;

publicMovieDAOImpl(EntityManager em){

this.em = em;}

@Overridepublic void addMovie(Movie

movie) {em.persist(movie);

}

@Overridepublic Movie getMovie(int

id) {

376

returngetAllMovies().get(id);

}

@Overridepublic void

deleteMovie(int id) {

em.remove(getMovie(id));}

@Overridepublic void

updateMovie(Movie movie) {em.merge(movie);

}

@Overridepublic List<Movie>

getAllMovies() {return

em.createQuery("SELECT m FROMMovie m", Movie.class)

.getResultList();}

}

In Listing 12-4, you create the DAO factory. TheEntityManager is created and injected intothis class and then passed as a constructor

377

argument to the createMovieDAO methodthat creates the DAO object. The factory patternis discussed in more detail in Chapter 6, soplease refer to it for more information.

LISTING 12-4: The DAO Factory

packagecom.devchronicles.dataaccessobject;

importjavax.enterprise.context.ApplicationScoped;importjavax.enterprise.inject.Produces;importjavax.persistence.EntityManager;importjavax.persistence.PersistenceContext;

@ApplicationScopedpublic class MovieDAOFactory {

@PersistenceContext(unitName="moviePU")private EntityManager em;

@Producespublic MovieDAO

createMovieDAO() {return new

378

MovieDAOImpl(em);}

}

The list of entities in your application is called apersistence unit, and the application’spersistence unit is defined in thepersistence.xml configuration file. Thisfile should reside in your application’sMETA-INF directory. The significant elementsof persistence.xml follow:

Persistence unit name—You can give thepersistence unit a name so that you can defineseveral persistence units and then select themat run time.

Persistence unit transaction type—In aJava SE application, the default transactiontype is RESOURCE_LOCAL, while in a Java EEenvironment, the transaction type is JTA. Thismeans that the entity manager participates inthe transaction.

Provider—This element identifies the classthat provides the factory for creating theEntityManager instance.

Class—The entity classes used in theapplication should be listed in the classelement.

379

Property—Additional properties can bespecified, such as database connectionproperties and persistence provider propertieslike options to drop-create new tables.

The EntityManager is associated with apersistence context that is defined in thepersistence.xml in Listing 12-5.

LISTING 12-5: The persistence.xml

<?xml version="1.0"encoding="UTF-8"?><persistence version="2.1"

xmlns="http://xmlns.jcp.org/xml/ns/persistence"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistencehttp://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">

<persistence-unitname="moviePU"transaction-type="JTA">

<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider><jta-data-source>jdbc/

380

sample</jta-data-source>

<class>com.devchronicles.dataaccessobject.Movie</class></persistence-unit>

</persistence>

The specific data source is defined in thispersistence.xml file. In this case, you havedefined a Derby database using the eclipse linkprovider. You have defined the transaction typeas JTA because this is a Java EE applicationimplementation, and you have specified theclass entity to becom.devchronicles.dataaccessobject.Movie.

Finally, you need to inject the DAO that youhave created and use it. The client in Listing12-6 gets an instance of the DAO injected anduses it to retrieve all movies.

LISTING 12-6: The client

packagecom.devchronicles.dataaccessobject;

import javax.ejb.Stateless;import javax.inject.Inject;import java.util.List;

381

@Statelesspublic class Client {

@InjectMovieDAO movieDAO;

public List<Movie>getAllMovies() {

returnmovieDAO.getAllMovies();

}

}

The preceding implementation of the DAO issimplistic and can be improved upon in severalways.

Type-Safe DAO ImplementationOne way to improve upon the DAOimplementation is to make the DAO interfacetype-safe. This allows a type-safe DAO that asubinterface can implement for each entity typeyou want to persist. A base DAO might look likethe code in Listing 12-7.

382

LISTING 12-7: Type-safe base DAO

packagecom.devchronicles.dataaccessobject;

import java.util.List;

public interface BaseDAO<E, K>{

public void create(Eentity);

public Movie retrieve(Kid);

public void update(Eentity);

public void delete(K id);}

The first type parameter, E, is used to representthe entity, whereas the K type parameter is usedas the key. A subinterface that would definemethods specific to that entity could thenextend the BaseDAO interface.

In Listing 12-8, you create an interface thatextends the BaseDAO and defines a methodthat returns a list of all movies.

383

LISTING 12-8: Specific movieimplementation of the base DAO

packagecom.devchronicles.dataaccessobject;

import java.util.List;

public interface MovieDAOextends BaseDAO<Movie,Integer>{

public List<Movie>findAllMovies();

}

A concrete class would implement this interfaceand provide code for each method.

WHERE AND WHEN TO USE THEDATA ACCESS PATTERNSome have argued that the DAO is no longer auseful pattern because you can easily invoke theEntityManager directly. This is a reasonableargument because the EntityManagerprovides a clean API that abstracts away theunderlying data access layer. It is alsoreasonable to suggest that the likelihood of a

384

change in the data provider is remote, whichmakes the abstraction that the DAO providesless purposeful. Although these arguments havemerit, it is still arguable that the DAO has itsplace in a well-designed Java EE application.(The place might not be where it was originallyintended, though.)

The value of extending the BaseDAO as shownin Listing 12-7 for each entity type is in theextensibility of each implementation. Methodsthat are specific to an entity can be writtenwhile maintaining a common interface. Youselect the DAO implementation once for eachentity rather than choosing the rightEntityManager method each time it isrequired to persist or retrieve data.

Named queries can be located within the entityto which they relate. This keeps the queries in alogical place, making maintenance easier. TheDAO allows for a uniformed and controlled dataaccess strategy because all access to the entity’sdata is required to go via the entity’s DAO. Itmaintains the principle of single responsibilitybecause only the DAO accesses andmanipulates the application’s data.

Don’t forget that even though it’s remote, thedata source might change. If it does, you’ll beglad that there is an abstraction on the datalayer.

385

SUMMARYThe DAO has its fans and detractors. Thedecision of whether to use the pattern in yourapplication should be based on the designrequirements of the application. Like allpatterns, its use for use’s sake is potentiallydangerous and could cause more confusionbecause over abstract obscures the purpose ofthe code. Ensure that you understand well thevarious implementations of the pattern andhow it interacts with the DTO and factorypattern.

EXERCISES

Write an interface and its implementationfor a movie order DAO. You can use theexamples in the text as a starting block.

Write a service façade and a DTO that usesthe MovieDAO.

NOTES

1. Core J2EE Patterns: Best Practices andDesign Strategies (Prentice Hall/SunMicrosystems Press, 2003): Deepak Alur,John Crupi, and Dan Malks.

2. The Java EE 7 Tutorial: Part VIIIPersistence.

386

http://docs.oracle.com/javaee/7/tutorial/doc/.

387

13RESTful Web ServicesWHAT’S IN THIS CHAPTER?

What REST is and what it does

The six constraints of REST

The Richardson Maturity Model of a REST API

How to design a RESTful API

Demonstrating REST in Action

How to implement REST in a Java EE

HATEOAS—The highest level in the RichardsonMaturity Model

WROX.COM CODE DOWNLOADS FORTHIS CHAPTER

The wrox.com code download for this chapter isfound at www.wrox.com/go/projavaeedesignpatterns on theDownload Code tab. The code is in the Chapter13 download and individually named accordingto the names throughout the chapter.

There is little doubt that you will have heard theterm REST. What is less certain is that you willunderstand exactly what it means and how it isimplemented. Many people who know nothingor very little about REST will tell you that your

388

site must be REST “compatible” and that,without REST, your site cannot possiblysurvive. REST is a buzzword to these people,but for those who know what REST is and whatbenefits it can offer, it’s much more than justanother buzzword. So what does REST reallymean, and where does it come from?

REST means REpresentational State Transferand is an architectural style of representing andtransferring data. It consists of a set of sixconstraints placed on data, components, andtheir interactions within a distributedhypermedia system (the Internet). It is not tiedto a protocol (although in almost all cases it isused with Hypertext Transfer Protocol[HTTP]), and it does not have a World WideWeb Consortium (W3C) standard. It is a set ofconventions, styles, and approaches that havebeen agreed upon over time by use andconvention.

The term REST was coined by Roy Fielding inhis 2000 doctoral dissertation titled“Architectural Styles and the Design ofNetwork-Based Software Architectures.”1 Sincethen, the REST concept has been widelyadopted by developers and architects such thatit has become an integral part of manylanguages and frameworks. For example, Rubyprovides a natural way to use RESTful routes,and the Spring framework provides a simplifiedway to implement Hypermedia As The Engine

389

Of Application State (HATEOAS), which is level3 of the Richardson Maturity Model of RESTsupport (more on this later).2

REST is usually referred to as an architecturalapproach rather than a design pattern.However, REST was developed against commonproblems faced in enterprise app, which is thesame idea behind the design patterns.

WHAT IS REST?REST means many things to many people, anddiscussions can become quite theoretical. Thischapter discusses it from the perspective of adeveloper who wants to implement a RESTfulapplication programming interface (API) for aforum site discussing movies.

IN THE WORDS OF ROYFIELDING

REST emphasizes scalability of componentinteractions, generality of interfaces,independent deployment of components, andintermediary components to reduceinteraction latency, enforce security, andencapsulate legacy systems.

The most practical way of thinking about RESTis as a style for formatting URIs that represents

390

resources (data) your application can provideand resources that it can store. What is meantby resources? In a forum website, you havemany resources, such as the site’s users and theusers’ posts. These resources are represented bynouns and combined with an HTTP method toform a RESTful uniform resource identifier(URI). For example, you can represent anaccount resource with the URI /accountsand combine it with the HTTP GET methodsuch that a request to this URI would return allaccounts. Likewise, you can represent anidentifiable account resource by appending thepost’s ID to the URI like so: /accounts/:id.A GET request to this URI returns the details ofthe account with the given ID. Not only can youget resource representations by using a RESTfulURI, you can create resources. To do this, youwould create a URI using the HTTP POSTmethod. For example, to create a new accountresource, you would send a POST request to theURI /accounts with a payload in the HTTPbody containing the data necessary to create theresource.

As you have gathered, a URI represents aresource on a remote server, and the method ofrequesting the resources (the HTTP method)implies certain actions on that resource.

It is tempting to map HTTP methods to create,retrieve, update, and delete (CRUD) actions (forexample, POST to Create and GET to Read).3

391

However, this is not in the spirit of REST anddoes not help in the understanding of resourcerepresentations. In fact, it’s more akin to aremote procedure call (RPC) patternimplementation, which is at level 0 on theRichardson Maturity Model. You are onlyinterested in implementing REST at the highestlevel: level 3, please refer to the section,“Richardson Maturity Model of REST API” forfull details.

A RESTful API is not about actions; it’s aboutnouns. These nouns represent resources. Soyou’ll learn about a post resource, a userresource, and an address resource as opposedto verbs such as getUser, addPost, anddeleteAddress. REST is different fromsimple object access protocol (SOAP) and RPC,which are about the actions you want toperform on the application’s data. In a RESTfulsense, you would call a URI with an appropriateHTTP method.

Each resource is identified by a URI. There maybe multiple ways to refer to the same resources,so you might be able to access the sameresource from different starting points. Forexample, you can obtain the resource thatrepresents a user by accessing the user directlyvia the URI GET /users/:id or by goingfrom one user to the list of users who followthat user and then to the user GET /user/:id1/followers/:id1. The representation

392

of the resource is not the actual resource itself;it’s a representation of the resource, and it isperfectly valid for the same resource to berepresented in different ways.

The resource representation flow isbidirectional between client and server andrepresents at least part of the resource state.When that happens, it contains just enoughdata to create, modify, or delete that resourceon the server.

Resource representations are typicallyJavaScript Object Notation (JSON) orExtensible Markup Language (XML), but theycan be any format, including a customrepresentation.

THE SIX CONSTRAINTS OF RESTAccording to Roy Fielding’s dissertation, a trulyRESTful architecture conforms to all but one ofthe stated constraints. This group of constraintsis called the REST style.

Client-ServerThe client-server constraint is based on theseparations of concerns principle and definesclearly the separation between the client andthe server. The constraint is simple andrequires a client to send a request and a serverto receive that request. The server may respondto the client’s request.

393

Uniform InterfaceThis constraint defines the interface betweenthe client and the server, stating that it shouldbe as generic and simple as possible. You havealready learned that a resource is arepresentation of the data, and the client doesnot have direct access to the data. Thisconstraint defines how that resource isrepresented by nouns and that the interface ismaintained by the creator of the actual datasystem. This is to ensure some degree ofconstancy of the interfaces over time. Theconstraint does not specify that theimplementation should use the HTTP protocol,but it is almost always based on HTTP. As youhave already seen, if you use the HTTPspecification, the URI is constructed from theresource nouns and the HTTP verbs.

StatelessThe server should not maintain client state. Inother words, each message/request isself-descriptive; it has enough information orcontext for the server to process that message.This implies that if there is state, it ismaintained on the client side. The advantage ofthis constraint is that it increases scalability,reliability, and visibility. The disadvantage isthat it decreases performance because messagesneed to be larger to maintain statelesscommunication.

394

CacheableThe server responses must be cacheable. TheRESTful interface should provide a mechanismfor marking messages as cacheable ornoncacheable. This can be implicit, explicit, ornegotiated and allows the client to reissue amessage if necessary.

Layered SystemThe client cannot assume direct access to theserver. The response may be a cached response,or it may retrieve the resource directly from theserver. This improves scalability because theremight be software or hardware between theclient and the server.

Code on DemandThis constraint defines a REST architecture asconsisting of hierarchical layers that are limitedto communicating with their immediateneighbors. This separation of concernssimplifies the architecture and isolatesdisparate and legacy components. The principlebenefit you receive is an increase in scalabilitybecause new components can be easilyintroduced and obsolete ones retired orreplaced. The drawback of this constraint is areduction in the system’s performance resultingfrom the increased indirection related to themultiple layer structure.

395

This constraint allows a client to download andexecute code from the server, which enables theserver to temporarily extend the client bytransferring logic. This may be in the form of aJavaScript snippet. The code on demandconstraint is the only optional one.

Violating any of these constraints (except codeon demand) means that the service is notstrictly RESTful. A constraint violation does notmean the service is not a viable and usefulimplementation, however.

RICHARDSON MATURITY MODELOF REST APIYou have already read about how a trulyRESTful API achieves level 3 of the RichardsonMaturity Model. Now you’ll look a little deeperand examine each level on the model.

The model, developed by Leonard Richardson,attempts to classify an API according to itsadherence to the constraints imposed by REST.The more compliant your implementation, thebetter it fares. There are four levels. The bottomis level 0, which designates the less compliantimplementation, and the top is level 3, which isthe most compliant and therefore the mostRESTful.4

396

Level 0: The Swamp of POX (Plain OldXML)This model uses HTTP as a transport protocolto invoke remote interactions. It does not usethe protocol to indicate an application state; itis usually just used to tunnel requests andresponses on one URI, such as /getUser,using only one HTTP method. This is a classicexample of an RPC model and is more akin toSOAP and XML-RPC than REST.

Level 1: ResourcesThis is where the model starts to be able todistinguish between different resources. It willtalk to different end points because each endpoint represents a different resource. It uses aURI like POST resources/123, but it stilluses just one HTTP method.

Level 2: HTTP VerbsAt this level, you implement full use of theHTTP verbs and combine them with yourresource nouns to provide the type of REST thathas been discussed so far in this chapter. Youtake full advantage of the features that HTTPoffers to implement your RESTful API.However, you still have not reached the level ofa truly RESTful API.

397

Level 3: Hypermedia ControlsAt this level, the model uses HATEOAS(Hypermedia As The Engine Of ApplicationState) to direct the application state. Theobjective of hypermedia controls is to advise theclient of what can be done next and to supplythe URIs necessary to perform the next action.You will see how this works and how toimplement HATEOAS later in this chapter.

DESIGNING A RESTFUL APIA well-designed RESTful API means awell-defined uniform interface. For this, athorough understanding of the HTTP methodsand response codes is important, and acomplete knowledge of the data structure ofyour application is needed. The objective is tocombine them into a simple, clean, andbeautiful resource URI.

WAR STORY

One of the companies I worked for had atradition that once a team completed aproject, it presented its project to the otherteams. It was at about the same time thatREST was getting popular. One of the teamsdecided to build a REST back end to serveboth the mobile and the web clients. We were

398

thrilled and listened intently to how theysuccessfully built a beautifully designedREST back end and how it was able to servedata for both systems. As the team’s leadstarted to give technical details about thesystem, we realized they were maintainingthe client state on the server side. Not at allRESTful.

I raised the issue and asked if that design wasreally following RESTful principles. Ofcourse, my words offended the projectarchitect, and he started showing us theREST API docs and how each client wouldwork with OAuth and passing parameters viauniform resource locators (URLs).Nevertheless, the system was relying onpreserving the state rather than transferringit.

Just like fashionistas, developers and systemdesigners love trends and want to looktrendy. However, without understanding theunderlying principles and determiningwhether they really address your concernsand problems, you may end up being theweird-looking guy who wanted to be trendybut failed to fully understand the technology.In their case, they had built a representativestate preserving (RESP?) back end instead ofREST.

399

You will soon learn the elements that make up aURI.

Resource NamingRESTful APIs are written for clients and shouldhave meaning for the clients of those APIs.When choosing nouns to name the resources,you should be familiar with the structure of theapplication’s data and how your clients arelikely to use them. There are no defined rules asto how you should name your resources, butthere are conventions that, if followed, can helpyou create a set of self-descriptive resourcenames that others intuitively understand.

Nouns Not VerbsYou must name the resources after nouns, notverbs or actions. The purpose of the resourcename is to represent the resource. The HTTPmethod describes the action to be performed.The next section covers the HTTP method inmore detail. To represent a single user resource,you would use the noun users to represent allusers and the user’s ID to identify the specificuser, like so: users/123456. An example of anon-REST and badly formed URI would beusers/123456/update, or it would includethe action in a query string such as users/123456?action=update.

The nature of data is that it is hierarchical. Soimagine that you want to represent all the posts

400

of the user with ID 123456. You would use thenoun posts to represent all posts and create theURI users/123456/posts. Earlier, it wasmentioned that the representation of theresource is not the actual resource itself, but arepresentation of the resource, and the sameresource can be represented in different ways.To represent all posts by a specified user, youcan use the URI posts/users/123456.Once you have a representation of a resource,you can decide what you want to do with it byusing one of the four HTTP methods. Toretrieve a resource, you use the GET method,and to create a resource, you use the POSTmethod. More on this in the next section.

Self-DescriptiveAs you have seen, the nouns chosen shouldreflect the resource they represent. Combiningthese representations with identifiers makes theURI easy to interpret and intuitive tounderstand. If you read a URI in combinationwith its HTTP method and it is not immediatelyobvious what resource it represents, it hasfailed as a RESTful URI.

Plural Not SingularResource names should be plural because theyrepresent collections of data. The resourcename users represents a collection of users, andthe resource name posts represents a collection

401

of posts. The idea is that plural nouns representa collection in the service, and the ID refers toone instance within that collection. It may bejustifiable to use a singular noun if there is onlyone instance of that data type in the entireapplication, but this is quite uncommon.

HTTP MethodsThere are eight HTTP methods defined inHypertext Transfer Protocol 1.1; however, onlyfour are commonly used when designingRESTful APIs. They are GET, POST, PUT, andDELETE. These methods have specifiedmeanings and usages within the context ofREST. The concept of idempotency is especiallyimportant when considering the HTTP method.The meaning of idempotency from a RESTfulAPI point of view is that a call repeatedly madeby a client to the same URI will always producethe same result. So making one requestproduces the same outcome, on the server, asthe request made multiple times. (This assumesthat a different and separate operation has notchanged the resource’s state.)

Only one of the four most commonly usedmethods is idempotent: GET. This means thatany resource URI that is executed with thismethod cannot effect change on the server. Youcannot use it to create, update, or delete aresource. The HTTP 1.1 specification refers tothis method as safe because it “should not have

402

the significance of taking an action other thanretrieval.” In the context of REST, this methodis used for getting a resource’s representationfrom the server. It must never be used to makechanges to data.

The other three methods—POST, PUT, andDELETE—are not idempotent methods and areexpected to effect change on the server. You’lllearn about each method and how to use it inthe context of a forum site. You’ll also learnabout the HTTP response codes(http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) that canbe returned, along with the responses to theclient and what they mean.

GETYou use this method to get resourcerepresentations from the service. You shouldnever use it to update, delete, or create aresource. Calling it once should have the sameeffect as calling it 100 times. If the resourcerequested is successful, the representation ofthe resource is returned in the body of theHTTP response in the requested data format,which commonly is either JSON or XML. TheHTTP response code returned is 200 (OK). Ifthe resource is not found, it should return 404(NOT FOUND), and if the resource request isbadly formed, it should return 400 (BADREQUEST). A well-formed URI that you might

403

use in your forum application could be GETusers/123456/followers, whichrepresents all the followers of the user 123456.

POSTYou use the POST method to create a newresource within the given context. For example,to create a new user, you would post to theusers resource the data necessary for a new userto be created. The service takes care of creatingthe new resource, associating it to the context,and assigning an ID. On successful creation, theHTTP response is 201 (CREATED), and a linkto the newly created resource is returned eitherin the Location header of the response or in theJSON payload of the response body. Theresource representation may be returned in theresponse body. This is often preferable to avoidmaking an additional call to the API to retrievea representation of the data that had been justcreated. This reduces the chattiness of the API.

In addition to the HTTP response codes to aGET request, a POST can return 204 (NOCONTENT) if the body of the request is empty.A well-formed URI that you might use in yourforum application could be POST users, witha request body containing the new user’s detailsor POST users/123456/posts to create anew post for the user 123456 from the data inthe request body.

404

PUTThe PUT method is most commonly used toupdate a known resource. The URI includesenough information to identify the resource,such as a context and an identifier. The requestbody contains the updated version of theresource, and if the update is successful, itreturns the HTTP response code 200. A URIthat updates a user’s information is PUTusers/123456. Less commonly, you can usethe PUT method to create a resource if theclient creates the identifier of the resource.However, this way of creating a resource is alittle confusing. Why use a PUT when a POSTworks just as well and is commonly known? Animportant point to note about updating aresource is that the entire representation of theresource is passed to the service in the HTTPbody request, not just the information that haschanged.

DELETESurprisingly, you use this method to delete aresource from a service. The URI contains thecontext and the identifier of the resource. Todelete a user with the ID 123456, you use theURI DELETE users/123456. The responsebody may include a representation of thedeleted resource. A successful deletion resultsin a 200 (OK) HTTP response code being

405

returned; if the resource is not found, a 400code is returned.

REST IN ACTIONYou are going to design the RESTful API for aforum site using what you have learned so far.

You start by examining the data structure of thesite and identifying the data domains. The twomain domains are users and posts. Users can befurther analyzed into followers, and posts areoften organized under topics. So with thesedomains, start thinking about the URI you needto represent these resources.

The users nounTo create a new user, you know that you mustuse POST and the users context, so a URI thatcreates a user would look like this:

POST /users

The body of the request contains all that youneed to create the new user. The responseincludes the URI to the representation of theuser. This is a GET method request, like so: GET/users/123456. This requests details of theuser with ID 123456.

If you want to update the user, you need to usethe PUT method like so: PUT /users/123456.

406

And if you want to delete the user, you use theDELETE method, like so: DELETE /users/123456.

If you want to do a batch delete, it is acceptableto pass all the IDs of the users you want todelete in the body of a call to DELETE/users. This would be far less chatty thanmultiple calls to each user’s resource.

You might want to get all users in the servicelike so: GET /users. This call would, ofcourse, be restricted by security so that only theusers that the caller is authorized to view wouldbe returned.

That is all for the user’s context. Now you’ll lookat the follower’s. A follower is a user whofollows another user because he is interested inthat person’s posts.

To get all the followers for a given user, use theGET method, like so:

GET /users/123456/followers

To create a new follower of a user, you pass theID of that follower in the body of a request toPOST /users/123456/followers. Youcan get the details of the follower in one of twoways:

GET /users/123456/followers/456789

or

407

GET /users/456789

This is an example of how you can represent aresource in two different ways. To delete afollower of a given user, you can do this:

DELETE /users/123456/followers/456789

This action removes user 456789 as a followerof user 123456 but does not actually delete theuser. However, the following deletes the user:

DELETE /users/456789

You have read about the followers context. Nowyou’ll look at the topics and posts.

The topics noun and the posts nounYou have already seen how to create a user byusing the POST method. The same is true whencreating a topic and a post.

To create a topic, use:

POST /topics

To create a post under a topic, use:

POST /topics/123/posts

Note that you cannot create a post by doingthis:

POST /posts

408

because you have no context. There is notenough information for the service to create apost because you don’t know to which topic thepost should be associated.

To get a topic and a post, use:

GET /topics/123

To get a specific post under a topic, use:

GET /topics/123/posts/456

or

GET /posts/456

To delete a topic or a post, use:

DELETE /topics/123

To delete a post, use:

DELETE /topics/123/posts/456

or

DELETE /posts/456

To amend a post or a topic, use can any of thefollowing three methods:

PUT /topics/123

PUT /topics/123/posts/456

or

PUT posts/456

409

Now that you have the simplest URIs andcontexts defined, you can start to have some funand combine the users, topic, and post to makethem more complicated.

To retrieve a representation of all topics postedby a given user, use this:

GET /users/123456/posts

To get all posts under a given topic for a givenuser, use this:

GET /users/123456/topics/123/posts

To get all posts by a follower of a given user of agiven topic, use this:

GET /users/123456/followers/456789/topics/123/posts

You can be creative with your combinations ofresource. Despite the seemingly complicatednature, you must never forget that the clients ofthe RESTful API use the URIs, so the URIsshould be easy to understand, and nestingshould be kept to a minimum. If you feel thatyour URI is so complicated that it should beaccompanied by an explanation, you shouldconsider refactoring it.

An example of a well-designed and thought outRESTful API has been implemented by thecloud storage company Sugarsync(https://www.sugarsync.com/developer). I

410

recommend that you review their resourcereference to see how they clearly define thefolder, address, and workspace resources. Notehow the HTTP methods are used to create,read, and delete resources.

IMPLEMENTING REST IN JAVAEEThis chapter has discussed at length the theorybehind a well-designed RESTful API. Now thatyou have seen how you might style the URIs,you can jump in and see how all this looks incode.

Java EE 7 provides some helpful annotationsthat make the job of constructing a RESTful APIstraightforward. The most useful is the @Pathannotation. This annotation defines the contextURI and the class or method that will processrequests made on that URI. Additionally, thereare annotations for each HTTP method: @GET,@POST, @PUT, @DELETE, and so on. Theseannotations mark methods that will processrequests made with the stated HTTP method.

Your application can have more than oneRESTful context. To take care of this case, the@ApplicationPath annotation takes aparameter that denotes the space in which yourRESTful API will exist. With just these twotypes of annotations, you have all you need toimplement a simple RESTful API.

411

Now in Listing 13-1 you’ll implement the URIGET /users.

LISTING 13-1: Simplestimplementation of a RESTful API inJava EE

packageco.uk.devchronicles.forum;

importjavax.ws.rs.ApplicationPath;import javax.ws.rs.GET;import javax.ws.rs.Path;importjavax.ws.rs.core.Application;

@ApplicationPath("/")@Path("users")public class Users extendsApplication{

@GETpublic String getUsers(){

return "Here we returna representation of all users";

}}

If you have this application deployed on yourlocal machine and your application is called

412

forum, you can test this URI by visitinghttp://localhost/forum/users. Youshould notice the text message Here wereturn a representation of allusers displayed in the browser window.

Note in Listing 13-1 how you can annotate theclass with the @Path annotation and pass it theusers context. The string that you pass doesnot have to be preceded by a forward slash or befollowed by a trailing slash. The space in whichthe RESTful interface will exist has beendefined as the root ("/") of the application. Themethod that is called when a GET request ismade to the URI users is annotated with the@GET annotation. In this simple example, astring is returned, but the real goal is to sendback the data retrieved for the database in aJSON or XML format along with an HTTPstatus code. This is what occurs in Listing 13-2.

LISTING 13-2: Responding to theclient with a JSON payload

packageco.uk.devchronicles.forum;

import java.util.ArrayList;

import javax.json.Json;

413

importjavax.json.JsonArrayBuilder;importjavax.ws.rs.ApplicationPath;import javax.ws.rs.GET;import javax.ws.rs.Path;import javax.ws.rs.Produces;importjavax.ws.rs.core.Application;importjavax.ws.rs.core.MediaType;importjavax.ws.rs.core.Response;

@ApplicationPath("/")@Path("users")public class Users extendsApplication{

@GET

@Produces(MediaType.APPLICATION_JSON)public Response getUsers(){

ArrayList<User>allUsers = this.findAllUsers();

JsonArrayBuilderjsonArrayBuilder =Json.createArrayBuilder();

414

for(User user :allUsers){

jsonArrayBuilder.add(

Json.createObjectBuilder()

.add("id", user.getId())

.add("firstname",user.getFirstname())

.add("lastname",user.getLastname())

);}

returnResponse.ok(jsonArrayBuilder.build()).build();

}

public ArrayList<User>findAllUsers(){

ArrayList<User>allUsers = new ArrayList<>();

allUsers.add(newUser(123456,"Alex","Theedom"));

allUsers.add(newUser(456789, "Murat","Yener"));

415

return allUsers;}

}

Listing 13-2 generates a JSON object from theuser data that’s in the database (for brevity, amethod is used to return the user data) andsends it back to the client with a 200 HTTPresponse code. The first thing you will notice isthat the getUsers() method is nowannotated with@Produces(MediaType.APPLICATION_JSON);this specifies the MIME type that this methodcan produce and returns to the client. Thejavax.json.Json andjavax.json.JsonArrayBuilder classesare used to build the JSON and wrap it as ajavax.ws.rs.core.Response objectbefore returning it to the client. If all goes well,you should see the following output in thebrowser:

[

{"id":123456,"firstname":"Alex","lastname":"Theedom"},

{"id":456789,"firstname":"Murat","lastname":"Yener"}]

416

So far, you have seen how to retrieve a resourcerepresentation of all users in the system, butwhat if you only want one user and you knowthe user’s identification number? Well, this isjust as simple. In the URI, you pass the user’sID number like so:

GET /users/123456

and in the REST controller class, yourecuperate the ID number by referencing theREST path and using a URI variable to pass theID to the method. You annotate the methodthat will consume the RESTful API call with@Path("/{id}"), and in the signature of themethod, you annotate the argument to whichthe ID value should be passed.

@GET@Path("/{id}")

@Produces(MediaType.APPLICATION_JSON)public Response

getUser(@PathParam("id") Stringid){

User user =this.findUser(id);

JsonArrayBuilderjsonArrayBuilder =Json.createArrayBuilder();

jsonArrayBuilder.add(

Json.createObjectBuilder()

417

.add("id", user.getId())

.add("firstname",user.getFirstname())

.add("lastname",user.getLastname())

);

returnResponse.ok(jsonArrayBuilder.build()).build();

}

public User findUser(Stringid){

return newUser("123456", "Alex","Theedom");

}

As you can see in the previous code snippet, theID string parameter is annotated with@PathParam("id") so that the IDrecuperated from the URI by the @Path("/{id}") annotation is passed into the method.It is not necessary to include the full path of theURI in the @Path annotation because the baseURI is set in the @Path annotation on theclass. All paths set on methods are relative tothe base path set on the class.

The URI variable can be a regular expression.For example, the path annotation @Path("/

418

{id: [0-9]*}") will match only IDs thatare numbers. Any IDs that don’t match willresult in a 404 HTTP response being returnedto the client.

You have seen some simple URI constructionsthat consist of one resource noun and a URIvariable. How do you deal with a morecomplicated URI, such as GET /users/123456/followers/456789? You do it inthe same way as before, just with a slightlymore complicated @Path and @PathParam.

@GET@Path("/{user_id}/followers/

{follower_id}")

@Produces(MediaType.APPLICATION_JSON)public Response getUser(@PathParam("user_id") String

user_id,@PathParam("follower_id")

String follower_id)

You have looked in detail at the GET HTTPmethod. What about the POST, PUT, andDELETE methods? To write a method thatresponds to an HTTP POST request, you doalmost the same as you would with GET, butyou change two elements. You annotate themethod with @POST instead of @GET and

419

@Consumes in place of @Produces. Here’s asimple example:

@POST

@Consumes(MediaType.APPLICATION_JSON)@Path("/{user_id}/followers/

")public Response

createUser(@PathParam("user_id")String user_id, String body)

This example works in the same way as for theGET methods, but notice that there is noexplicit mapping of the HTTP request body to amethod parameter. The mapping is implicit.The content of the HTTP body is passed to theonly unannotated parameter that it finds in themethod signature. No more than one is allowedto avoid confusion.

The PUT and DELETE HTTP methods operatein a similar way to the POST method.

Your URI may contain query parameters. Youcan retrieve these from the URI by annotating aparameter in the method signature with@QueryParam("page"). This annotationretrieves the page query parameter from theURI /users?page=10.

There are many more annotations in theJAX-RS API that facilitate the design of a good

420

RESTful API. It’s recommended that youfamiliarize yourself with all of them.

HATEOASAs has already been discussed, HATEOAS is atthe highest level of REST implementation in theRichardson Maturity Model and should beconsidered the nirvana of RESTfulness.

Imagine that a client requests a resource thatrepresents all the posts in the system that theuser has permission to view. The URI would beGET /posts, and the response, if successful,might return with the following HTTP body:

{"posts": [

{"id": 71892,"title": "Best movie of

2015","content": "I think the

best movie of 2015 is the GoldenEgg of Siam.",

"links": [{

"rel": "self","href":

"http://localhost:8080/rest/posts/71892",

"method": "GET"},

421

{"rel": "replies","href":

"http://localhost:8080/rest/posts/71892/posts",

"method": "GET"},{

"rel": "follower","href":

"http://localhost:8080/rest/posts/71892/followers",

"method": "GET"},{

"rel": "owner","href":

"http://localhost:8080/rest/posts/71892/users",

"method": "GET"}

]},{

"id": 71893,"title": "Worst movie of

2015","content": "The worst

movie has gotta be Just BeingMe.",

"links": [{

"rel": "self",

422

"href":"http://localhost:8080/rest/posts/71893",

"method": "GET"},{

"rel": "owner","href":

"http://localhost:8080/rest/posts/71893/users",

"method": "GET"}

]}

]}

There’s a lot going on here. The response is inJSON format and is formed of one JSON objectnamed post that contains an array of posts:

{"posts": [

{... element one in the

array},{

... element two in thearray

}]

}

423

In the example, there are only two elements tothe array representing two posts. Each post is aJSON object that follows the same format:

{"id": 71892,"title": "Best movie of

2015","content": "I think the

best movie of 2015 is the GoldenEgg of Siam.",}

As can be seen from the JSON snippet itcontains an ID that identifies the post resourcefollowed by the post’s title and content. This isthe minimum that you would expect to see in aresponse to a request for a post resourceregardless of the maturity of the rest interface.What makes this response special is the linkselement.

"links": [{

"rel": "self","href":

"http://localhost:8080/rest/posts/71892",

"method": "GET"},...

]

424

This is where HATEOAS comes to life. Thereare three parts to each link in the link array.The rel is the relation that the href link hasto the current resource. The href is a link tomore resources, and the method is the methodthat must be used to obtain the resource. Therel element can have any value and does nothave to follow a convention, although it iscustomary for 'self' rel to refer to a linkthat represents more information about thecurrent resource. In this example, it just refersto itself. The other links refer to other users’responses to the post (replies or responses), theusers who follow the post (followers), and theuser who posted the post (owner). Any resourcethat relates to the principle post resource can berepresented by a link in the link array.

As you can see from the example, the first postin the array has four links in its links array,whereas the second has only two. This isbecause the second post does not have usersfollowing it or any responses.

Providing links in this way gives the client theinformation it needs to navigate to furtherresources and allows you to easily extend andgrow the API with relatively little pain.

A good example of a well-designedimplementation of HATEOAS is the oneimplemented by Paypal?.com(https://developer.paypal.com/webapps/developer/docs/integration/direct/

425

paypal-rest-payment-hateoas-links/). Theyhave used HATEOAS to allow you to build anAPI that interacts with their payment systemsimply by following the links provide in thelinks array.

WHERE AND WHEN TO USERESTREST is an easy and well-established approachthat is not constrained by standards. Some mayargue that this is a distinct disadvantage whencompared to SOAP, which is an industrystandard with its own well-defined protocol andimplementation rules. However, its ease ofimplementation and use by others outweighsany difficulty created by a lack of a standard.Making a RESTful resource for consumption isas simple as providing a URI, and using theHTTP protocol cross-language communicationis easy. The common language is HTTP, thelanguage of the web, which is simple andunderstood by all.

Bandwidth limitation situations prove noproblem for REST’s lightweight approach andare especially attractive on mobile devices. Itcosts little to make a request for a resourcefrom a RESTful API. Remember that it is justan HTTP request and that the data returned canbe in any appropriate format. The format doesnot have to be JSON or XML; it can be AtomSyndicate Format (ATOM) or some custom

426

format. The flexibility afforded by using just asimple URI to represent a resource allows theclient developer to be imaginative. You can useAsynchronous Javascript and XML (AJAX) tocall one or more URIs, perhaps from differentREST providers. You can combine theresponses to these calls to provide rich contentfor the site’s visitors.

If your implementation of REST uses the HTTPprotocol (which it most probably will), youreceive the bonus feature of free caching. TheHTTP protocol incorporates a cache as a corefeature that you can exploit in your applicationby setting appropriate HTTP header values.

SUMMARYYour application’s REST API should be simpleand intuitive for other developers to use, and itis your responsibility as a developer to designan API that fits the requirement of yourapplication while ensuring that the API’s userscan access the resources required for the properfunction of their application.

In this chapter we have touched upon the basicsof a good RESTful API design. There are manymore considerations that we have not evenmentioned, such as security, the use of querystrings, and how to provoke server side tasks.

Luckily REST is ubiquitous, and resources tohelp you develop a truly RESTful API are

427

plentiful. Just search the Internet and you willnot be at a loss for articles, forums, and booksdevoted to the topic of REST.

EXERCISES

Search the Internet for public RESTful APIs,and write some simple code that consumesthem.

Implement the URI for the forum sitedetailed in the preceding text, and write afront end client that consumes them.

Develop one journey through the site using afully HATEOAS-style approach.

NOTES

1. “Architectural Styles and the Design ofNetwork-Based Software Architectures,” RoyFielding, 2000. Chapter 5:www.ics.ucl.edu/~fielding/pubs/dissertation/rest_arch_style.htm.

2. Leonard Richardson explained the model ofRESTful maturity during a QCon talk in2008. www.crummy.com/writing/speaking/2008-QCon/act3.html.

3. The HTTP/1.1 RFC standard defines thefollowing methods: OPTIONS, GET, HEAD,

428

POST, PUT, DELETE, TRACE, andCONNECT.

4. Martin Fowler provides a good overview onhis website: www.martinfowler.com/article/richardsonMaturityModel.html.

429

14Model View ControllerPatternWHAT’S IN THIS CHAPTER?

An introduction to the MVC pattern

The MVC pattern’s origins

How to implement the MVC pattern usingcompound patterns

Implementing the MVC pattern In Java EE

When and where to use the MVC pattern

WROX.COM CODE DOWNLOADS FORTHIS CHAPTER

The wrox.com code download for this chapter isfound at www.wrox.com/go/projavaeedesignpatterns on theDownload Code tab. The code is in the Chapter14 download and individually named accordingto the names throughout the chapter.

The model view controller (MVC) pattern is oneof the most ubiquitous architectural designpatterns in modern application developmentthat is listed in the book from the Gang of Four.It is built on the philosophy of separation ofconcerns and encapsulates the processing ofapplication data from the presentation of the

430

data. Not encapsulating the processing of datafrom the presentation of data leads to highlycoupled systems that are hard to maintain andextend. The separation of concerns that theMVC pattern provides makes modifications toboth the business logic and the user interfacemuch easier and more independent.

The MVC pattern is not much different thanbuying a subscription from a cable provider anda TV set from an electrical store. One providesthe content, and the other makes sure you viewit in the right way. Neither worries about thechanges in the technology on the field. You canalways buy a new TV set when better panels arereleased or subscribe to more channels withoutbuying new hardware.

Developers of web applications use the MVCpattern extensively, and it is within this contextthat its implementation will be discussed.

WHAT IS THE MVC DESIGNPATTERN?In MVC, the model represents the application’sdata and related business logic. The model maybe represented by one object or a complexgraph of related objects. In a Java EEapplication, the data is encapsulated in domainobjects often deployed in an EJB module. Datais transported to and from the database accesslayer in data transfer objects (DTOs) and

431

accessed via data access objects (DAOs). SeeChapter 12, “Data Access Pattern.”

The view is the visual representation of the datacontained in the model. A subset of the model isrepresented in a single view; thus, the view actsas a filter to the model data. The user interactswith the model data via the view’s visualrepresentation and invokes business logic thatin turn acts upon the model data.

The controller links the view to the model anddirects application flow. It chooses which viewto render to the user in response to the user’sinput and the business logic that’s processed.The controller receives a message from theview, which it forwards to the model. The modelin turn prepares a response and sends it back tothe controller where the view is chosen and sentto the user.

The MVC pattern logically spans the client andmiddle tier of a multitier architecture. In a JavaEE environment, the model is located in thebusiness layer, normally in the form of anEnterprise JavaBeans (EJB) module. Thecontroller and view are located in the web tier.The view is likely to be constructed fromJavaServer Faces (JSF) or JavaServer Pages(JSP) with the help of Expression Language(EL). The controller is normally a servlet thatreceives Hypertext Transfer Protocol (HTTP)requests from the user. See Chapter 2, “Basicsof Java EE” for a discussion of multitier

432

architecture and the different applicationlayers.

Often the MVC pattern is combined with otherpatterns, such as the command (or action),strategy, composite, and observer patterns. Thischapter doesn’t delve into the depths of thesepatterns, but it does touch on the action patternin the example that follows.

BACKGROUND

The first mention of this pattern occurredbefore the invention of the modern-dayInternet in a paper published by theSmallTalk programmer Trygve Reenskaug inDecember 1979 while he was working atXerox Parc.1

Even though the MVC elements of this patternwere defined more than 30 years ago, they aresurprisingly relevant to their current use in aweb application.

Figure 14.1 shows the user making a request tothe controller. The controller handles therequest by updating the model and rendering anew view, which is then sent to the user.

433

Figure 14.1 Diagram of the model viewcontroller pattern

WAR STORY

Back when JSP was all the rage and the Y2Kbug had not brought on the worldwidenuclear destruction that we had beenpromised, I was working for a small webstart-up. Our start-up was composed of just afew JSP/Java developers and some flashdesigners. We wanted to build a websiteportal that would serve dynamic content thatdepended on the specific needs of the clientthat had contracted us.

So we jumped into the project with 100percent enthusiasm and developed a highlydynamic website that displayed differentfeatures for different clients. We were trulyproud of our creation, and so were the manyclients who bought our wonderful site. In

434

fact, we were becoming quite successful, andrather quickly, too. It seemed that everyonewas really happy with our product, and wewere happy with our success. But thathappiness was short lived. As more and moreclients bought our product, the site becameincreasingly difficult to manage. What wehad done was mix the business logic with theview logic, so for each new client, we had toamend all the JSP in the site. Soon the JSPbecame a horrible mishmash of business anddisplay logic, and we ended up withunmanageable spaghetti code. It became anightmare, so we had no choice but to rewritethe entire application, but this timeimplementing the MVC pattern.

We did rewrite the application, and it becamemanageable, but only after many late nightsand a lot of weekends spent in the office. Themoral of this story is that the MVC pattern isgood, not only for your application’smaintenance and extensibility, but for yourlife-work balance.

MVC TypesThe MVC pattern comes in many differentforms. The two most recognized are referred toas Type I and Type II.

435

MVC Type I—This type is a page-centricapproach in which the view and the controllerexist as one entity referred to as theview-controller. With this approach, thecontroller logic is implemented within the view,such as in a JSF. All the tasks that the controllerperforms, including retrieving HTTP requestattributes and parameters, invoking thebusiness logic, and managing the HTTP session,are embedded in the view using scriptlets andtag libraries. Type I highly couples the viewgeneration with the application flow, makingmaintenance troublesome.

MVC Type II—The maintenance problemswith Type I are overcome in Type II by movingthe controller logic out of the view and into aservlet, leaving the JSF to concern itself withthe rendering of the data for the view.

ALTERNATIVE TO MVC—MEETMVP

Sorry for the disillusion, but MVP does notstand for most valuable pattern. MVP is theabbreviation for model view presenter, whichis an alternative to model view controller.Instead of creating a triangular relationshipbetween controller, view, and model likeMVC, MVP offers one way of communicationto each party—the presenter takes charge of

436

all communication between the view andmodel. It is pretty popular in .NET,Silverlight, Google Web Toolkit, and Vaadin.

The principle difference between Type I andType II is where the controller logic is located:in Type I it is in the view, and in Type II it is ina servlet.

Many frameworks, such as Spring MVC, Struts,Grails, and Wicket, implement their ownversion of the Type II MVC pattern. Forexample, Spring MVC includes the concept ofthe Dispatcher servlet that interacts with theHTTP requests and delegates to the controller,view (and view resolver), and handlers. Figure14.2 shows a diagram of Spring’simplementation of the MVC pattern.

Figure 14.2 Diagram of Spring’s MVCimplementation

437

IMPLEMENTING THE MVCPATTERN IN PLAIN CODEYou are going to implement the MVC patternwith the help of the action pattern. This patterntakes on the responsibility of determiningwhere to redirect the user based on the user’srequest. It helps maintain the singleresponsibility of the controller.

You’ll start with the controller class. In Listing14-1, you have implemented a simple controllerthat responds to any HTTP GET request madeto the /users/* path. The mapping of thisrelationship is defined in the web.xml file:

<servlet>

<servlet-name>FrontController</servlet-name>

<servlet-class>com.devchronicles.mvc.plain.FrontController</servlet-class></servlet><servlet-mapping>

<servlet-name>FrontController</servlet-name>

<url-pattern>/users/*</url-pattern></servlet-mapping>

In the listing, you map the controller classcom.devchronicles.mvc.plain.FrontControllerto the request URL /users/*. Therefore, for

438

every request made to this URL, it is directed tothe FrontController class for processing.

SERVLETS 3.0

Alternatively, you can annotate the controllerclass with the request URL like so:@WebServlet({"/users/*"}). Thisannotation removes the need to define theservlet mapping in the web.xml.

The doGet() method is invoked for suchrequests, and an Action object is retrievedfrom the AbstractActionFactory, whichdetermines the location of the view that shouldbe returned to the user.

LISTING 14-1: The refactoredUserService class

packagecom.devchronicles.mvc.plain;

import java.io.IOException;importjavax.servlet.ServletException;importjavax.servlet.annotation.WebServlet;import

439

javax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;

public class FrontControllerextends HttpServlet {

protected voiddoGet(HttpServletRequestrequest, HttpServletResponseresponse)

throwsServletException, IOException {

Action action =

AbstractActionFactory.getInstance().getAction(request);

String view =action.execute(request,response);

getServletContext().getRequestDispatcher(view).forward(request,response);

}

}

440

Listing 14-2 has two classes:AbstractActionFactory andActionFactory. TheAbstractActionFactory class creates aninstance of the ActionFactory class. TheAction Factory’s getAction method acceptsan HttpServletRequest object, whichcontains a reference to the URI of the requestedlocation. The factory uses the URI to determinewhich Action object to return to thecontroller. You maintain a map of URI requestpaths and Action objects in the action Map.An Action object is chosen from the mapbased on the URI request path and returned tothe controller.

LISTING 14-2: The Factory class

packagecom.devchronicles.mvc.plain;

public classAbstractActionFactory {

private final staticActionFactory instance = newActionFactory();

public staticActionFactory getInstance() {

441

return instance;}

}

packagecom.devchronicles.mvc.plain;

import java.util.HashMap;import java.util.Map;importjavax.servlet.http.HttpServletRequest;

public class ActionFactory {

private Map<String,Action> actions = newHashMap<>();

private Action action;

public ActionFactory() {actions.put("GET/

users", new HomeAction());actions.put("GET/users/

listusers", newListUsersAction());

}

public synchronized ActiongetAction(HttpServletRequestrequest) {

442

String path =request.getServletPath() +request.getPathInfo();

String actionKey =request.getMethod() + path;

System.out.println(actionKey);action =

actions.get(actionKey);if(action == null){

action =actions.get("GET/users");

}

return action;}

}

What is important in the Action object is thatthe concrete implementation provides animplementation of the execute() method.This method performs business-specific logicrequired to generate the page that the userrequested. It may query a database to obtaindata, perform calculations, or generate a file.

In Listing 14-3, the ListUserAction’sexecute method constructs a list of users that itadds as an attribute to the request object; thenit returns the location of the view to render anddisplay to the user. The data now stored in the

443

request object is accessed by thelistuser.jsp page and displayed.

For brevity, a List object has been populatedand returned, but in a real application, this iswhere you would use EJB or other data objectsthat connect to a database.

LISTING 14-3: The Action class

packagecom.devchronicles.mvc.plain;

import java.util.ArrayList;import java.util.List;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;

public class ListUsersActionimplements Action {

public Stringexecute(HttpServletRequestrequest, HttpServletResponse

response) {

List<String> userList= new ArrayList<>();

userList.add("John

444

Lennon");userList.add("Ringo

Starr");userList.add("Paul

McCartney");userList.add("George

Harrison");

request.setAttribute("listusers",userList);

return "/WEB-INF/pages/listusers.jsp";

}}

The Action object returns to the controller,which receives the location of the page to whichit should dispatch the request and responseobjects.

String view =action.execute(request,response);getServletContext().getRequestDispatcher(view).forward(request,response);

In Listing 14-4, the JSP accesses the page’srequestScope variable and retrieves theuserList list object created in

445

ListUserAction. It then iterates over thecollection and displays the usernames.

LISTING 14-4: The listuser.jsp accessgenerates the page the userrequested

<%@ page language="java"contentType="text/html;charset=ISO-8859-1"pageEncoding="ISO-8859-1"%><%@ tagliburi="http://java.sun.com/jsp/jstl/core" prefix ="c" %><!DOCTYPE html PUBLIC"-//W3C//DTD HTML 4.01Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"><html><head><metahttp-equiv="Content-Type"content="text/html;charset=ISO-8859-1"><title>List of users</title></head>

<body><h1>Our users are:</h1>

446

<c:forEachitems="${requestScope.listusers}"var="listusers">

<br> ${listusers}</c:forEach></body></html>

The example that’s been demonstrated is asimple implementation of the MVC pattern.You’ll continue by looking at how you wouldimplement the same application but using theadvantages of Java EE 7.

IMPLEMENTING THE MVCPATTERN IN JAVA EEThe plain code implementation of the MVCpattern required you to write the controllerlogic, map the URLs to controller classes, andwrite a lot of plumbing code. However, in thelatest release of Java EE, the plumbing code hasbeen done for you. You only need toconcentrate on the view and the model. TheFacesServlet takes care of the controllerimplementation.

447

THE FACESSERVLETThe FacesServlet takes control of managinguser requests and delivering the view to theuser. It manages the life cycle for webapplications that use JSF to construct the userinterface. All user requests go through theFacesServlet. The servlet is integral to JSF andcan be configured if nonconventional behavioris required. However, thanks to the concept ofconvention over configuration, you will findthat for all but the most complex webapplications, it is not necessary to change thedefault configurations.

CONFIGURING THEFACESSERVLET

If you do need to change the FacesServletconfiguration, you must amend thefaces-config.xml file.

Since JSF 2.2, you can perform the mostcommon configurations by using annotation,further reducing the need to touch thefaces-config.xml file.

MVC USING THE FACESSERVLETYou are going to rewrite the preceding exampleusing the FacesServlet servlet and JSF. The

448

view declaration language for JSF is calledfacelets. Facelets are the replacement for JSPsand are written in XHTML using cascadingstyle sheets (CSS).

JSF includes the concept of backing beans.These are Plain Old Java Objects (POJOs)annotated with the @Named and the@RequestScope annotations. These beansare accessible by the JSF page for the durationof the HTTP request. You can refer to theirmethods directly in the JSF. In Listing 14-5, yourewrite ListUsersAction.class to makeit a backing bean.

LISTING 14-5: The ListUserActionclass rewritten as a backing bean

packagecom.devchronicles.mvc.javaee;

import java.util.ArrayList;import java.util.List;importjavax.enterprise.context.RequestScoped;import javax.inject.Named;

@RequestScoped@Namedpublic class ListUsersAction {

449

private List<String>userList = new ArrayList<>();

public List<String>getUserList() {

return userList;}

public String execute() {userList.add("John

Lennon");userList.add("Ringo

Starr");userList.add("Paul

McCartney");userList.add("George

Harrison");return "/WEB-INF/pages/

listusers.xhtml";}

}

Because all backing beans are annotated with atleast @Named and @RequestScope, there is aStereotype annotation you can use that gives itall the behavioral characteristics of a backingbean when it’s applied. This annotation is the@Model annotation.

Next, you need to create an index.xhtml file.This replaces home.jsp and is called directlyfrom the browser. The purpose of this JSF is to

450

call the execute method onListUsersAction that prepares the data forthe view listusers.xhtml.

Listing 14-6 shows how this method isprovoked.

LISTING 14-6: The home page to thesimple MVC example

<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"xmlns:h="http://java.sun.com/jsf/html">

<h:head><title>Welcome</title></h:head>

<h:body><h1>Welcome to our site</h1><h:form>

<h2>Click to see a<h:commandLink value="list ofusers"

action="#{listUsersAction.execute}"/>.</h2>

451

</h:form></h:body></html>

You use the h:commandLink tag andreference the backing bean and theexecute() method in the action element. Theexecute() method is called directly from theJSF; it generates the user list, returns thelocation of the view that will render the list, andthen invokes the getUserList() methodand displays the user list. Listing 14-7demonstrates this.

LISTING 14-7: The view that rendersthe model data

<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"

xmlns:ui="http://java.sun.com/jsf/facelets"

452

xmlns:h="http://java.sun.com/jsf/html">

<head><title<List of users</title></head><body>

<h1>Our users are:</h1><ui:repeat

value="#{listUsersAction.userList}"var="listusers">

<h:outputTextvalue="#{listusers}" />

<br/>>/ui:repeat<

</body></html>

In the backing bean, the action class is referredto as listUsersAction starting inlowercase, and the method getUserList()omits the word get. If a method starts withget, you can omit it.

When you deploy this application, theindex.xhtml view renders the link, whichwhen clicked will display a list of users asfollows:

453

Our users are:John LennonRingo StarrPaul McCartneyGeorge Harrison

You have now successfully built an MVC-stylewebsite using the latest features of Java EE 7.

WHERE AND WHEN TO USE THEMVC PATTERNThe most prolific use of the MVC pattern is inweb applications, although you can use itanywhere there is a benefit to separating theview logic from the business logic. In fact, theuse of the MVC pattern in web applicationarchitecture is so ubiquitous that anysuggestion not to use it would be met withderision and disdain.

There is no doubt that the two principlebenefits of using the pattern are strong. Itsseparation of concerns makes for a flexible andadaptable web application, and its separation ofproduction allows different parts of theapplication to be developed virtuallyindependently of each other. For example, oneteam can work on the display logic whileseparately another team can work on thebusiness logic and domain objects.

454

SUMMARYThe MVC pattern has many commentatorsoffering their point of view on its use,implementation, and even validity. You willread my interpretations of this pattern and seemany implementations. It can be confusing tosee the real benefits of this pattern.

You should go back to the essence of the MVCpattern: the separation of the display logic fromthe business logic. If you implement code thatstays true to this objective, you havesuccessfully implemented the MVC pattern.

The concept behind a separation ofpresentation and business logic is to maintain aclear divide between domain objects that modelyour problem and the presentation of that logic.This separation allows the business data to bepresented in any number of different ways,simultaneously and without the need for thedomain object to know anything about the wayit is being displayed. It could be displayed onthe screen in a variety of formats or as Word orExcel files.

EXERCISESDevelop the example in the chapter further byadding different views to display the user list.

455

NOTE

1. Professional website of Trygve M. H.Reenskaug: http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html.

456

15Other Patterns in Java EEWHAT’S IN THIS CHAPTER?

WebSockets

Message-oriented middleware

Microservices versus monoliths

WROX.COM CODE DOWNLOADS FORTHIS CHAPTER

The wrox.com code download for this chapter isfound at www.wrox.com/go/?projavaeedesignpatterns on theDownload Code tab. The code is in the Chapter15 download and individually named accordingto the names throughout the chapter.

This chapter discusses some of the things thatare benefits of Java EE and development. Youmight think of this chapter as containing all thetopics that are important to know but don’t fitin any of the other chapters.

This chapter introduces web sockets, which isan exciting new feature of Java EE. Then itintroduces message-orientated middlewarebefore moving on to the related topic ofmicroservice architecture.

Enjoy this eclectic bag of tech goodies!

457

WHAT ARE WEBSOCKETS?WebSockets might be the most interestingimprovement on the web since the introductionof Asynchronous JavaScript And XML (AJAX).It has been popular since the emergence ofHTML5 and is supported by many webframeworks. However, it took quite a long timeto have a stable and compatible specification forWebSockets.

The Hypertext Transfer Protocol (HTTP) modelwas designed long before the Internet waspopular, and it relied on simple specificationand design. In the traditional HTTP model, aclient opens a connection to the back-endserver, sends an HTTP request of type1 GET,POST, PUT, or DELETE, and the HTTP serverreturns an appropriate response. There havebeen several attempts to hack and communicateover standard HTTP, such as AJAX, as well asdesign a new model such as SPDY.

The traditional HTTP model has beencumbersome for almost any application thatgoes beyond the simple get-and-submit-contentdata model. Think about a chat client, in whichthe participants can send messages in anyorder, and hundreds can be chatting at thesame time. The standard request-responseapproach would be too limiting for suchpurposes. Some early approaches to get pastthis limitation were AJAX and Comet. Both

458

relied on long polling: opening an HTTPconnection and keeping it alive (maintainingthe connection open) by not finalizing theresponse.

With WebSockets, the client can initiate a rawsocket to the server and execute full-duplexcommunication. WebSockets support wasintroduced with JSR-356. The packagejavax.websocket and its server subpackagecontain all classes, interfaces, and annotationsrelated to WebSockets.

To implement WebSockets in Java EE, youneed to create an endpoint class with theWebSocket life-cycle methods shown in Listing15-1.

LISTING 15-1: An example of anendpoint

packagecom.devchronicles.websockets;public class HelloEndpointextends Endpoint {

@Overridepublic void onOpen(final

Session session,EndpointConfig config) {

459

session.addMessageHandler(newMessageHandler.Whole<String>(){

@Overridepublic void

onMessage(String msg) {try {

session.getBasicRemote().sendText("Hello" + msg);

} catch(IOException e) { }

}});

}}

The Endpoint class introduces three life-cyclemethods: onOpen, onClose, and onError.At least the extending class needs to implementthe onOpen method.

You can deploy this endpoint in two differentways: either by configuration orprogrammatically.

To programmatically deploy the code in Listing15-1, your application needs to invoke thefollowing:

460

ServerEndpointConfig.Builder.create(HelloEndpoint.class,"/hello").build();

The deployed WebSocket is available fromws://<host>:<port>/<application>/hello. However, a better way is to useannotation configuration. Therefore, the sameendpoint becomes Listing 15-2.

LISTING 15-2: An example of anendpoint with annotations

packagecom.devchronicles.websockets;

@ServerEndpoint("/hello")public class HelloEndpoint {

@OnMessagepublic void

onMessage(Session session,String msg) {

try {

session.getBasicRemote().sendText("Hello" + msg);

} catch (IOExceptione) { }

}}

461

This approach lets you use annotations andkeep up with the Plain Old Java Object (POJO)approach because you are not extending a baseclass. The annotated endpoint has the samelife-cycle methods as the one in Listing 15-2,but it introduces an additional onMessagelife-cycle method. Rather than implementingonOpen and adding the onMessage handler,it’s enough to implement an annotatedonMessage method in the annotation-basedapproach. You can annotate several methodswith @OnMessage to receive different types ofdata, such as String or ByteBuffer forbinary.

The client-side implementation of WebSocketsdepends on the web frameworks in use.However, a simple JavaScript version is shownin the following snippet.

var webSocket = newWebSocket('ws://127.0.0.1:8080/websockets/hello');webSocket.send("world");

A better example is to send a complex object inJavaScript Object Notation (JSON) format,which can be marshaled to an object, as in thefollowing code snippet.

var msg = {type: "message",text: "World",

462

date: Date.now()};

webSocket.send(JSON.stringify(msg));

webSocket.onmessage =function(evt) { /* Expect toreceive hello world */ };

WebSockets are great for building webapplications that need persistent andasynchronous messaging between the client andthe server. Java EE offers an easyimplementation of WebSockets. They have farmore configurations and implementationoptions than discussed here. If we have sparkedyour interest in WebSockets we suggest youvisit Oracle’s Java EE Tutorial,2 which explainsin more details how to program WebSocketsusing the Java API.

WHAT ISMESSAGE-ORIENTATEDMIDDLEWAREThe communication between components in aJava EE system is synchronous. A call chain isstarted from the calling Enterprise JavaBean(EJB) to a data access object (DAO) to theentity, and so on to the final target. Allcomponents of the call chain must be availableand ready to receive the call, and the calling

463

component must wait for a response beforeproceeding. The success of the invocationdepends on the availability of all components.As you saw in Chapter 9, “Asynchronous,” aninvocation of an asynchronous method does notrequire the calling object to wait for a response.It can continue with the normal flow ofexecution, while the asynchronous method setsup its own call chain.

Message-oriented middleware (MOM) providesa type of buffer between systems that allows thecommunication to be delayed if a component isnot up and running. Messages are delivered assoon as all components are available.Invocations are translated into messages andsent via a messaging system to a targetcomponent that processes the message and mayrespond. If the target component is notavailable, the messages are queued waiting forthe system to become available. When thecomponent is available, the messages areprocessed.

At one end of the chain is a producer thattranslates the call into a form that can betransmitted as a message, and at the other endis a consumer who receives the message. Theconsumers and producers are highly decoupled,because they don’t know anything about eachother. They don’t even have to be written in thesame language or be hosted on the same

464

network; they may even be distributed overseveral external servers.

A MOM system is composed of four players:messages, consumers, producers, and brokers.Producers generate the messages and sendthem to brokers, who distribute the messages todestinations where they’re stored until aconsumer connects and processes them.

There are two architectural implementations ofMOM: point-to-point and publish/subscribe.

In the point-to-point implementation, theproducer sends a message to the destination,which is called a queue. In the queue, themessage waits for a consumer to pick it up andconfirm that it has been processed successfully.If it has, the message is then removed from thequeue. Figure 15.1 shows the producer puttingthe message M1 onto the queue and then theconsumer picking up the message from thequeue and processing it. In this implementationthe message is only processed by one consumer.

Figure 15.1 Point-to-point implementation

In the publish/subscribe implementation, thedestination is called a topic. A producerpublishes a message to a topic, and allconsumers who subscribe to the topic receive acopy of the message. This is shown in Figure

465

15.2, where messages M1 and M2 are publishedto the topic T1 and consumed by consumer C1and C2, and message M3 is published on topicT2 and consumed by consumers C2 and C3.

Figure 15.2 Publish/subscribeimplementation

Java EE provides a convenient applicationprogramming interface (API) that deals withthese implementations and is called the JavaMessage Service (JMS). It is a set of interfacesthat describe the creation of messages,providers, and consumers. When implementedin an EJB container, message-driven beans(MDBs) act as listeners for JMS messages beinginvoked asynchronously.

WHAT IS THE MICROSERVICEARCHITECTURE?Over the past few years, the microservicearchitecture pattern has become a hotlydiscussed and popular pattern. The idea behindit is to design a large distributed scalableapplication that consists of small cohesiveservices that are able to evolve or even be

466

completely rewritten over the life of theapplication.

This is not a new idea, and it is similar to theService Orientated Architecture (SOA) patternthat has been in use for a long time. Theessence of the microservice is the idea that eachservice should be small—perhaps as small asonly a few hundred lines of code. The objectiveis to decompose a large, monolithic applicationinto much smaller applications to solvedevelopment and evolutionary problems.

This chapter discusses the reasons for followingthe microservice path, its disadvantages andbenefits, and how it compares to the moreestablished and familiar monolithicarchitecture.

Monolithic ArchitectureThe most common way to develop and packagea web application has always been to collect allthe resources, components, and class files into asingle Web application ARchive (WAR) orEnterprise ARchive (EAR) file and deploy it to aweb server. A typical application for a bookstoremight include components that manage theuser’s accounts, process payment, control stock,administer customer services, and generatefront-end views. All this is developed in onemonolithic application and then packaged anddeployed to a web server. Figure 15.3 shows a

467

simplified representation of a monolithicapplication.

Figure 15.3 Monolithic architecture

The components are packaged together in alogical modular form and deployed as onesingle monolithic application. It’s a simple wayto develop and deploy an application becausethere’s only one application to test. IntegratedDevelopment Environments (IDEs) and otherdevelopment tools are designed with themonolithic architecture in mind. Despite thesebenefits of monolithic architecture, applicationsbuilt to this design are often very large.

A small application is easy for developers tocome to grips with, to understand, andmaintain, but a large monolithic application canbe difficult, especially for those developers whohave recently joined the team. They may takemany weeks or months to thoroughlyunderstand the application.

468

Frequent deployments are not practical becausethey require the coordination of manydevelopers (and perhaps other departments). Itmay take hours or days to arrange adeployment, hindering the testing of newfeatures and bug fixes. A significant drawbackto the monolithic design is that it’s difficult tochange the technology or framework. Theapplication was developed based on technologydecisions made at the beginning of the project.You are stuck with these decisions; if atechnology is found that solves the problem in amore elegant or performant way, it is difficult tostart using it. Rewriting an entire application isalmost never an affordable option. Themonolithic architecture pattern does not lenditself well to scalability.

ScalabilityScalability refers to an application’s ability togrow (and shrink) as demand for its serviceschanges without noticeably affecting the userexperience. A badly performing e-commercewebsite loses customers quickly, makingscalability very important. The first go-tosolution is to scale horizontally and duplicatethe application over many servers and loadbalance the traffic in a High Availability (HA)manner, with a passive peer that becomesactive if the active peer goes down. X-axisscaling improves the capacity and availability ofthe application. This option does not have

469

development cost implications but does resultin higher hosting and maintenance expense.3

You can scale an application along the Z-axis.The application code is duplicated onto severalservers, similar to an X-axis split, but in thiscase each server is responsible for only afraction of the data. A mechanism is put inplace to route data to the appropriate server,perhaps based on a user type or primary key.Z-axis scaling benefits from much the sameperformance improvements as X-axis scaling;however, it implies new development expenseto rearchitect the application.

None of these solutions resolves the worseningapplication and development complexity. Forthis, you need vertical scaling.

The application can be scaled along the Y-axis.It is decomposed into functionality, service, orresource. The way you do this is entirely yourchoice and will depend on the situation,although division by use case is common. Theidea is that each decomposed part shouldencapsulate a small set of related activities.

To visualize the X-, Y-, and Z-axis scaling, youdraw an AKF scale cube,4 as in Figure 15.4.

470

Figure 15.4 The AKF cube should have X-, Y-,and Z-axis scaling.

Decomposing into ServicesThe microservice approach decomposes amonolithic application along the Y-axis intoservices that satisfy a single use case or a set ofrelated functionality. These services are thenduplicated on several servers and placed behinda load balancer, X-axis split. The datapersistence may be scaled along the Z-axis bysharding the data based on a primary key.

If you decompose the applications in Figure15.3 along the Y-axis, you end up with thearchitecture in Figure 15.5.

471

Figure 15.5 Y-axis decomposition

The front-end views have been split intoseparate applications that access thefunctionality of several back-end services. Theservices have been split from the monolithicapplication into standalone applications thatmanage their own data. You can achieve splitsalong the Z-axis by sharding the data andscaling along the X-axis by clustering and loadbalancing.

You have seen how to decompose a monolithicapplication into microservices and learned theimportance of scalability for the continuance ofan application.

Now you’ll look more closely at the specificbenefits and cost of the microservicearchitecture.

472

Microservice BenefitsFrom the development perspective, the benefitsof a microservice architecture result from thesize and agility of the small applications ofwhich it consists. They are easy for developersto understand and for the IDE to manage. Alarge application that consists of manyhundreds of modules can take considerabletime to load, which negatively affects thedevelopers’ productivity. Each microserviceapplication can be deployed quicker and oftenwithout the cooperation of other teams.Because each service stands alone, localchanges to code do not affect othermicroservices; therefore, continuousdevelopment is possible. Each microservice canbe developed by a dedicated team of developerswho manage the deployment and resourcerequirements of their service independently ofother teams.

The user interface (UI) is normally divorcedfrom back-end development; your developmentteam may never see a line of UI code. If you areprogramming to a REpresentational StateTransfer (REST) API (see Chapter 13, “RESTfulWeb Services”), you are only required to honorthe resource representation contract, not tothink about the way the front end will beimplemented. This allows true separation ofconcerns.

473

From the perspective of applicationperformance, the main benefit comes frombeing able to deploy each microservice onto itsown tailored environment. The resourcerequirements of your microservice may differfrom another, thereby allowing resourceallocation to be fine grained. A monolithicapplication is deployed on one environmentwith shared resources.

Fault tolerance and isolation are increased. Afault in one microservice does not affect theoperations of the others, allowing theapplication to continue to perform. In a systemthat uses MOM to communicate betweenservices, messages destined for a failedmicroservice wait in the queue until the fault isresolved and the microservice (consumer)begins to consume the messages. If theapplication is scaled horizontally, there’s nobreak in service because one of the duplicatemicroservices consumes the messages. In amonolithic application, such a fault could bringdown the entire application.

Among all the benefits attributed to themicroservice architecture, the most talkedabout is the ease with which you can change thetechnology stack. Because each microservice issmall, rewriting it is not expensive. In fact, newmicroservices can be written in any language,allowing you to choose the most suitablelanguage for solving the problem. Technology

474

decisions made at the beginning of the projectdo not dictate the technology that you must usethroughout the application’s life.

Nothing in Life Is FreeThe benefits of the microservice architecture donot come free. There are costs involved.

The ease with which you can develop amicroservice makes it easy for the number ofmicroservices to grow, and to grow very quickly.Fifteen microservices can easily become thirtyor more, especially when different versions ofthe same microservice are counted. This posesseveral difficulties.

The responsibility for operations may move tothe development team. With only a handful ofservices to maintain, it’s not a difficult task, butas the number of microservices grows, the taskof maintaining them increases. A significantinvestment needs to be made to ensure that themicroservices are deployed and maintained.Processes need to be automated to reduce theburden of deploying and maintaining a largenumber of services. There may be a knowledgegap you need to fill, adding to the overallrunning costs.

Cross-cutting changes to semantics means thatall microservices must update their code tokeep in sync. This can be time consuming toperform and has significant retesting costs.

475

Alterations to interface contracts and messageformats can be the cause of such changes andrequire that all teams work in a coordinatedway. Equally, failing to change an interface ormessage format early on in the project results insignificantly greater costs as the number ofmicroservices grows.

Duplicated code is something that you havebeen taught is bad, and it is. In a microserviceenvironment, the risk of code duplication ishigh. To avoid coupling and dependencies, codemust sometimes be duplicated, meaning everyinstance of that code must be tested andmaintained. You may be able to abstract code toa share library, but this does not work in apolyglot environment.

The inherent unreliability and complexity ofdistributed systems are duplicated in amicroservice environment. Every service maybe hosted in a distributed way, communicatingvia networks that suffer from latency issues,incompatible versions, unreliable providers,hardware problems, and more. Constantmonitoring of network performance is vital.

ConclusionsThe monolithic architecture has been used formany years to develop applications and servessmall applications and development teams well.It’s easy to develop and test because IDEs aredesigned to manage these types of application

476

structures. But as you have seen, it does notscale well and hinders development. It isdifficult to introduce new technology, andrefactoring is expensive.

Microservices decompose into logical servicesof related functionality. Their small size makesthem easy for developers to understand.Development and deployment are continuous.Scalability is built into the architecture, and youare not stuck with initial technology decisions.

FINALLY, SOME ANTI-PATTERNSThe purpose of this book is to fill the gapbetween “classical” patterns and Java EE. Youwill find many books discussing anti-patterns,but there is no harm in discussing a few here.

Anti-patterns usually occur because of misuseof one or several patterns. A Java EE developerwho has enough experience can easily list moreanti-patterns than patterns. Here are a few thatare common or that you may already have comeacross.

Uber ClassThere is probably no single project without ahuge class that serves many purposes andresponsibilities. Not only does this violate JavaEE principles, but such classes override basicobject-oriented programming (OOP) principlesand must be avoided.

477

Services that are overloaded with manyresponsibilities fall into the same category. Ifyou are not a big fan of OOP, that’s fine, but ifyou do want to continue to write code in anOOP language, it is best to keep your classessmall and highly cohesive.

Although many others had expressed thisanti-pattern, Reza Rahman may have firstintroduced the name.

Lasagna ArchitectureJava EE promoted layers starting from the earlydays, which may have resulted in manyunnecessary interfaces and packages. Althoughthis pattern may look like an answer to uberclass and monolithic applications, usually itcomplicates things unnecessarily.

Lasagna architecture in the OOP world is notmuch different from spaghetti programming instructural programming. Too much abstractionis unnecessary and provides no help. Interfacesand loose coupling are great tools only whenyou use them in the right amount, in the rightcontext, and only when they are needed.

This anti-pattern has been expressed by manydevelopers with many different names, such asBaklava Code. However, the name lasagna mayhave been first given by Adam Bien,5 who isheavily against unnecessary use of interfaces.

478

Mr. ColombusAlmost all experienced Java EE developerswant to invent or implement their own perfectsolution. Most of the time these are onlyattempts to abstract and provide a betterinterface to a common library, such as loggingor testing, where it may even go to extremesand rewrite an important functionality that hasbeen supported by the open source communityfor years, such as an Object Relational Mapping(ORM) layer.

Although inventing something new may lookappealing, reinventing something is just a wasteof time. If you are going to write a new loggingor an ORM framework, you should really have agood reason to do it. If you don’t, you arerewriting a well-supported mature product, andmost likely you’ll end up maintaining it andproviding all the support, tests, and futuredevelopment alone.

Always make sure you have done enoughliterature searches on open source projectsbefore starting to write a framework fromscratch.

Friends with BenefitsOne huge problem of J2EE was vendor locking.By the time J2EE 1.4 was released, most vendorservers only worked with the same vendor’stools and IDEs. This looked like a mutually

479

beneficial relationship at first because thevendor provided professional support for itsown tools, and open source tools and serverswere left to the community to support.However, in the long term, many J2EEdevelopers observed how open source tools andservers provided standard behavior andcompatibility to Java specifications whenvendors failed to do so.

There is nothing wrong with buyingprofessional support and services and usingtools, servers, and IDEs from vendors as long asthe project is not locked to that vendor. Vendorlocking may introduce problems that areimpossible to solve without new releases andpatches from the vendor, whereas buildingapplications always make it possible to changeto other vendors.

Bleeding EdgePassionate developers love to use bleeding-edgetechnologies. For example, WebSockets wereintroduced many years ago, but they still suffercompatibility issues with old versions ofbrowsers. No one can argue against the joy oflearning something new and implementing ableeding-edge technology in a project.However, it may become cumbersome tosupport such projects if you are targeting themainstream.

480

A good approach to deciding which frameworkor technology to use is to see how it fits withyour target user base. If you are building abanking application for clients who may still beusing Internet Explorer 6, using WebSockets isthe best choice (although most WebSocketsframeworks provide fallback scenarios).

You always need to make sure an outsourcelibrary or framework is well supported, mature,and fits your project before moving on.

UtilitymanUtility classes and packages are common inprojects. No one can argue that you need a classto perform some math operations, such asrounding or converting different number types.If you do have such utility or helper classes, youprobably need to organize them with a packagename of util or helper, right? No, in reality,they just help you collect junk. Because utiland helper sound too generic, many classesare moved into these packages. Any class thatmay not be categorized easily will end up inyour package. The generic name does notprovide real information, so even though thoseclasses are not used anymore, no one woulddare to remove them.

If you have a great utility that everybody needsto use, just place it where it belongs with thecurrent usage and provide proper

481

documentation. You can move it to some moregeneric package in the future if needed.

Just like lasagna, Adam Bien first described andnamed this pattern.

NOTES

1. The complete list of HTTP methods is: GET,POST, DELETE, PUT, PATCH, OPTION,HEAD, TRACE and CONNECT.

2. Oracle’s WebSocket API tutorial:http://docs.oracle.com/javaee/7/tutorial/doc/websocket.htm.

3. This could introduce a development cost ifthe system makes use of HTTP session dataand there is not a clustered solution in placefor HTTP session replication.

4. The Art of Scalability: Scalable WebArchitecture, Processes, and Organizationsfor the Modern Enterprise, Martin L.Abbott, Michael T. Fisher. January 1, 2009.

5. Adam Bien. Author and Java Champion.www.adam-bien.com

482

PART IIISummaryCHAPTER 16 : Design Patterns: The Good, theBad, and the Ugly

483

16Design Patterns: The Good,the Bad, and the UglyWHAT’S IN THIS CHAPTER?

The good—how design patterns can lead tosuccess

The bad—how overuse and misuse of designpatterns can lead to trouble

And the ugly—how some “de-facto” standardscan lead to failure

So far, this book has covered many of theclassical design patterns from the GoF1 book aswell as some additional patterns that may findtheir way to becoming classics in the future.This book was written with the aim of beingsomething that the authors would have boughtthemselves if they had not written it.

As is true with everything in life, designpatterns do not always do good. They can doharm as well by leading you into implementingan anti-pattern. This chapter focuses on thegood, the bad, and the ugly aspects of designpatterns and hopefully provides a betterapproach for your heavy arsenal of patterns.

484

THE GOOD: PATTERNS FORSUCCESSAs has been mentioned many times before,design patterns are the collective wisdom andexperience of many smart developers. Theyunleash a great depth of experience that youcan utilize to solve many common problemsthat occur in software development. Even in theearly days of programming when using gotowas considered legal (and acceptable), manyprojects failed. One of the early importantresources on software engineering and projectmanagement was The Mythical Man-Monthwritten by Frederick Brooks while he wasmanaging development of OS360 for IBM.2

Although the book was published in 1975, it stilladdresses many concerns and problems inmodern software projects. At that time, one ofthe first design patterns in software wasbecoming popular: object-orientedprogramming (OOP). OOP was a set of designrules and patterns that enabled real-lifesituations to be modeled in code moreeffectively and easily. It simply offered a magicwand for designing, coding, and maintainingsoftware. Smalltalk, C++, and Objective-Cpioneered the early golden years of OOP.Although Edsger Dijkstra3 commented that“Object-oriented programming is anexceptionally bad idea which could only have

485

originated in California,” it was the first majorshift that changed how programs were written.

However, OOP was not a silver bullet either.First, using an object-oriented language did notreally mean using an object-oriented approach.Developers were, and still are, allowed to writeprocedural code in any object-orientedlanguage. Second, complex and badly designedobjects being used were at least as capable atcomplicating things as any non-OOP systems.

In the early 1990s, the famous Gang of Four,Erich Gamma, Richard Helm, Ralph Johnson,and John Vlissides, published Design Patterns:Elements of Reusable Object-OrientedSoftware, which was the first book to bringtogether a collection of solutions to commonproblems as design patterns. That book covered23 design patterns that have been referred to asclassical patterns throughout this book, andthey included code examples in C++ andSmalltalk. Over the years, many new patternshave been introduced and added to patterncatalogs by many great programmers such asJim Coplien.4

However, design patterns are not language andplatform dependent and can be implemented inany software project. Design patterns solvecommon problems and offer a commondictionary between developers. Instead ofdescribing how you implemented a callbackmechanism, which is only triggered when there

486

is a change on the resource, you can say, “Oh,we have observers on x.”

When Java was developed in the mid-1990s,many design patterns were integrated into itsrun time. Java made good use of designpatterns in its internal design and exposedmany patterns in the language itself byproviding a default implementation applicationprogramming interface (API).

With the release of Java EE, even more patternswere introduced, many of which were publishedin the book Core J2EE Patterns: Best Practicesand Design Stratgies.5

Reading pattern catalogues and learning theiruse cases does increase your knowledge ofmany common problems and how to solvethem, even before they have appeared. Thisbook has listed many war stories about how aparticular design pattern has affected theproject. These stories are from real-lifeexperiences. Reading and memorizing a patternis no guarantee of a magic solution, but it maygive you some clues and hints about how tosolve a problem when you come across a similardifficulty or challenge. Very soon, and withexperience, you will end up addressingproblems even before they have occurred byusing an appropriate pattern.

Initially, the J2EE programming model reliedheavily on Extensible Markup Language (XML)

487

configuration and a heavyweight EnterpriseJavaBeans (EJB) container. Beans needed toextend specific classes and implement eachmethod to work properly. Very soon, thisapproach proved not to be productive andalmost became an anti-pattern. AlthoughSpring6 offered a lightweight containerapproach, the upcoming design of Java EEfavored inline code annotations overconfiguration files. The lightweight containerand EJB based on Plain Old Java Objects(POJOs) offered a productive and easy-to-testprogramming model. Subsequent releases ofJava EE offered many desired features, most ofwhich have been covered throughout the book.Finally, Context and Dependency Injection(CDI) introduced a new container with greatflexible features. With the help of CDI, you canimplement many patterns, such as observer anddecorator, with little hassle.

WAR STORY

When I was given the responsibility to workon the Eclipse Libra project, I had limitedknowledge of Eclipse plug-ins. After readingthe only available book, Eclipse: BuildingCommercial-Quality Plug-Ins, by Dan Rubeland Eric Clayberg (Addison-Wesley, 2008), I

488

decided to jump into the existing codebase inthe Eclipse repository.

Very soon, I was amazed with the overallarchitecture of Eclipse and how the plug-inswere built. Design patterns such as adapter,decorator, strategy, memento, and manyothers were everywhere, used in the rightcontext, and they provided an efficient andclear implementation.

Eclipse code repository is one of the best livesources for good implementation of designpatterns in a real-world project that millionsof developers use.

THE BAD: OVER AND MISUSE OFPATTERNSThe first training I received on design patternssimply blew my mind. The following month Ispent all my time reading Head First DesignPatterns7 and next, of course, the GoF book. Iwas armed with the knowledge of patterns andwas ready to use them. As time passed by, Irealized I didn’t even need to use inheritanceand could build all models and objecthierarchies with decorators. I even created a setof utility classes consisting of several singletons,some message busses for observers, and some

489

generic decorator and observers that I alwaysincluded when I created a new project.

I was always proud to show my code and letothers see how great and sophisticated aprogrammer I was. It did not take long torealize my way of using design patterns was justover-complicating my code and adding toomany layers during run time. Even simplifyingthe existing code resulted in betterperformance. Complex and sophisticated codedoes not make you a better programmer, and itdoesn’t make the code optimized andmaintainable. Engineering is the art of usingthe right tool at the right place and building asystem efficiently.

WAR STORY

I was once asked to implement a datastructure to handle transactional databaseoperations for a job I was applying for. I wasto complete the code at home and send itback to the company for review via e-mail.The system would be able to add new valuesand perform a save operation once a commitwas done. Also, the system would be able togo back to a previous state when a rollbackwas executed. Little voices in my head werescreaming, “Memento!” Although I had neverneeded to apply memento until that day, I

490

knew it was a perfect match. The mementopattern would let me commit to a save pointthat I could then roll back. So I set aboutrevising my knowledge of the mementopattern’s implementation. I created myCaretaker, Memento and Originatorclasses, placed them in an internal package,and implemented the database logic codethat uses internal memento classes.

I was proud and confident about the code Idelivered. Surprisingly (for me), the companydidn’t want to continue with the interviewprocess. Maybe it was looking for someonewho would use a simple stack to push andpull values, but the code I delivered gave meconfidence in my knowledge of designpatterns, even for the patterns I don’t useoften.

After going back over the original questionyears later, I realized there were performanceconstraints of using minimal objects and anO(log N) runtime performance. My code wasreadable, clean, and maintainable, but itfailed to address the key points that theinterviewer asked in the first place.

If knowing a pattern blinds you to makinggood decisions, design patterns do moreharm than good.

491

…AND THE UGLYDesign patterns and Java EE are old pals.However, this friendship did not always workout well. As J2EE became more accepted in thecorporate world and began addressing largeprojects, design patterns came to the rescue.Many of the classical patterns from GoF foundtheir place in J2EE applications. Enterprisepatterns followed soon after to addresscommon problems in the J2EE platform.

J2EE gained popularity and drove many newconcepts such as Service OrientatedArchitecture (SOA) and Web Services.However, the complex structure of J2EEdoomed many projects to fail. J2EE beansrelied on extending classes and needed aheavyweight container on which to run.Because the beans rely on the container, thedevelopment process needed full-blownheavyweight servers to slow down thedevelopment and needed costly hardware torun on. Still, those enterprise containers wereslow, resulting in sluggish restarts andrefreshes. Testing and unit testing was hard toperform properly.

Besides, J2EE configuration was heavy andrelied on XML files. Although separating theconfiguration and code seemed like a good idea,soon it turned out to be an XML hell. Heavyconfiguration was needed to create a simplebean.

492

As J2EE became the platform of the enterprise,consultants, architects, and vendors releasedsophisticated guidelines that resulted inover-complex, over-architected, and overlylayered applications that were impossible totest and hard to develop (due to long restarts),debug, and deploy.

Luckily, Enterprise Java had a happy ending.The POJO and lightweight container movementled by Rod Johnson8 gained a huge followingand soon became a competitor to J2EE. Springoffered a lightweight container and the abilityto run on simple Java servers. The POJOapproach was great for testing and did not needthe container most of the time, but even if thecontainer was needed, it was not hard to use.

The success of Spring caused a renaissance inthe Java Community Process. Java EE 5 wasdesigned from scratch to support POJO EJBand lighter containers. Java EE had evolved andmatured.

However, old habits and developmenttechniques did not change overnight. Still,many developers follow the patterns of J2EE,creating overly layered and complexapplications while not using the lightweightcontainers and servers. Just like the Englishlanguage has changed since Shakespeare’s time,platforms and programming languages havechanged. Don’t get stuck in the past by resistingchange.

493

WAR STORY

It was the early days of J2EE 1.4, and wewere to implement the next generation ofbanking systems. We had implemented allthe best practices, patterns, guidelines, andanything else we could find in books andonline resources.

Our application was heavily dependent on aparticular vendor and was not portable. Wehad to run the vendor integrateddevelopment environment (IDE) and thevendor server, and this was in the age of 32bits when Windows refused to address morethan 3GB of RAM. The server and IDE wereso slow when started in debug mode that wedid not need breakpoints to stop execution.

The vendor assured us that the productionenvironment was going to be fast;nevertheless, the development life cycle waslike a ball and chain. We could easily go forcoffee breaks while the server restarted.

Things got even more fun when we wanted togo live. The production environment turnedout to be as slow as the development boxes.Soon we all had the habit of watching prodand test environment’s memory statuses.

494

Finally, we hired a famous consultant toshow us what we were doing wrong. He wasan old and wise guy whom we treated likeGandalf. After reviewing our code for a fewdays, he asked us to delete almost all façades(we had façades for almost every bean) andall unnecessary interfaces (again, we almosthad interfaces for interfaces). He also askedus to minimize our lasagna-like layers bycutting down the call hierarchy (EJB callingEJB calling EJB…).

It was the J2EE 1.4 days with heavy vendorservers, so nothing magical happened. Still,we gained some performance and at leastachieved much readable code.

Assuming that everything may change,developing with needs for flexibility in minddoes not offer an easier future but mostprobably a more crippled today.

SUMMARYDesign patterns are one of the most important,challenging, and useful topics in software. Noobject-oriented programmer would be completewithout proper knowledge of common designpatterns.

Good knowledge provides a great toolset forcommon problems you are likely to face. Java

495

EE takes this a step further and introduces amuch easier and integrated way to use designpatterns in enterprise projects. Most patterns inJava EE have been introduced after longdebates and pain, which ensures they are wellimplemented and mature.

All patterns described in this book rely on JavaEE standards, so they are almost guaranteed towork successfully.

Still, patterns are neither silver bullets normagic wands. If they are used extensivelywithout reason, they tend to overcomplicate theproject. Knowing a pattern does not necessarilymean you have to use it unless you know it fitsand solves a potential problem.

Read and learn design patterns, and try to keepyour memory fresh on where they fit and whatproblems they solve. You will save many lines ofcode and earn respect.

NOTES

1. Design Patterns: Elements of ReusableObject-Oriented Software (Addison-Wesley,1994): Erich Gamma, Richard Helm, RalphJohnson, John Vlissides.

2. The Mythical Man-Month: Essays onSoftware Engineering (Addison-Wesley,1975): Frederick P. Brooks Jr.

496

3. Edsger Wybe Dijkstra was a Dutch computerscientist who received the 1972 TuringAward for fundamental contributions todeveloping programming languages.

4. James O. Coplien is an author, lecturer, andresearcher in computer science.

5. Core J2EE Patterns: Best Practices andDesign Strategies (Prentice Hall, 2003):Deepak Alur, Dan Malks, John Crupi.

6. A Java-based framework that provides manyfeatures including dependency injection andaspect-orientated programming.

7. Head First Design Patterns (O’Reilly, 2004):Eric Freeman, Elisabeth Robson, Bert Bates,Kathy Sierra.

8. Rod Johnson is an Australian computerprogrammer who created the Springframework.

497

PROFESSIONALJava® EE DesignPatterns

Murat YenerAlex Theedom

498

499

Professional Java® EE Design Patterns

Published byJohn Wiley & Sons, Inc.10475 Crosspoint BoulevardIndianapolis, IN 46256www.wiley.com

Copyright © 2015 by John Wiley & Sons, Inc.,Indianapolis, Indiana

Published simultaneously in CanadaISBN: 978-1-118-84341-3ISBN: 978-1-118-84358-1 (ebk)ISBN: 978-1-118-84345-1 (ebk)

No part of this publication may be reproduced,stored in a retrieval system or transmitted in anyform or by any means, electronic, mechanical,photocopying, recording, scanning or otherwise,except as permitted under Sections 107 or 108 of the1976 United States Copyright Act, without either theprior written permission of the Publisher, orauthorization through payment of the appropriateper-copy fee to the Copyright Clearance Center, 222Rosewood Drive, Danvers, MA 01923, (978)750-8400, fax (978) 646-8600. Requests to thePublisher for permission should be addressed to thePermissions Department, John Wiley & Sons, Inc.,111 River Street, Hoboken, NJ 07030, (201)748-6011, fax (201) 748-6008, or online athttp://www.wiley.com/go/permissions.

Limit of Liability/Disclaimer of Warranty:The publisher and the author make norepresentations or warranties with respect to the

500

accuracy or completeness of the contents of this workand specifically disclaim all warranties, includingwithout limitation warranties of fitness for aparticular purpose. No warranty may be created orextended by sales or promotional materials. Theadvice and strategies contained herein may not besuitable for every situation. This work is sold with theunderstanding that the publisher is not engaged inrendering legal, accounting, or other professionalservices. If professional assistance is required, theservices of a competent professional person shouldbe sought. Neither the publisher nor the author shallbe liable for damages arising herefrom. The fact thatan organization or Web site is referred to in this workas a citation and/or a potential source of furtherinformation does not mean that the author or thepublisher endorses the information the organizationor Web site may provide or recommendations it maymake. Further, readers should be aware that InternetWeb sites listed in this work may have changed ordisappeared between when this work was writtenand when it is read.

For general information on our other products andservices please contact our Customer CareDepartment within the United States at (877)762-2974, outside the United States at (317)572-3993 or fax (317) 572-4002.

Wiley publishes in a variety of print and electronicformats and by print-on-demand. Some materialincluded with standard print versions of this bookmay not be included in e-books or inprint-on-demand. If this book refers to media suchas a CD or DVD that is not included in the versionyou purchased, you may download this material athttp://booksupport.wiley.com. For more

501

information about Wiley products, visitwww.wiley.com.

Library of Congress Control Number:2014946684

Trademarks: Wiley, the Wiley logo, Wrox, theWrox logo, Programmer to Programmer, and relatedtrade dress are trademarks or registered trademarksof John Wiley & Sons, Inc. and/or its affiliates, in theUnited States and other countries, and may not beused without written permission. Java is a registeredtrademark of Oracle America, Inc. All othertrademarks are the property of their respectiveowners. John Wiley & Sons, Inc., is not associatedwith any product or vendor mentioned in this book.

502

To Nilay and all my family (Semra andMusfata Yener), for all your support and time Ineededto write this book.

—MURAT

To Mariu, for all your support andencouragement.

—ALEX

503

ABOUT THE AUTHORSMURAT YENER is a code geek and opensource committer, working at Intel New DevicesGroup as an Android developer. He hasextensive experience with developing Java, webframeworks, JavaEE, and OSGi applications, inaddition to teaching courses and mentoring.Murat is an Eclipse committer and one of theinitial committers of the Eclipse Libra project,he is currently working on building native andHybrid mobile apps with HTML5 and mGWT.

Murat has been a user group leader at GDGIstanbul since 2009, organizing, participating,and speaking at events. He is also a regularspeaker at JavaOne, EclipseCon, and Devoxxconferences.

Linkedin—www.linkedin.com/in/muratyener

twitter—@yenerm

blog—www.devchronicles.com

ALEX THEEDOM is a Senior Java Developerat Indigo Code Collectiveindigocodecollective.com (part of the E-scapeGroup) where he played a pivotal role in thearchitectural design and development of amicroservice based, custom built lottery andinstant win game platform.

504

Prior to that, he developed ATM software for aninternational Spanish bank and code qualityanalysis software for a software consultancy.

Alex is experienced with Java web applicationdevelopment in a diverse range of fieldsincluding finance, e-learning, lottery andsoftware development. His passion fordevelopment has taken him to projectsthroughout Europe and beyond. He is a bloggerat alextheedom.com and can be found helpingfellow problem solvers in online forums.

Linkedin—www.linkedin.com/in/alextheedom

Twitter—@alextheedom

Blog—www.alextheedom.com

505

ABOUT THE TECHNICALEDITORMOHAMED SANAULLA is a SoftwareDeveloper with over five years of professionalexperience developing software. He is currentlyworking for India's largest e-Commerceestablishment and is also a moderator on theJavaRanch Forums. When he is not working onhis PC, he is busy tending to his cute littledaughter. He shares his experiments andthoughts on software development athttp://blog.sanaulla.info.

506

CREDITS

ASSOCIATE PUBLISHERJim Minatel

PROJECT EDITORAdaobi Obi Tulton

TECHNICAL EDITORMohamed Sanaulla

PRODUCTION MANAGERKathleen Wisor

COPY EDITORKaren A. Gill

MANAGER OF CONTENTDEVELOPMENT AND ASSEMBLYMary Beth Wakefield

MARKETING DIRECTORDavid Mayhew

507

MARKETING MANAGERCarrie Sherrill

PROFESSIONAL TECHNOLOGY ANDSTRATEGY DIRECTORBarry Pruett

BUSINESS MANAGERAmy Knies

PROJECT COORDINATOR, COVERPatrick Redmond

PROOFREADERNancy Carrasco

INDEXERJohn Sleeva

COVER DESIGNERWiley

COVER IMAGE© iStock.com/pavlen

508

BACKGROUND© PhotoAlto Images/Fotosearch

509

ACKNOWLEDGMENTSAS MY COAUTHOR Alex always says, wewanted to write a book we would like to ownand read for ourselves. To begin with, I want tothank Alex for all his patience, hard work, andgreat knowledge. Without him, this bookwouldn't be nearly as good.

I am grateful to Mary James, our formeracquisitions editor, who contacted me aboutwriting a book on Spring but listened to myideas that formed the basis of this book.Without her support and guidance, this bookwouldn't have become a reality. No wordswould be enough to thank Adaobi Obi Tulton,who patiently worked on all the details whilekeeping most of the schedule stresses awayfrom us. And thanks, of course, to everyone atWrox/Wiley who got this book on the shelves.Thanks, also, to Reza Rahman for all hisencouragement.

I must thank three important people who had ahuge impact on where I am in my professionallife in terms of software.

First, thanks to my dad, Mustafa Yener, forbuying me my first computer, a C64, at an earlyage while I was asking for slot cars. Thatcomputer is where I wrote my very first codes.

510

Second, thanks to my thesis advisor, Prof.Mahir Vardar, whom I owe all the earlyguidance I needed to start my career.

Finally, thanks to my life-time mentor andfriend (also my ex-boss) Naci Dai, who taughtme almost anything I know about being aprofessional software developer.

—MURAT

WE ARE VERY PROUD of this, our firstbook, and hope that you will get as much fromreading it as we have writing it. We approachedwriting this with the perspective that it shouldbe the kind of book we would buy if we hadn'twritten it. We have achieved that.

However, this book would not have beenpossible without the dedication, patience, andunderstanding of the many others who havecontributed directly and indirectly to itscreation. We would like to acknowledge thecontributions made by the dedicated andexperienced team at Wiley Publishing. Theyhave stuck with us through thick and thin andbelieved that it was all possible. We would liketo give special thanks to Mary James, ouracquisitions editor, whose support made thisbook a reality. Thanks also to Adaobi ObiTulton, whose patience and gentle nudges keptus on our toes and whose attention to detailsaved us from tripping over ourselves. I would

511

like to thank my coauthor, Murat Yener, for hisinspiration and sense of humor that makes thisbook unique; and finally, but not least, I wouldlike to thank my wife, Maria Eugenia GarcíaGarcía, for her total support and understandingwhile writing this book. Thank you.

—ALEX

512

513

WILEY END USER LICENSEAGREEMENTGo to www.wiley.com/go/eula to access Wiley’sebook EULA.

514

WILEY END USER LICENSEAGREEMENTGo to www.wiley.com/go/eula to access Wiley’sebook EULA.

515