4 Ways to Deploy Spring Boot Angular App(Maven + Tomcat)

author-imageBy Dhiraj, 12 January,2018   39K

In my last spring boot angular 5 article, we implemented a full stack end to end web application using spring boot angular 5.In this article we will discuss about different ways to deploy spring boot and angular app on tomcat. We will be creating a multi module maven project with backend(server) and fronted(client) and look into 4 ways about how to deploy it using maven-war-plugin, maven-resources-plugin, jar packaging etc.

Spring Boot Angular 5 Project

First of all, let me brief about what we built in our last example. We used angular CLI to generate angular 5 project and modified it to have functionality such as list user and add user. We used spring boot to expose REST API for the crud operation and integrated spring data to communicate with MySql database. We made use of ng serv to serv the angular project on localhost:4200 and it was consuming APIs exposed on localhost:8080. Following was the final project structure.

spring-boot-angular-5-project-strct

Different Ways to Deploy Spring Boot Angular Application

The best practice to deploy a spring boot and angular application is to seperate the user interface code with the business logic.This provides decoupling of the client code with server code and hence the application becomes highly scalable and manageable. The fronted developer can continue with the fronted development in parallel with the backened developer. The backend code becomes free to use and integrate different technology stacks and it becomes available for multiple clients such as the same APIs can be re-used for building android application and same can be integrated with third party clients too.It also reduces the downtime of your application. Whenever, your APIs are not available or down, your client application is still up.

But sometimes it becomes an overhead to manage two server for a small team and a small application. If a single full stack developer is handling all the UI and server related configurations, packaging fronted and backend application into a single web application is sometimes more helpful. Still, you can expose REST APIs and integrate angular fronted code within the same application and deploy to a tomcat and other mobile client can reuse the same APIs.

Now when coming to deploy a java web application, we have two different ways to do this. After the introduction of Spring Boot, you can package your application as a FAT jar file with embedded tomcat and database and run as an executable file. Also, you can use multiple maven plugins to create a .war file and deploy it to a standalone tomcat.

In this article, we will mainly look into 4 ways to deploy spring boot angular application and they are - using node server and tomcat, using maven war plugin, using maven resources plugin and spring boot jar packaging

Spring Boot Angular Multi Module Project

We already have two existing projects - userPortal(server) and portalApp(client) and now we will convert it into a multi module project. To do this create a new folder - portal-parent and move both the existing project into this folder and create a pom.xml file in portal-parent directory. This pom.xml will have module defined as the two existing child project - userPortal and portalApp and the packaaging type will be pom. So, whenever we build this parent the child modules will be built first.

Make sure we have client project i.e. portal-app as the first child included in parent pom else the build will fail as there won't be dist folder generated while generating the .war file.

 <modelVersion>4.0.0</modelVersion>

    <groupId>com.devglan</groupId>
    <artifactId>portal-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <name>portal parent</name>
    <description>portal parnt</description>

    <modules>
        <module>portal-app</module>
        <module>user-portal</module>
    </modules>

And, following is the sample pom file of client project i.e. portal-app

<groupId>com.devglan</groupId>
  <artifactId>portal-app</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>portal-app</name>
  <description>Demo project for Spring Boot</description>

  <build>
    <plugins>

      <plugin>
        <artifactId>maven-clean-plugin</artifactId>
        <version>2.5</version>
        <configuration>
          <filesets>
            <fileset>
              <directory>dist</directory>
              <includes>
                <include>*</include>
              </includes>
            </fileset>
          </filesets>
        </configuration>
      </plugin>

      <plugin>
        <groupId>com.github.eirslett</groupId>
        <artifactId>frontend-maven-plugin</artifactId>
        <version>1.6</version>
        <executions>
          <execution>
            <id>install node and npm</id>
            <goals>
              <goal>install-node-and-npm</goal>
            </goals>
            <configuration>
              <nodeVersion>v8.9.0</nodeVersion>
              <npmVersion>5.5.1</npmVersion>
            </configuration>
          </execution>

          <execution>
             <id>npm run build</id>
            <goals>
              <goal>npm</goal>
            </goals>
            <configuration>
              <arguments>run build</arguments>
            </configuration>
          </execution>

        </executions>
      </plugin>
    </plugins>
  </build>

Deployment with Maven War Plugin

The maven war plugin creates a .war file by collecting all the artifact dependencies, classes, resources of the web application. Hence, here in this configuration we will configure our client project to push all the static resources to target/client and later while creating the war file we will use maven war plugin to include this in the .war generation and put it inside /static folder. And of course, spring boot has a feature to look into static folder for static resources and our angular static resources will be served.

So now how will we get the final build of static resources. Well, this will be done by angular itself.If you look into angular-cli.json you willl find one JSOn property as - "outDir": "dist",. This means the final output will be pushed to dist folder if we build the angular project. And we will have now configuration in the client pom.xml file to build the angular project using npm. To so this we have to make changes in the client pom.xml as follow:

This configuration will download and install the node and npm as configured in the pom file and npm install will install all modules listed as dependencies in package.json and in the execution phase the final sources will be pushed to dist folder as per the configuration in package.json.

Also, we will have configuration in the pom file of server where we will configure our maven war plugin to include the resources of ../client/target while building the war file.Also, it will have the angular client as jar dependency. And like this the final war will be generated and now you can deploy it to any standalone tomcat.

client pom.xml
 <build>
    <finalName>client</finalName>
    <plugins>
      <plugin>
        <groupId>com.github.eirslett</groupId>
        <artifactId>frontend-maven-plugin</artifactId>
        <version>1.6</version>

        <configuration>
          nodeVersion>v8.9.0</nodeVersion>
          <npmVersion>5.5.1</npmVersion>

        </configuration>

        <executions>
          <execution>
            <id>install node and npm</id>
            <goals>
              <goal>install-node-and-npm</goal>
            </goals>
          </execution>

          <execution>
            <id>npm install</id>
            <goals>
              <goal>npm</goal>
            </goals>
          </execution>

          <execution>
            <id>npm run build</id>
            <goals>
              <goal>npm</goal>
            </goals>

            <configuration>
              <arguments>run build</arguments>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
    <resources>
      <resource>
        <directory>target/client</directory>
        <targetPath>static</targetPath>
      </resource>
    </resources>
  </build>
server pom.xml
<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.2.0</version>
				<configuration>
					<webResources>
						<resource>
							<directory>../user-portal/target</directory>
						</resource>
					</webResources>
				</configuration>
			</plugin>
		</plugins>
	</build>

After these changes run mvn clean install and your war will be generated.

deployment-result

Deployment with Maven Resources Plugin

We have already configured our client to push all the static sources to dist folder in above configuration. Now, we will be using maven resource plugin to copy all files from dist folder to /src/main/resources/static folder of our server project and spring boot will server these resources from the /static folder. Following is the pom configuration.

<plugin>
	<artifactId>maven-resources-plugin</artifactId>
	<executions>
		<execution>
			<id>copy-resources</id>
			<phase>validate</phase>
			<goals><goal>copy-resources</goal></goals>
			<configuration>
				<outputDirectory>${build.directory}/classes/static/</outputDirectory >
				<resources>
					<resource>
						<directory>../portal-app/dist</directory>
					</resource>
				</resources>
			</configuration>
		</execution>
	</executions>
</plugin>

Deployment with Spring Boot Jar Packaging

In this case we will be packaging the angular project as a jar. So no changes reqired in the client pom file.Also, we do not require to configure any maven plugin in the server pom file. Remove all the build configuration except spring-boot-maven-plugin. Don't forget to add client project jar dependency in the server pm file. So, now when we build our project the jar will be included in the META-INF/resources directory and Spring Boot is preconfigured to serve static content from this resources folder. One thing you require to change is in the build parameter of package.json.

"build": "ng build -prod –output-path META-INF/resources"

Node and Tomcat Server Deployment

In this case the angular project can be hosted on node server and spring boot application can be hosted on any other application server. To do this run ng build command to generate the dist folder and copy this folder to backend node server. Doing this can help in load balancing both the server separately.

Deploying Angular app on Nginx

Above methods of deploying angular app useful while deploying as a single war file but there are use cases when we want to deploy the angular app as a standalone app. While doing so, either we can make use of Node Js for server side rendering. One use case of server side rendering is SEO. But we can also use Nginx on the cloud to serve our angular pages. Here is my another article where I have explained about deploying angular app on Nginx in cloud.

Further Reading on Spring Boot

1. Deploy Angular App Nginx

2. Angular 6 Example

3. Angular Material App

4. Spring Boot Angular Example

5. File Upload Angularjs Spring Boot Rest

If You Appreciate What We Do Here On Devglan, You Should Consider: