- System requirements
- Overall structure
- Run
- Build and Run
- Functionalities
- Delivery
- Repositories
- Reference Documentation
- Guides
This application leverages cutting-edge technologies to deliver a robust and versatile user experience:
-
Programming Language: The application is written in Kotlin 1.9.10, a versatile, open-source, statically-typed language. Kotlin is renowned for its adaptability and is commonly used for Android mobile app development. Beyond that, it finds application in server-side development, making it a versatile choice.
-
Build System: The application utilizes Gradle 8.3 as build system. Gradle is renowned for its flexibility in automating the software building process. This build automation tool streamlines tasks such as compiling, linking, and packaging code, ensuring consistency and reliability throughout development.
-
Framework: The application employs Spring Boot 3.1.3 as a framework. This technology requires Java 17 and is fully compatible up to and including Java 20. Spring Boot simplifies the creation of production-grade Spring-based applications. It adopts a highly opinionated approach to the Spring platform and third-party libraries, enabling developers to initiate projects with minimal hassle.
The structure of this project is heavily influenced by the clean architecture:
- A
coremodule where we define the domain entities and the functionalities (also known as uses cases, business rules, etc.). They do not know that this application. has a web interface or that data is stored in relational databases. - A
repositoriesmodule that knows how to store domain entities in a relational database. - A
deliverymodule that knows how to expose in the Web the functionalities. - An
appmodule that contains the main, the configuration (i.e. it linkscore,deliveryandrepositories), and the static assets (i.e. html files, JavaScript files, etc. )
Usually, if you plan to add a new feature, usually:
- You will add a new use case to the
coremodule. - If required, you will modify the persistence model in the
repositoriesmodule. - You will implement a web-oriented solution to expose to clients in the
deliverymodule.
Sometimes, your feature will not be as simple, and it would require:
- To connect a third party (e.g. an external server).
In this case you will add a new module named
gatewayresponsible for such task. - An additional application.
In this case you can create a new application module (e.g.app2) with the appropriate configuration to run this second server.
Features that require the connection to a third party or having more than a single app will be rewarded.
The application can be run as follows:
./gradlew bootRunNow you have a shortener service running at port 8080. You can test that it works as follows:
$ curl -v -d "url=http://www.unizar.es/" http://localhost:8080/api/link
* Trying ::1:8080...
* Connected to localhost (::1) port 8080 (#0)
> POST /api/link HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.71.1
> Accept: */*
> Content-Length: 25
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 25 out of 25 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 201
< Location: http://localhost:8080/tiny-6bb9db44
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Tue, 28 Sep 2021 17:06:01 GMT
<
* Connection #0 to host localhost left intact
{"url":"http://localhost:8080/tiny-6bb9db44","properties":{"safe":true}}% And now, we can navigate to the shortened URL.
$ curl -v http://localhost:8080/6bb9db44
* Trying ::1:8080...
* Connected to localhost (::1) port 8080 (#0)
> GET /tiny-6bb9db44 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.71.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 307
< Location: http://www.unizar.es/
< Content-Length: 0
< Date: Tue, 28 Sep 2021 17:07:34 GMT
<
* Connection #0 to host localhost left intactThe uberjar can be built and then run with:
./gradlew build
java -jar app/build/libs/app-0.2023.1-SNAPSHOT.jarThe project offers a minimum set of functionalities:
-
Create a short URL. See in
corethe use caseCreateShortUrlUseCaseand indeliverythe REST controllerUrlShortenerController. -
Redirect to a URL. See in
corethe use caseRedirectUseCaseand indeliverythe REST controllerUrlShortenerController. -
Log redirects. See in
corethe use caseLogClickUseCaseand indeliverythe REST controllerUrlShortenerController.
The objects in the domain are:
ShortUrl: the minimum information about a short urlRedirection: the remote URI and the redirection modeShortUrlProperties: a handy way to extend data about a short urlClick: the minimum data captured when a redirection is loggedClickProperties: a handy way to extend data about a click
The above functionality is available through a simple API:
POST /api/linkwhich creates a short URL from data send by a form.GET /{id}whereididentifies the short url, deals with redirects, and logs use (i.e. clicks).
In addition, GET / returns the landing page of the system.
All the data is stored in a relational database. There are only two tables.
- shorturl that represents short url and encodes in each row
ShortUrlrelated data, - click that represents clicks and encodes in each row
Clickrelated data.
For further reference, please consider the following sections:
The following guides illustrate how to use some features concretely: