📜 ⬆️ ⬇️

We invent a bicycle in Java - we write our Framework (DI, ORM, MVC and etc)

It all started with the fact that I decided to write my Java Common library. Very often, for typical tasks on Stack Overflow, solutions are found in 3-5-10 lines of code. Copy-paste yourself into projects tired. I decided to put it into a separate library that can be made open source and used in current and future projects. Of course, there are such good ones as Google Guava and Apache Commons, which I also use in my work, but they are rather “correct” and flexible, which results in more than one line of code.

As a result, in the evenings at home in my free time I covered the following areas for 1 week: Sleep / Delay / Pause, Timer for Benchmark, Random range generator, File operations, Tasks / Threads, Reflection, JSON, URL, Logging, Strings. I looked at my projects for copy-paste standard solutions and wrote solutions to the library. Once again, I used the TDD approach to develop the library. First, you write a test for non-existing classes and methods, and then you implement the code so that the tests turn green. Solves two problems: firstly, you try to conveniently use your classes and their methods until they are implemented, secondly, you still have tests that may fail in the future, and you will understand what broke during the next refactoring or bug fixes.

Further more. I began to analyze, as I and many others, typically use Spring / JBoss, and I realized that legacy and the breadth of possibilities make everything more difficult. You can implement a simplified, typical Dependency Injection. No sooner said than done. Added DI Framework to my library. My acquaintances watched my implementation and said that it’s impossible to figure out how Spring works; there is a complete sheet of inheritance and wrapping, and you can see everything right at the first level of implementation and everything is clear. They were interested in how to work with annotations, etc.

Having implemented the DI Framework, I thought about the fact that a little more and there will be a full-fledged Enterprise Server. It remains to add the ORM and Web-server with MVC, REST and security. All in the best traditions, so to speak. And I sucked. Another week in the evenings after work, quarrels with his wife, and it turned out Simplified Enterprise Server. I did not adhere to the JavaEE standards, as I wrote, as it seemed to me, it was convenient and understandable to use. I myself use Spring Boot, Spring Data, JPA 2.0, Spring MVC, Spring Rest, Spring Security at work. Before doing this project on JBoss, I saw the other side of JEE, so to speak. But all this versatility and flexibility of course in the subject. But when you need to quickly build a prototype in the style of JEE or you need to learn how to code serious projects in Java, dive into the world of Spring, Hibernate, etc. long and painstakingly. The only alternative is Spring Boot, but really there is a lot going on hidden from you and if you don’t know how Spring works under the hood, it only slows you down, as any step to the left or to the right is a complete dive into the details ...
')
As a result, the code on the github framework github.com/evgenyigumnov/common

An example of a web service using this framework on the github github.com/evgenyigumnov/example and online it can also be viewed java.igumnov.com:8181 User: demo Password: demo

Example structure:
./: pom.xml ./javascript: user.js ./pages: index.html layout.html login.html ./sql: 1.sql ./src/main/java/com/igumnov/common/example: App.java ExampleUser.java 


pom.xml
  <dependencies> <!--    --> <dependency> <groupId>com.igumnov</groupId> <artifactId>common</artifactId> <version>3.15</version> </dependency> <!--   --> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.4.187</version> </dependency> <!--  Bootstrap, AnglularJS    webjars  --> <dependency> <groupId>org.webjars</groupId> <artifactId>angular-ui-bootstrap</artifactId> <version>0.12.0</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>angularjs</artifactId> <version>1.3.8</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>3.3.1</version> </dependency> </dependencies> 


App.java
 public class App { public static void main(String[] args) throws Exception { ORM.connectionPool("org.h2.Driver", "jdbc:h2:mem:test", "SA", "", 1, 3); //      ( 3 ) ORM.applyDDL("sql"); //             WebServer.init("localhost", 8181); //    - WebServer.security("/login", "/login", "/logout"); //           URL- WebServer.addRestrictRule("/*", new String[]{"user_role"}); //        user_role WebServer.addAllowRule("/static/*"); //        WebServer.addClassPathHandler("/static", "META-INF/resources/webjars"); //        classpath  webjars WebServer.addAllowRule("/js/*"); //       Java Script- WebServer.addStaticContentHandler("/js", "javascript"); //         Java Script WebServer.addTemplates("pages",0); //          //     "/",        ,    index.html WebServer.addController("/", (request, model) -> { model.put("time", new Date()); return "index"; }); //     "/login",  ,    login.html WebServer.addController("/login", (request, model) -> { return "login"; }); //  REST-   "/rest/user"      POST/PUT  JSON-  ExampleUser.class WebServer.addRestController("/rest/user", ExampleUser.class, (request, postObj) -> { switch (request.getMethod()) { case (WebServer.METHOD_GET): //  GET  ArrayList<Object> users; try { users = ORM.findAll(ExampleUser.class); //    } catch (Exception e) { throw new WebServerException(e.getMessage()); //  ,     JSON } return users; //        JSON case (WebServer.METHOD_POST): //  POST  ExampleUser ret = null; try { ret = (ExampleUser) ORM.insert(postObj); //     } catch (Exception e) { throw new WebServerException(e.getMessage()); } return ret; //          JSON case (WebServer.METHOD_DELETE): //  DELETE  ExampleUser user; try { user = (ExampleUser) ORM.findOne(ExampleUser.class, request.getParameter("userName")); //     if(user.getUserName().equals("demo")) { //   demo    throw new WebServerException("You cant delete user demo"); } else { ORM.delete(user); //     delete- } } catch (Exception e) { throw new WebServerException(e.getMessage()); //  ,     JSON } return user; //  JSON ,        default: throw new WebServerException("Unsupported method"); //      ,  PUT   } }); ArrayList<Object> users = ORM.findAll(ExampleUser.class); //      if (users.size() == 0) { //      ExampleUser user = new ExampleUser(); user.setUserName("demo"); user.setUserPassword("demo"); ORM.insert(user); //  demo/demo    WebServer.addUser("demo", "demo", new String[]{"user_role"}); //  -    demo/demo   user_role } users.stream().forEach((user) -> { //       ExampleUser u = (ExampleUser) user; WebServer.addUser(u.getUserName(), u.getUserPassword(), new String[]{"user_role"}); //  -      user_role }); WebServer.start(); //             Exception,   - :) } } 


ExampleUser.java
 //     JSON          public class ExampleUser { @Id(autoIncremental = false) //  ORM     Primary Key     insert    private String userName; private String userPassword; ... } 


1.sql
 #         ORM   ExampleUser.class CREATE TABLE ExampleUser (userName VARCHAR(255) PRIMARY KEY, userPassword VARCHAR(255)) 


login.html
 <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd"> <!--      layout  layout.html --> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="layout"> <body> <!--         layout.html --> <div layout:fragment="content"> <form name="form" action="/j_security_check" method="POST"> <div class="modal-header"> <h3 class="modal-title">Login</h3> </div> <div class="modal-body"> <div class="form-group"> <input type="text" name="j_username" class="form-control" value="" placeholder="Login"/> </div> <div class="form-group"> <input type="password" name="j_password" class="form-control" placeholder="Password"/> </div> <div class="form-group"> <button type="submit" id="login" class="btn btn-primary">OK</button> </div> </div> </form> </div> </body> </html> 


index.html
 <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd"> <!--      layout  layout.html --> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="layout"> <body> <!--         layout.html --> <div layout:fragment="content"> <!--     AngularJS--> <script src="/js/user.js"></script> <h1 th:text="${time}"></h1> //       <!--      UserCtrl --> <div ng-controller="UserCtrl"> <table class="table"> <thead> <tr> <th>Name</th> <th>Password</th> <th></th> </tr> </thead> <tbody> <!--      --> <tr ng-repeat="user in users"> <td>{{user.userName}}</td> <td>{{user.userPassword}}</td> <!--            --> <td><a href="#"><span class="glyphicon glyphicon-remove" tooltip="Delete" ng-click="deleteUser(user)"/></a></td> </tr> </tbody> </table> <div ng-model="user"> <!--    --> <div class="form-group"> <input type="text" class="form-control" ng-model="user.userName" placeholder="Login"/> </div> <div class="form-group"> <input type="password" class="form-control" ng-model="user.userPassword" placeholder="Password"/> </div> <div class="form-group"> <!--           --> <button class="btn btn-primary" ng-click="addUser(user)">Add</button> </div> </div> </div> </div> </body> </html> 


layout.html
 <!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd"> <!--      AngularJS --> <html ng-app="com.igumnov.common.example"> <head> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap/3.3.1/css/bootstrap.min.css" /> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> </head> <body> <script src="/static/angularjs/1.3.8/angular.min.js"></script> <script src="/static/angularjs/1.3.8/angular-resource.min.js"></script> <script src="/static/angular-ui-bootstrap/0.12.0/ui-bootstrap-tpls.min.js"></script> <div class="container"> <!--      --> <div layout:fragment="content"></div> </div> </body> </html> 


user.js
 angular.module('com.igumnov.common.example', ['ui.bootstrap', 'ngResource']) .factory('User', ['$resource', function ($resource) { //  REST- User return $resource('/rest/user', {}, { list: { //   method: 'GET', cache: false, isArray: true //    }, add: { //   method: 'POST', cache: false, isArray: false //     }, delete: { //   method: 'DELETE', cache: false, isArray: false //     } }); }]) .controller('UserCtrl', function ($scope, User) { //    UserCtrl $scope.users = User.list({}); //       $scope.addUser = function (user) { //    User.add({},user,function (data) { //  REST- $scope.users = User.list({}); //   ,    }, function (err) { alert(err.data.message); //   ,   }); } $scope.deleteUser = function (user) { //    User.delete({"userName" : user.userName},user,function (data) { //  REST- $scope.users = User.list({}); //   ,    }, function (err) { alert(err.data.message); //   ,   }); } }); 


In conclusion, I will be glad to any criticism and suggestions for improving the library code. For myself, I got a profit in kneading the brain when writing a library and using closures / lambda. Sometimes it's boring to write commercial products, you want to create your own space ship. Feel free to fork my lib and modify it yourself to fit your needs. It is quite simple and easy to make modifications to it. I would be grateful if you will send pull requests to make your modifications to the library. I am personally determined to check and accept them quickly enough. I'm just a fanatic programmer, it sticks me. I love coding!

PS Yes, yes, I don’t like to write javadoc, send pull-requests with it, now it’s clear from the code that every method does it ...

Source: https://habr.com/ru/post/259005/


All Articles