simple web development in java
DESCRIPTION
The slides of my talk at Confoo 2014 in Montréal, Qc. Let's get back to simplicity when doing Java web development. Forget about DI frameworks, ORMs and complex build tools and see how we can develop well-tested, well-crafted web applications using only simple tools, libraries and techniques. In this talk, I will share my experience rewriting a web application based on Spring MVC, Spring, Hibernate and Maven with only Simple and JDBC. We'll discuss the benefits and challenges of simplicity.TRANSCRIPT
![Page 1: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/1.jpg)
Simple Web Development in Java
Vincent Tencé@testinfected
http://vtence.comhttp://github.com/testinfected
![Page 2: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/2.jpg)
Déjà vu?
You start a new project by assembling multiple libraries and frameworks
It’s a lot of initial complexity
One of the frameworks keeps getting in the way
The framework feels like a prison
It keeps surprising you with unintended behaviour
![Page 3: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/3.jpg)
![Page 4: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/4.jpg)
The Original Version
• Spring with Spring MVC
• Velocity and SiteMesh, UrlRewriteFilter
• Hibernate, JPA, MySQL
• Hibernate Validator
• Maven
• ... 53 jars!
![Page 5: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/5.jpg)
![Page 6: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/6.jpg)
http://thepresentationdesigner.co.uk/blog/portfolio-item/bruce-lee-slide-2/
![Page 7: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/7.jpg)
The Challenge
• Use simple tools and libraries
• Framework (Web, ORM, DI)
• DIYS (Do It Yourself Simply)
• Ease of assembly, configuration and deployment
• Minimum startup and shutdown costs
• XML
• Annotations
![Page 8: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/8.jpg)
The Simple Version
• Simple
• Mustache
• JDBC and MySQL
• CLI
• Buildr
• 4 jars
![Page 9: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/9.jpg)
![Page 10: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/10.jpg)
Build File
define 'petstore', [..] do define 'domain' do compile.with test.with HAMCREST package :jar end
define 'persistence' do compile.with project(:domain) test.with HAMCREST, :flyway, :mysql, NO_LOG, [...] package :jar end
define 'webapp' domain compile.with :simpleframework, :jmustache, [...] test.with HAMCREST, :antlr_runtime, :cssselectors, :hamcrest_dom, [...] test.with transitive(artifacts(:nekohtml, :htmlunit, :jmock_legacy))
package :jar end[...]end
![Page 11: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/11.jpg)
Dependency Injection
AttachmentStorage attachments = new FileSystemPhotoStore("/photos");Connection connection = new ConnectionReference(request).get();Transactor transactor = new JDBCTransactor(connection);ProductCatalog products = new ProductsDatabase(connection);ItemInventory items = new ItemsDatabase(connection);OrderBook orders = new OrdersDatabase(connection);ProcurementRequestHandler procurement =
new PurchasingAgent(products, items, transactor)OrderNumberSequence orderNumbers = new OrderNumberDatabaseSequence(connection);Cashier cashier = new Cashier(orderNumbers, orders, transactor);Messages messages =
new BundledMessages(ResourceBundle.getBundle("ValidationMessages"))
Router router = Router.draw(new DynamicRoutes() {{[...]
}});
![Page 12: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/12.jpg)
Routing
[...]
Router router = Router.draw(new DynamicRoutes() {{ get("/products").to(new ListProducts(products, attachments, pages.products())); post("/products").to(new CreateProduct(procurement)); get("/products/:product/items").to(new ListItems(items, pages.items())); post("/products/:product/items").to(new CreateItem(procurement)); get("/cart").to(new ShowCart(cashier, pages.cart())); post("/cart").to(new CreateCartItem(cashier)); get("/orders/new").to(new Checkout(cashier, pages.checkout())); get("/orders/:number").to(new ShowOrder(orders, pages.order())); post("/orders").to(new PlaceOrder(cashier)); delete("/logout").to(new Logout()); map("/").to(new StaticPage(pages.home()));}});
![Page 13: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/13.jpg)
MVC
public class ShowOrder implements Application { private final OrderBook orderBook; private final Page orderPage;
public ShowOrder(OrderBook orderBook, Page orderPage) { this.orderBook = orderBook; this.orderPage = orderPage; }
public void handle(Request request, Response response) throws Exception { String number = request.parameter("number"); Order order = orderBook.find(new OrderNumber(number)); orderPage.render(response, context().with("order", order)); }}
![Page 14: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/14.jpg)
Data Access
public class OrdersDatabase implements OrderBook { [...] public OrdersDatabase(Connection connection) { this.connection = connection; }
private List<LineItem> findLineItemsOf(Order order) { return Select.from(lineItems). where("order_id = ?", idOf(order).get()). orderBy("order_line"). list(connection); }
private Order findOrder(OrderNumber orderNumber) { return Select.from(orders, "_order"). leftJoin(payments, "payment", "_order.payment_id = payment.id"). where("_order.number = ?", orderNumber). first(connection); } [...]}
![Page 15: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/15.jpg)
Transactions
public class Cashier implements SalesAssistant { [...] public OrderNumber placeOrder(PaymentMethod paymentMethod) throws Exception {
[...] QueryUnitOfWork<OrderNumber> order = new QueryUnitOfWork<OrderNumber>() { public OrderNumber query() throws Exception { OrderNumber nextNumber = orderNumberSequence.nextOrderNumber(); final Order order = new Order(nextNumber); order.addItemsFrom(cart); order.pay(paymentMethod); orderBook.record(order); cart.clear(); return nextNumber; } }; return transactor.performQuery(order); } [...]}
![Page 16: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/16.jpg)
Validation Constraints
public class CreditCardDetails extends PaymentMethod implements Serializable { private final CreditCardType cardType; private final Constraint<String> cardNumber; private final NotNull<String> cardExpiryDate; private final Valid<Address> billingAddress;
public CreditCardDetails(CreditCardType type, String number, String expiryDate, Address billingAddress) {
this.cardType = type; this.cardNumber = Validates.both(notEmpty(number),
correctnessOf(type, number)); this.cardExpiryDate = Validates.notNull(expiryDate); this.billingAddress = Validates.validityOf(billingAddress); }
public String getCardNumber() { return cardNumber.get(); } [...]}
![Page 17: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/17.jpg)
Validation
public class Validator {
public <T> Set<ConstraintViolation<?>> validate(T target) { Valid<T> valid = Validates.validityOf(target); valid.disableRootViolation(); ViolationsReport report = new ViolationsReport(); valid.check(Path.root(target), report); return report.violations(); }
[...]}
![Page 18: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/18.jpg)
Forms
public class PaymentForm extends Form {
public static PaymentForm parse(Request request) { return new PaymentForm(new CreditCardDetails( valueOf(request.parameter("card-type")), request.parameter("card-number"), request.parameter("expiry-date"), new Address(request.parameter("first-name"), request.parameter("last-name"), request.parameter("email")))); }
private final Valid<CreditCardDetails> paymentDetails;
public PaymentForm(CreditCardDetails paymentDetails) { this.paymentDetails = Validates.validityOf(paymentDetails); }
public CreditCardType cardType() { return paymentDetails().getCardType(); } public CreditCardDetails paymentDetails() { return paymentDetails.get(); }}
![Page 19: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/19.jpg)
Thoughts
• Not very “enterprisy”
• What are we missing?
• Use a proven solution or develop our own?
• Not a silver bullet
![Page 20: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/20.jpg)
Takeaways
• Avoid the temptation of frameworks
• Use simple tools that do one thing and do it well
• Build your own tools
• Copy the best ideas; write only the simple code you need
• Keep your tools simple and specialized
![Page 21: Simple Web Development in Java](https://reader033.vdocuments.net/reader033/viewer/2022042700/55632f3ed8b42a5c7b8b4c5a/html5/thumbnails/21.jpg)
Thanks!
• Simple version :https://github.com/testinfected/simple-petstore
• Spring version :https://github.com/testinfected/petstore
•Web :https://github.com/testinfected/molecule
• Data Mapping :https://github.com/testinfected/tape