Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases now! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Building Web Apps with Spring 5 and Angular
Building Web Apps with Spring 5 and Angular

Building Web Apps with Spring 5 and Angular: Modern end-to-end web application development

eBook
€22.99 €32.99
Paperback
€41.99
Subscription
Free Trial
Renews at €18.99p/m

What do you get with a Packt Subscription?

Free for first 7 days. $19.99 p/m after that. Cancel any time!
Product feature icon Unlimited ad-free access to the largest independent learning library in tech. Access this title and thousands more!
Product feature icon 50+ new titles added per month, including many first-to-market concepts and exclusive early access to books as they are being written.
Product feature icon Innovative learning tools, including AI book assistants, code context explainers, and text-to-speech.
Product feature icon Thousands of reference materials covering every tech concept you need to stay up to date.
Subscribe now
View plans & pricing
Table of content icon View table of contents Preview book icon Preview Book

Building Web Apps with Spring 5 and Angular

Introduction to Spring Web Framework

In this chapter, you will learn about the key concepts of the Spring framework, and how we can use this framework to develop web applications. The following are some of the topics that will be dealt with:

  • Introduction to the Spring IOC container
  • Introduction to the Spring web MVC
  • Building a Hello World web application with Spring Boot
  • Implementing controllers
  • Handling request parameters
  • Handler interceptors
  • Handling responses
  • Creating a RESTful Web Service
  • Dockerizing Spring Boot Application

Starting with the section, Implementing controllers in this chapter, we will start building a sample healthcare web application to demonstrate the key concepts. The following are some of the key functionalities of the sample app which will be covered as part of building the app:

  • Signup for doctors and patients
  • Logging into the app
  • Searching for doctors based on their specialties
  • Fixing an appointment
  • Interacting with the doctor

Introduction to the Spring IOC container

As a primer to learning the Spring Web MVC framework, it is recommended to learn some of the following object-oriented design principles, which act as a basis for the Spring Web framework. Note that these principles form a part of the famous Single responsibility, Open-closed, Liskov substitution, Interface segregation, and Dependency inversion (SOLID) principle by Robert Martin (Uncle Bob):

  • Single Responsibility Principle (SIP): This principle states that a module, a class, or a method should have the responsibility of serving just one functionality of the underlying software. In other words, a module, a class or a method should have just one reason to change. Modules or classes following SIP have high cohesiveness, and thus, can be termed as reusable entities. Classes violating SIP are found to have high cyclomatic complexity, and thus, low testability.
  • Open-Closed Principle (OCP): This principle states that the classes are open for extension, but closed for modification. Based on this principle, the core classes of the Spring Web MVC consist of some methods which are marked as final, which, essentially, means that these final methods can not be overridden with custom behavior.
  • Liskov Substitution Principle (LSP): This principle states that if a class A (child class) is derived from class B (parent class), then the object of class B can be replaced by (or substituted with) an object of class A without changing any of the properties of class B. It can be inferred that the functions which use references of the base class must be able to use objects of the derived class without the need to know about the implementation of the base class. For example, let's consider the square and rectangle example. In the case where square derives from rectangle, then, as per LSP, an object of the class Rectangle can be substituted with an object of the class Square. However, in reality, this is not possible without doing appropriate implementation in the Square class setter methods, where setting either of length or breadth sets another side of equal length, and/or code using these classes do appropriate checks to find out whether the object is an instance of the class Square or Rectangle.
  • Interface Segregation Principle (ISP): This principle states that the fat interfaces having large number of API definitions should be split into smaller interfaces defining a set of cohesive APIs. Not following this principle leads to the client providing empty implementations for unwanted APIs.
  • Dependency Inversion Principle (DIP): This principle is pretty much related to the IOC principle, which is discussed in the next section. It states that the dependency relationship between higher-level modules with low-level modules is reversed, thus making these modules independent of each other's implementation details.

Before we get into understanding what is Spring IOC Container, let us quickly learn what is IOC. 

What is IOC?

Many a times, the Hollywood principle of Don't call us, we will call you is used to explain the concept of Inversion of Control. In Hollywood, this is what one gets to hear after auditioning is done. If we apply this principle to the programming model, instead of the classes creating dependencies along with serving functionality, the dependencies are appropriately made available to the classes during runtime, and the classes just need to focus on delivering the functionality.

Simply speaking, Inversion of Control (IOC) is about inverting the flow of control that the traditional programming model used to have in terms of objects at the higher-level handling the creation and management of lower-level objects' (can also be termed as dependencies) life cycle. In the IOC programming model, higher-level objects rather receive one or more instances of these dependencies from the calling object or external framework. This is why IOC is also termed Dependency Injection, wherein the dependencies are injected appropriately, and, objects bother themselves solely with the program execution and not with the object creation. Inversion of Control is related to the object-oriented principle known as the Dependency Inversion Principle (DIP), coined by Robert Martin (Uncle Bob).

Let's take a look at the following code sample, which represents higher-level objects handling the creation of lower-level objects (dependencies):

    /*
* This class demonstrates the dependency of higher-level object
* (DrawWithoutIOC)
* onto lower level objects such as Rectangle, Square which are
* created within
* Shape class based on the value of shapeType which is passed as a
* method
* parameter to draw method.
*/

public class DrawWithoutIOC {

Logger logger = Logger.getLogger(DrawWithoutIOC.class.getName());

public void draw(String shapeType) {
Shape shape = new Shape();
try {
shape.draw(shapeType);
}
catch (UndefinedShapeException e) {
logger.log(Level.INFO, e.getMessage(), e);
}
}
/*
* Note that Shape class creates instances of Rectangle or Square
class
* based on the value of shapeType. Any new value that needs to be
supported requires change in the draw method of Shape class.
*/

private class Shape {
public void draw(String shapeType) throws
UndefinedShapeException
{
if(shapeType.equals("rectangle")) {
Rectangle rectangle = new Rectangle();
rectangle.draw();
} else if(shapeType.equals("square")) {
Square square = new Square();
square.draw();
} else {
String shapeNotSupportedMessage = "Shape " + shapeType + "
not supported";
logger.log(Level.INFO, shapeNotSupportedMessage);
throw new UndefinedShapeException
(shapeNotSupportedMessage);
}
}
}

public static void main(String[] args) {
DrawWithoutIOC drawWithoutIOC = new DrawWithoutIOC();
drawWithoutIOC.draw("circle");
}
}

Let us take a look at the class DrawWithIOC, which accepts the implementation of the Shape object in its public constructor. Note that the dependencies, such as different implementations of the Shape object, are rather injected, and code just does the execution of business logic without bothering about creation of objects related to the different implementations of Shape. Other alternatives to injecting the dependencies are passing arguments to a factory method of the class, or through properties that are set on the object instance:

    /**
* In this class, the Shape is passed as parameter to DrawWithIOC
* constructor.
* draw method on a DrawWithIOC object just invokes the draw method
* on Shape object.
* It, no longer, manage the creation of Shape object based on
* shapeType and there upon, invoke the draw method.
**/

public class DrawWithIOC {
Logger logger = Logger.getLogger(DrawWithIOC.class.getName());

private Shape shape;

public DrawWithIOC(Shape shape) {
this.shape = shape;
}

public void draw() {
this.shape.draw();
}

public static void main(String[] args) {
Shape shape = new Rectangle();
DrawWithIOC drawWithIOC = new DrawWithIOC(shape);
drawWithIOC.draw();
}
}

What is a Spring IOC container?

A Spring IOC container is a framework which, basically, manages the life cycle of plain old Java objects (POJOs), and injects them into the application as required. Java objects define their dependencies using one of the following methods:

  • Dependencies are passed as arguments to the constructor method of the object. See how the object is passed as an argument to the constructor method in the example cited in the previous section.
  • Dependencies are passed as arguments to the setter method of the object.
  • Dependencies are passed as arguments to a factory method of the object.

A Spring IOC container injects the dependencies after it creates the beans. Note the fact that dependencies are no longer managed by Java objects. They are rather managed and injected by the framework, and hence, Inversion of Control.

The following are the packages which are core to the IOC container:

  • org.springframework.beans
  • org.springframework.context

It is the interface, org.springframework.context.ApplicationContext (sub-interface of the interface, BeanFactory), which represents the Spring IOC container and is responsible for managing the life cycle of beans. The instructions related to creating, configuring, and assembling the objects is termed Configuration Metadata. The configuration metadata is often represented using Java annotations or XML. A Java application using Spring IOC Container is created by combining Business POJOs with the previously mentioned configuration metadata, and passing it on to the IOC Container (an instance of ApplicationContext). The same is represented using the following diagram:

Figure 1: Java Application with Spring IOC Container

Let's illustrate the preceding diagram with an example. The following code represents how a service, namely, UserService is instantiated using Spring IOC container in a Spring Boot web application. Notice how the annotation-based autowiring feature has been used to have ApplicationContext autowired to the userService field in this code:

    package com.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.services.UserService;
import com.services.domain.User;

@Controller
@SpringBootApplication (scanBasePackages={"com.services"})
public class DemoApplication {

@Autowired
private UserService userService;


@RequestMapping("/")
@ResponseBody
String home() {
User user = null;
return "Hello " + userService.getUsername(user) + ". How are you?";
}

public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

Introduction to Spring Web MVC

In this section, we will learn the key elements of the Spring Web model-view-controller (Spring Web MVC) framework, and how to quickly get started with a Spring web application using the Spring Web MVC components. The following will be covered in detail in this section:

  • Key building blocks of a Spring Web MVC application
  • Introduction to the Dispatcher servlet

Key building blocks of a Spring Web MVC application

In this section, we will learn about the key building blocks of a Spring web MVC application. The following diagram represents the key building blocks:

Figure 2: Key building blocks of Spring web MVC framework

The following are the details in relation to the preceding diagram:

  • Dispatcher servlet: Dispatcher servlet, also termed the front controller, is at the core of the Spring Web MVC framework. Simply speaking, the Dispatcher servlet determines which controller class and method needs to be called when a page request or an API request arrives. In addition, it sends the response using the appropriate JSP page or JSON/XML objects. It dispatches the incoming requests to the appropriate handlers (custom controllers) with different handler mappings. This is integrated with the Spring IOC container, which allows it to use all the features that the Spring framework provides.
  • Handler Mappings: Handler mappings are used to map the request URL with the appropriate handlers such as controllers. The Dispatcher servlet uses the handler mappings to determine the controllers which will process the incoming requests. The handler mappings are specified in the XML file, or as annotations such as @RequestMapping,  @GetMapping, or @PostMapping, and so on. The following diagram represents the @RequestMapping annotation that is used for URL mapping.
  • Handler Interceptors: Handler interceptors are used to invoke preprocessing and post-processing logic before and after the invocation of the actual handler method respectively.
  • Controllers: These are custom controllers created by the developers and used for processing the incoming requests. The controllers are tagged with annotations such as @Controller or @RestController. Controllers are used to access the application behavior through one or more service interfaces. Controllers are used to interpret the user input, pass them to the services for implementation of business logic, and transform the service output into a model which is presented to the user as a view. The following diagram shows the @Controller annotation which represents the DemoApplication class to play the role of a controller:
Figure 3: Representing handler mappings (URL mapping) and Controller annotation
  • Services: These are the components coded by the developers. These components contain the business logic. One or more methods of services are invoked from within the Controller methods. Spring provides annotations such as @Service for identifying services. The following code represents the service class UserService, which consists of a method, getUsername. Pay attention to the @Service annotation. Note how the instance of UserService is defined in @Controller, as shown in the preceding code, and the method getUsername is invoked on the instance of UserService.
        import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.services.dao.UserDAO;
import com.services.domain.User;

@Service ("userService")
public class UserService {

@Autowired
private UserDAO userDAO;

public String getUsername(User user) {
return userDAO.getUsername(user);
}
}
  • Data Access Objects (DAO): The classes which represent DOA, are used to do data processing with the underlying data sources. These classes are annotated with annotations such as @Repository. The preceding code of UserService consists, a DAO, namely, UserDAO. Note the @Repository annotation used by the class, UserDAO, in the following code:
        import org.springframework.stereotype.Repository;

import com.services.domain.User;

@Repository ("userDAO")
public class UserDAO {

public String getUsername(User user) {
return "Albert Einstein";
}
}
  • View Resolvers: View resolvers are components which map view names to views. They help in rendering models in the browser based on different view technologies such as JSP, FreeMarker, JasperResports, Tiles, Velocity, XML, and so on. Spring comes with different view resolvers such as InternalResourceViewResolver, ResourceBundleViewResolver, XMLViewResolver, and others. View resolvers are used by the Dispatcher servlet to invoke the appropriate view components.
  • Views: Views are used to render the response data on the UI. They can be represented using different technologies such as JSP, Velocity, Tiles, and so on.

Introduction to the Dispatcher servlet

In this section, we will learn about the core component of a Spring web MVC application, the Dispatcher servlet.

As introduced in the previous section, Dispatcher servlet is the front controller which processes the user requests by invoking the appropriate components such as handler mappings, interceptors, adapters, custom controllers, services, DOA, view resolver, and finally, the views. The following diagram represents the web request/response workflow of the Dispatcher servlet:

Figure 4: Web request/response flow across the Dispatcher servlet

As per the preceding diagram, the journey of a request/response through a Spring web MVC application looks like the following:

  1. The user requests arrive at the server, and are intercepted by the Dispatcher servlet.
  2. The Dispatcher servlet gets a handler object (primarily, an instance of HandlerExecutionChain) from the HandlerMapping object based on the URL mapping. URL mappings can be defined with the web.xml file or as annotations on the Controllers' methods.
  1. One or more instances of the HandlerInterceptor objects are retrieved from the handler object, and preprocessing logic is processed on the request object.
  2. The instance of HandlerAdapter is retrieved from the handler object, and the handle method is invoked. This results in execution of logic within the controller class. In the preceding diagram (Figure 3), the request with RequestMapping as "/" leads to the execution of code within the home method as part of this step.  
  3. The post-processing logic on the HandlerInterceptor instances is executed. This is the final step before the rendering method is invoked. 
  4. TheViewResolver instance is used to retrieve the appropriate view component.
  5. The render method is invoked on the instance of view.

Building Hello World web application with Spring Boot

In this section, we will learn how to quickly build a web application using Spring Boot. The following will be covered in this section:

  • The Spring Tool Suite (STS) setup in Eclipse IDE
  • Introduction to Spring Boot
  • Building the Hello World web app using Spring Boot

The Spring STS Setup in Eclipse IDE

Spring Tool Suite (STS) provides the development environment for Spring-powered enterprise applications. This can be easily downloaded from the Eclipse marketplace in the following manner:

  1. Within the Eclipse IDE, click on Help | Eclipse Marketplace... and search for Spring STS by submitting Spring STS in the Find text field. The search result would show up different versions of STS for different Eclipse versions. 
  2. Choose the appropriate version and install. The most current version is 3.9.0.RELEASE.
  3. Restart Eclipse, and you are all set to create your first Spring Boot web application.

Introduction to Spring Boot

Spring Boot is a quick and easy way to get up and running with production-grade standalone applications in no time. If you hated all the XML configurations required to be set for creating a Spring web application, Spring Boot helps us to get away with all those troubles, and lets us focus on developing the application from the word go. The following are some of the key attributes of a Spring Boot application:

  • Requires no XML configuration or code generation.
  • Automatically configures Spring wherever appropriate and possible. 
  • Supports embedded web servers such as Tomcat, Jett, and so on. One of the key disadvantages while working with the Spring web framework prior to Spring Boot was deploying these apps explicitly on the web server either manually, or using some tools/scripts. This is no more required with Spring Boot, as it comes with support for embedded web servers. 
  • Helps to quickly and easily get started with microservices development.  Spring Boot has seen great adoption in recent times thanks to the advent of micro-services architecture style apps. Spring Boot supports creation of micro-services in the form of a JAR file, which could easily be deployed within a server container.
  • Supports features such as health checks, metrics, and so on.
  • Provides useful annotations such as @ConfigurationProperties to accomplish tasks such as loading properties' details from the application.properties file.

Building  Hello World web app using Spring Boot

In this section, we will go through the steps required to build a Hello World Web App using Spring Boot. The following given steps assume that you have set up Spring STS within your Eclipse IDE by following the steps given earlier. Now, with the steps given next, one can set up the Hello World web app in an easy manner:

  1. Press Ctrl N to open up the Project creation Wizard dialog box.
  2. Write Spring in the Wizards text field. This will show various project options related to Spring projects. Select the option Spring Starter Project, and click on Next.
  1. Name the project HelloWorld, or leave the default name demo, and click on Next:
  1. Select Web in the list of dependencies as shown in the following screenshot, and click on Finish:
  1. Clicking on Finish will create a HelloWorld project whose file structure will look as seen in the following screenshot. Pay attention to the annotation @SpringBootApplication in the HelloWorldApplication class shown in the screenshot. Spring applications are commonly found to be annotated with annotations such as @Configuration, @EnableAutoConfiguration, and @ComponentScan. Spring Boot came up with @SpringBootApplication as an alternative to using three annotations together:
  1. Right-click on the project, and start Spring Boot App, as shown in the following screenshot. It will start the app on the embedded Tomcat server. Access the URL http://localhost:8080 on your browser. It will show up a page with the heading as Whitelabel Error Page followed by some content.
  1. At times, the project may not run successfully due to one or more errors encountered during setting up the project. One can open the Problems View, and find out if there are any issues. As creating and running a Maven project requires the dependencies to be downloaded from the internet, it is to be ensured that the internet connection is active while setting up and running the project.
  2. It is time to write some custom code in the HelloWorldApplication Java file, and run the app. Place the following code (in bold) as shown and run the app. Access the URL http://localhost:8080, and you will find the following getting printed: Hello World. How are you?. Pay attention to the usage of the @Controller annotation, which is required to annotate a class as a controller. In case one wants the class to serve REST APIs, one can use either @Controller and @ResponseBody together appropriately at the class and method level, or use @RestController at the class level:
        @Controller
@SpringBootApplication
public class HelloWorldApplication {

@RequestMapping("/")
String home() {
return "Hello world. How are you?";
}

public static void main(String[] args) {
SpringApplication.run(HelloWorldApplication.class, args);
}
}
  1. When wanting to use the JSP files for displaying views, the following steps needed to be taken:
  • Include the following code in the pom.xml file. This is done to enable JSP support:
            <dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
  • The following needs to be put in src/main/resources/application.properties in order to define the template prefix and suffix for the JSP files:
            spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
  • Create the JSP files in the folder src/main/resources/META-INF/resources/WEB-INF/jsp/. For the sake of this current example, let's call the file as index.jsp
  • The code for @Controller would look like the following to render the index.jsp file. Note the absence of the @ResponseBody annotation on the home() method. This is why the JSP file, index.jsp, is rendered. Otherwise, a string object would have been returned as a response leading to errors while rendering.

 

            @Controller
@SpringBootApplication
public class HelloWorldApplication {

@RequestMapping("/")
String home() {
return "index";
}

public static void main(String[] args) {
SpringApplication.run(HelloWorldApplication.class, args);
}
}

Implementing Controllers

Before we go into the details of understanding the different aspects of implementing the controllers, let's quickly go over how controllers take part in the MVC workflow. 

The following is the workflow representing the processing of a web request and the response by a controller:

  1. The requests are first intercepted by the Dispatcher servlet.
  1. The Dispatcher servlet does the initial stage of request processing by resolving locale/themes, performing activities such as taking snapshots of the request attributes, and making framework objects available to handlers and view objects.
  2. Once the initial processing is done as mentioned in the preceding step, an appropriate handler is determined and invoked for further processing the request. It is the handleRequest method that is invoked on the handler instance, which, in turn, invokes the appropriate method on the appropriate controller determined using HandlerMappings.
  3. The controller then processes the request, and returns an instance of ModelAndView appropriately.
  4. The instance of ModelAndView is further processed by the Dispatcher servlet to send out the response to the user. 

Let us start building the sample healthcare app for doctors and patients. This app will be used to illustrate the controllers' implementations with multiple examples. In this section, we will see how to implement the controllers for handling users' requests for accessing the home page, signup form, login form, and so on. In the previous section, we have seen how to build a Hello World web app using Spring Boot. We will start implementing controllers using the Spring Boot app.

The following are the different controllers which are used to process requests for accessing the home page, signup form, and login page:

  • UserAccountController
  • RxController
  • DoctorSearchController

We will see the implementation of the preceding controllers in code examples listed as follows. In the most trivial form, controller classes can be implemented in the following manner:

  • The controller class can be annotated with @Controller or @RestController annotations at the class level. The code samples given below represent the usage of both types of annotations. @RestController is used as a convenience annotation to represent the annotations such as @Controller and @ResponseBody. When used at the class level, the controller can serve REST API requests.
  • When using the @Controller or @RestController annotation, request mappings can be provided using one of the following techniques:
    • Using RequestMapping Annotation at Method Level: The following code represents the RequestMapping annotation at the method level, home(). Spring framework 4.3 introduced annotations such as @GetMapping, @PostMapping, @PutMapping, and so on to simplify mappings for common HTTP method types such as GET, POST, PUT, and so on respectively. These new annotations enhance code readability. In the following code, the aforementioned annotations have been used interchangeably for providing greater clarity and ease of understanding. When the application is started, accessing http://localhost:8080/ would lead to a display of the view, index.jsp file. Note the controller class HealthApplication.
            @Controller
@SpringBootApplication
public class HealthApplication {

@RequestMapping("/")
String home() {
return "index";
}

public static void main(String[] args) {
SpringApplication.run(HelloWorldApplication.class, args);
}
}
    • In the code given next, the @GetMapping annotation is used in place of @RequestMapping, as shown in the preceding code sample. GetMapping is a composed annotation which acts as a shortcut for @RequestMapping (method = RequestMethod.GET). When the application is started, accessing http://localhost:8080/ will print Hello world. This is a health application!.

            @RestController
@SpringBootApplication
public class HealthApplication {

@GetMapping("/")
String home() {
return "Hello world. This is a health application!";
}


public static void main(String[] args) {
SpringApplication.run(HelloWorldApplication.class, args);
}
}
  • Using RequestMapping Annotation at both, Method & Class Level: The following code represents RequestMapping at both the class and the method level. When the URL such as  http://localhost:8080/account/ is accessed, one will be taken to the login page. Note that a URL such as http://localhost:8080/account (without trailing "/") would result in an error. The point to note is that the login method does not have URL mapping with the RequestMapping annotation. This, primarily, acts as a catch--all method to handle all the requests with different paths represented by using "/*" (defined at the class level) except /account/.  When a URL such as http://localhost:8080/account/signup is accessed, the signup page is displayed. Similar is the case with the URL http://localhost:8080/account/forgotpassword which would open up the forgot password page.
        @Controller
@RequestMapping("/account/*")
public class UserAccountController {

@RequestMapping
public String login() {
return "login";
}

@GetMapping("/signup")
public String signup() {
return "signup";
}

@GetMapping("/forgotpassword")
public String forgotpassword() {
return "forgotpassword";
}
}
  • Using RequestMapping Annotations with Http Requests Type: In the following example, the HTTP request type Get is mapped to the method login:
        @Controller
@RequestMapping("/account/login")
public class LoginController {
//
// @GetMapping can as well be used
//
@RequestMapping(method = RequestMethod.GET)
public String login() {
return "login";
}
}

In the next section, we will learn the concepts and examples of handling request parameters in relation to handling forms such as signup, login, and so on as discussed in this section.

Handling request parameters

There are different ways in which user request parameters can be handled. We shall be taking the example of the signup form to understand the following concepts related to the most common ways of handling request parameters:

  • Using the RequestParam annotation: This is used to bind the method parameters to web request parameters
  • Using the RequestBody annotation: This is used to bind the method parameter to the body of the web request
  • Using the PathVariable annotation: This is used to bind the method parameter to the URI template variable

The RequestParam annotation

In this section, we will learn how to use the RequestParam annotation for reading web request parameters in the controller class. The following image shows what the signup form looks like with three input fields such as Nick Name, Email address, and Password

Figure: New User Signup form

On submission of the preceding form, the user request parameters will be handled using the @RequestParam annotation. The RequestParam annotation is used to bind a method parameter to a web request parameter. The following code displays the binding of method parameters such as nickname, emailAddress, and password with web request parameters such as nickname, emailaddress, and password respectively. In simple words, the frontend has to send parameters with keys as nickname, email address, and password for the code given next to work. 

    @Controller
@RequestMapping("/account/*")
public class UserAccountController {

@GetMapping("/signup")
public String signup() {
return "signup";
}

@PostMapping("/signup/process")
public String processSignup(ModelMap model,
@RequestParam("nickname") String nickname,
@RequestParam("emailaddress") String emailAddress,
@RequestParam("password") String password) {
model.addAttribute("login", true);
model.addAttribute("nickname", nickname);
return "index";
}
}

The RequestBody annotation

In this section, we will learn when and how to use the RequestBody annotation (@RequestBody) for handling web requests.

The RequestBody annotation is used to bind the method parameter with the body of the incoming request. In the process of binding, HttpMessageConverters converts the body of the request appropriately (most commonly into the parameter object) based on the content type of the request.

The RequestBody annotation is most commonly used in scenarios dealing with REST APIs. 

The following example demonstrates the usage of the @RequestBody annotation using a domain object, User, which is made a parameter to the controller method:

    @RestController
public class RestDemoController {

@PostMapping("/hello")
public HelloMessage getHelloMessage(@RequestBody User user) {
HelloMessage helloMessage = new HelloMessage();
String name = user.getName();
helloMessage.setMessage( "Hello " + name + "! How are you doing?");
helloMessage.setName(name);
return helloMessage;
}
}

In the preceding example, note some of the following:

  • The @PostMapping annotation maps the REST API endpoint, /hello, with the handler method, getHelloMessage. Recall that @PostMapping is a composed annotation which acts as a shortcut for @RequestMapping (method = RequestMethod.POST).
  • The @RequestBody annotation is used with the User object. This binds (or maps) the method parameter, user of type User, with the body of the web request. The body of the request arrives in the following JSON format:
        {"name": "Calvin Hobbes"}

The HttpMessageConverter method converts the preceding into the User object, whose code looks like the following:

    public class User {
private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}
  • The @RestController annotation, a convenient annotation, which is itself annotated with @Controller and @ResponseBody annotations, and is used for programming REST API integration endpoints.
  • The HelloMessage class is returned as a response. The following is the code for HelloMessage:
   public class HelloMessage {
private String message;
private String name;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

The HttpMessageConverter method converts the preceding response object into the following response message:

    {"message": "message text goes here...", "name": "name goes here..."}

The PathVariable annotation

In this section, we will learn how to use the PathVariable annotation for handling request parameters.

The PathVariable annotation is used to bind a method parameter to a URI template variable. A URI template is a URI-like string containing one or more variables. For example, in  the following code, /{nickname} is a URI template consisting of nickname as a variable. A method can have multiple @Pathvariable annotations to bind multiple variables present in the URI template. PathVariable is seen to be mainly used in the REST web service. Later, while going through Angular chapters, you will see that PathVariable is very similar to handling routing parameters using the ActivatedRoute concept:

    @Controller
@SpringBootApplication
public class HealthAppApplication {

@RequestMapping("/")
public String home() {
return "index";
}

@GetMapping("/{nickname}")
public String home(ModelMap model, @PathVariable String nickname) {
model.addAttribute("name", nickname);
return "index";
}

public static void main(String[] args) {
SpringApplication.run(HealthAppApplication.class, args);
}
}

Both RequestParam and PathVariable can be used to read the request parameters. @RequestParam is used to retrieve the query parameters from the request URL. On the other hand, @PathVariable is used to retrieve one or more placeholders from the URI. URLs without query parameters, for example, paths, tend to be cached. The following code demonstrates the usage of both RequestParam and PathVariable. Different URLs will be handled using different methods represented in the code as follows:

  • URL (http://localhost:8080, localhost:8080/?name=calvin): This URL consists of a parameter such as name. The value of this parameter is obtained using RequestParam. Note that as required = false is declared with the @RequestParam definition in the code example given next, thus, a request URL such as http://localhost:8080/ would also get mapped to the usingRequestParam method. 
  • URI (http://localhost:8080/calvin): This URL consists of a name which can be handled using a placeholder variable whose value can be obtained using the PathVariable method.

The following code displays the usage of both RequestParam and PathVariable:

    @Controller
@SpringBootApplication
public class HealthAppApplication {
//
// RequestParam is used to retrieve value of parameter, name.
//
@RequestMapping("/")
public String usingRequestParam(Model model,
@RequestParam(value="name", required=false) String nickname) {
model.addAttribute("nickname", nickname);
return "index";
}

@RequestMapping("/{nickname}")
public String usingPathVariable(Model model, @PathVariable String nickname)
{
model.addAttribute("nickname", nickname);
return "index";
}
}

In the next section, you will learn how to use interceptors to handle web requests-response, before and after the requests are handled by the controller respectively.

Handling Interceptors

In this section, we will learn about some of the following:

  • Why use interceptors?
  • How to implement interceptor methods such as pre-handle and post-handle to process the web requests before and after the requests get processed by the controllers respectively. 

Interceptors' implementation provides methods for intercepting incoming requests before it gets processed by the controller classes or, intercepting the outgoing response after being processed by the controller and before being fed to the client. Interceptor methods help to get away with boilerplate code which is required to be invoked on each request and response. For example, let's take the authentication scenario where every request need to be checked for an authenticated session before being processed by the code in the controller. If the session is not found to be authenticated, the request is forwarded to the login page, else the request is forwarded to the controller for further processing. Given that the controller logic could span across multiple controller classes, and the aforementioned authentication logic needs to be processed before one or more controllers processes the incoming requests, it is suitable to put the authentication processing in the interceptor method. Another example of using interceptor methods includes measuring the time spent in the method execution.

For implementing interceptors for processing web requests-response, custom interceptor classes need to be implemented. Custom interceptor classes need to implement one or all of the methods provided in the HandlerInterceptor interface which are as follows:

  • preHandle: The code within the preHandle method gets executed before the controller method is invoked
  • postHandleThe code within the postHandle method is executed after the controller method is invoked
  • afterCompletion: The code within afterCompletion is executed after the view gets rendered 

In the following example, we will use an interceptor to process web requests arriving from the signup form. The following steps are required to be taken:

  • Create an Interceptor class: Create an Interceptor class extending the HandlerInterceptorAdapter class. In the following example, only the preHandle method is implemented. Other methods such as postHandle and afterCompletion are not provided with the implementation:
        public class SignupInterceptor extends HandlerInterceptorAdapter {

@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {

String emailAddress = request.getParameter("emailaddress");
String password = request.getParameter("password");

if(StringUtils.isEmpty(emailAddress) ||
StringUtils.containsWhitespace(emailAddress) ||
StringUtils.isEmpty(password) ||
StringUtils.containsWhitespace(password)) {
throw new Exception("Invalid Email Address or Password.
Please try again.");
}

return true;
}

@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler, Exception exception)
throws Exception {
...
}

@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler, ModelAndView modelAndView)
throws Exception {
...
}
}
  • Implement the Configuration class: Implement a custom @Configuration class by extending WebMvcConfigurerAdapter, thereby adding the interceptor with appropriate path patterns within the addInterceptors method. If the path pattern is not specified, the interceptor is executed for all the requests.
    @Configuration 
    public class AppConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new SignupInterceptor()).addPathPatterns("/account/signup/process");
    }
    }
  • Make sure that the controller with the appropriate URI pattern is implemented as specified within the addInterceptors method in the aforementioned @Configuration class.
    @Controller
    @RequestMapping("/account/*")
    public class UserAccountController {

    @RequestMapping("/signup")
    public String signup() {
    return "signup";
    }

    @RequestMapping("/signup/process")
    public String processSignup(ModelMap model, @RequestParam("nickname") String nickname,
    @RequestParam("emailaddress") String emailAddress, @RequestParam("password") String password) {
    model.addAttribute("login", true);
    model.addAttribute("nickname", nickname);
    return "index";
    }

    }

In the next section, you will learn about the different types of responses from controllers.

Handling Response

The following are some of the common types of responses returned from controllers:

  • An instance of ModelAndView 
  • Using @ResponseBody

Response as an instance of ModelAndView

ModelAndView is a container object to hold both Model and View. With ModelAndView as a return object, the controller returns the both model and view as a single return value. The model is a map object which makes it possible to store key-value pairs. The following code sample represents the usage of ModelAndView in a Controller:

    @Controller
@RequestMapping("/account/*")
public class UserAccountController {

@PostMapping("/signup/process")
public ModelAndView processSignup(ModelMap model, @RequestParam("nickname") String nickname, @RequestParam("emailaddress")
String emailAddress, @RequestParam("password") String password) {
model.addAttribute("login", true);
model.addAttribute("nickname", nickname);
model.addAttribute("message", "Have a great day ahead.");
return new ModelAndView("index", model);
}
}

The following code samples represent the different ways in which an instance of ModelAndView is returned with different sets of information:

    // Will result in display of index.jsp page
return new ModelAndView("index");

// Will result in display of index.jsp page.
//The JSP page could consist of code such as "Hello ${name}"
//which will get displayed as "Hello Calvin Hobbes"

return new ModelAndView("index", "name", "Calvin Hobbes");

// Will result in display of index.jsp page.
// The JSP page could consist of code such as
//"Hello ${model.firstName} ${model.lastName}"
//which will get displayed as "Hello Calvin Hobbes"

UserInfo userInfo = new UserInfo();
userInfo.setFirstName("Calvin");
userInfo.setLastName("Hobbes");
return new ModelAndView("index", "model", userInfo);

// Will result in display of index.jsp page.
// The JSP page could consist of code such as "Hello ${name}"
// which will get displayed as "Hello Calvin Hobbes"

Map<String, Object> map = new HashMap<String, Object>();
map.put("name", "Calvin Hobbes");
return new ModelAndView("index", map);

Using @ResponseBody annotation

This section represents the concepts related to the usage of the @ResponseBody annotation for returning a response to the client request.

The @ResponseBody annotation can be applied both at the class level and the method level. When @ResponseBody is applied at the class level along with the @Controller annotation, another annotation such as @RestController can be used instead.

The @ResonseBody annotation represents the fact that the value returned by the method will form the body of the response. When the value returned is an object, the object is converted into an appropriate JSON or XML format by HttpMessageConverters. The format is decided based on the value of  the produce attribute of the @RequestMapping annotation, and also the type of content that the client accepts. Take a look at the following example:

    @Controller
public class RestDemoController {

@RequestMapping(value="/hello", method=RequestMethod.POST, produces="application/json")
@ResponseBody
public HelloMessage getHelloMessage(@RequestBody User user) {
HelloMessage helloMessage = new HelloMessage();
String name = user.getName();
helloMessage.setMessage( "Hello " + name + "! How are you doing?");
helloMessage.setName(name);
return helloMessage;
}
}

Creating a RESTful web service

In this section, you will learn how to create a RESTful web service. The concepts explained earlier in this chapter will be used.

The following are some of the key aspects of creating a RESTful web service. Let's take the example of retrieving the doctors' list based on the specialties, location, and so on.

  • Create a controller representing the RESTful endpoint: In the following code, note the usage of the @RestController annotation, which is used to represent the annotation @Controller and @ResponseBody. The controller has a method, searchDoctor, for handling the request represented using the URL such as /doctors?location=xxx&speciality=yyy. Note the @RequestMapping annotation and its attributes, especially, "produces", which signifies the fact that the output sent to the user will be in the JSON format.
    @RestController
public class DoctorSearchController {

@Autowired
DoctorService docService;

@RequestMapping(value="/doctors", method=RequestMethod.GET,
produces="application/json")

public DoctorList searchDoctor(
@RequestParam(value="location", required=false) String location,
@RequestParam(value="speciality", required=false) String speciality)
{
DoctorList docList = docService.find(location, speciality);
return docList;
}
}

The following is how the DoctorService implementation may look like:

    @Service
public class DoctorServiceImpl implements DoctorService {

@Autowired
private DoctorDAO doctorDAO;

@Override
public List<Doctor> findByLocationAndSpeciality(String location, String
speciality) {
return doctorDAO.findByLocationAndSpeciality(location, specialityCode);
}
}

The following is how the DoctorDAO implementation may look like:

    @Repository
@Transactional
public class DoctorDAOImpl implements DoctorDAO {

private SessionFactory sessionFactory;

@Autowired
public DoctorDAOImpl(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}

@Override
public List<Doctor> findByLocationAndSpeciality(String location, String speciality) {
Session session = this.sessionFactory.getCurrentSession();
TypedQuery<Doctor> query = session.getNamedQuery("findByLocationAndSpeciality");
query.setParameter("location", location);
query.setParameter("speciality", speciality);
List<Doctor> doctors = query.getResultList();
return doctors;
}
}
  • Create a RESTful API: For retrieving the list of doctors based on location and speciality, the URL could look like  http://localhost:8080/doctors?location=xxx&speciality=yyy.
  • Identify the method of processing incoming requests data: @RequestParam will be used to process the incoming requests data as mentioned in the preceding URL. In the previous code, note how @RequestParam is used for processing the value of both the location and the specialty parameter. The following code represents the same:
        public DoctorList searchDoctor(
@RequestParam(value="location", required=false)
String location,
@RequestParam(value="specialty", required=false)
String speciality) {
// Code goes here
}
  • Create a class representing ResponseBody: The return value is the DoctorList object, which consists of a list of Doctors. The following code represents the DoctorList object which is a list of the Doctor object:
    // The class representing the list of Doctor; Returned as a response
public class DoctorList {
private List<Doctor> doctors;

public DoctorInfo(List<Doctor> doctors) {
this.setDoctors(doctors);
}
public List<Doctor> getDoctors() {
return doctors;
}
public void setDoctors(List<Doctor> doctors) {
this.doctors = doctors;
}
}

