0% found this document useful (0 votes)
4 views

Wa05 SpringBoot

Corso di Web Application II del prof G.Malnati - Politecnico di Torino, 2021

Uploaded by

giagio.vit
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

Wa05 SpringBoot

Corso di Web Application II del prof G.Malnati - Politecnico di Torino, 2021

Uploaded by

giagio.vit
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 17

We should be able to represent and main coherent information even in case of failure in a distributed

environment (es. when user start paying an object need to lock the resources).

Typically, when we create program in the object-oriented model, we split our code between two different
kinds of needs or activities: on one side we have lines of code to implement the business logic (set of
behaviors and data management that are behind the purpose of the application as a whole). On the other
side, we typically need also to write lines of code used for configuring our object graph.

Object are interconnected; sometimes we use element that need to operate on another element. Before
starting really operating, so having the code doing something useful, we need to configure the tree of
objects so that they are properly interconnected. This second part is used to configure or set the
dependencies.

These two parts of code are intermixed and not easy distinguish between each other. When the code
grows, they become more and more interconnected.

So, the idea is to try to split the code base, so that we can leave all the procedural part, the one related to
the business logic and move out the configuration.

We would like to have the configuration being created declaratively, by having some way of saying who
depends on whom. That is the exact idea around which the Spring framework as a set of libraries have been
built. So, we have an object-oriented application where elementary object provides their own
functionalities, but they don’t have inside in the code that describe the behavior, directly the
dependencies. They have references to dependencies and annotation and the framework takes care of
finding out who relying on whom based on the annotations, create the object graph and run the
application.

05: Spring Boot Pag. 1 a 17


So, the programmer when using the Spring framework is responsible to define the class of each
component. In Spring framework, they are named Beans.

The programmer is responsible of defining components which make our application, elementary classes
and declare via annotations their dependencies, their configuration, so the set of other components they
are connected to, so the framework will be able when application start, to inspect all the declared
components, instantiate them as necessary and connect one to another, according to what is the
declaration.

This is possible because Spring as a framework,


basically creates what we call a container for
application context.

It is a data structure where all the objects we named


inside the program gets instantiated and stored,
because Spring will inspect elements inside such a
container, such a context and try to assess the
dependencies it needs and look to other components
that can fit properly to connect them.

This means that our main function instead of starting


building object, will just create the container
(application context) and it will start inspecting
available classes.

We do not need to manually instantiate object, but to instantiate classes and provide suitable annotations
because the container will start looking at all available classes and selecting those that looks important to
the job to be run according to the annotation they have.

This is the basic idea of the Spring framework as a whole. Spring framework is made by a lot of different
libraries.

Spring Boot is one of the layers, that helps us to create applications, a single-entry point that can be packed
as a single file. It is specialized in packaging all the application and the application at the end is one simple
Jar file and we can move it across different deploy environments.

It is not specifical for web application, even if we use it for that.

05: Spring Boot Pag. 2 a 17


Typically, it assumes that we work based on conventions and opinionated assumptions. The program can
save a lot of work by hearing conventions (naming, where to store things, how the code is organized in
packages and sub-packages, the meaning of annotations) and opinionated assumptions (somebody found
out that even if a given job can be performed in a lot of different ways, the most convenient when
operating with their framework is a specific one).

Most of the time the assumption is good and working for us. In any situations, we can override and change
them and define alternatives.

Spring Boot provides a set of pluggable ready-made building block, that are easy to customize and
assemble together they provide a layer of custom code. We have small lines of code with respect to the
overall number of lines of code we run. This is possible because it makes a lot of clever assumption and
deduction looking around what can be necessary, based on what we put on the class. We can also use
project properties to define customizations, so they can be modified easily without require touching the
code base.

Thanks to the fact the Spring boot project is based to the Spring core libraries and the idea of object
container, all available components provided by the programmer or implicitly provided by the framework
are automatically wired together. This is what we usually called convention over configuration (most of the
things are obvious, there is no need to tell them). In most other situations, we need to spell one of the
time all the steps, here we just put a generic idea.

Also, it provides support for building all the project in one single jar, putting together all the useful classes
and assemble everything in one single executable. There is no risk of dropping things along the road.

