During the last decade I have worked with Java, mostly within Vaadin R&D, support and technical marketing. I have had an awesome position to see a number of very different kind of applications being built and I built a couple of them myself, too. All applications have different requirements, but most of them basically just read and write data persisted in a RDBMS. Sincerely, I can't say I liked them all. It is bit sad that an area where I have struggled myself and where many Java developers seem to perform badly is something that the Java ecosystem actually supports really well: modularization and re-use - from the class level to the architecture.
I hope I can share my experience back to the community by going through some key parts of a basic CRUD (Create,Read,Update, Delete) example I built recently. Some design decisions are naturally controversial, and don't fit for all purposes, but this is my current base recipe for data centric rich internet applications.
The example app contains basic CRUD features for a Customer entity and some visual and geographical analysis for the data.
Build, libraries and modules
Back in the days when your dad started to make applications with the first version of Java, they used JDK libraries only and compiled the code with a weird command line tool called "javac". Today the software industry is largely choosing a set of libraries and combining them intelligently, making fast changes to the product based on changed requirements and automatically deploying a new automatically tested artifact by your CI server.
You’ll probably throw in many Vaadin add-ons, not to mention generic apache commons libraries, Java EE APIs etc. In this pretty simple CRUD application alone, we include various Apache commons libraries, a Vaadin UI "framework" that automatically creates a main layout and a cool responsive menu from your views, a helper library to simplify creating forms/layouts and for visualizing the data, we use extensions for both charting and geographical visualization.
If you want to be relevant in the modern software development, you must control your libraries/dependencies instead of letting them control you. And your software must be easily built by you, your colleagues, your favorite IDE and your shared CI server. Maven is the de-facto standard that handles both dependencies and builds, but also tackles some other development related details. Learning its basics is almost as essential for Java developers as learning the basics of OO design. If you want to be a dev-hipster, feel free to try Gradle instead - but I strongly suggest you to forget about plain ANT or going in commando style by yourself.
Choose a proper basis for your application
Although dependency management tools help to collect a custom set of libraries for your application, it isn’t necessarily wise to choose each and every library for your application by yourself. You’d still need to configure them and make sure they work well together.
Java EE is a set of extensions to the basic JDK libraries. Or actually, it is mostly a set of standard interfaces that servers like Wildfly, TomEE and WebSphere implement. Java EE has a reputation of being “enterprisey”, meaning lots of configuration, slow development cycles and huge server softwares. It sure might have been like this in the past, but the latest Java EE specifications and implementations are really well optimized for developer productivity and suit extremely well for smaller projects as well. Application servers nowadays launch in a matter of seconds due to their modularity and you can pretty much forget about those old xml configurations - good defaults, conventions and some annotations will do most of your job for you.
If a modern Java EE stack feels “enterprisey” or doesn’t suit your needs, you are most probably doing something wrong. Pretty much all modern Java web apps should be based on either Java EE 6/7 or Spring. I personally like both of them, but I like to promote the standard.
ORM over low level SQL queries
One essential thing that comes with the Java EE stack is a standard object relational mapping API called Java Persistence API (JPA). JPA has many quality implementations of which one is provided for you by your application server. Since version 2.0 you seldom need to use implementation specific APIs or raw SQL.
In addition to making your code more readable and maintainable, JPA can e.g. help to implement optimistic locking for your application. As we have introduced an integer field with the @Version annotation, persisting an entity that has been concurrently modified by another user/process, will throw an exception instead of overwriting previous exceptions. Once you master the basics of JPA, you’ll never want to get back to writing low level SQL queries to your database again.
Most often all your JPA handling should be hidden behind a service layer. That’d be introducing a stateless EJB. With modern EJBs, you only need to create a normal java class and annotate that with @Stateless. Inject your JPA EntityManager there and Java EE will “magically” do transaction handling, efficient database usage (EJB and DB connection pooling) and possibly even set-up a second level cache for you. Lots of stuff, that is error prone to implement manually, will just be taken care of for you.
CDI - why would I need that?
Today, in Java EE world, Contexts and Dependency Injection (CDI) is one of the most essential tools you’ll need. You can think of it as the glue that you use to put together your well decoupled parts. Almost all Java developers have seen the famous @Inject annotation, but there is also a powerful event mechanism provided by CDI.
In the example, the Vaadin UI code is also “bootstrapped” by CDI. By using the Vaadin CDI extension you can often say goodbye to your servlet.xml and even the @WebServlet annotation. Instead you can just inject your UI class by marking it with the @CDIUI annotation. When the context starts, those UIs are searched from the classpath and introduced automatically for the end user. They will also be “managed beans”, so you can further @Inject stuff like your EJB right into your UI code.
In the example app, we actually have quite a little UI code, but still I wanted to separate e.g. the customer form and listing into separate classes. To react on e.g. updated customer details, the CustomerListView listens to CDI events raised by the CustomerForm. CDI events gives you tools for a perfect decoupling that helps you reuse your components. This way I could easily re-use the form part and introduce editing features also for the map view.
Words on structuring your UI code
A constantly open debate with users of component based UI frameworks is whether you should use MVP or MVC or some other pattern to structure your UI code. The answer is, it depends. If you have lots of developers, with varying skills and/or a large UI code base, I'd say definitely. MVP can also improve the testability of your UI logic. Still, in a small to medium sized project, it might be an overkill. If you have a well defined "backend" and can write meaningful names for your methods and classes, you can write quality code just by placing well decoupled UI building blocks into separate classes. The service layer and domain model already give you a pretty good separation of concerns.
Another common debate is whether to generate your UI on runtime or express it with code or markup. While autogeneration may sound like a cool idea, it seldom gives you a decent outcome. Either the UI will be a compromise or you'll waste your time configuring your UI generator. The latter option, with automatic bean binding, has been my choice already in the Vaadin 6 era, and it is nowadays endorsed by the BeanFieldGroup class in the core as well. If you are afraid of boilerplate code you need to write for various entity types, you can use tooling to overcome this inconvenience. I'm most often autogenerating the first draft of the form code based on the entity class with EntityExpander or ViewGenerator. You could also check out this promising project or use Vaadin Designer to draft the initial version.
What is missing?
It depends a bit where you deploy the application, but most likely you'll want to have some sort of authentication and possibly also some authorization for your application. The perfect way to do this depends so much on your requirements and existing infrastructure (e.g. company LDAP server) that I didn't want to introduce any half baked solutions. If you want some hints for this task, I’d suggest to have a look at the excellent Apache Shiro library.
Another critical aspect that is missing from this example is testing. If you intend to build any larger application or maintain it after its initial release, you'll definitely want to have a set of tests that cover the relevant parts of your code. In addition to simple unit tests, you should throw in e.g. Arquillian to test your backend in a Java EE container and Vaadin TestBench to verify everything works like it should for the end-user as well.
The full code for the example application is available via JazzHub. Deploy it to Bluemix or check it out and play with it locally, with your favourite IDE and Java EE server.