├── LICENSE └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/ or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Java is one of the most popular programming languages around, but no one seems 2 | to enjoy using it. Well, Java is actually an alright programming language, and 3 | since Java 8 came out recently, I decided to compile a list of libraries, 4 | practices, and tools to make using Java better. 5 | 6 | This article was originally posted on 7 | [my blog](http://blog.seancassidy.me/better-java.html). 8 | 9 | # Style 10 | 11 | Traditionally, Java was programmed in a very verbose enterprise JavaBean style. 12 | The new style is much cleaner, more correct, and easier on the eyes. 13 | 14 | ## Structs 15 | 16 | One of the simplest things we as programmers do is pass around data. The 17 | traditional way to do this is to define a JavaBean: 18 | 19 | ```java 20 | public class DataHolder { 21 | private String data; 22 | 23 | public DataHolder() { 24 | } 25 | 26 | public void setData(String data) { 27 | this.data = data; 28 | } 29 | 30 | public String getData() { 31 | return this.data; 32 | } 33 | } 34 | ``` 35 | 36 | This is verbose and wasteful. Even if your IDE automatically generated this 37 | code, it's a waste. So, [don't do this][dontbean]. 38 | 39 | Instead, I prefer the C struct style of writing classes that merely hold data: 40 | 41 | ```java 42 | public class DataHolder { 43 | public final String data; 44 | 45 | public DataHolder(String data) { 46 | this.data = data; 47 | } 48 | } 49 | ``` 50 | 51 | This is a reduction in number of lines of code by a half. Further, this class 52 | is immutable unless you extend it, so we can reason about it easier as we know 53 | that it can't be changed. 54 | 55 | If you're storing objects like Map or List that can be modified easily, you 56 | should instead use ImmutableMap or ImmutableList, which is discussed in the 57 | section about immutability. 58 | 59 | ### The Builder Pattern 60 | 61 | If you have a rather complicated object that you want to build a struct for, 62 | consider the Builder pattern. 63 | 64 | You make a subclass in your object which will construct your object. It uses 65 | mutable state, but as soon as you call build, it will emit an immutable 66 | object. 67 | 68 | Imagine we had a more complicated *DataHolder*. The builder for it might look 69 | like: 70 | 71 | ```java 72 | public class ComplicatedDataHolder { 73 | public final String data; 74 | public final int num; 75 | // lots more fields and a constructor 76 | 77 | public static class Builder { 78 | private String data; 79 | private int num; 80 | 81 | public Builder data(String data) { 82 | this.data = data; 83 | return this; 84 | } 85 | 86 | public Builder num(int num) { 87 | this.num = num; 88 | return this; 89 | } 90 | 91 | public ComplicatedDataHolder build() { 92 | return new ComplicatedDataHolder(data, num); // etc 93 | } 94 | } 95 | } 96 | ``` 97 | 98 | Then to use it: 99 | 100 | ```java 101 | final ComplicatedDataHolder cdh = new ComplicatedDataHolder.Builder() 102 | .data("set this") 103 | .num(523) 104 | .build(); 105 | ``` 106 | 107 | There are [better examples of Builders elsewhere][builderex] but this should 108 | give you a taste for what it's like. This ends up with a lot of the boilerplate 109 | we were trying to avoid, but it gets you immutable objects and a very fluent 110 | interface. 111 | 112 | ## Dependency injection 113 | 114 | This is more of a software engineering section than a Java section, but one of 115 | the best ways to write testable software is to use [dependency injection][di] 116 | (DI). Because Java strongly encourages OO design, to make testable software, 117 | you need to use DI. 118 | 119 | In Java, this is typically done with the [Spring Framework][spring]. It has a 120 | either code-based wiring or XML configuration-based wiring. If you use the XML 121 | configuration, it's important that you [don't overuse Spring][springso] because 122 | of its XML-based configuration format. There should be absolutely no logic or 123 | control structures in XML. It should only inject dependencies. 124 | 125 | Good alternatives to using Spring is Google and Square's [Dagger][dagger] 126 | library or Google's [Guice][guice]. They don't use Spring's XML 127 | configuration file format, and instead they put the injection logic in 128 | annotations and in code. 129 | 130 | ## Avoid Nulls 131 | 132 | Try to avoid using nulls when you can. Do not return null collections when you 133 | should have instead returned an empty collection. If you're going to use null, 134 | consider the [@Nullable][nullable] annotation. [IntelliJ IDEA][intellij] has 135 | built-in support for the @Nullable annotation. 136 | 137 | If you're using [Java 8][java8], you can use the excellent new 138 | [Optional][optional] type. If a value may or may not be present, wrap it in 139 | an *Optional* class like this: 140 | 141 | ```java 142 | public class FooWidget { 143 | private final String data; 144 | private final Optional bar; 145 | 146 | public FooWidget(String data) { 147 | this(data, Optional.empty()); 148 | } 149 | 150 | public FooWidget(String data, Optional bar) { 151 | this.data = data; 152 | this.bar = bar; 153 | } 154 | 155 | public Optional getBar() { 156 | return bar; 157 | } 158 | } 159 | ``` 160 | 161 | So now it's clear that *data* will never be null, but *bar* may or may not be 162 | present. *Optional* has methods like *isPresent*, which may make it feel like 163 | not a lot is different from just checking *null*. But it allows you to write 164 | statements like: 165 | 166 | ```java 167 | final Optional fooWidget = maybeGetFooWidget(); 168 | final Baz baz = fooWidget.flatMap(FooWidget::getBar) 169 | .flatMap(BarWidget::getBaz) 170 | .orElse(defaultBaz); 171 | ``` 172 | 173 | Which is much better than chained if null checks. The only downside of using 174 | Optional is that the standard library doesn't have good Optional support, so 175 | dealing with nulls is still required there. 176 | 177 | ## Immutable-by-default 178 | 179 | Unless you have a good reason to make them otherwise, variables, classes, and 180 | collections should be immutable. 181 | 182 | Variable references can be made immutable with *final*: 183 | 184 | ```java 185 | final FooWidget fooWidget; 186 | if (condition()) { 187 | fooWidget = getWidget(); 188 | } else { 189 | try { 190 | fooWidget = cachedFooWidget.get(); 191 | } catch (CachingException e) { 192 | log.error("Couldn't get cached value", e); 193 | throw e; 194 | } 195 | } 196 | // fooWidget is guaranteed to be set here 197 | ``` 198 | 199 | Now you can be sure that fooWidget won't be accidentally reassigned. The *final* 200 | keyword works with if/else blocks and with try/catch blocks. Of course, if the 201 | *fooWidget* itself isn't immutable you could easily mutate it. 202 | 203 | Collections should, whenever possible, use the Guava [ImmutableMap][immutablemap], 204 | [ImmutableList][immutablelist], or [ImmutableSet][immutableset] classes. These 205 | have builders so that you can build them up dynamically and then mark them 206 | immutable by calling the build method. 207 | 208 | Classes should be made immutable by declaring fields immutable (via *final*) 209 | and by using immutable collections. Optionally, you can make the class itself 210 | *final* so that it can't be extended and made mutable. 211 | 212 | ## Avoid lots of Util classes 213 | 214 | Be careful if you find yourself adding a lot of methods to a Util class. 215 | 216 | ```java 217 | public class MiscUtil { 218 | public static String frobnicateString(String base, int times) { 219 | // ... etc 220 | } 221 | 222 | public static void throwIfCondition(boolean condition, String msg) { 223 | // ... etc 224 | } 225 | } 226 | ``` 227 | 228 | These classes, at first, seem attractive because the methods that go in them 229 | don't really belong in any one place. So you throw them all in here in the 230 | name of code reuse. 231 | 232 | The cure is worse than the disease. Put these classes where they belong, or 233 | if you must have common methods like this, consider [Java 8][java8]'s default 234 | methods on interfaces. Then you could lump common actions into interfaces. 235 | And, since they're interfaces, you can implement multiple of them. 236 | 237 | ```java 238 | public interface Thrower { 239 | default void throwIfCondition(boolean condition, String msg) { 240 | // ... 241 | } 242 | 243 | default void throwAorB(Throwable a, Throwable b, boolean throwA) { 244 | // ... 245 | } 246 | } 247 | ``` 248 | 249 | Then every class which needs it can simply implement this interface. 250 | 251 | ## Formatting 252 | 253 | Formatting is so much less important than most programmers make it out to be. 254 | Does consistency show that you care about your craft and does it help others 255 | read? Absolutely. But let's not waste a day adding spaces to if blocks so that 256 | it "matches". 257 | 258 | If you absolutely need a code formatting guide, I highly recommend 259 | [Google's Java Style][googlestyle] guide. The best part of that guide is the 260 | [Programming Practices][googlepractices] section. Definitely worth a read. 261 | 262 | ### Javadoc 263 | 264 | Documenting your user facing code is important. And this means 265 | [using examples][javadocex] and using sensible descriptions of variables, 266 | methods, and classes. 267 | 268 | The corollary of this is to not document what doesn't need documenting. If you 269 | don't have anything to say about what an argument is, or if it's obvious, 270 | don't document it. Boilerplate documentation is worse than no documentation at 271 | all, as it tricks your users into thinking that there is documentation. 272 | 273 | ## Streams 274 | 275 | [Java 8][java8] has a nice [stream][javastream] and lambda syntax. You could 276 | write code like this: 277 | 278 | ```java 279 | final List filtered = list.stream() 280 | .filter(s -> s.startsWith("s")) 281 | .map(s -> s.toUpperCase()) 282 | .collect(Collectors.toList()); 283 | ``` 284 | 285 | Instead of this: 286 | 287 | ```java 288 | final List filtered = new ArrayList<>(); 289 | for (String str : list) { 290 | if (str.startsWith("s") { 291 | filtered.add(str.toUpperCase()); 292 | } 293 | } 294 | ``` 295 | 296 | This allows you to write more fluent code, which is more readable. 297 | 298 | # Deploying 299 | 300 | Deploying Java properly can be a bit tricky. There are two main ways to deploy 301 | Java nowadays: use a framework or use a home grown solution that is more 302 | flexible. 303 | 304 | ## Frameworks 305 | 306 | Because deploying Java isn't easy, frameworks have been made which can help. 307 | Two of the best are [Dropwizard][dropwizard] and [Spring Boot][springboot]. 308 | The [Play framework][play] can also be considered one of these deployment 309 | frameworks as well. 310 | 311 | All of them try to lower the barrier to getting your code out the door. 312 | They're especially helpful if you're new to Java or if you need to get things 313 | done fast. Single JAR deployments are just easier than complicated WAR or EAR 314 | deployments. 315 | 316 | However, they can be somewhat inflexible and are rather opinionated, so if 317 | your project doesn't fit with the choices the developers of your framework 318 | made, you'll have to migrate to a more hand-rolled configuration. 319 | 320 | ## Maven 321 | 322 | **Good alternative**: [Gradle][gradle]. 323 | 324 | Maven is still the standard tool to build, package, and run your tests. There 325 | are alternatives, like Gradle, but they don't have the same adoption that Maven 326 | has. If you're new to Maven, you should start with 327 | [Maven by Example][mavenexample]. 328 | 329 | I like to have a root POM with all of the external dependencies you want to 330 | use. It will look something [like this][rootpom]. This root POM has only one 331 | external dependency, but if your product is big enough, you'll have dozens. 332 | Your root POM should be a project on its own: in version control and released 333 | like any other Java project. 334 | 335 | If you think that tagging your root POM for every external dependency change 336 | is too much, you haven't wasted a week tracking down cross project dependency 337 | errors. 338 | 339 | All of your Maven projects will include your root POM and all of its version 340 | information. This way, you get your company's selected version of each 341 | external dependency, and all of the correct Maven plugins. If you need to pull 342 | in external dependencies, it works just like this: 343 | 344 | ```xml 345 | 346 | 347 | org.third.party 348 | some-artifact 349 | 350 | 351 | ``` 352 | 353 | If you want internal dependencies, that should be managed by each individual 354 | project's **** section. Otherwise it would be difficult 355 | to keep the root POM version number sane. 356 | 357 | ### Dependency Convergence 358 | 359 | One of the best parts about Java is the massive amount of third party 360 | libraries which do everything. Essentially every API or toolkit has a Java SDK 361 | and it's easy to pull it in with Maven. 362 | 363 | And those Java libraries themselves depend on specific versions of other 364 | libraries. If you pull in enough libraries, you'll get version conflicts, that 365 | is, something like this: 366 | 367 | Foo library depends on Bar library v1.0 368 | Widget library depends on Bar library v0.9 369 | 370 | Which version will get pulled into your project? 371 | 372 | With the [Maven dependency convergence plugin][depconverge], the build will 373 | error if your dependencies don't use the same version. Then, you have two 374 | options for solving the conflict: 375 | 376 | 1. Explicitly pick a version for Bar in your *dependencyManagement* section 377 | 2. Exclude Bar from either Foo or Widget 378 | 379 | The choice of which to choose depends on your situation: if you want to track 380 | one project's version, then exclude makes sense. On the other hand, if you 381 | want to be explicit about it, you can pick a version, although you'll need to 382 | update it when you update the other dependencies. 383 | 384 | ## Continuous Integration 385 | 386 | Obviously you need some kind of continuous integration server which is going 387 | to continuously build your SNAPSHOT versions and tag builds based on git tags. 388 | 389 | [Jenkins][jenkins] and [Travis-CI][travis] are natural choices. 390 | 391 | Code coverage is useful, and [Cobertura][cobertura] has 392 | [a good Maven plugin][coberturamaven] and CI support. There are other code 393 | coverage tools for Java, but I've used Cobertura. 394 | 395 | ## Maven repository 396 | 397 | You need a place to put your JARs, WARs, and EARs that you make, so you'll 398 | need a repository. 399 | 400 | Common choices are [Artifactory][artifactory] and [Nexus][nexus]. Both work, 401 | and have their own [pros and cons][mavenrepo]. 402 | 403 | You should have your own Artifactory/Nexus installation and 404 | [mirror your dependencies][artifactorymirror] onto it. This will stop your 405 | build from breaking because some upstream Maven repository went down. 406 | 407 | ## Configuration management 408 | 409 | So now you've got your code compiled, your repository set up, and you need to 410 | get your code out in your development environment and eventually push it to 411 | production. Don't skimp here, because automating this will pay dividends for a 412 | long time. 413 | 414 | [Chef][chef], [Puppet][puppet], and [Ansible][ansible] are typical choices. 415 | I've written an alternative called [Squadron][squadron], which I, of course, 416 | think you should check out because it's easier to get right than the 417 | alternatives. 418 | 419 | Regardless of what tool you choose, don't forget to automate your deployments. 420 | 421 | # Libraries 422 | 423 | Probably the best feature about Java is the extensive amount of libraries it 424 | has. This is a small collection of libraries that are likely to be applicable 425 | to the largest group of people. 426 | 427 | ## Missing Features 428 | 429 | Java's standard library, once an amazing step forward, now looks like it's 430 | missing several key features. 431 | 432 | ### Apache Commons 433 | 434 | [The Apache Commons project][apachecommons] has a bunch of useful libraries. 435 | 436 | **Commons Codec** has many useful encoding/decoding methods for Base64 and hex 437 | strings. Don't waste your time rewriting those. 438 | 439 | **Commons Lang** is the go-to library for String manipulation and creation, 440 | character sets, and a bunch of miscellaneous utility methods. 441 | 442 | **Commons IO** has all the File related methods you could ever want. It has 443 | [FileUtils.copyDirectory][copydir], [FileUtils.writeStringToFile][writestring], 444 | [IOUtils.readLines][readlines] and much more. 445 | 446 | ### Guava 447 | 448 | [Guava][guava] is Google's excellent here's-what-Java-is-missing library. It's 449 | almost hard to distill everything that I like about this library, but I'm 450 | going to try. 451 | 452 | **Cache** is a simple way to get an in-memory cache that can be used to cache 453 | network access, disk access, memoize functions, or anything really. Just 454 | implement a [CacheBuilder][cachebuilder] which tells Guava how to build your 455 | cache and you're all set! 456 | 457 | **Immutable** collections. There's a bunch of these: [ImmutableMap][immutablemap], 458 | [ImmutableList][immutablelist], or even [ImmutableSortedMultiSet][immutablesorted] 459 | if that's your style. 460 | 461 | I also like writing mutable collections the Guava way: 462 | 463 | ```java 464 | // Instead of 465 | final Map map = new HashMap<>(); 466 | 467 | // You can use 468 | final Map map = Maps.newHashMap(); 469 | ``` 470 | 471 | There are static classes for [Lists][lists], [Maps][maps], [Sets][sets] and 472 | more. They're cleaner and easier to read. 473 | 474 | If you're stuck with Java 6 or 7, you can use the [Collections2][collections2] 475 | class, which has methods like filter and transform. They allow you to write 476 | fluent code without [Java 8][java8]'s stream support. 477 | 478 | 479 | Guava has simple things too, like a **Joiner** that joins strings on 480 | separators and a [class to handle interrupts][uninterrupt] by ignoring them. 481 | 482 | ### Gson 483 | 484 | Google's [Gson][gson] library is a simple and fast JSON parsing library. It 485 | works like this: 486 | 487 | ```java 488 | final Gson gson = new Gson(); 489 | final String json = gson.toJson(fooWidget); 490 | 491 | final FooWidget newFooWidget = gson.fromJson(json, FooWidget.class); 492 | ``` 493 | 494 | It's really easy and a pleasure to work with. The [Gson user guide][gsonguide] 495 | has many more examples. 496 | 497 | ### Java Tuples 498 | 499 | One of my on going annoyances with Java is that it doesn't have tuples built 500 | into the standard library. Luckily, the [Java tuples][javatuples] project fixes 501 | that. 502 | 503 | It's simple to use and works great: 504 | 505 | ```java 506 | Pair func(String input) { 507 | // something... 508 | return Pair.with(stringResult, intResult); 509 | } 510 | ``` 511 | 512 | ### Joda-Time 513 | 514 | [Joda-Time][joda] is easily the best time library I've ever used. Simple, 515 | straightforward, easy to test. What else can you ask for? 516 | 517 | You only need this if you're not yet on Java 8, as that has its own new 518 | [date time][java8datetime] library that doesn't suck. 519 | 520 | ### Lombok 521 | 522 | [Lombok][lombok] is an interesting library. Through annotations, it allows you 523 | to reduce the boilerplate that Java suffers from so badly. 524 | 525 | Want setters and getters for your class variables? Simple: 526 | 527 | ```java 528 | public class Foo { 529 | @Getter @Setter private int var; 530 | } 531 | ``` 532 | 533 | Now you can do this: 534 | 535 | ```java 536 | final Foo foo = new Foo(); 537 | foo.setVar(5); 538 | ``` 539 | 540 | And there's [so much more][lombokguide]. I haven't used Lombok in production 541 | yet, but I can't wait to. 542 | 543 | ### Play framework 544 | 545 | **Good alternatives**: [Jersey][jersey] or [Spark][spark] 546 | 547 | There are two main camps for doing RESTful web services in Java: 548 | [JAX-RS][jaxrs] and everything else. 549 | 550 | JAX-RS is the traditional way. You combine annotations with interfaces and 551 | implementations to form the web service using something like [Jersey][jersey]. 552 | What's nice about this is you can easily make clients out of just the 553 | interface class. 554 | 555 | The [Play framework][play] is a radically different take on web services on 556 | the JVM: you have a routes file and then you write the classes referenced in 557 | those routes. It's actually an [entire MVC framework][playdoc], but you can 558 | easily use it for just REST web services. 559 | 560 | It's available for both Java and Scala. It suffers slightly from being 561 | Scala-first, but it's still good to use in Java. 562 | 563 | If you're used to micro-frameworks like Flask in Python, [Spark][spark] will 564 | be very familiar. It works especially well with Java 8. 565 | 566 | ### SLF4J 567 | 568 | There are a lot of Java logging solutions out there. My favorite is 569 | [SLF4J][slf4j] because it's extremely pluggable and can combine logs from many 570 | different logging frameworks at the same time. Have a weird project that uses 571 | java.util.logging, JCL, and log4j? SLF4J is for you. 572 | 573 | The [two-page manual][slf4jmanual] is pretty much all you'll need to get 574 | started. 575 | 576 | ### jOOQ 577 | 578 | I dislike heavy ORM frameworks because I like SQL. So I wrote a lot of 579 | [JDBC templates][jdbc] and it was sort of hard to maintain. [jOOQ][jooq] is a 580 | much better solution. 581 | 582 | It lets you write SQL in Java in a type safe way: 583 | 584 | ```java 585 | // Typesafely execute the SQL statement directly with jOOQ 586 | Result> result = 587 | create.select(BOOK.TITLE, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME) 588 | .from(BOOK) 589 | .join(AUTHOR) 590 | .on(BOOK.AUTHOR_ID.equal(AUTHOR.ID)) 591 | .where(BOOK.PUBLISHED_IN.equal(1948)) 592 | .fetch(); 593 | ``` 594 | 595 | Using this and the [DAO][dao] pattern, you can make database access a breeze. 596 | 597 | ## Testing 598 | 599 | Testing is critical to your software. These packages help make it easier. 600 | 601 | ### jUnit 4 602 | 603 | [jUnit][junit] needs no introduction. It's the standard tool for unit testing 604 | in Java. 605 | 606 | But you're probably not using jUnit to its full potential. jUnit supports 607 | [parametrized tests][junitparam], [rules][junitrules] to stop you from writing 608 | so much boilerplate, [theories][junittheories] to randomly test certain code, 609 | and [assumptions][junitassume]. 610 | 611 | ### jMock 612 | 613 | If you've done your dependency injection, this is where it pays off: mocking 614 | out code which has side effects (like talking to a REST server) and still 615 | asserting behavior of code that calls it. 616 | 617 | [jMock][jmock] is the standard mocking tool for Java. It looks like this: 618 | 619 | ```java 620 | public class FooWidgetTest { 621 | private Mockery context = new Mockery(); 622 | 623 | @Test 624 | public void basicTest() { 625 | final FooWidgetDependency dep = context.mock(FooWidgetDependency.class); 626 | 627 | context.checking(new Expectations() {{ 628 | oneOf(dep).call(with(any(String.class))); 629 | atLeast(0).of(dep).optionalCall(); 630 | }}); 631 | 632 | final FooWidget foo = new FooWidget(dep); 633 | 634 | Assert.assertTrue(foo.doThing()); 635 | context.assertIsSatisfied(); 636 | } 637 | } 638 | ``` 639 | 640 | This sets up a *FooWidgetDependency* via jMock and then adds expectations. We 641 | expect that *dep*'s *call* method will be called once with some String and that 642 | *dep*'s *optionalCall* method will be called zero or more times. 643 | 644 | If you have to set up the same dependency over and over, you should probably 645 | put that in a [test fixture][junitfixture] and put *assertIsSatisfied* in an 646 | *@After* fixture. 647 | 648 | ### AssertJ 649 | 650 | Do you ever do this with jUnit? 651 | 652 | ```java 653 | final List result = some.testMethod(); 654 | assertEquals(4, result.size()); 655 | assertTrue(result.contains("some result")); 656 | assertTrue(result.contains("some other result")); 657 | assertFalse(result.contains("shouldn't be here")); 658 | ``` 659 | 660 | This is just annoying boilerplate. [AssertJ][assertj] solves this. You can 661 | transform the same code into this: 662 | 663 | ```java 664 | assertThat(some.testMethod()).hasSize(4) 665 | .contains("some result", "some other result") 666 | .doesNotContain("shouldn't be here"); 667 | ``` 668 | 669 | This fluent interface makes your tests more readable. What more could you want? 670 | 671 | # Tools 672 | 673 | ## IntelliJ IDEA 674 | 675 | **Good alternatives**: [Eclipse][eclipse] and [Netbeans][netbeans] 676 | 677 | The best Java IDE is [IntelliJ IDEA][intellij]. It has a ton of awesome 678 | features, and is really the main thing that makes the verbosity of Java 679 | bareable. Autocomplete is great, 680 | [the inspections are top notch][intellijexample], and the refactoring 681 | tools are really helpful. 682 | 683 | The free community edition is good enough for me, but there are loads of great 684 | features in the Ultimate edition like database tools, Spring Framework support 685 | and Chronon. 686 | 687 | ### Chronon 688 | 689 | One of my favorite features of GDB 7 was the ability to travel back in time 690 | when debugging. This is possible with the [Chronon IntelliJ plugin][chronon] 691 | when you get the Ultimate edition. 692 | 693 | You get variable history, step backwards, method history and more. It's a 694 | little strange to use the first time, but it can help debug some really 695 | intricate bugs, Heisenbugs and the like. 696 | 697 | ## JRebel 698 | 699 | Continuous integration is often a goal of software-as-a-service products. What 700 | if you didn't even need to wait for the build to finish to see code changes 701 | live? 702 | 703 | That's what [JRebel][jrebel] does. Once you hook up your server to your JRebel 704 | client, you can see changes on your server instantly. It's a huge time savings 705 | when you want to experiment quickly. 706 | 707 | ## The Checker Framework 708 | 709 | Java's type system is pretty weak. It doesn't differentiate between Strings 710 | and Strings that are actually regular expressions, nor does it do any 711 | [taint checking][taint]. However, [the Checker Framework][checker] 712 | does this and more. 713 | 714 | It uses annotations like *@Nullable* to check types. You can even define 715 | [your own annotations][customchecker] to make the static analysis done even 716 | more powerful. 717 | 718 | ## Eclipse Memory Analyzer 719 | 720 | Memory leaks happen, even in Java. Luckily, there are tools for that. The best 721 | tool I've used to fix these is the [Eclipse Memory Analyzer][mat]. It takes a 722 | heap dump and lets you find the problem. 723 | 724 | There's a few ways to get a heap dump for a JVM process, but I use 725 | [jmap][jmap]: 726 | 727 | ```bash 728 | $ jmap -dump:live,format=b,file=heapdump.hprof -F 8152 729 | Attaching to process ID 8152, please wait... 730 | Debugger attached successfully. 731 | Server compiler detected. 732 | JVM version is 23.25-b01 733 | Dumping heap to heapdump.hprof ... 734 | ... snip ... 735 | Heap dump file created 736 | ``` 737 | 738 | Then you can open the *heapdump.hprof* file with the Memory Analyzer and see 739 | what's going on fast. 740 | 741 | # Resources 742 | 743 | Resources to help you become a Java master. 744 | 745 | ## Books 746 | 747 | * [Effective Java](http://www.amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683) 748 | * [Java Concurrency in Practice](http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601) 749 | 750 | ## Podcasts 751 | 752 | * [The Java Posse](http://www.javaposse.com/) 753 | 754 | 755 | [immutablemap]: http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableMap.html 756 | [immutablelist]: http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableList.html 757 | [immutableset]: http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableSet.html 758 | [depconverge]: https://maven.apache.org/enforcer/enforcer-rules/dependencyConvergence.html 759 | [copydir]: http://commons.apache.org/proper/commons-io/javadocs/api-release/org/apache/commons/io/FileUtils.html#copyDirectory(java.io.File,%20java.io.File) 760 | [writestring]: http://commons.apache.org/proper/commons-io/javadocs/api-release/org/apache/commons/io/FileUtils.html#writeStringToFile(java.io.File,%20java.lang.String) 761 | [readlines]: http://commons.apache.org/proper/commons-io/javadocs/api-release/org/apache/commons/io/IOUtils.html#readLines(java.io.InputStream) 762 | [guava]: http://code.google.com/p/guava-libraries/ 763 | [cachebuilder]: http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/cache/CacheBuilder.html 764 | [immutablesorted]: http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ImmutableSortedMultiset.html 765 | [uninterrupt]: http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/util/concurrent/Uninterruptibles.html 766 | [lists]: http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Lists.html 767 | [maps]: http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html 768 | [sets]: http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html 769 | [collections2]: http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Collections2.html 770 | [rootpom]: https://gist.github.com/cxxr/10787344 771 | [mavenexample]: http://books.sonatype.com/mvnex-book/reference/index.html 772 | [jenkins]: http://jenkins-ci.org/ 773 | [travis]: https://travis-ci.org/ 774 | [cobertura]: http://cobertura.github.io/cobertura/ 775 | [coberturamaven]: http://mojo.codehaus.org/cobertura-maven-plugin/usage.html 776 | [nexus]: http://www.sonatype.com/nexus 777 | [artifactory]: http://www.jfrog.com/ 778 | [mavenrepo]: http://stackoverflow.com/questions/364775/should-we-use-nexus-or-artifactory-for-a-maven-repo 779 | [artifactorymirror]: http://www.jfrog.com/confluence/display/RTF/Configuring+Artifacts+Resolution 780 | [gson]: https://code.google.com/p/google-gson/ 781 | [gsonguide]: https://sites.google.com/site/gson/gson-user-guide 782 | [joda]: http://www.joda.org/joda-time/ 783 | [lombokguide]: http://jnb.ociweb.com/jnb/jnbJan2010.html 784 | [play]: http://www.playframework.com/ 785 | [chef]: http://www.getchef.com/chef/ 786 | [puppet]: http://puppetlabs.com/ 787 | [ansible]: http://www.ansible.com/home 788 | [squadron]: http://www.gosquadron.com 789 | [googlestyle]: http://google-styleguide.googlecode.com/svn/trunk/javaguide.html 790 | [googlepractices]: http://google-styleguide.googlecode.com/svn/trunk/javaguide.html#s6-programming-practices 791 | [di]: http://en.wikipedia.org/wiki/Dependency_injection 792 | [spring]: http://projects.spring.io/spring-framework/ 793 | [springso]: http://programmers.stackexchange.com/questions/92393/what-does-the-spring-framework-do-should-i-use-it-why-or-why-not 794 | [java8]: http://www.java8.org/ 795 | [javastream]: http://blog.hartveld.com/2013/03/jdk-8-33-stream-api.html 796 | [slf4j]: http://www.slf4j.org/ 797 | [slf4jmanual]: http://www.slf4j.org/manual.html 798 | [junit]: http://junit.org/ 799 | [junitparam]: https://github.com/junit-team/junit/wiki/Parameterized-tests 800 | [junitrules]: https://github.com/junit-team/junit/wiki/Rules 801 | [junittheories]: https://github.com/junit-team/junit/wiki/Theories 802 | [junitassume]: https://github.com/junit-team/junit/wiki/Assumptions-with-assume 803 | [jmock]: http://jmock.org/ 804 | [junitfixture]: https://github.com/junit-team/junit/wiki/Test-fixtures 805 | [initializingbean]: http://docs.spring.io/spring/docs/3.2.6.RELEASE/javadoc-api/org/springframework/beans/factory/InitializingBean.html 806 | [apachecommons]: http://commons.apache.org/ 807 | [lombok]: http://projectlombok.org/ 808 | [javatuples]: http://www.javatuples.org/ 809 | [dontbean]: http://www.javapractices.com/topic/TopicAction.do?Id=84 810 | [nullable]: http://code.google.com/p/google-guice/wiki/UseNullable 811 | [optional]: http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html 812 | [jdbc]: http://docs.spring.io/spring/docs/4.0.3.RELEASE/javadoc-api/org/springframework/jdbc/core/JdbcTemplate.html 813 | [jooq]: http://www.jooq.org/ 814 | [dao]: http://www.javapractices.com/topic/TopicAction.do?Id=66 815 | [gradle]: http://www.gradle.org/ 816 | [intellij]: http://www.jetbrains.com/idea/ 817 | [intellijexample]: http://i.imgur.com/92ztcCd.png 818 | [chronon]: http://blog.jetbrains.com/idea/2014/03/try-chronon-debugger-with-intellij-idea-13-1-eap/ 819 | [eclipse]: https://www.eclipse.org/ 820 | [dagger]: http://square.github.io/dagger/ 821 | [guice]: https://code.google.com/p/google-guice/ 822 | [netbeans]: https://netbeans.org/ 823 | [mat]: http://www.eclipse.org/mat/ 824 | [jmap]: http://docs.oracle.com/javase/7/docs/technotes/tools/share/jmap.html 825 | [jrebel]: http://zeroturnaround.com/software/jrebel/ 826 | [taint]: http://en.wikipedia.org/wiki/Taint_checking 827 | [checker]: http://types.cs.washington.edu/checker-framework/ 828 | [customchecker]: http://types.cs.washington.edu/checker-framework/tutorial/webpages/encryption-checker-cmd.html 829 | [builderex]: http://jlordiales.wordpress.com/2012/12/13/the-builder-pattern-in-practice/ 830 | [javadocex]: http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ImmutableMap.Builder.html 831 | [dropwizard]: https://dropwizard.github.io/dropwizard/ 832 | [jersey]: https://jersey.java.net/ 833 | [springboot]: http://projects.spring.io/spring-boot/ 834 | [spark]: http://www.sparkjava.com/ 835 | [assertj]: http://joel-costigliola.github.io/assertj/index.html 836 | [jaxrs]: http://en.wikipedia.org/wiki/Java_API_for_RESTful_Web_Services 837 | [playdoc]: http://www.playframework.com/documentation/2.3.x/Anatomy 838 | [java8datetime]: http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html 839 | 840 | 841 | 842 | --------------------------------------------------------------------------------