Wednesday, November 25, 2015

Book Review: Digital Java EE 7 Web Application Development

Packt Publishing recently (September 2015) published Peter Pilgrim's Digital Java EE 7 Web Application Development with the subtitle "Develop Java enterprise applications to meet the emerging digital standards using Java EE 7." Digital Java EE 7 Web Application Development contains 9 chapters and 4 appendices spanning over 400 pages. The book's subtitle is "Develop Java enterprise applications to meet the emerging digital standards using Java EE 7."

Preface

The Preface of Digital Java EE 7 Web Application Development states that the book is "a continuation of the first book Java EE 7 Developer Handbook" with Digital Java EE 7 Web Application Development focusing on "the Java presentation tier." The Preface adds that "the book was written for the developers who want to become superior and adept at building a web application on JVM with the standard Java EE 7 platform" and with specific focus on JavaServer Faces with some coverage of JavaScript and AngularJS.

The Preface contains short summaries (2-3 sentences each) of each of the book's chapters and appendices. It also lists the software necessary to run the examples provided in the book: Java 8, GlassFish 4.1, Gradle 2.6, Chrome DevTools, Firefox Developer Tools, "Chris Pederick's Web Developer and User Agent Switcher extensions", and "a decent Java Editor or IDE for coding."

In describing "who this book is for," the Preface of Digital Java EE 7 Web Application Development states, "this book is pitched at intermediate Java developers" with "a good command over the programming language" that includes Java SE knowledge of "classes, inheritance, and Java Collections" and Java EE knowledge of "Java persistence, Java servlets, and deployment of the WAR files to an application server."

Chapter 1: Digital Java EE 7

The initial chapter of Digital Java EE 7 Web Application Development begins with a high-level introduction to working in the digital domain and looks at how Java fits inside the digital domain. There is specific focus on recent changes in Java 8 including removal of PermGen, introduction of the G1 garbage collector and introductory code listing and explanatory text related to lambda expressions.

Chapter 1 also looks at JavaScript with specific focus on JavaScript libraries such as jQuery, AngularJS, and GruntJS. The chapter provides a brief overview of Java EE 7 features that are applicable in the digital design world and introduces application servers that implement Java EE 7 including GlassFish 4.1, Payara Server, and WildFly. There is also a brief introduction (with code listing) to JavaServer Faces.

Chapter 2: JavaServer Faces Lifecycle

JavaServer Faces (JSF) is the exclusive topic of Chapter 2 of Digital Java EE 7 Web Application Development. The chapter introduces JavaServer Faces with a historical perspective and references terminology such as responsive design, mobile web design, Digital by Default, and Default to Open. A brief history of JSF is outlined and some key new features of JSF 2.2 are listed. Arguments for choosing JSF over other Java-based web frameworks are also made and mostly center around JSF being a standard.

The second chapter introduces Model-View-Controller (MVC) and describes how JSF implements MVC. The chapter provides a high-level overview of Facelets and looks at the JSF request processing lifecycle. The chapter provides multiple JSF code listings and demonstrates JSF features such as JSF annotations, expression language, web descriptor, and JSF XML namespaces. After providing another JSF code example, Chapter 2 returns to more in-depth coverage of expression language.

Chapter 3: Building JSF Forms

Like the second chapter, Digital Java EE 7 Web Application Development's third chapter is JSF-centric, but does include some HTML5/CSS/Bootstrap code in the example that is built throughout the chapter. This chapter begins with an example of implementing a CRUD-oriented application using a JSF Facelet with Bootstrap via passthrough. Several JSF tags and tag libraries are introduced as they are applied in the example being built up in Chapter 3. The example constructed in Chapter 3 also demonstrates use of Java Persistence API (JPA) as functionality to allow contacts to be created, read, updated, and deleted is added.

One of the things that can be confusing to someone new to JavaServer Faces is the difference between the older JSF managed beans and the newer CDI-based beans. The third chapter concludes with a discussion that addresses this.

Chapter 4: JSF Validation and AJAX

The fourth chapter of Digital Java EE 7 Web Application Development begins with an explanation of why validation is important in web applications and then introduces and contrasts server-side validation with client-side validation. The chapter then details using the h:message and h:messages JSF tags to display errors.

Chapter 4's coverage of validation in JSF introduces "two main ways of achieving validation": Java EE 7's Bean Validation 1.1 and "traditional" JSF validation. The chapter provides a code example, a table of relevant annotations, and explanatory text in its introduction of bean validation. Explanatory text and code listings are also provided in the introduction to JSF validation.

This fourth chapter also introduces applying the attributes requiredMessage, validatorMessage, and conversionMessage for custom messages. The chapter looks at overriding validation messages globally via properties files and demonstrates adding a custom validation method to a rendering tag.

The section of Chapter 4 on custom validators demonstrates creating a custom validator by writing a class that implements javax.faces.validator.Validator and annotating it with @javax.faces.validator.FacesValidator. The "Converters" section of Chapter 4 describes converters as "JSF classes that convert between strings and objects" and then provides detailed discussion and code examples implementing a custom converter.

Chapter 4 also looks at "validating immediately with AJAX." This section introduces Ajax and JSF's "built-in support for AJAX requests and responses." It introduces <f:ajax>, provides multiple code listings demonstrating use of it, provides a table of its attributes, and looks at how it relates to the JSF lifecycle.

One of Chapter 4's major sections is "Handling views" and this concluding section of the chapter covers invoking and passing parameters to controller methods, invoking an action event listener, redirecting pages, and debugging JSF with <ui:debug>.

Chapter 5: Conversations and Journeys

Chapter 5 of Digital Java EE 7 Web Application Development focuses on "JSF conversation scope." The chapter begins by looking at how JSF integrates Context and Dependency Injection (CDI) context and dependency injection. The chapter defines "conversational scope" as "defined by a lifecycle that spans many HTTP requests to the server." The @javax.enterprise.context.ConversationScoped annotation and the CDI-injected javax.enterprise.context.Conversation interface are introduced and demonstrated early in this chapter before coverage of the lifecycle of a conversation scoped bean.

There are several screen snapshots and code listings in this chapter. These payday loan application examples include application of Bootstrap CSS and JSF 2.2's support for HTML5-friendly pages with new namespace http://xmlns.jcp.org/jsf. They illustrate applying Ajax, jQuery, and the HTML5 Range element.

The final major section of the fifth chapter covers JSF custom components. An example of a custom component implemented with an XHTML-defined Facelet view backed by a backing bean is provided. Another portion of this section introduces the JSF 2.2 ability to "generate the custom tag without specifying any XML declaration."

Chapter 6: JSF Flows and Finesse

Digital Java EE 7 Web Application Development's sixth chapter emphasizes what I think may be the most interesting feature of JSF 2.2: Faces Flows. The chapter begins by explaining the use cases and sample applications that inspired and can make most use of Faces Flow before delineating some key characteristics of Faces Flow. Several early sections use code listings to demonstrate use of annotations (such as @javax.faces.flow.FlowScoped) and other Faces Flow concepts in simple flows.

Chapter 6 demonstrates use of the <error-page> element to declare "an association between an exception type and a page view" that allows for nicer presentation of the "one of the most notorious exceptions" encountered in JSF-based applications (javax.faces.application.ViewExpiredException).

The sixth chapter also looks at complex flows. It demonstrates and describes flows that switch on different cases (conditional) and nest flows. In addition to the inline explanatory examples, the chapter includes a "a real-world example" with significant discussion on security-related aspects.

Faces Flows is not the only JSF 2.2 feature covered in Chapter 6. The chapter also introduces Resource Library Contracts. Several nuances are demonstrated with code listings and there is a section on using Resource Library Contracts in conjunction with Faces Flows. The chapter concludes with a bullet list of tips for using Faces Flows.

Chapter 7: Progressive JavaScript Frameworks and Modules

Chapter 7 of Digital Java EE 7 Web Application Development begins with the observation that "in the contemporary way of building a website, there is no escape from the language of JavaScript because it is a de facto standard of modern web browsers." Although earlier chapters touched on JavaScript and related technologies, this is the first chapter that focuses on something other than JSF. The focus of the chapter is JavaScript and JavaScript libraries and frameworks.

The seventh chapter begins with an introduction to the basics of JavaScript. After covering some of the basics and gotchas of JavaScript and introducing some JavaScript features in comparison to similar Java features, the chapter moves onto introducing jQuery (and sizzle) in more detail. Along with demonstrating use of jQuery for DOM manipulation and simple animation, the chapter also demonstrates including jQuery code in a JSF application.

RequireJS, Underscore, and Grunt are also introduced in Chapter 7. There are several pages devoted to each that introduce some key features and uses of each framework.

Chapter 8: AngularJS and Java RESTful Services

