Before getting int more Java programming, it's important to
understand a couple of terms. They may or may not be new
to you, depending on how much extra reading you've been doing,
but they're terms for things you've actually already been
coding in Java! You've already written POJOs
and Java Beans!
POJO
stands for Plain Old Java Object. A POJO
is a Java class that's simple and doesn't extend
any classes or implement any interfaces. It's generally
a re-usable class used to perform simple tasks in a program.
A POJO has the following characterisitcs:
Doesn't implement any interfaces.
Doesn't extend any class.
Can have any modifier (public, protected, etc.)
Can have data members or not. If it has data
members, those members can have any modifiers.
Can have any constructors (or none).
Performs simple tasks or models a simple business
object.
A Java Bean is a type of POJO that models business
objects. A Java Bean MUST follow these rules in order
to be considered a Java Bean:
All data members must have accessor and mutator
methods.
It must have a default constructor. It can have
other constructors too, if necessary.
Data members may only be accessed via constructors,
accessors, and mutators.
Why have such strict rules for Java Beans? Because
it means that other components and frameworks are able
to use beans, knowing that the bean will have a certain kind
of structure (e.g. a
default constructor, accessors, mutators, etc). For example,
a component might be able to take any bean object
and display the object's state in the component's area
on a GUI. For this to work, the component needs to be
able to take the bean (requiring Java to invoke the bean's
default constructor with no arguments), set the values of
the object's data members to create its state (calling the
bean's mutator methods for each data member), and then
retrieve the data member values to display on the GUI
(requiring Java to call the bean's accessor methods to
retrieve each data member's value).
What is java.io.Serializable?
The Serializable interface is used to
take an object
and its state and convert it into a series of bytes so
that it can be saved to a file. That process is called
"serialization". Later, a program can read those bytes
and "deserialize" them into the object, with its state
intact. For example, say you have the following
Java Bean:
Book
- isbn : String
- title: String - author : String
- year : int - publisher : String
- price : double
Book
isbn: 978-9920002123
title: How to Write Code No One Else Can Read
author: Dick Coder
year: 2014
publisher: Sydney House Publishers
price: $61.49
Assuming Book implements Serializable (it must, since
this is a valid Java Bean), you can then use an
ObjectOutputStream to convert the above book object
and its state into a stream of bytes that are then saved to a file
(serialization). You can also use an ObjectInputStream
to read the stream of bytes and convert it back
into the above book object, with its state intact
(deserialization).
In some cases, serialization and deserialization might
be easier or more efficient than simply saving each
field value as a record of text in a flat file, XML
file, JSON file, or as a record in a database.
You won't need to override any methods when you
implement serializable on your Java Bean. For this course,
we won't even be using it for anything, except to
ensure that our beans follow the rules for Java Beans.
When you make a bean serializable, you'll need to add
an extra data member called serialVersionUID.
serialVersionUID is always a long
integer, and it should be static final.
Other than that, it can have any modifier (public, private, etc)
although usually it's private.
The serialVersionUID variable is always initialized to a long
integer. This value is a unique ID (UID). The JVM
uses this ID to make sure that the class you used to serialze
an object is the exact same class you're using to
deserialize the object. Imagine serializing an object
with ClassA and then accidentally deserializing it
with ClassB!! That could result in some problems in your
application, especially since ClassB probably has different
data members from ClassA. The JVM won't let this happen
because it checks the serialVersionUID when you
deserialize, to make sure it matches the same serialVersionUID
on the classed that serialized the object.
serialVersionUID should then be assigned a random long
integer, and most editors will have some kind of
shortcut that will make up a very large random value
for you. When we're not going to be serializing
or deserializing instances of our class, we just assign
it the literal 1L
(that's the number 1, followed by upper-case L,
since 1 is by default an int).
private static final long serialVersionUID = 1L;
// or
private static final long serialVersionUID = 86749450483745054673L;
You won't need to create accessors and
mutators for serialVersionUID.
Where Would You Use Serialization?
You would use serialization any time you needed to
store an object and its state.
Example 1
You are writing software to manage drivers and customers
of a ride-sharing service. Whenever a new customer
requests a ride, a Trip object is constructed. A Trip
object contains data for the customer, the pick up
location, the date and time, the requested destination,
and the driver assigned to the trip. Once the driver
has driven and dropped off the customer, the Trip object
is no longer needed in the program, but it does need
to be saved to a file in case it needs to be reconstructed
later (e.g. when a driver or customer wants to view a
history of their trips). You can use serialization
to save the Trip object to the file and then
reconstruct it later.
If you didn't use serialization, you could keep a database
table of trips and have columns for customer, pick up location,
date and time, requested destination, and driver. Then when
you save a Trip object, you simply call the accessor method
for each data member and write the return value into a row
of the table.
Example 2
A program is used to keep track of players that are
currently logged into an online game. Whenever a player
starts a new session, a PlayerSession object is created.
A PlayerSession object stores the player's name, the
date/time they logged in, their current activity (e.g.
idle, engaged in a task, editing their character, etc),
and their virtual location within the game grid. When
the game server needs to do a restart, a program runs
that saves all the active PlayerSession objects to a file,
right before the game shuts down, so that when the game
starts back up, all the players can be reconstructed
exactly as they were, doing what they were doing, before
the shut down began.
Overview of Terms/Technologies
This is simply an overview of the various terms and technologies you'll
be using in this course.
Writing Spring Boot Applications
Java EE (JEE)
Java EE (Enterprise Edition) contains classes that help
the engine work with a browser
Java EE sits on top of Java SE, so you can use all the
Java you learned in first year.
Java EE is used to develop larger multi-tier
applications that
can securely run and communicate over a network.
Maven
An automation and management tool used in software development
Created by Apache in 2004, is actually written in Java!
Helps you to build complex projects and manage dependencies and
documentation for all your project's components
Dependency: when an application depends upon or needs
another application or component (e.g. a library, plugin, etc)
in order to work.
Dependencies are external items that your project requires
Dependencies are stored as artifacts:
usually these are JAR files. They're stored in a
repository.
It's integrated into the IDE we're going to use, so you won't have to
do anything extra to start using it.
Maven manages the different dependencies of your project
inside the "POM File", or the pom.xml file.
POM stands for Project Object Model.
When you create a project, you'll see the pom.xml
file right in the project's root.
It's written in XML (Extensible Markup Language,
which is a sort of sibling or cousin to HTML)
In this course, you may occasionally have to
view or edit the POM File to configure
how certain dependencies should work with your
application.
Spring, Spring Boot
Spring = Spring Framework, a technology used to develop enterprise
applications in Java (and in fact, it's written in Java!)
Uses Inversion of Control and Dependency Injection to develop
applications with re-usable components and artifacts.
Inversion
of Control: a principal
where classes/components that have a dependency with each other
are actually made independent by reversing/inverting the control
one object has over the creation of another. It's really hard
to explain this concept simply, but I'll give you an example
in an upcoming lesson that will make it more clear.
Dependency Injection:
an Inversion
of Control technique where an instance of a class
is created outside of the dependent class.
We'll spend a lesson looking at an example of this.
Spring automates a lot of the process of
developing software, so that you end up writing less code.
Spring Boot is one module of Spring that allows you to build client-server
applications much more easily.
Spring Boot contains components that make it
easy to write applications that interact with HTTP
requests and responses.
Spring Boot comes with Apache Tomcat, which is a special version of the
Apache web server that can run Java applications on the server side.
Thymeleaf
Thymeleaf is a template engine that allows you to easily
build dynamic web pages.
Thymeleaf is mostly just special attributes and commands
that you put right inside your regular HTML elements and
tags.
Thymeleaf can take stored data from a process and
store it in a page. For example, you could have
the user enter a search key in a form to search for
books. Your controller can call a data access method
to query the database for matching books and then
send the results to an HTML page that has Thymeleaf
code in it. The Thymeleaf code can iterate through
the collection of matching books and display them
to the user on the page.
Lombok
Lombok simplifies the coding of Java Beans by
using annotations to automate the creation
of methods.
For example, @NoArgsConstructor will add the
default constructor to a bean class and @Data
will add accessor and mutator methods, and a
toString() method.
JDBC - Java Database Connectivity
Using a database to temporarily or persistently
store data.
Temporary data can be stored using an
in-memory database. This is handy for data
your application uses that doesn't really
change much.
Persistent data can be stored using a
database server like MySQL or with
XML or JSON files.
JDBC can retrieve data e.g. show a list of products,
look up a user so they can log in, etc.
We're using H2 for in-memory storage, and
MySQL for persistent storage (which you used in Web 2)
so you'll already be somewhat familiar with MySQL
(although we're using a different tool to manage
the database outside of our IDE)
Architecture of a Java Web Application
Presentation Layer
UI written with HTML and technologies such as
Thymeleaf
Web pages with forms request data from user;
web pages show output/response
Business Layer
Server-side code that performs the processing tasks e.g.
process form data, control application flow, etc.
Other Java classes e.g.
POJO,
Beans for
entities or business objects,
store/retrieve data.
Data Access Layer
Database (we'll be using H2 in-memory database and
JDBC) to temporarily and persistently store data, retrieve data
Could also be flat files, binary files, XML, JSON, etc.
Model - entities or business objects, classes used to model things
e.g. an Employee class, a Customer class, a User class
(Beans, POJO)
View - the presentation, the user interface (UI)
Controller - processing code, code that manages application
flow, code that updates the model and the view
For Java Web Apps:
Model: Beans, POJO
View: web pages
Controller: special component classes like @Controllers,
@Repositories (data access), @Services, etc. and any other classes
that perform tasks that communicate between the View and
the Model.
As usual, we try to keep each part as independent as possible.