The following represents the Doctor class which is returned as part of the response object:

    public class Doctor {

private String id;
private String firstName;
private String lastName;
private String specialityCode;

public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getSpecialityCode() {
return specialityCode;
}
public void setSpecialityCode(String specialityCode) {
this.specialityCode = specialityCode;
}
}
  • Client response: The client receives the response body in the JSON format. The following is a sample response which is returned by the execution of the preceding code:
    [{
"id": "doc1",
"firstName": "Calvin",
"lastName": "Hobbes",
"specialityCode": "pediatrics"
},
{
"id": "doc2",
"firstName": "Susan",
"lastName": "Storm",
"specialityCode": "cardiology"
}]

Dockerizing a Spring Boot application

In this section, you will learn how to Dockerize a Spring Boot application. The detailed introduction to Docker and the related aspects such as Docker images, containers, Dockerfile, and so on is provided in Chapter 2Preparing Spring Web Development Environment. In case, you are new to Docker, it may be a good idea to get an understanding of Docker before going ahead with this section.

The following are some of the reasons why it may be a good idea to Dockerize a Spring Boot application:

  • Containerized Springboot App-- a Microservice: It aligns well with the cloud-native architecture style, which recommends containerizing a microservice (using Docker or other runtimes such as rkt), and managing these containers using container orchestration tools such as Kubernetes, Docker Swarm, and so on. It should be noted that Spring Boot can be used to create a microservice. Thus, one may need to Dockerize a Spring Boot microservice when creating a cloud-native app.
  • Quick Dev/QA environments: A containerized/Dockerized Spring Boot app is easy to commission or decommission. 
  • Continuous delivery made easy: It is easy to achieve a continuous delivery of containerized/Dockerized Spring Boot app in different environments such as QA, UAT, production. 

It should be noted that Docker can be used while working with both Maven and Gradle, details of which will be presented in the next chapter while understanding the aspects of build. The following are some of the key aspects of Dockerizing a Spring Boot app. The same instructions can be used to wrap Spring boot micro-services within Docker containers.

  • Dockerfile: The first step is to create the Dockerfile which will be used to build the Docker image. The following is the content of the Dockerfile. Save the Dockerfile as Dockerfile in the root folder.
    FROM frolvlad/alpine-oraclejdk8:slim
VOLUME /tmp
ADD target/demo-0.0.1-SNAPSHOT.jar app.jar
RUN sh -c 'touch /app.jar'
ENV JAVA_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -
Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]
  • Build and test the Spring Boot app:
  1. Go to the Spring Boot app root folder. Make sure that you saved Dockerfile in the root folder. Execute the following command to build the Docker image:
    docker built -t springboot-app:latest .

// In case you are executing the above command from another folder
docker built -t springboot-app:latest -f path_to_dockerfile.
  • Execute the following command to start and access the container:
    // Start the container; Name of the container is sbapp
docker run -tid -p 8080:8080 --name sbapp springboot-app:latest

// Access the container
docker exec -ti sbapp bash

// Access the logs
docker logs sbapp

Once started, open the REST client, and test the preceding RESTful API with URL as http://localhost:8080/doctors?location=xxx&speciality=yyy.

Summary

In this chapter, you learnt the fundamentals of the Spring web framework with a focus on understanding the key concepts such as IOC container, Dispatcher servlet, implementing controllers, web requests and response handling, using custom interceptors, and so on. You also learnt how to create a web application using Spring Boot, how to create a RESTful web service, and finally, how to Dockerize a Spring Boot application.

In the next chapter, you will learn how to prepare a Spring web development environment.

Left arrow icon Right arrow icon
Download code icon Download Code

Key benefits

  • • This hands on guide will teach you how to build an end-to-end modern web application using Spring and Angular.
  • • It is easy to read and will benefit Java developers who have been used to develop the back-end part of web application while front-end (UI) has been left for UI developers.
  • • Learn the core aspects involved in developing the backend and the UI, right from designing to integrating and deploying.

Description

Spring is the most popular application development framework being adopted by millions of developers around the world to create high performing, easily testable, reusable code. Its lightweight nature and extensibility helps you write robust and highly-scalable server-side web applications. Coupled with the power and efficiency of Angular, creating web applications has never been easier. If you want build end-to-end modern web application using Spring and Angular, then this book is for you. The book directly heads to show you how to create the backend with Spring, showing you how to configure the Spring MVC and handle Web requests. It will take you through the key aspects such as building REST API endpoints, using Hibernate, working with Junit 5 etc. Once you have secured and tested the backend, we will go ahead and start working on the front end with Angular. You will learn about fundamentals of Angular and Typescript and create an SPA using components, routing etc. Finally, you will see how to integrate both the applications with REST protocol and deploy the application using tools such as Jenkins and Docker.

Who is this book for?

This book is targeted towards Java Web Developers with a basic knowledge of Spring who want to build complete web applications in a fast and effective way. They will want to gain a stronghold on both frontend and backend development to advance in their careers.

What you will learn

  • • Set up development environment for Spring Web App and Angular app.
  • • Process web request and response and build REST API endpoints.
  • • Create data access components using Spring Web MVC framework and Hibernate
  • • Use Junit 5 to test your application
  • • Learn the fundamental concepts around building Angular
  • • Configure and use Routes and Components.
  • • Protect Angular app content from common web vulnerabilities and attacks.
  • • Integrate Angular apps with Spring Boot Web API endpoints
  • • Deploy the web application based on CI and CD using Jenkins and Docker containers

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Aug 24, 2017
Length: 370 pages
Edition : 1st
Language : English
ISBN-13 : 9781787284661
Vendor :
Pivotal
Languages :
Tools :

What do you get with a Packt Subscription?

Free for first 7 days. $19.99 p/m after that. Cancel any time!
Product feature icon Unlimited ad-free access to the largest independent learning library in tech. Access this title and thousands more!
Product feature icon 50+ new titles added per month, including many first-to-market concepts and exclusive early access to books as they are being written.
Product feature icon Innovative learning tools, including AI book assistants, code context explainers, and text-to-speech.
Product feature icon Thousands of reference materials covering every tech concept you need to stay up to date.
Subscribe now
View plans & pricing

Product Details

Publication date : Aug 24, 2017
Length: 370 pages
Edition : 1st
Language : English
ISBN-13 : 9781787284661
Vendor :
Pivotal
Languages :
Tools :

Packt Subscriptions

See our plans and pricing
Modal Close icon
€18.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
€189.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts
€264.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total 120.97
Spring 5 Design Patterns
€36.99
Building Web Apps with Spring 5 and Angular
€41.99
Mastering Spring 5.0
€41.99
Total 120.97 Stars icon

Table of Contents

11 Chapters
Introduction to Spring Web Framework Chevron down icon Chevron up icon
Preparing the Spring Web Development Environment Chevron down icon Chevron up icon
Data Access Layer with Spring and Hibernate Chevron down icon Chevron up icon
Testing and Running Spring Web App Chevron down icon Chevron up icon
Securing Web App with Spring Security Chevron down icon Chevron up icon
Getting Started with Angular Chevron down icon Chevron up icon
Creating SPA with Angular and Spring 5 Chevron down icon Chevron up icon
Unit Testing with Angular Apps Chevron down icon Chevron up icon
Securing an Angular App Chevron down icon Chevron up icon
Integrating Angular App with Spring Web APIs Chevron down icon Chevron up icon
Deploying the Web Application Chevron down icon Chevron up icon

Customer reviews

Top Reviews
Rating distribution
Full star icon Full star icon Half star icon Empty star icon Empty star icon 2.1
(8 Ratings)
5 star 12.5%
4 star 12.5%
3 star 12.5%
2 star 0%
1 star 62.5%
Filter icon Filter
Top Reviews

Filter reviews by




Pranav Sheoran Jul 31, 2020
Full star icon Full star icon Full star icon Full star icon Full star icon 5
This book would be very useful to anyone wanting to learn how to build web applications. The author has decades of experience building applications that would clearly show in how the material is presented. Can't wait for the next edition on this subject or for the author to explore and write about other development frameworks.
Amazon Verified review Amazon
Alok Kher Dec 27, 2017
Full star icon Full star icon Full star icon Full star icon Empty star icon 4
I had to modify the POM. (Change Spring 2.x to 1.x and add JUnit 5) to make the Spring app work. So cutting one star. I think the "tour of heroes" on Angular 2 is helpful before this book. Otherwise a good book on the full stack application development with the latest technologies.
Amazon Verified review Amazon
Nahom Abebe Nov 02, 2021
Full star icon Full star icon Full star icon Empty star icon Empty star icon 3
This is old book not going with today's technology
Amazon Verified review Amazon
Madhav Nov 09, 2018
Full star icon Empty star icon Empty star icon Empty star icon Empty star icon 1
Code presented in the book is not complete and author expects you to correct it and make it run
Amazon Verified review Amazon
Hariharan Vaidhyanathan Jul 28, 2018
Full star icon Empty star icon Empty star icon Empty star icon Empty star icon 1
Waste of money. None of the concepts were explained in detail and the examples are very vague with no proper instructions on how to follow.
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is included in a Packt subscription? Chevron down icon Chevron up icon

A subscription provides you with full access to view all Packt and licnesed content online, this includes exclusive access to Early Access titles. Depending on the tier chosen you can also earn credits and discounts to use for owning content

How can I cancel my subscription? Chevron down icon Chevron up icon

To cancel your subscription with us simply go to the account page - found in the top right of the page or at https://subscription.packtpub.com/my-account/subscription - From here you will see the ‘cancel subscription’ button in the grey box with your subscription information in.

What are credits? Chevron down icon Chevron up icon

Credits can be earned from reading 40 section of any title within the payment cycle - a month starting from the day of subscription payment. You also earn a Credit every month if you subscribe to our annual or 18 month plans. Credits can be used to buy books DRM free, the same way that you would pay for a book. Your credits can be found in the subscription homepage - subscription.packtpub.com - clicking on ‘the my’ library dropdown and selecting ‘credits’.

What happens if an Early Access Course is cancelled? Chevron down icon Chevron up icon

Projects are rarely cancelled, but sometimes it's unavoidable. If an Early Access course is cancelled or excessively delayed, you can exchange your purchase for another course. For further details, please contact us here.

Where can I send feedback about an Early Access title? Chevron down icon Chevron up icon

If you have any feedback about the product you're reading, or Early Access in general, then please fill out a contact form here and we'll make sure the feedback gets to the right team. 

Can I download the code files for Early Access titles? Chevron down icon Chevron up icon

We try to ensure that all books in Early Access have code available to use, download, and fork on GitHub. This helps us be more agile in the development of the book, and helps keep the often changing code base of new versions and new technologies as up to date as possible. Unfortunately, however, there will be rare cases when it is not possible for us to have downloadable code samples available until publication.

When we publish the book, the code files will also be available to download from the Packt website.

How accurate is the publication date? Chevron down icon Chevron up icon

The publication date is as accurate as we can be at any point in the project. Unfortunately, delays can happen. Often those delays are out of our control, such as changes to the technology code base or delays in the tech release. We do our best to give you an accurate estimate of the publication date at any given time, and as more chapters are delivered, the more accurate the delivery date will become.

How will I know when new chapters are ready? Chevron down icon Chevron up icon

We'll let you know every time there has been an update to a course that you've bought in Early Access. You'll get an email to let you know there has been a new chapter, or a change to a previous chapter. The new chapters are automatically added to your account, so you can also check back there any time you're ready and download or read them online.

I am a Packt subscriber, do I get Early Access? Chevron down icon Chevron up icon

Yes, all Early Access content is fully available through your subscription. You will need to have a paid for or active trial subscription in order to access all titles.

How is Early Access delivered? Chevron down icon Chevron up icon

Early Access is currently only available as a PDF or through our online reader. As we make changes or add new chapters, the files in your Packt account will be updated so you can download them again or view them online immediately.

How do I buy Early Access content? Chevron down icon Chevron up icon

Early Access is a way of us getting our content to you quicker, but the method of buying the Early Access course is still the same. Just find the course you want to buy, go through the check-out steps, and you’ll get a confirmation email from us with information and a link to the relevant Early Access courses.

What is Early Access? Chevron down icon Chevron up icon

Keeping up to date with the latest technology is difficult; new versions, new frameworks, new techniques. This feature gives you a head-start to our content, as it's being created. With Early Access you'll receive each chapter as it's written, and get regular updates throughout the product's development, as well as the final course as soon as it's ready.We created Early Access as a means of giving you the information you need, as soon as it's available. As we go through the process of developing a course, 99% of it can be ready but we can't publish until that last 1% falls in to place. Early Access helps to unlock the potential of our content early, to help you start your learning when you need it most. You not only get access to every chapter as it's delivered, edited, and updated, but you'll also get the finalized, DRM-free product to download in any format you want when it's published. As a member of Packt, you'll also be eligible for our exclusive offers, including a free course every day, and discounts on new and popular titles.