How To Create Own Framework In Java
Creating a Java web framework from scratch
Why ?
Well, that's a good enough question to start with, with all the existing solutions, why would I want to create my own ?
- 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
Voterbased security system - An
ExpressionLanguage(that one is funny 😉) - A
Controller/Routehandling 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
methodsthat will be call just after instantiation - An optional
Configuration
Dependency Injection
Consider the following 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:
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. 😐
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