Toolbox
Various tools and technologies which are useful.
Guava
The Guava project contains several of Google’s core libraries that we rely on in our Java-based projects: collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, and so forth. Each of these tools really do get used every day by Googlers, in production services.
Preconditions
In PLI you can find in a wrapper implementation. Use a precondition checking utilities.
Throwables
For Exception propagation. Several of the Java API forces us to handle checked Exceptions even if we could do not do anything with that. Most of the times we just log, wrap into RuntimeException then throw again and let calling process to deal with it. Lots of repetitive steps.
It will shorten it.
Immutable collections
Immutable collections are faster to use in multithreaded environment. Majority of the operations are just more clear using immutable (value) objects. Using immutable collections is more memory efficient than using mutable counterpart.
Plus lost of useful function to make life more easy when dealing with collections.
1 Map<?, ?> ret = ImmutableMap.of("status", "OK", "data", resp);
Imagine when you want to filter a collections - getting a subset based on certain conditions
1 List<InterpreterDto> relevantInterpreters = Collections2.filter(interpreters, new Predicate<InterpreterDto>() { 2 public boolean apply(InterpreterDto input) { 3 for (InterpreterBoothDto b : input.getBooths()) { 4 if (langs.contains(b.getLanguage())) { 5 return true; 6 } 7 } 8 return false; 9 } 10 });
Of course you could reuse that Predicate
. Imagine when you get a list of object and want to lookup based on some id
of that object.
1 Function<Unavailability, Long> interp_pers_uid_extractor = new Function<Unavailability, Long>() { 2 @Override 3 public Long apply(Unavailability input) { 4 return input.getPers_pers_uid(); 5 } 6 }; 7 ... 8 List<Unavailability> unavs = search(s) 9 ListMultimap<Long, Unavailability> res = groupBy(unavs, interp_pers_uid_extractor)
Where the interp_pers_uid_extractor
can be reused in multiple places. In this example the groupBy
is synonym for Multimaps.index
.
Using functional programing idioms can produce shorter and simpler programs.
Strings
Joiner
Splitter
Typical problem o splitting String. I java you could use Spring.split
which can be difficult because you have to deal with regex; or StringTokenizer
which is failing when want split by multiple characters.
But you can feel the difference:
1 List<String> tokens = copyOf(Splitter.on(CharMatcher.WHITESPACE).omitEmptyStrings().trimResults().split(prop));
EventBus
In a desktop application it can be very useful.
1 // Class is typically registered by the container. 2 class EventBusChangeRecorder { 3 @Subscribe public void recordCustomerChange(ChangeEvent e) { 4 recordChange(e.getChange()); 5 } 6 } 7 // somewhere during initialization 8 eventBus.register(new EventBusChangeRecorder()); 9 // much later 10 public void changeCustomer() { 11 ChangeEvent event = getChangeEvent(); 12 eventBus.post(event); 13 }
Generic hibernate Dao
We had worked on a project where we hand-coded all of our DAOs. This produced four irksome difficulties: (1) Method names and implementations were not altogether consistent. (2) It was a pain to make additional columns sortable or filterable, and as a result, a lot of pages lacked good sorting and filtering. (3) Making additional DAOs was tedious and took a fair amount of time. (4) Writing tests for DAOs is tricky and tedious, so no one really did.
What we use:
- Generic DAO: with lots of useful implementation like, get, save, remove, search (see later), etc.
- powerful search API
Examples - Generic dao interface:
Example - search:
Search search = new Search(Project.class);
1 //filtering 2 search.addFilterEqual("name", "hibernate-generic-dao"); 3 search.addFilterLessThan("completionDate", new Date()); 4 search.addFilterOr( 5 Filter.equal("name", "Jack"), 6 Filter.and( 7 Filter.equal("name", "Jill"), 8 Filter.like("location", "%Chicago%"), 9 Filter.greaterThan("age", 5) 10 ) 11 ); 12 search.addFilterIn("name", "Jack", "Jill", "Bob"); 13 //paging 14 search.setMaxResults(15); //a.k.a. results per page 15 search.setPage(3);
And if any of the features are suitable to your need you still have access to hibernate session.
iText and table builder
Within the team we have an electronic book (ask Otto) which contains lots of really good examples of using iText. (iText in Action)
iText is a really low level API for building PDF. Low level and, that is the why, flexible.
But to make it effective you have to build your high level API to use that. For example when creating complex layouts you have to use tables and cells in the PDF document. For building up you could use TableBuilder
Example use of TableBuilder:
1 TableBuilder table = new TableBuilder(); 2 //@formatter:off 3 table 4 .attr("totalWidth", 1842F) 5 .attr("headerRows", 1) 6 .newRow() 7 .newHeaderCell().text(i18n.get("pdf.table.name"),"header") 8 .attr("colspan", Integer.valueOf(2)) 9 .attr("verticalAlignment", ALIGN_BOTTOM) 10 .attr("backgroundColor", "header") 11 ; 12 List<Date> valueDates = data.getValueDates(); 13 for(Date valueDate: valueDates){ 14 table 15 .newHeaderCell().text(dayNameOfWeek(valueDate).toUpperCase(),"header").text("\n") 16 .text(formatIfNotNull(valueDate, DATE_FORMAT),"header") 17 .attr("horizontalAlignment", ALIGN_CENTER) 18 .attr("backgroundColor", "header") 19 ; 20 } 21 table.endRow(); 22 //@formatter:on
After building up an abstract table you could apply a visitor which will interpret this abstract table to specific implementation. For example: this table can be rendered in both HTML and PDF.
1 public class ITextTableVisitor extends ReflectiveVisitor { 2 private static final Map<String, Font> fonts = Map(); 3 static { 4 fonts.put("default", new Font(Font.HELVETICA, 8, Font.NORMAL, Color.BLACK)); 5 fonts.put("error", new Font(Font.HELVETICA, 8, Font.NORMAL, Color.RED)); 6 fonts.put("header", new Font(Font.HELVETICA, 8, Font.NORMAL, Color.YELLOW)); 7 fonts.put("title", new Font(Font.HELVETICA, 16, Font.NORMAL, Color.BLACK)); 8 fonts.put("title-emph", new Font(Font.HELVETICA, 16, Font.BOLD, Color.BLACK)); 9 } 10 private static final Map<String, Color> colors = Map(); 11 static { 12 colors.put("header", new Color(0, 0, 128)); 13 colors.put("plain", Color.WHITE); 14 } 15 16 static Color getColor(String color) { 17 return colors.get(color); 18 } 19 20 static Font getFont(String fontDesc) { 21 Font res = fonts.get(fontDesc); 22 if (null == res) { 23 res = fonts.get("default"); 24 } 25 return res; 26 } 27 28 private Image getImage(String image) throws Exception { 29 if ("eu_logo".equals(image)) { 30 return Image.getInstance(this.getClass().getResource("/img/eu_flag.jpg")); 31 } 32 return null; 33 } 34 35 private PdfPTable table; 36 37 public void visitTTable(TTable t) throws DocumentException { 38 table = new PdfPTable(t.getMaxColOfRows()); 39 table.setWidthPercentage(100); 40 if (null != t.getWidthPercentage()) { 41 table.setWidthPercentage(t.getWidthPercentage()); 42 } 43 ... 44 for (TRow r : t.getRows()) { 45 r.accept(this); 46 } 47 } 48 49 public void visitTCell(TCell c) throws Exception { 50 PdfPCell cell = new PdfPCell(); 51 cell.setHorizontalAlignment(Element.ALIGN_LEFT); 52 cell.setBackgroundColor(Color.LIGHT_GRAY); 53 cell.setBorderColor(Color.GRAY); 54 cell.setPadding(2); 55 if (null != c.getHorizontalAlignment()) { 56 cell.setHorizontalAlignment(c.getHorizontalAlignment()); 57 } 58 if (null != c.getVerticalAlignment()) { 59 cell.setVerticalAlignment(c.getVerticalAlignment()); 60 } 61 cell.setColspan(c.getColspan()); 62 ... 63 64 for (TTable t : c.getTables()) { 65 ITextTableVisitor innerVisitor = new ITextTableVisitor(); 66 t.accept(innerVisitor); 67 PdfPTable innerTable = innerVisitor.getTable(); 68 cell.addElement(innerTable); 69 } 70 table.addCell(cell); 71 } 72 73 public void visitTRow(TRow r) { 74 for (TCell c : r.getCells()) { 75 c.accept(this); 76 } 77 } 78 79 public PdfPTable getTable() { 80 return table; 81 } 82 83 public void setTable(PdfPTable table) { 84 this.table = table; 85 } 86 }
jGrowl
Useful visual utility for displaying message.
Usage example:
1 // Sample 1 2 $.jGrowl("Hello world!"); 3 // Sample 2 4 $.jGrowl("Stick this!", { sticky: true }); 5 // Sample 3 6 $.jGrowl("A message with a header", { header: 'Important' }); 7 // Sample 4 8 $.jGrowl("A message that will live a little longer.", { life: 10000 }); 9 // Sample 5 10 $.jGrowl("A message with a beforeOpen callback and a different opening animation.", { 11 beforeClose: function(e,m) { 12 alert('About to close this notification!'); 13 }, 14 animateOpen: { 15 height: 'show' 16 } 17 });
Bootstrap
Sleek, intuitive, and powerful front-end framework for faster and easier web development.
Bootstrap is a CSS and JavaScript framework to make initial website development easy and as a result having a consistent look and feel.
By applying Bootstrap we can have good looking website without any effort and lots of really useful visual effect which can spice up the look of certain components.
You must review Base CSS, Components and JavaScript sections.
Underscore.js
Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects.
Really useful utility library for JavaScript.
Learn and apply utilities to make you JavaScript code shorter and simpler.
Templates
Templating when you take a spring the put values into certain places to produce a final string result.
By default you could implement with string concatenation. But after just a few variables to concatenate into string it become a really painful experience to read that source code.
Most of the time we want to generate some HTML fragment.
Teamplating in Java
Commons StrSubstitutor
JATL
1 final Html html = new Html(that) { 2 { 3 Map<DateRange, List<LanguageCoverageInfo>> li = dto.getLang_coverage_info(); 4 for (DateRange range : li.keySet()) { 5 div().id(dto.getSess_uid() + "-" + cssId(range)); 6 span().classAttr("label").text(timeInfo(range)).end(); 7 new LanguageCoverageFormatter(li.get(range)).format(this); 8 end(); 9 } 10 endAll(); 11 done(); 12 } 13 };
Templating in JavaScript
Simple templating
See.
Underscore.js has utility called template.
Jaml
Spring SpEL
Cases:
- accessing object attributes (even if nested) dynamically.
- accessing nested, potentitally null intermediate objects
You might write several of the following code in you life:
Common attribute is that you intend to access a nested attribute but for not throwing NullPointerException
you have to check the presence of intermediate object.
Lets simplify:
The construct if ?.
is called Safe Navigation operator whihc become popular with Groovy. We could use the same concept in Java with Spring:
Of course Spring expressions are much more powerfull than using for this purposes. Van be used for validation or in complex formatting in JSP.
Logging
slf4j
Use slf4j only. And in the bacground you could still use log4j configs as before.
Do you need asingle reason why using slf4j?
Before:
After:
1log.debug("Some text {} and other to log", something);
Trick to optimize
Although slf4j is really effective and optimized not to call toString
unnecceseraly. It is still not enough. Sometimes the loggable object generation is as consuming as calling toString
.
Try the following trick:
1// The important part 2log.debug("{}",new Object(){ 3 public String toString(){ 4 return Iterables.transform(col, BeanFieldValueExtractor.byField("interesting")) 5 } 6}); 7 8... 9//This is not so relevant just helps understanding the previous block 10public class BeanFieldValueExtractor<T> implements Function<Object, T> { 11 private final String attr; 12 //... constructor omited 13 public T apply(Object input) { 14 return (T) ReflectionUtil.getField(input, attr); 15 } 16 public static <T> BeanFieldValueExtractor<T> byField(String attr) { 17 return new BeanFieldValueExtractor<T>(attr); 18 } 19}
So we are replacing an expensive operation by a cheap object creation.
JodaTime
Joda-Time provides a quality replacement for the Java date and time classes.
Once you have to use java.util.Date
intensively you will understand how painfull it can be.
Just remove the pain by using Joda Time.
- Easy to Use. Calendar makes accessing ‘normal’ dates difficult, due to the lack of simple methods. Joda-Time has straightforward field accessors such as
getYear()
orgetDayOfWeek()
.- Easy to Extend. The JDK supports multiple calendar systems via subclasses of Calendar. This is clunky, and in practice it is very difficult to write another calendar system. Joda-Time supports multiple calendar systems via a pluggable system based on the Chronology class.
- Comprehensive Feature Set. The library is intended to provide all the functionality that is required for date-time calculations. It already provides out-of-the-box features, such as support for oddball date formats, which are difficult to replicate with the JDK.
- Up-to-date Time Zone calculations. The time zone implementation is based on the public tz database, which is updated several times a year. New Joda-Time releases incorporate all changes made to this database. Should the changes be needed earlier, manually updating the zone data is easy.
- Calendar support. The library currently provides 8 calendar systems. More will be added in the future.
- Easy interoperability. The library internally uses a millisecond instant which is identical to the JDK and similar to other common time representations. This makes interoperability easy, and Joda-Time comes with out-of-the-box JDK interoperability.
- Better Performance Characteristics. Calendar has strange performance characteristics as it recalculates fields at unexpected moments. Joda-Time does only the minimal calculation for the field that is being accessed.
Simple and expressive.
Should I exmplain the following code?
It is possible to use in hibernate mapping:
Autocomplete Javascript solutions
Intelligent dropdown:
- http://harvesthq.github.com/chosen/ Candidate tools:
- http://code.drewwilson.com/entry/autosuggest-jquery-plugin
- http://www.devthought.com/projects/jquery/textboxlist/ (commercial)
- http://harvesthq.github.com/chosen/ Looks really good, but ajax is only with http://stackoverflow.com/questions/12044330/jquery-chosen-plugin-dynamically-populate-list-by-ajax
- http://ivaynberg.github.com/select2 also impressive
- http://loopj.com/jquery-tokeninput/ good old…
Maps with default values or on the fly init values
Jakarta commons way: Lazy Map
Technology stack
- Physical software project structure
- Service layer
- Data access layer
- Spring MVC
- Web view
- Toolbox
- Testing
- Jawr, webjars, bootstrap, Spring setup trick
- Jakarta Equivalence Relation
- Difficult to test example refactoring