The eighth chapter of Digital Java EE 7 Web Application Development shifts from JSF to an "alternate design mode." I like the author's articulation (probably because it coincides with my own observations) of where JSF fits best and where this alternate design mode fits best. Pilgrim writes:

The design philosophy behind building an application on a single page such that it resembles a desktop application is in marked contrast to the JavaServer Faces' original design of navigation links between pages. ... JSF lends itself to applications that are extremely stateful in nature and design, where the customer journey is based on page-to-page navigation.

After successfully explaining why JSF in not a good fit for the single-page design model, the author lists some advantages and disadvantages of the single-page model. An example of a single-page application for this chapter is introduced and is related to managing case worker information. This example is defined in more detail after the AngularJS coverage.

Chapter 8 introduces one of the trendiest and most popular web development frameworks in AngularJS. The introduction is fairly thorough for only being part of a single chapter. Significantly more details of AngularJS are illustrated with a return to the caseworker application implemented with AngularJS. The casework sample application demonstrates use of Java EE features such as JPA, REST-based web services with JAX-RS, and WebSocket in addition to AngularJS.

Chapter 9: Java EE MVC Framework

The final chapter of Digital Java EE 7 Web Application Development is a future-looking chapter that looks past Java EE 7 and introduces the JSR 371: Model-View-Controller (MVC 1.0) Specification. The chapter explains why this specification is being planned for Java EE 8 and also introduces a reference implementation of it (Ozark). Because Java EE 8 (JSR 366) is still forthcoming, Pilgrim warns the reader of this chapter, "the information here is subject to change because MVC is evolving."

This ninth chapter introduces the new package called javax.mvc and the @javax.mvc.Controller annotation. The chapter then explains and illustrates applying MVC 1.0 with JAX-RS annotations. The examples and explanations also cover using JSF for the view portion and using the javax.mvc.Models interface for the model portion of an MVC 1.0-based application.

Chapter 9 introduces JavaScript-based Handlebars.js (and Mustache) and then segues from there into an introduction of the Java port of this. Several pages are devoted to building up the example of the application using Ozark and Handlebars for Java.

The final chapter concludes with a look at a couple ways in which the Java MVC 1.0 specification might still change and with a discussion of design considerations when using Java MVC.

The Appendices

Appendix A ("JSF with HTML5, Resources, and Faces Flows") is a "quick reference" on the JSF library. The first part of this appendix is a standard library reference with emphasis on Java EE 6 (JSF 2.0) and Java EE 7 (JSF 2.2) versions of JavaServer Faces. The second part covers Faces Flows with a thorough reference.

Appendix B ("From Request to Response") covers common topics associated with a web application's architecture. These topics include HTTP (protocol itself, advancements, request methods and response codes), standard Java EE web architecture (servlet + CDI + EJB), extended Java EE web architectures (NoSQL, Model-View-ViewModel, Java Temporary Caching, embedded server/containerless system, microservices), and brief discussion addressing the question, "Is it important to be known as a full stack developer?"

Appendix C ("Agile Performance – Working inside Digital Teams") consists on ten pages that look at structure of agile digital development teams and roles on those teams.

Appendix D ("Curated References") is over six pages of "references around the digital software development" that are categorized "into concepts and themes" of "Service delivery", "Agile and leadership", "Architecture", "User interface", and "Java EE and JVM technology." Because these references include URLs, it is easy to click on these in the electronic versions to be taken directly to the referenced resource.

What is Digital Java EE 7 Web Application Development and Who Is It Best Suited For?

One of the most valuable insights I believe I can provide to someone trying to decide whether to purchase or borrow this book is to articulate what this book covers and who it is best suited for. I attempt that here.

  • Digital Java EE 7 Web Application Development provides significant coverage of JavaServer Faces (JSF).
    • Chapters 2 through 6 are almost exclusively JSF-focused and JSF has significant presence in Chapter 1 and Chapter 9.
    • It's not just JSF, however, and covers using HTML5 and related popular frameworks and libraries with JSF.
    • Chapter 8 (single-page applications with AngularJS) is not JSF at all.
  • Digital Java EE 7 Web Application Development focuses on newer JSF features.
    • As its title implies, the focus of this book is on Java EE 7 and JSF 2.2 with some mention of Java EE 6 (JSF 2.0).
    • This is probably NOT the book you want to get to learn JSF for the first time, but rather is more suited for someone with minimal JSF experience through JSF 2.0 who wants to learn what's available in JSF 2.2 and Java EE 7.
  • Digital Java EE 7 Web Application Development provides broad coverage of developing Java EE 7 web application user interfaces.
  • Digital Java EE 7 Web Application Development is most likely to appeal to these types of developers:
    • Intermediate-level (or advanced) Java developers (as described in the book's preface) who have only basic familiarity with JSF and want to learn more about newer (Java EE 7/JSF 2.2) JSF features.
    • Java developers with only limited awareness of modern web client technologies and frameworks who want to learn how to use JSF with HTML5 and related technologies.
    • Java developers who want a broad view of the currently favored and standard Java EE 7 technologies for web development and want an introductory chapter on Java EE MVC coming with Java EE 8.
  • Digital Java EE 7 Web Application Development may not meet expectations of these types of developers:
    • Developers looking for an introduction to JavaServer Faces; this book is better suited to developers with at least minimal JSF experience as it's not an introductory book and it mostly focused on newer JSF features.
    • Developers looking for a reference on HTML5, JavaScript, CSS or related frameworks and libraries such as AngularJS, jQuery, and Bootstrap; although this book does introduce using these technologies with JSF, the coverage of these particular technologies is mostly introductory.
    • Developers looking for a book on developing Java-based web applications with JAX-WS (SOAP/WSDL-based web services), Java servlets, or one of the many available non-standard Java/JVM web frameworks; this book does not cover these older and/or non-standard technologies and instead focuses it coverage on JSF 2.2 and JAX-RS.

Other General Observations

The following are some general observations and opinions of mine formed while reading the PDF version of Digital Java EE 7 Web Application Development provided to me by Packt Publishing.

  • Digital Java EE 7 Web Application Development includes numerous code examples
    • Code listings tend to build upon same simple example applications that highlight benefits and advantages of the approach being demonstrated.
    • Code listings are black font on white background with no color syntax highlighting and no line numbers even in the electronic (PDF) version of the book that I read.
    • I liked that there are extensive code listings and understand that printed books would not be able to have color syntax highlighting, but having color syntax in the code examples (especially the larger ones) or otherwise emphasized code would have helped with code readability.
    • I recommend acquiring code listings in Pilgrim's GitHub repository so that an IDE or text editor can be used to view the code.
  • There are several color screen snapshots in the PDF version of Digital Java EE 7 Web Application Development to help illustrate the web pages rendered by JSF and related web technologies. There are also color graphics for illustrating concepts in the electronic version.
  • Although Digital Java EE 7 Web Application Development is a Java EE book, it does a nice job of inserting some Java SE 7 JDK libraries in the examples. In particular, the Java 8 date/time library is used multiple times and Chapter 1 introduces lambda expressions.
  • For the most part, Digital Java EE 7 Web Application Development reads fairly well. However, as with several other Packt Publishing titles I have reviewed, it could have used more editing. There are several typos in Digital Java EE 7 Web Application Development, but these rarely prevent the content from being understood. To help convey the type of typos for you to judge how they might impact your ability to understand what is being communicated, I include some examples here:
    • "SERVERITY_WARNING"
    • "these tags render the content from the javax.faces.HtmlMessages and javax.faces.HtmlMessages components respectively"
    • "The JavaScript support functions as a first-class citizen and rules on a and supports the declaration of functions..."
    • "JSF 1.0 was created in the early noughties,..."
    • "...new package structure reserved for MVC under javax.mvc. The @javac.mvc.Controller annotation..."
  • Each of the chapters has a set of questions and exercises at the end of the chapter. I didn't run through any of these and cannot comment on the benefits of them. I also am not aware of any answers or solutions being provided for any of the exercises or questions.
  • Pilgrim references his other Packt title, Java EE 7 Developer Handbook, several times in this book for readers who need additional background Java EE details, particularly in areas outside of the user interface.
    • Reviews for the earlier book probably provide good indicators of what one can expect from Digital Java EE 7 Web Application Development. Indeed, I noticed that several of the positive and negative comments on Amazon.com apply to the book I'm reviewing as well. As of this writing, there are 10 reviews of Java EE 7 Developer Handbook on Amazon.com with an average 3.8 (out of 5) rating.
  • Find the author's own description of his book in the blog post My Digital Java EE 7 book is now published.

Conclusion

Digital Java EE 7 Web Application Development provides a survey of the most popular Java EE 7 approaches for developing web applications. JavaServer Faces receives the lion's share of the discussion with focus particularly on Java EE 7's version of JSF (2.2). Digital Java EE 7 Web Application Development introduces JavaScript and AngularJS and discusses using HTML5 technologies, libraries, and frameworks with JSF. There is also forward-looking chapter on Java EE 8's forthcoming Java EE MVC. Digital Java EE 7 Web Application Development is a book largely on modern JSF, but it's not accurate to say it's only a JSF book and it's probably not the best introductory book for those who have never used JSF. Instead, this book is best suited for Java developers with some awareness of JSF, but who want to learn more about JSF 2.2 and integrating JSF with other non-Java web languages, libraries, and frameworks.

Tuesday, November 10, 2015

Does PostgreSQL Have an ORA-01795-like Limit?

The Oracle database requires that no more than 1000 entries be used in a SQL IN portion of a WHERE clause and will throw an ORA-01795 error if that number is exceeded. If a value needs to be compared to more than 1000 values, approaches other than use of IN must be applied. I wondered if this limitation applies to PostgreSQL and decided to write a simple application to find out.

For my simple test application, I wanted a very simple table to use with both an Oracle database and a PostgreSQL database.

Oracle: Creating Single Column Table And Inserting Single Row
CREATE TABLE numeral(numeral1 number);
INSERT INTO numeral (numeral1) VALUES (15);
PostgreSQL: Creating Single Column Table and Inserting Single Row
CREATE TABLE numeral(numeral1 numeric);
INSERT INTO numeral (numeral1) VALUES (15);

Building the SQL Query

Java 8 makes it to build up a query to test the condition of more than 1000 values in an IN clause. The next code snippet focuses on how this can be accomplished easily.

Java 8 Construction of SQL Query
final String queryPrefix = "SELECT numeral1 FROM numeral WHERE numeral1 IN ";
final String inClauseTarget =
   IntStream.range(1, numberOfInValues+1).boxed().map(String::valueOf).collect(Collectors.joining(",", "(", ")"));
final String select = queryPrefix + inClauseTarget;

The string constructed by the Java 8 code shown in the last code listing looks like this:

SELECT numeral1 FROM numeral WHERE numeral1 IN (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001)

Running the Query

When the above SQL query statement is executed against an Oracle database, the ORA-01795 error is manifest:

java.sql.SQLSyntaxErrorException: ORA-01795: maximum number of expressions in a list is 1000

The PostgreSQL database does not have this same limitation as shown by its output below:

15

The full Java class I used to demonstrate the above findings in available at https://github.com/dustinmarx/databasedemos/blob/master/dustin/examples/inparameters/Main.java.

Conclusion

There are numerous ways to avoid the ORA-01795 error when using an Oracle database. However, I was curious if the same limitation existed for PostgreSQL and apparently it doesn't (I'm using PostgreSQL 9.4.4 in these examples). In fact, when I tried as many as one million IN values, PostgreSQL was still able to process the query, albeit noticeably slower than with a smaller number of IN values.

