📜 ⬆️ ⬇️

Simple webdev in java 8

I want to talk about how I got the idea to do web development in Java.

So, as soon as I matured for this business, I made a small list to which the development tools I chose should correspond:

Going hard, I found what I needed: Spark , jade4j and OrmLite .

So, tools are chosen, we will consider each of them separately.

Spark Framework


I chose the latest version, which requires Java 8 to work. The framework itself is positioned as Sinatra-inspired, since I am not familiar with Sinatra too closely, it rather reminded me of Express for Node.js.
')
The idea was close, especially since there was already a positive experience with Express. The documentation seems to be poor, but in the development process you are convinced that it is more than enough. I think it’s a big plus that the development does not require pre-setting the environment, installing a servlet container, and so on. All you need to do is add a dependency in pom.xml, write a couple of lines - and everything will take off.

Jade4j


If you have worked with Node.js template engines, in particular with jade, then you probably want to use it more. Easy to read code, good documentation, many beautiful features and experience of using earlier made me choose this template engine.

A small example of layout.jade:

doctype html html head block headsection body header div#main block content footer 

Elements {block blockname} are implemented in other files as follows:

 extends layout block headsection title , ! block content h1 Hello, habr! 


Ormlite


Most likely, some android developers are well acquainted with this ORM. It is easy to use, lightweight and configurable with annotations.

Here is a simple example of a pojo User class:

 package com.vagga.pojo; import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; @DatabaseTable(tableName = "users") public class User { @DatabaseField(columnName = "user_id", generatedId = true) private int userId; @DatabaseField(columnName = "username", unique = true, canBeNull = false) private String userName; @DatabaseField(columnName = "user_pass") private String password; public User() { } /* *  - */ } 

Interaction with the database can be carried out through the built-in ORM Dao. I wrote a small singleton class to simplify my life (maybe the code below will upset you a bit, so I’ll make another reservation: the main goal was to be easy to implement and use):

 package com.vagga.utils; import com.j256.ormlite.dao.Dao; import com.j256.ormlite.dao.DaoManager; import com.j256.ormlite.jdbc.JdbcConnectionSource; import com.vagga.pojo.Category; import com.vagga.pojo.Comment; import com.vagga.pojo.Post; import com.vagga.pojo.User; import java.sql.SQLException; public class DbUtil { private static DbUtil ourInstance = new DbUtil(); private JdbcConnectionSource dbSource; private Dao<User, Integer> userDao; private Dao<Post, Integer> postDao; private Dao<Category, Integer> categoryDao; private Dao<Comment, Integer> commentDao; public static DbUtil getInstance() { return ourInstance; } private DbUtil() { try { dbSource = new JdbcConnectionSource("jdbc:mysql://localhost:3306/vagga?user=root&characterEncoding=utf8"); userDao = DaoManager.createDao(dbSource, User.class); postDao = DaoManager.createDao(dbSource, Post.class); categoryDao = DaoManager.createDao(dbSource, Category.class); commentDao = DaoManager.createDao(dbSource, Comment.class); } catch (SQLException e) { e.printStackTrace(); System.out.println("Cannot establish DB connection " + e.getMessage() + " " + e.getCause()); } } public Dao<User, Integer> getUserDao() { return userDao; } public Dao<Post, Integer> getPostDao() { return postDao; } public Dao<Category, Integer> getCategoryDao() { return categoryDao; } public Dao<Comment, Integer> getCommentDao() { return commentDao; } } 

Several solutions that may disappoint you


Having started the coding process, I came across several problems that had to be solved in some way.

The number one problem was that Spark did not support the jade out of the box, so I had to google and figure out how to make friends with them. The solution to the problem was quite simple. You just need to inherit from the TemplateEngine class and implement the interface render method.

In the same google group, I found this quite working code:

 package com.vagga.utils; import de.neuland.jade4j.JadeConfiguration; import de.neuland.jade4j.exceptions.JadeException; import de.neuland.jade4j.model.JadeModel; import de.neuland.jade4j.template.FileTemplateLoader; import de.neuland.jade4j.template.JadeTemplate; import de.neuland.jade4j.template.TemplateLoader; import spark.ModelAndView; import spark.TemplateEngine; import java.io.File; import java.io.IOException; import java.io.StringWriter; import java.util.Map; public class JadeEngine extends TemplateEngine { private JadeConfiguration configuration; private String directory = new File(".").getCanonicalPath(); public JadeEngine() throws IOException { this.configuration = new JadeConfiguration(); this.directory = this.directory + "/src/main/resources/templates/"; TemplateLoader loader = new FileTemplateLoader(directory, "UTF-8"); configuration.setTemplateLoader(loader); } @SuppressWarnings("unchecked") @Override public String render(ModelAndView modelAndView) { StringWriter stringWriter = new StringWriter(); try { JadeTemplate template = this.configuration.getTemplate(modelAndView.getViewName()); JadeModel jadeModel = new JadeModel((Map<String, Object>) modelAndView.getModel()); template.process(jadeModel, stringWriter); } catch (JadeException | IOException e) { e.getCause(); } return stringWriter.toString(); } } 

The next problem was related to the fact that I did not know how to properly split the request mapping into different classes. As a result, I decided to create an interface with three methods:

 package com.vagga.routes; public interface BaseRoute { public void initBeforeAction(); public void initActions(); public void initAfterActions(); } 

Next, I created the base class of the route, in which I initialized the template rendering helpers:

 package com.vagga.routes; import com.vagga.utils.JadeEngine; import com.vagga.utils.JsonTransformer; import java.io.IOException; public class Route { protected JadeEngine templateEngine; protected JsonTransformer jsonTransformer; protected Route() throws IOException { templateEngine = new JadeEngine(); jsonTransformer = new JsonTransformer(); } } 

The implementation of the final mapper class is here:

 package com.vagga.routes; import com.vagga.pojo.Category; import com.vagga.pojo.User; import com.vagga.utils.DbUtil; import spark.ModelAndView; import java.io.IOException; import java.sql.SQLException; import java.util.HashMap; import java.util.List; import java.util.Map; import static spark.Spark.*; public class HomeRoute extends Route implements BaseRoute { public HomeRoute() throws IOException { super(); } @Override public void initBeforeAction() { } @Override public void initActions() { get("/", (req, res) -> { Map<String, Object> model = new HashMap<String, Object>(); try { List<Category> categories = DbUtil.getInstance().getCategoryDao().queryForAll(); User user = DbUtil.getInstance().getUserDao().queryForId(1); model.put("user", user); model.put("categories", categories); model.put("title", ""); } catch (SQLException e) { e.printStackTrace(); } return new ModelAndView(model, "home/index.jade"); }, this.templateEngine); } @Override public void initAfterActions() { } } 

Now all the mapping classes need to be instantiated somehow. I do it right in the main class, because I haven't thought of anything smarter yet (I will be grateful if someone suggests how it can be done better):

 public class VaggaMain { public static void main(String[] args) { try { ArrayList<BaseRoute> routes = new ArrayList<>(); routes.add(new HomeRoute()); routes.add(new AdminRoute()); routes.add(new ApiRoute()); routes.forEach((route) -> { route.initBeforeAction(); route.initActions(); route.initAfterActions(); }); } catch (IOException e) { e.printStackTrace(); } } } 


Total


All the goals that I set for myself were realized. I was satisfied with the tools. The main problems encountered are the extreme scarcity of information on the Internet about the above tools. In general, the framework is cool, simple and makes you happy.

Thank you all for your attention! Constructive criticism is welcome.

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


All Articles