In today’s world of Java development, frameworks like SpringBoot, Quarkus, Play, and Micronaut offer convenience - but at a cost.
With these frameworks, developers often find themselves overwhelmed by hidden conventions, unnecessary layers of complexity, and an over-reliance on "magic" to get things working.
Once you need to optimize and debug, the once-simple setup becomes a tangled mess that’s hard to understand and even harder to improve.
It’s 20 minutes to implement 80% of functionality but 80 hours to debug and optimize the necessary 20%.
Just like our use of Comic Sans for this paragraph, we’re here to break conventions.
Opiniated, magicky frameworks, with lots of hidden conventions are making developers dumb.
Interviewers from all around the world
Small and lightweight Less than 100 files, totalling less than 2000 lines of code, less than 500Kb in total size. |
||
Easy to learn and develop with No unnecessary layers of abstraction. |
||
No reinvention of the wheel Uses standard Java servlets, filters, SQL. No new conventions to learn. No mismatched paradigms to wrestle (ORM much?). |
||
VERBOSE and fully in control No mysterious conventions, no hidden "magic", you are in charge, not the framework. Be confident in your code, not "seems to be working if I do this". Know exactly where to debug and optimize, because you wrote the code, not hidden inside the framework. |
@Path(value = "/order/checkout", allow = {}, deny = {}) public View checkout(@Parameter("person") Cart cart) { Integer setting = 1000; return transactionService.action(new TransactionContext<View>() { public View action(Object... array) { Cart cart = (Cart) array[0]; Integer setting = (Integer) array[1]; // for each product in cart // if there is enough inventory to fullfil order then reduce inventory else throw a RuntimeException // if user's wallet has enough wallet, then deduct from wallet's balance, else throw a RuntimeException return ok; } }, cart, setting); }
@Singleton public class TransactionService { @Transactional public void execute(TransactionContext transactionContext) { transactionContext.execute(); } @Transactional public void execute(TransactionContext transactionContext, Object... array) { transactionContext.execute(array); } @Transactional public <T> T action(TransactionContext<T> transactionContext) { return transactionContext.action(); } @Transactional public <T> T action(TransactionContext<T> transactionContext, Object... array) { return transactionContext.action(array); } }
@Transactional public List<Person> list(Boolean active) { // tri-state, if active is null it returns all return (list(Person.class, "select " + "id, storageMapData, name, email, password, active, image, birthDate, roleSetData, attachmentListData " + "from person " + "where (? is null or active = ?) order by id", active, active); } @Transactional public Material findById(Long id, boolean calculateQuantity) { // since the SQL is a regular String (as opposed to an annotation), you can do conditional statements and any other String operations return fromDecorator.decorate(find(Material.class, "select " + "material.*" + (calculateQuantity ? ", coalesce(data.quantity, 0) as quantity" : "") + "from material " + (calculateQuantity ? "left join (select materialId, sum(movement) as quantity from materialMovement group by materialId) data on material.id = data.materialId " : "") + "where material.id = ?", id)); } @Transactional public List<Person> list(Integer offset, Integer limit, String sortField, String sortDirection) { // guard against SQL injection List<String> fieldList = Arrays.asList("id", "name", "email", "active", "role"); if (fieldList.contains(sortField) && ("asc".equals(sortDirection) || "desc".equals(sortDirection))) { } else { sortField = "id"; sortDirection = "desc"; } return fromDecorator.decorate(list(Person.class, "select " + "id, storageMapData, name, email, password, active, image, birthDate, roleSetData, attachmentListData " + "from person " + "order by " + sortField + " " + sortDirection + " limit ? offset ?", limit, offset)); }
// if this is your entity object public class Product extends BaseModel { protected String name; protected String brandName; // getters and setters } @Transactional public List<Product> list() { // since brand.name has a name/alias of "brandName", the framework will call product.setBrandName() return list(Product.class, "select product.*, brand.name as `brandName` from product left join brand on brand.id = product.brandId order by product.name"); } // if your base model (where it is inherited by each Model) looks like this (i.e. it has a Map) public class BaseModel { protected Long id; protected Map<String, Object> map = new HashMap<>(); public Object get(String key) { if (map != null) { return map.get(key); } return null; } public Object set(String key, Object value) { if (map != null) { return map.put(key, value); } return null; } } // then you don't need to even create a special field like brandName, just map it to the Map @Transactional public List<Product> list() { // since brand.name has a name/alias of "map.brandName", the framework will call product.getMap().put("brandName", value) return list(Product.class, "select product.*, brand.name as `map.brandName` from product left join brand on brand.id = product.brandId order by product.name"); } // another example @Transactional public List<Shop> listAgain() { // framework will call shop.setId(), shop.setName() // shop.getMap().put("whatever", value), shop.getAdditionalProductList().get(2).setName() // shop.getMap().get("level1").get("level2").get("level3").get("level4").get("level5").put("name", value) return list(Shop.class, "select id, name, slug as `map.whatever`, name as `additionalProductList[2].name`, name as `map.level1.level2.level3.level4.level5.name` from shop order by name"); }
// return as object array @Transactional public List<Object[]> listMultiple() { List<Object[]> list = list(Builder.build(PersistenceModule.classTypeMapping, null, new Specification[] { // new Specification("first", Brand.class), // new Specification("second", Product.class) // }), "select " + // "brand.id as firstId, brand.name as firstName, brand.slug as firstSlug, " + // "product.id as secondId, product.name as secondName, product.slug as secondSlug " + // "from product join brand on product.brandId = brand.id order by brand.name"); return list; }
@Transactional public List<Shop> listBuild() { return apply(list(new Builder<Shop>() { public Shop build(ResultData rd) throws SQLException { Shop shop = new Shop(); shop.setId(rd.getLong("shop.id")); shop.setSlug(rd.getString("shop.slug")); shop.setName(rd.getString("shop.name")); shop.set("whateverName", rd.getString("product.name")); shop.set("whateverSlug", rd.getString("product.Slug")); shop.set("whateverQuantity", rd.getString("product.Quantity")); return shop; } }, "select shop.id, product.slug as name from shop join product on product.shopId = shop.id order by shop.name"), sanitizer); }
@Transactional(type = "Master") public int save(Shop shop) { if (shop.getId() != null) { return super.update("shop", shop, new String[] { "id" }, "slug", "name"); } else { return super.create("shop", shop, "id", "slug", "name"); } } @Transactional(type = "Slave") public Shop find(Long id) { return apply(find(Shop.class, "select * from shop where id = ?", id), sanitizer); }
public static final Decorator<Person> toDecorator = new Decorator<Person>() { public Person decorate(Person entity) { if (entity == null) { return entity; } toDecorate(entity); if (entity.getRoleSet() != null) { entity.setRoleSetData(Utility.gson.toJson(entity.getRoleSet())); } return entity; } }; public static final Decorator<Person> fromDecorator = new Decorator<Person>() { public Person decorate(Person entity) { if (entity == null) { return entity; } fromDecorate(entity); entity.set("birthDate", Utility.format(Utility.dateFormat, entity.getBirthDate())); entity.set("birthDateFull", Utility.format(Utility.fullDateFormat, entity.getBirthDate())); if (Utility.isNotBlank(entity.getRoleSetData())) { entity.setRoleSet(Utility.gson.fromJson(entity.getRoleSetData(), Utility.typeSetOfPersonRole)); entity.setRoleSetData(null); } return entity; } };
public static Function<Person, Person> sanitizerNoPassword = new Function<Person, Person>() { public Person apply(Person entity) { if (entity != null) { entity.setPassword(null); } return entity; } }; @Path(value = "/system/person", allow = { "Administrator", "Tenant" }, deny = {}) public View find(@Parameter("id") Long id) { Person person = personService.apply(personService.findById(id), personService.sanitizer, personService.sanitizerNoPassword); return person != null ? ok(person) : notFound; }
// via query string/post data would be person.name=Bob&person.gender=Male @Path(value = "/system/person/add", allow = { "Administrator", "Tenant" }, deny = {}) public View add(@Parameter("person") Person person) { return ok; } // via request body would be {"person":{"name":"Bob","gender":"Male"}} @Path(value = "/system/person/edit", allow = { "Administrator", "Tenant" }, deny = {}) public View add(@Parameter("person") Person person) { return ok; } // path regex // path variable // a method handling multiple paths @PathSet({ // @Path(value = "/system/common/shop/([0-9]+)", name = "entityId", allow = {}, deny = {}), // @Path(value = "/system/common/(store|shop)/find/([0-9]+)", name = "qualifier,entityId", method = "POST", allow = {}, deny = {}) // }) public View find( // @Parameter("productId") Long productId, // @Parameter("queryObject") Object queryObject, // @Parameter("entityId") Long entityId, // @Parameter("qualifier") String qualifier, // @Parameter("genericMap") Map genericMap, // @Parameter("shop") Shop shop, // @Parameter("shopList") List<Shop> shopList, // @Parameter("object") Object object // ) { return ok; }
@Transactional public void batchInsert(List<Shop> entityList) { String sql = "insert into shop (slug, name) values (?, ?)"; batch(50, sql, toDecorator, new BatchPreparer<Shop>() { public Object[] toFieldArray(Shop entity) { return new Object[] { entity.getSlug(), entity.getName() }; } }, entityList); }