Tuesday, November 3, 2015

What Might a New @Deprecated Look Like?

JDK Enhancement Proposal (JEP) 277 ("Enhanced Deprecation") proposes to "revamp the deprecation annotation and provide tools to strengthen the tail end of the feature life cycle." Some of the limitations of the current @java.lang.Deprecated have bothered me for some time. I particularly would like to be able to provide text with @Deprecated rather than being forced to place explanatory text in a corresponding Javadoc @deprecated comment. In this post, I look at a custom annotation that gives a feel for the type of extra metadata JEP 277 proposes be included in a new and improved @Deprecated annotation.

The code listing that follows contains the definition of dustin.examples.annotations.Deprecated, an implementation which mostly mirrors what is described in the JEP 277 proposal.

dustin.examples.annotations.Deprecated

package dustin.examples.annotations;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.TYPE;

/**
 * Conceptual improvement on standard @java.lang.Deprecated annotation
 * based on preliminary discussion related to JEP 277 and on
 * desire to include context details with deprecation annotation
 * rather than relying on presence of Javadoc's @deprecated.
 *
 * Javadoc comments in this annotation definition are largely
 * based on descriptions in JEP 277 (http://openjdk.java.net/jeps/277).
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({CONSTRUCTOR,FIELD,LOCAL_VARIABLE,METHOD,PACKAGE,PARAMETER,TYPE})
public @interface Deprecated
{
   /**
    * JEP 277-defined reasons and associated explanations.
    */
   public enum Reason
   {
      /**
       * This API has been deprecated without any reason having been given.
       * This is the default value; everything that's deprecated today
       * implicitly has a deprecation reason of UNSPECIFIED.
       */
      UNSPECIFIED,
      /**
       * This API is earmarked for removal in a future JDK release. Note,
       * the use of the word "condemned" here is used in the sense of a
       * structure that is intended to be torn down. The term is not mean
       * to imply any moral censure.
       */
      CONDEMNED,
      /**
       * Use of this API can lead to data loss, deadlock, security
       * vulnerability, incorrect results, or loss of JVM integrity.
       */
      DANGEROUS,
      /**
       * This API is no longer necessary, and usages should be removed.
       * No replacement API exists. Note that OBSOLETE APIs might or
       * might not be marked CONDEMNED.
       */
      OBSOLETE,
      /**
       * This API has been replaced by a newer API, and usages should be
       * migrated away from this API to the newer API. Note that SUPERSEDED
       * APIs might or might not be marked CONDEMNED.
       */
      SUPERSEDED,
      /**
       * Calling this has no effect or will unconditionally throw an exception.
       */
      UNIMPLEMENTED,
      /**
       * This API is not a stable part of the specification, and it may
       * change incompatibly or disappear at any time.
       */
      EXPERIMENTAL;
   }

   /**
    * Provides any combination of one or more of the enum constants,
    * although not all combinations make sense. It is syntactically possible,
    * though perverse, to provide an empty array. Such a case should be
    * treated as if UNSPECIFIED were present.
    *
    * @return One or more Reasons for deprecation; default value is the enum
    *    constant UNSPECIFIED and absence of values should be treated as such.
    */
   Reason[] value();

   /**
    * Provides Strings representing any APIs that replace this API.
    * This should not specify any replacements if reason is OBSOLETE.
    *
    * @return Strings returned by this method should be links to replacement
    *    APIs for the API being deprecated. Each string should be in the same
    *    format as the @link Javadoc tag.
    */
   String[] replacement();

   /**
    * Provides the release in which the API was deprecated.
    *
    * @return Release number at which this API became deprecated
    *    in a free-form syntax String with the release numbering
    *    following the same scheme as the @since Javadoc tag.
    */
   String since();

   /**
    * Provides the anticipated complete removal of this deprecated API
    * if any known date or version is anticipated for the API's removal.
    * This value is most likely to be set for reasons of CONDEMNED,
    * OBSOLETE, and SUPERSEDED. This value is NOT described in JEP 277.
    *
    * @return Date or version in which it is anticipated that this
    *    API will be removed altogether.
    */
   String anticipatedRemoval() default "Not Planned";
}