runApplication is a generic function written by people at Spring Boot which initializes the application
context, so the container of all Java beans we can create.

At the very beginning if there is a @Component, Spring generates it and if there is nothing useful, the
project drops.

05: Spring Boot Pag. 3 a 17


A Spring Boot project generates some structure where we can find plugins (a Kotlin plugin for the JVM and
some plugins specific from Spring Boot) that provides information to the project. Then we define the
groups, the repository when we can download repositories (mavenCentral) and some definitions.

In the example in the slide, we can see the Jackson module library that we do not have by default.

The Gradle Boot plugin is what assembles all the many files of the libraries we list and the libraries we
imply. Also, it applies the dependency management plugin, that is the one in charge of connecting together
different components.

When we create a Spring Boot project, we typically


list in the dependencies a set of starters (for example,
we have spring-web-starter). This is a way in which
people at Spring manages a group of related libraries,
so that the version is mutually supportive (we do not
have to put libraries that fight due to the version).

Whenever we add a specific starter pack to our


project, Spring boot configure them based on
opinionated assumptions.

05: Spring Boot Pag. 4 a 17


When we create a standalone application or any other kind of application, Spring Boot provide one single
entry point, the main function. In the function, we have one line that is runApplicaiton. It needs to
reference a class that which must be labeled with SpringBootApplication and understand the component
we need.

Spring Framework, which was the seed library created


for supporting creation of large web applications, is
based on three principal ideas.

Differently from what happens in other frameworks


that builds impressive high hierarchies of inheritance
classes, that is class A inherit from B, from C and so
on, Spring Boot try to leave the total freedom to the
programmer. They called it POKOs.

It can still use Spring; we do not need to create


something that is an instance of something.
Components are not recognized by their history, but
it’s important what an object is able to do.

Here we have an example of the things that can happen. Here we want to have some business logic. We
want to create a knight capable to rescuing a damsel. The actual implementation of the knight will be
embarking on a damsel rescue quest, a specific quest.

This is possible but has some drawbacks. This class in order to be compiled and tested and executed need
to meet the RescueDamselQuest class. If we create the class as declared it will break because we do not
have the RescueDamselQuest class, and nothing can be done until we create it.

When we create software, we need to create software one piece of a time and tested it; if we create a lot
of classes together, we cannot test them. We need an approach that let me keep things separated.

05: Spring Boot Pag. 5 a 17


So, the DamsleRescuingKnight depends on RescueDamselQuest class. This means that our system is fragile,
difficult to create and evolve. However, is normal that one object interact with another, we want to prevent
data coupling.

To prevent it, we need to create two levels: a source code level, so DamselRescuingKnight should not have
a dependency on the other class. But at runtime, since we want it depends on it, we define a Quest
interface and see that RescuingDamselQuest is an instance of the quest and the knight this time instead of
depending on DamselRescuingQuest depends on a quest and somebody later on decide which quest is it.

In this way we can compile the code independently, but we are not able to instantiate the knight anymore
because we do not have any quest.

At this point we can create our quest. We have to make our quest recognizable to the application context,
so we can label the BraveKnight as a @Component. Spring understand it is a component and understand it
needs a component and link it.

runApplication instantiate the application context, search for all components, wires them together and
return a reference to the context, so that if we need it, we can ask for more. At this point we ask if it finds
any Knight.

05: Spring Boot Pag. 6 a 17


Now we can see that DamselRescuingKnight was created, and all the things are wired together. We have
found a way of splitting our classes, they are no longer intermingle. At compile time classes are separated,
at runtime they are together because they fit into each other.

If we have two Knights (BraveKnight and RescueDamselKnight) in the system, we can have an ambiguity
and the program crash. We can solve it adding extra constraints. Most of the time we do not have this type
of ambiguity and in case there are many alternatives, and we can label them as primary or non-primary.

This is called inversion of control, because instead of having Knight class that knowing exactly at compile
time every instance where it operates, the Knight class only knows it will operate on an interface. The
actual class will be provided at runtime by inspecting existing constraints.

The interface separates two planes: what must be done (the concrete class DamselRescuingQuest class
know what has to be done) from where it must be executed (not our business, it is decided externally, who
uses the quest know when it will be invoked).

More generally, this kind of inversion moving from a directly invocation of an object of our choice, to an
indirect invocation of an object supplied by somebody else. Whoever instantiates the Knight, will have to
provide a quest and that quest will decide the behavior of our Knight.

This happens also on other situation in programming; if we have a graphical user interface, the fact that the
mouse clicked on a given position, emit some events. That piece of code totally ignored who will grad that
event and react to it. Eventually listener will be attached later on, the mouse only notify.

Also, it is typical to the plugin pattern. In chrome we can add a lot of plugins that extend the behavior of
Chrome. If chrome cannot display some type of file, we can add a plugin. The plugin has a common
interface (start method, stop method, …) and doesn’t know who is going to invoke it (hosted in Chrome,
Firefox etc.) but only provide an interface through others can invoke it.

Now the Knight does not depend anymore on a


concrete class but depends on an interface. We need
to provide an implementation of the interface, but
this is very simple. At runtime in the final system, we
provide the RescueDamselQuest that is the real
purpose for which the Knight was born, but while we
develop our software we can supply a test quest, so
that we can be sure that is going to invoke it in the
right place and the right moment.

Here we drop the RescueDamselQuest adding a test


quest to see if the method was invoked as expected.

The way in which the injection was performed was via a primary constructor parameter, one of the ways
supported by Spring. We can see another way.

Instead of giving the special parameter RescueDamselQuest (val quest: Quest), we can move the
val into a lateinit var and we label it as @Autowired (if we do not put lateinint it is wrong, the class has not
a value and this is dangerous)

05: Spring Boot Pag. 7 a 17


This is a second way in which Spring gives us to wiring together things. We can pass them via the
constructor or put a normal property that will be a lateinit var (we ask to the compiler to set the property
not during construction, but later on). Sometimes we are obliged for some external reason to have an
empty constructor, so we can still inject things inside using the @Autowired. It has to be var because we
update it later. Also, we need to remove the label @Component from the Knight.

Inversion of control has to do with our choices in code that is we do not directly name the actual
dependent class inside our other class, but we just name an interface.

Inversion of control alone is useless but becomes interesting because there is dependency injection. We
named an interface, but the container takes care of filling the variable, property we defined as instance of
the interface with an actual value. Dependency injection is a program impactor in charge of wiring objects
at runtime instead of compile time.

For that reason, we need to use a dedicated component that is the application context, that is the
machinery which knows about all our object, instantiate them according to their labels, bean components
and whatever and properly wiring as necessary.

What it is interesting is that the container takes into consideration the fact that each object has
dependencies, so it builds a dependency graph and decide who create first and last. If we create a circular
dependency graph it will fail, it will recognize it and stop.

From the code analysis point of view, dependency injection works because we use inversion of control, so
only interfaces are implemented. Objectives are dynamically wired on the basis of declarative pieces of
information. The name they have, the type they have, the annotation they have. There is no computation in
there (no if, for etc.). The framework itself is in charge to make this.

All dependencies are created and kept in a software container. Once everything was created, those objects
will be inspected, properly wired and whatever they need. Once everything is ready, control is returned to
the program, so we have run the runApplication and it returns us the set of wired objects that we can use
and operate with them.

This is in contrast with the naïve approach of the application configuration where the program entry point
is in charge of instantiating programmatically object and all the dependencies making code difficult to read.

05: Spring Boot Pag. 8 a 17


Actually, Spring along the years introduce many ways of recreating dependencies. Originally, they have to
be specified via an XML file that said what class wired with another.

Today, we use either explicit configuration based on data type and constructor parameters (mark it as
Controller and add val quest: Quest) or via an implicit bean discovering and autowiring (with lateinit
var and @Autowired).

They are equivalent. The form depends on personal preferences or some constraint that exist. For create
unit test and integration test, jUnit need to have the test constructor without any parameters, so we need
@Autowired.

The third pillar on which the Spring framework was built is the Aspect oriented programming. When we
write programs, there are some lines of code which pertain a specific business we are doing, but there are
others rather generic which are independent on the specific business and apply horizontally on many things
like log. We probably need to log everywhere. Another is transaction management or security. These things
need to be present almost everywhere, they are not bounded with one business aspect.

We call this cross-cutting concerns. They horizontally cut all the application. We can spread those lines of
code along the method, but it makes method unreadable and also makes it difficult to change for example
the log style.

