Code Monkey home page Code Monkey logo

meuccifra / eclipse-vert.x-apache-freemarker-bootstrap5-boilerplate Goto Github PK

View Code? Open in Web Editor NEW
1.0 1.0 0.0 54.05 MB

This is intended to be a boilerplate for Vert.x, Freemarker, Bootstrap5, jquery and a bit of my code to start building a web application.

License: Eclipse Public License 2.0

Kotlin 1.53% Java 21.13% HTML 17.41% CSS 3.82% JavaScript 5.31% FreeMarker 25.06% Shell 18.38% Batchfile 7.36%
bootstrap5 freemarker freemarker-template jquery vertx vertx-web java boilerplate localization resourcebundle

eclipse-vert.x-apache-freemarker-bootstrap5-boilerplate's Introduction

Eclipse-Vert.x-Apache-Freemarker-Bootstrap5 boilerplate of a simple Web Application

This is intended to be a boilerplate for a (non-professional as I am) developer that decides to embrace the power of Vert.x and build a simple web application.

Background

I was studying Vert.x because I was looking for something powerfull, immediate to undertand, easy to scale and without overwelming Notations or the additonal complication in having Tomcat up and running in my IDE (I'm using Intellij Idea community edition, do you get my point right?!). I found from the beginning Vert.x very tailored for my brain and it's so easy to have a service (any kind of) up and running that looks kinda of magic. So let's play with it...

What I did

I started from the Eclips Vert.x application generator that gives all the code and Gradle settings necessary to have a working system. I tried to expand this powerfull starting point with the following customizations:

  1. Rewrite the MainVerticle to be a kind of Verticle deployer/coordinator class. In fact, the standard template start the webserver in the MainVerticle class but this was a bit confusing for me, at the first glance. The main verticle should be, in my humble opinion, where the magic of services happens.

  2. Create a structure of folders that can be used by Verti.x with the Static Handler.

        //  Configure static files
        router.route().handler(StaticHandler.create());
    

    This is necessary to serve static files (for example .css and .js) in separate file and it requires to put the static contents in the webroot folder under resources folder. All of them should be created manually if you don't start from this template. I spent a couple of hours before to understand this simple rule.

  3. Get Freemarker working properly.

    1. The dependency is added by application generator if the option is selected but that was not enough because you need at least one .ftl file to play with
    2. I added the boilerplate.ftl (a Freemarker page) this is actually a kind of importer of Freemarker Macros living in other .ftl files (one for the head, one for the general scripts, one for the footer, etc...)
  4. The HTML behind the above mentioned boilerplate and relative macros is a composition of Bootstrap5 template and this one htmlboilerplates that added jQuery but also a good starting point for the cookies code

  5. Added a simple form management on a different route that should clarify how to get form variable setting up the routeter to use BodyHandler

       //Configure body handler to enable multipart form data parsing
       router.route().handler(bodyHandler);
    
  6. Introduced session

       //Enable session
       router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx)));
    

    generation and usage (see how session variable is generated in the index route and used in page route.

  7. Set the target and source compatibility to Java 14 to get benefits from the last Switch constructor in point below

       java {
         sourceCompatibility = JavaVersion.VERSION_14
         targetCompatibility = JavaVersion.VERSION_14
       }   
    
  8. Added the ResourceBundle usage for Localization with LabelsBundle.properties and LabelsBundle_it.properties to translate the welcome message in Italian if the browser first language preference is Italian

      //Initialize the resource Bundle for this request
      ResourceBundle labels = null;
      //GET THE FIRST LOCALE PREFERENCE
      LanguageHeader language = ctx.acceptableLanguages().get(0); //GET THE FIRST PREFERENCE
      //use Switch to get the lables translated base don Locale preference
      labels = switch (language.tag()) {
          case "it" -> ResourceBundle.getBundle("LabelsBundle", Locale.ITALIAN);
          default ->ResourceBundle.getBundle("LabelsBundle", Locale.ENGLISH);
      };
      data.put("sitewelcome",labels.getString("site.welcome"));
    
  9. Added a localization strategy that provide the correct template based on the browser first language preference. Not completely happy about the solution because I was not able to get the system working as expected... I tried to use this suggestion from stackoverflow and the implementation of unwrap()

    Configuration conf = engine.unwrap();
    Template temp = conf.getTemplate("freemarkerlocalization",Locale.ITALIAN);
    String localizedTemplate = temp.getSourceName(); "--> expected to be: freemarkerlocalization_it_IT, I always get: freemarkerlocalization"
    

    It is not working, and suspect is that environment is overriding the config settings. This: Environement env = engine.unwrap(); not works.

  10. Authentication! also said...the Login (and Logout). After some fights due to my poor knowledge and poor time available I've now implemented successfully the login through the SQL Authenticator Provider very inspiring and those examples here and here. I moved important steps toward the solution implementing the DataBase Class and the DBVerticle that I used to populate the Database (P.S: I'm running the database on an original Raspberry Pie 512MB RAM :) ). The DataBase and Tables shall be exactly like this to run this boilerplate... when you have the rules, you can customize.

CREATE DATABASE `dbtest` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;

-- dbtest.users definition
CREATE TABLE `users` (
  `username` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- dbtest.roles_perms definition
CREATE TABLE `roles_perms` (
`role` varchar(255) NOT NULL,
`perm` varchar(255) NOT NULL,
PRIMARY KEY (`role`,`perm`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- dbtest.users_roles definition
CREATE TABLE `users_roles` (
  `username` varchar(255) NOT NULL,
  `role` varchar(255) NOT NULL,
  PRIMARY KEY (`username`,`role`),
  CONSTRAINT `users_roles_FK` FOREIGN KEY (`username`) REFERENCES `users` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  1. This was necessary to test a fantastic feature...Authenticated users can visit /private/* route and in particular I created a page that can be visited only if Authenticated. Once the http://localhost:8080/loginhandler says: "Login successful", try navigate to: http://localhost:8080/private/private_page and you will see that you will be able to see something. It is also interesting to notice that static resources available in "non-private" folders can be also used in "private" mode. I need to refactor a bit the code and maybe make the navigation more elegant but concepts are there. Ah... for sure you can also log out.

  2. Also, the SQLAuthorization feature works like a charm and based on the Role and or Permission your user has in the database, you can protect some parts of your website from unauthorized users. For example, here:

    authorizationProvider.getAuthorizations(user).onSuccess(done -> {
                if (RoleBasedAuthorization.create("admin").match(user)) {
                    logger.info("User has the admin Role");
                    if(PermissionBasedAuthorization.create("full_control").match(user)){
                        logger.info("User has the full_control Permission");
    

    If you change "admin" (that is role given to the user "tim") to "giant" that is a role that doesn't exist, you are redirected (check my code) to the home. I know it should work the way around (try to log in with a user having different authorizations) but this is easier for a quick and dirty test.

  3. Inspired by this I was curious to test how it works. Wow! with few lines, I can upload multiple files and thanks to the method:

    bodyHandler.setUploadsDirectory("uploads");
    

    It set up an Upload Directory creating a new one if it doesn't exist at the same level of "src" folder having the name "uploads" as specified. It also renames the files once uploaded and the ctx.fileUploads() gives file properties available for further use.

Next steps

Share it... Done
Improve it... On going

eclipse-vert.x-apache-freemarker-bootstrap5-boilerplate's People

Contributors

meuccifra avatar

Stargazers

 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.