The next code listing provides examples of the above annotation being applied to a deprecated class.

DeprecatedClass.java: Examples of Using Improved @Deprecated

package dustin.examples.annotations.demo;

import java.text.DateFormat;
import java.text.SimpleDateFormat;

import static dustin.examples.annotations.Deprecated.Reason.*;

/**
 * Demonstrates how new and improved @Deprecated might be used.
 */
@dustin.examples.annotations.Deprecated(
   value={SUPERSEDED, CONDEMNED},
   since="1.5", anticipatedRemoval="1.9",
   replacement="dustin.examples.annotations.demo.OtherClass")
public class DeprecatedClass
{
   final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");

   @dustin.examples.annotations.Deprecated(
      value={DANGEROUS}, since="1.0",
      replacement="java.text.SimpleDateFormat#SimpleDateFormat")
   public DateFormat getDateFormatter()
   {
      return dateFormat;
   }
}

This last example demonstrates use of the improved @Deprecated annotation. The "anticipatedRemoval" element of the @Deprecated annotation is not mentioned in JEP 277 and I gave it a default value for situations in which a deprecated construct may have no anticipated removal date but rather is deprecated to warn off new uses of it only.

The code listings above demonstrate defining a new and improved @Deprecated annotation such as spelled out in JEP 277. However, JEP 277 proposes much more than the existence of an improved annotation. The proposal also discusses "runtime changes" to provide "warnings about usage of deprecated APIs on an opt-in basis," "dependency-tool enhancements" to analyze annotation dependencies in fashion similar to and possibly even based on the jdeps tool, and "Javadoc enhancements."

Although Java's custom annotations support made it easy to implement a version of @Deprecated that reflects many of the ideas in JEP 277, the new and improved @java.lang.Deprecated would enjoy many benefits that a custom Java annotation does not enjoy such as built-in support in the JDK and use by JDK classes. The JDK-provided @Deprecated would also continue to enjoy IDE and tooling benefits such as striked-out names of deprecated code constructs.

Monday, November 2, 2015

Applying IDE Inspections to Custom Java Annotations

The introduction of annotations with J2SE 5 has changed how we write and process Java. Besides Java SE's predefined annotations, frameworks, IDEs, and toolkits have introduced their own custom annotations. The Checker Framework has provided examples of how custom annotations can be used to add greater type safety in Java. In this post, I look at the writing of a simple custom annotation and using it in NetBeans (8.0.2) and IntelliJ IDEA (14.0.3) to help developers identify issues in their code that need further attention.

In the article Making the Most of Java's Metadata, Part 2: Custom Annotations, Jason Hunter demonstrates an @Unfinished annotation as an example of writing a custom Java annotation. I will demonstrate a different implementation of an @Unfinished annotation in this post. That's the beauty of custom annotations: one can write an annotation to best fit one's needs. The code for my @Unfinished annotation is shown in the next code listing.

Unfinished.java: Defining Custom @Unfinished Annotation

package dustin.examples.annotations;

import static java.lang.annotation.ElementType.*;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Example of a custom annotation that marks Java code constructs
 * that are not yet completed.
 *
 * Notes about custom annotations specific to this example:
 *   - @Documented indicates available for public documentation
 *   - CLASS retention policy means that compiler places annotation
 *     information in compiled .class files, but JVM is NOT aware
 *     of the annotation at runtime.
 *   - @Target parameters (statically imported) indicate that this
 *     annotation can be applied to constructors, fields,
 *     local variables, methods, packages, parameters, and
 *     classes/interfaces.
 *   - Methods defined for this @interface without 'default' are
 *     required settings for application of this annotation. In
 *     this case, the "finishBy" element is NOT required (but
 *     recommended!) but the "value" element is required.
 *   - "value" element has special significance in custom Java
 *     annotations: it is the assumed annotation element if
 *     a String is provided to the annotation without explicit
 *     element name called out.
 */
@Documented
@Retention(RetentionPolicy.CLASS)
@Target({CONSTRUCTOR,FIELD,LOCAL_VARIABLE,METHOD,PACKAGE,PARAMETER,TYPE})
public @interface Unfinished
{
   /** Description of the unfinished construct. */
   String value();

   /**
    * Date, build, or event by which the annotated construct
    * is anticipated to be finished.
    */
   String finishBy() default "Unknown";
}

The next code listing shows application of @Unfinished in a simple class that has a lot of work still to be completed on it.

WorkInProgress.java: Applying @Unfinished Custom Annotation

package dustin.examples.annotations.demo;

import dustin.examples.annotations.Unfinished;

/**
 * Demonstrates custom Java annotation @Unfinished.
 */
public class WorkInProgress
{
   @Unfinished("This will do something good by Revision 2.")
   public void doSomethingGood()
   {
   }

   @Unfinished(value = "Do something good here.", finishBy = "Revision 2")
   public void doSomethingElseGood()
   {
   }
}

The incomplete class uses the annotation's "value" element by default for one method and then adds use of the "finishedBy" element for the second method. There are a few observations that can be made from the last two code listings definition or and use of @Unfinished:

  1. Inclusion of "default" for an annotation element means that those who use the annotation are not required to provide a value for that element.
  2. The "value" element is assumed if only one value is provided to the annotation and is provided without an explicit element name.
  3. The name "value" does not need to be provided if only a single annotation element is specified, but must be provided if more than one annotation element is specified.
  4. The retention level of CLASS was used here because I felt like tools working with the compiled version of Java classes would be able to use this information and I don't anticipate runtime use of the information.
  5. Careful selection of which annotation elements should have "default" values is desirable because not having a "default" requires an element to be specified, which can be the desired behavior in some cases.

Use of custom annotations can provide a standardized mechanism for building "executable" and more controlled descriptions for other developers and for tools. This approach is often advantageous when compared to leaving messages with comments as comments tend to be less standardized and subject to typos and differences in case sensitivity, spelling, and other discrepancies. Annotations enforce conventions better and allow for tooling to make more efficient use of what they communicate than parsing arbitrary text. Perhaps the most obvious way to gain some of this benefit of custom annotations over arbitrary comments is with an annotation processor. Several IDEs and frameworks such as the Checker Framework process annotations. There are also numerous online references regarding writing of custom annotations processors that can be used with the Jav compiler to provide warnings. In the remainder of this post, I focus on how one can apply two of the more popular Java IDEs (NetBeans and IntelliJ IDEA) to report these annotations as hints/inspections. I am not looking in this post at integrating an annotation processor into the IDEs' compilation processes or at integrating a custom processor with the command-line Java compiler.

Inspecting the @Unfinished Annotation in NetBeans

I have blogged before on Creating a NetBeans 7.1 Custom Hint and the process is pretty much the same still with NetBeans 8. The first step is to use the Refactor -> Inspect and Transform ... option as shown in the next screen snapshot.

When Refactor -> Inspect and Transform... is selected, a popup like that shown next is seen.

I'm going to apply this new inspection to all my open projects as shown in the last screen snapshot's "Inspect" field. Clicking on the "Browse" button leads to the "Manage Inspections" window coming up as shown in the next screen snapshot.

Clicking on the "New..." button allows the developer to create a custom inspection under Custom->Inspection.

You can click the "Edit Script" button to create the custom inspection, which includes the ability to rename the inspection. I have renamed the Inspection "Unfinished Code." The next screen snapshot shows the code I added to the "Unfinished Code" inspection.

In the script code for this "Unfinished Code" inspection (which is also shown below), the description is specified as "Unfinished Code". The source pattern is specified as @dustin.examples.annotations.Unfinished($parameters$) (the entire package name of the @interface defining the custom annotation with $parameters$ indicating one or more parameters). The => symbols point to the target pattern. In this case, the target pattern is empty, indicating that the proposed transformation is to remove the @Unfinished annotation. For more details on the syntax of the NetBeans inspections editor, see Geertjan Wielenga's post Custom Declarative Hints in NetBeans IDE 7.1.

<!description="Unfinished Code">
@dustin.examples.annotations.Unfinished($parameters$)
=>
;;

With the NetBeans inspection created, it is time try it out. The next two screen snapshots demonstrate selecting that Inspection to run and the results of running it.

The output from running the inspection is an example of how we can use NetBeans in conjunction with a custom annotation to quickly identify annotated code and treat it appropriately.

Inspecting the @Unfinished Annotation in IntelliJ IDEA

One way to start creating a custom annotation in IntelliJ IDEA is to open Analyze -> Inspect Code... and click on the "..." button in the "Specify Inspection Scope" pop-up as shown in the next two screen snapshots.

The next screen snapshot shows the "Inspections" dialog box.

The screen snapshot just shown indicates that the "Structural Search Inspection" is NOT checked. Checking it (checkbox is to the right of the name "Structural Search Inspection") leads to the "Severity" level being selectable and allows a particular inspection to be added (plus sign turns from gray to green).

Clicking on the green plus sign (+), leads to two choices: "Add Search template..." or "Add Replace template...". The differentiation here is similar to NetBeans's differentiation between Source -> Inspect and Refactor -> Inspect and Transform... and I'll focus on the "Replace template" here.

When "Add Replace template..." is selected, the "Structural Replace" dialog is displayed.

The easiest way to create a custom inspection here it to adapt an existing template. This is done by clicking on the "Copy existing template..." button. For the two inspections I create for this blog post, I copied the "annotated class" and "annotated methods" existing templates respectively to create my own custom templates "Unfinished Class" and "Unfinished Method."

The screen snapshots above show the "existing templates" I copied and the screen snapshots below showed the custom templates I created from them for "Unfinished Class" and "Unfinished Method."

For each of the custom templates ("Unfinished Class" and "Unfinished Method"), I need to click on the "Edit variables..." button and specify the regular expressions for each variable (identifiers marked with $ on front and back) to be searched. For most variables (such as class name, method name, and so forth), I use an "all characters" regular representation (.*), but for the $Annotation$ in each of these templates, I use dustin.examples.annotations.Unfinished. The next screen snapshot is a representative sample of this that shows the Annotation variable setting for the "Undefined Method" template.

I can use Analyze -> Run Inspection by Name... to run either of my new inspections. The next three screen snapshots demonstrate running the new "Unfinished Method" inspection.

The output from running the inspection is an example of how we can use IntelliJ IDEA in conjunction with a custom annotation to quickly identify annotated code and treat it appropriately.

Conclusion

This post has demonstrated using NetBeans's and IntelliJ IDEA's abilities to create custom inspections to create inspections that can alert developers to the presence of custom annotations in their code. The post demonstrated a simple @Unfinished annotation and how to apply custom inspections in NetBeans and IntelliJ IDEA to help identify code that uses those annotations.