05: Spring Boot Pag. 9 a 17


AOP allows the programmer to express a given functionality in one single place without having to manually
manipulate all the places where we need it. Those things are not simply function calls, what characterize
cross-cutting concerns is that often we have to do some operation before something else or around
something else or after and so on.

So, we prepare what we need to do in a special class called advice and then we ask to Spring to wire it by
re-writing the byte code dynamically when its loaded so that it appears as if the aspects were fit together
with the source code, but we insert in runtime.

We can create advice that goes before, after, ater-returning, after throwing or around (something before
and something after).

To do that, we need to include in our project boot-starter-aop.

In the example I create a new annotation class called Timed, so that I can label the places where we want
some cross-cutting concerns to be applied. For example, we introduce an annotation and say that we can
apply it to any function. This allows us simply to put @Timed. That annotation will do nothing by itself.

Then we create the second block that is a component. So, Spring boot will automatically instantiate it. This
is not only a component, but also has the @Aspect annotation. When Spring boot find a component that is
an aspect, understand it can use it to rewrite dynamically the code which it has.

05: Spring Boot Pag. 10 a 17


The log aspect that in this case contain a single method will be around (as the annotation say) each element
that has the annotation @Timed. It says that whenever it finds something that is called @Timed, surround
it with the function that should return Any? Because propagate the function that return something that we
don’t know, so we mark it in the most general possible way.

This function will receive a parameter generated by spring boot that has a syntactical sugar for saying a
representation of what must be invoked. We store the nanotime in a variable and then invoke the
joint.proceed that invoke the actual function. At the end of the function the final block will be executed in
any case (if the function return or give an error).

We can do it adding for example @Timed on the embarkOnQuest and when method return, we have a
print on the output. To remove it we need to remove the @Timed label, or we drop the @Aspect at all. If
we want to change the way in which the time happen, we only need to change the log aspect, so we can
concentrate some kind of operations in one single place. We use declarativity for expressing the behavior.

In a Spring application, objects are creating by the software container that takes care of dependency
injection and aspect weaving (it is like putting wire together and creating a tissue to having the original
code and the aspect).

Spring provides several kinds of container; we will just use ApplicationContext.

05: Spring Boot Pag. 11 a 17


ApplicationContext allows to maintain and manage the lifecycle of all beans that is complex and support
dynamic resource loading, provide an observe pattern which allows to subscribe and publish events,
support internalization and nested context handling.

How do we create components in Beans? For example, we create a class and label it as @Component. Or
we can label it with other annotations that are derived from component like controller, restController,
service and so on.

When we need something to exist, we can just put a label in front of the class and the class will be
instantiated and if that class needs other classes, they will be wired together.

There is another possibility. One of the many components is @Configuration. Spring boot application is
configuration, so it derives from configuration.

If we have a class that is configuration and has any method inside equipped with @Bean automatically that
method will be invoked, and the return value will be stored as a component. So, we can drop the
@Component from the class and no longer instantiate it because it becomes a component itself.

This gives the possibility also to consider Beans things that are out of our control, like string component.

Apart of the fact that the programmer can use a set of potential components, Spring library comes with a
large number of ready-made components which are potentially included in our code base. Potentially
because they are annotated with some extra feature which makes them candidates if nothing better can be
found 8something more specific or provided by the programmer itself).

05: Spring Boot Pag. 12 a 17


They represent some default objects which in most cases provide the functionality we need, so allows us to
have rather powerful projects where we have to provide only few classes. For example, we can find an
email client and so on.

Those are components which have some extra annotations which represent a conditional candidate, we
should take into consideration in the ApplicationContext only if some conditions hold, for example if a
programmer does not insert a class like this of it is support a class that the programmer introduce that by
itself is not enough.

Here we have an example. It is a pruned version to have a general idea. This class plays the role of providing
a Java database connectivity driver (something to connect with a relational db). This class provide a driver
when we don’t explicitly provide one. It is @Configuration, so it will be a component if it has some method
with @Beans. It also has @ConditionalOnClass, that means that only if inside the project I can find the
presence of a class called DataSource.class or Jdbctemplate.class it should be considered, otherwise we skip
it.

Also, we need to be sure that there is only one datasource class (@ConditionalOnSingleCandidate),
otherwise this is not a good candidate. It should be autoconfigured after data source autoconfiguration,
that means in the process of considering all the dependencies, data source autoconfiguration should be
properly invoked and resolved, and later on the content of the class will be further inspected
(@AutoConfigureAfter).

Moreover, it says also @EnableConfigurationProperties(@JdbcProperties.class) that means that when the


class is selected as a candidate, then it will look inside a special file in the resource directory called
application.properties searching some lines where the content is defined in the Jdbc to connect to the db.

Inside the class, we find two inner classes. The first is called NamedPArameterJdbcConfiguration and the
other is JdbctemplateConfiguration. Both are labeled as @Configuraiton, so if the container class is
selecte,c they are processed and their Benas method produce something. In this case we have a method
called t that return a NamedJdbcTemplate which must be dependent on the existence of a JdbcTemplate
and provide the bean providing that there is only a Jdbc template available, and no other parameter called
like that.

Whenever we do not use an application framework and we want to create an object, we have to instantiate
it, provide the dependency and at some point, of time to remove it (dispose it). Typically, for disposing an

05: Spring Boot Pag. 13 a 17


object we simply forget it, so we take care no variable is stored at its address, so the gargabe collector
remove it.

Spring is much more sophisticated; it strictly tracks the life cycle of Beans and govern how they behave in
many sub steps.

First, whenever we use Spring, it is the framework that is in charge to instantiate the object. In there is any
annotation in the bean classes or if those elements implement some interfaces, some steps will be inserted
by the ApplicationContext to deal with the life cycle.

The first step the ApplicationContext perform when it bootstraps, it’s reading and locating all beans
definitions. It will simply inspect classes searching for annotations and mark all of them together with the
possible constraints. It builds a kind of dependency graph for the analysis phase.

Once all these readings happen, the ApplicationContext know about which Benas potentially existing, so
instantiate something only if a bean is searched it or if there is some annotation that want to create it
immediately.

This will mean that first an object will be created using the constructor. Clearly this is possible if the primary
constructor has no dependency, otherwise the creation of that beans will be subject first to the list of
parameters the primary constructor requires. Dependencies can be specified both via the constructor
parameter or also internally by defining lateinit var.

Depending on how the bean are declared and located, some special rules may be applied. By default,
Spring considers all beans as singleton, that mean just one instance will be created throughout the whole
lifecycle of the process duration. As soon as a bean is seen if there are no other annotations, Spring will try
to instantiate it and keep that instance for all the duration of the process.

If the bean as a @Scope annotation, different rules may be applied.

There are several possible scopes. We can have beans bound to a connection, a websocket and so on.

Moreover, the bean classes are inspected to see if implement any kind of interface. If a bean declares to
implement the BeanPostProcessor interface, so it has a method called postPorcessBeforeInitialization, the
ApplicationContext will invoke it passing relevant parameters and so on.

Depending on the kind of beans, they can remain alive until the ApplicationContext will be alive (the entire
application) or related to other scopes if declared.

05: Spring Boot Pag. 14 a 17


The prototype will be abandoned when its container will go out of scope (useful for injection). Request will
be destroyed when request is complete.

Whatever kind of class we have, we can easily make it fit the purpose we want.

05: Spring Boot Pag. 15 a 17


The way in which a bean know about its dependencies is called autowiring and this is a capability the spring
framework gives us to inject some components into other components. Typically, when a bean declares
something that is based upon, the ApplicationContext search it, resolve ambiguity, and inject it.

The way in which it happens depends on various possibilities but typically we have three approaches.

By constructor is usually the preferred way when we have control over the constructor and no constraints
prevent us to do that. The major constraint we have is in test for example. It is very clean.

When we use this kind of dependency if it is not a collection, there should be no ambiguity otherwise we
have an exception that will be thrown. A way of dealing with it is labeling the beans that have multiplicity
with the @Primary annotation for example or we can use the @Profile annotation that requires a label that
is a text (debugging, deploy and so on). So, I give preference to this bean if my compilation have that flag
upon. We define different situations.

05: Spring Boot Pag. 16 a 17


05: Spring Boot Pag. 17 a 17

You might also like