banner



How To Create Own Framework In Java

Creating a Java web framework from scratch

Raphaël Vigée

Why ?

Well, that's a good enough question to start with, with all the existing solutions, why would I want to create my own ?

  1. It all started from a University project, as a group we had to create a Human Resources Management System (Whatever…). We started to look for a web framework that is both easy to setup and use (easy learning curve) and powerful. Something similar to Symfony from the PHP sphere.

After some digging we couldn't find any suitable solution; that's where the second arguments comes in!

2. It's a very interesting project ! Thats it. 🚀

Features

Originally being a Symfony developer, I knew how the framework was working in the background, and some features were in my opinion mandatory:

  • A Container : A single instance that holds all the services together
  • Dependency Injection : That auto-magically injects the required services
  • An EventDispatcher
  • A Voter based security system
  • An ExpressionLanguage (that one is funny 😉)
  • A Controller / Route handling system

I'm going to cover 2 aspects of the actual framework, which were in my opinion the most difficult and/but interesting to implement so far

Container & Dependency Injection

To be as extensible as possible, each service would be defined by:

  • An alias : the internal reference class for the service
  • A type : the actual class that will be instantiated as later
  • A set of constructors (usually a single one but due to the multiple constructors capabilities of Java, it would be weird not having them defined as a set)
  • A set of methods that will be call just after instantiation
  • An optional Configuration

Dependency Injection

Consider the following example :

Services dependencies example

Service 1 needs Service 4 and Service 2

S e rvice 2 needs Service 4 and Service 3

The natural instantiation order would be; (Service 3 /Service 4 ) then Service 2 and finally Service 1 . Straightforward.

Okay, that was an easy one… What about this one:

Circular Reference example

Yes, a circular reference, or in other words an infinite loop. ➿

To prevent the Container instantiator from infinite looping over these two poor services, circular references had to be detected before doing anything else.

In order to solve these problems in a programmatical way, and after a few experimentations, I choose to go for the tree representation of every service dependencies, and then by going from the leafs to the root checking if the service was already instantiated and not already in the tree I was able to tell if the root service could be itself instantiated. This approach might not be the fastest, but it ensures a 100% accuracy. It's actual implementation can be found here, here and here.

Voters, Routes, Security and ExpressionLanguage

First of all, a bit of vocabulary:

Security voters are the most granular way of checking permissions (e.g. "can this specific user edit the given item?")

A route is a map from a URL path to a controller.

The ExpressionLanguage provides an engine that can evaluate expressions. An expression is a string that returns a value (mostly, but not limited to, Booleans).

Definitions inspired from symfony.com

A very cool feature of Symfony is that it allows you to write the following:

          class MyController extends Controller
{
/**
* @Security("is_granted('POST_SHOW', post)")
*/
public function showAction(Post $post)
{
// ...
}
}

What is happening here ?

In the controller MyController the showAction is protected by a condition: is the current user allowed to show the post ?

The is_granted function in the background calls a voter that's going to decide whether or not the user is allowed to see this post.

I thought having such a feature in Java would be great !

ExpressionLanguage

Java has out-of-the-box an engine that can run Javascript. Great ! No need to reinvent the wheel !

But, wait, one small issue. In Javascript, when you call a function; just its name matters, not its signature. It's the opposite from Java. But the way the ScriptEngine binds the Javascript calls to the actual Java code takes into account the signature. 😐

Brainfuck

The Java ScriptEngine allows you to inject variables as a HashMap , ie:

          <identity name> = <value>        

But what if you want to inject this behavior :

          public void sayHello()
{
System.out.println("Hello");
}

public void sayHello(String name)
{
System.out.println("Hello " + name);
}

One single method name with two different behaviors depending on the parameters

That's the problem, you can't. Or… can you ?!

The solution is to use aFunctionalInterface and Java 8 default methods in interfaces.

This example is a very simple case, but in more complex cases having one method name per signature can be a real nightmare.

          @FunctionalInterface
public interface ConsumerSayHello
{
void sayHello(String name);

default void sayHello()
{
sayHello(null);
}
}

That allows me to register the Binding, as they call it, like this:

          bindings.put("sayHello", (ConsumerSayHello) this::sayHello);        

And to have my expression that looks like this:

          sayHello()        

Or like that :

          sayHello("Java")        

Clean 👌. Problem solved ! 🔥

Now the exact same behavior can be created with an @Security annotation on our Routes !

Security documentation here

How To Create Own Framework In Java

Source: https://medium.com/@raphaelvigee/creating-a-java-web-framework-from-scratch-9d9881c76303

Posted by: bealsgrany1997.blogspot.com

0 Response to "How To Create Own Framework In Java"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel