6

Let me just start off by saying, I am new to Maven / Spring and am having a hard time figuring out what to do when my directory does not follow the preferred Maven structure.

I followed instructions for setting up a project with Angular 2 and Spring Boot via this tutorial. This tutorial creates two modules, frontend and backend, with corresponding pom.xml's and one parent pom.xml. I can run the application just fine using my IDE, IntelliJ, or by running "mvn spring-boot:run" from the backend directory. However, for deployment, I wish to package the application into a WAR file to drop into a Tomcat server. I am unsure how to do this using the pom.xml's that I currently have. I am quite sure that it has to do with my directory structure, however I am not sure if I should restructure my application or of there is a way to configure Maven to place the two modules into resulting WAR file that works as intended.

I have found a similar answer here but the last part is what throws me off. I do not have a /src/main/webapp/WEB-INF folder and am unsure where to make it.

My application structure is as follows:

AppRoot

-backend
--src
---main
----java
--pom.xml

-frontend
--src
---main
----frontend
--pom.xml

-pom.xml

My root pom.xml is:

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

<name>c-cop</name>
<description>C-COP Project</description>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.2.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
</properties>

<modules>
    <module>frontend</module>
    <module>backend</module>
<module>web</module>

Frontend pom.xml:

<artifactId>frontend</artifactId>

<name>frontend</name>
<description>C-COP Project frontend</description>

<parent>
    <groupId>com.trinityinnovations</groupId>
    <artifactId>parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</parent>

<build>
    <plugins>
        <plugin>
            <groupId>com.github.eirslett</groupId>
            <artifactId>frontend-maven-plugin</artifactId>
            <version>1.3</version>

            <configuration>
                <nodeVersion>v6.9.1</nodeVersion>
                <npmVersion>4.0.3</npmVersion>
                <workingDirectory>src/main/frontend</workingDirectory>
            </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/frontend</directory>
            <targetPath>static</targetPath>
        </resource>
    </resources>
</build>

Backend pom.xml:

<artifactId>backend</artifactId>

<name>backend</name>
<description>C-COP Project backend</description>

<parent>
    <groupId>com.trinityinnovations</groupId>
    <artifactId>parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
</properties>

<dependencies>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.restdocs</groupId>
        <artifactId>spring-restdocs-mockmvc</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.trinityinnovations</groupId>
        <artifactId>frontend</artifactId>
        <version>${project.version}</version>
        <scope>runtime</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/commons-httpclient/commons-httpclient -->
    <dependency>
        <groupId>commons-httpclient</groupId>
        <artifactId>commons-httpclient</artifactId>
        <version>3.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-csv -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-csv</artifactId>
        <version>1.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>6.0.6</version>
    </dependency>
    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-hibernate5</artifactId>
    </dependency>
    <dependency>
        <groupId>com.javaetmoi.core</groupId>
        <artifactId>javaetmoi-hibernate5-hydrate</artifactId>
        <version>2.3</version>
    </dependency>
<dependency>
  <groupId>com.google.maps</groupId>
  <artifactId>google-maps-services</artifactId>
  <version>0.1.20</version>
</dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

Please let me know if there is any more information that is needed.

Community
  • 1
  • 1
landesko
  • 373
  • 1
  • 5
  • 16

3 Answers3

8

After doing a lot of searching, I came across the Maven War Plugin. This allowed me to pull in the necessary frontend files to the backend for the successful creation of my WAR file. The changes that need to be made are as follows:

Backend pom.xml - after the description tags add:

<packaging>war</packaging>

Then, inside the build tags, inside plugins add this plugin:

  <plugin>
    <artifactId>maven-war-plugin</artifactId>
    <configuration>
      <webResources>
        <resource>
          <directory>../frontend/target/frontend</directory>
        </resource>
      </webResources>
    </configuration>
  </plugin>

Other than that, you can keep the existing pom.xml's the same as only the backend pom.xml needs include war packaging. It ended up being a rather simple answer.

Also need to set the base-href in the package.json. Note "build":

"scripts": {
"ng": "ng",
"start": "ng serve --proxy-config proxy.conf.json",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"build": "ng build --base-href=\"./\""
},
landesko
  • 373
  • 1
  • 5
  • 16
  • in my project i don't have backend, do you have any idea where should I copy my dist folder in spring boot project, to deploy it as a war file? – Shilan Oct 09 '17 at 13:34
  • I'm not entirely sure, but I am curious... If you don't have a backend, why does your project need to be wrapped up into a war file? – landesko Oct 13 '17 at 17:34
  • :) there is a backend, that contains only restful services but I cannot put the angular code together with that code into one module, basically I am not allowed to modify the other backend module, i can only call the restful services. – Shilan Oct 13 '17 at 19:48
  • You should be able to just copy the dist folder into your tomcat instance and not have to deploy it as a war. You should rename it accordingly. You can also place all of the contents in the root directory of your tomcat instance. – landesko Oct 13 '17 at 20:39
  • Yes, i did and that worked actually, but the intention was to run the ng build via gradle or maven on a bamboo sever, that’s why i had to wrap it in a war file. – Shilan Oct 13 '17 at 22:43
  • I actually found out which folder I should copy it to. It’s statistic folder. However it works fine locally but when I create the war file, apparently it cannot find the index file. – Shilan Oct 13 '17 at 22:47
  • @Shilan : Are you able to access the rest point. I am facing same problem. – Anil Kumar Jun 06 '19 at 07:36
  • No, never worked properly on the server. I copy them to tomcat folder every time I deploy. @AnilKumar – Shilan Jun 16 '19 at 20:32
2

Hello i use Angular 4 and Spring boot to deploy war. It's work fine and i share it.

Here pom.xml :

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>Spring_Angular</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging><name>Spring_Angular</name>
<description>Demo project for Spring Boot</description>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.2.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <configuration>
                <webResources>
                    <resource>
                        <directory>${basedir}/target/angular4Client</directory>
                    </resource>
                </webResources>
            </configuration>
        </plugin>

        <plugin>
            <groupId>com.github.eirslett</groupId>
            <artifactId>frontend-maven-plugin</artifactId>
            <version>1.6</version>
            <configuration>
                <nodeVersion>v8.9.2</nodeVersion>
                <npmVersion>5.6.0</npmVersion>
                <installDirectory>target</installDirectory>
                <workingDirectory>${basedir}/src/main/angular4client</workingDirectory>
            </configuration>
            <executions>
                <!-- It will install nodejs and npm -->
                <execution>
                    <id>install node and npm</id>
                    <goals>
                        <goal>install-node-and-npm</goal>
                    </goals>
                    <configuration>
                        <nodeVersion>v8.9.2</nodeVersion>
                        <npmVersion>5.6.0</npmVersion>
                    </configuration>
                </execution>

                <!-- It will execute command "npm install" inside "/e2e-angular2" directory -->
                <execution>
                    <id>npm install</id>
                    <goals>
                        <goal>npm</goal>
                    </goals>
                    <configuration>
                        <arguments>install</arguments>
                    </configuration>
                </execution>
                <!-- It will execute command "npm build" inside "/e2e-angular2" directory 
                    to clean and create "/dist" directory -->
                <execution>
                    <id>npm build</id>
                    <goals>
                        <goal>npm</goal>
                    </goals>
                    <configuration>
                        <arguments>run build</arguments>
                    </configuration>
                </execution>
            </executions>
        </plugin>

        <!-- Plugin to copy the content of /angular/dist/ directory to output 
            directory (ie/ /target/transactionManager-1.0/) -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy-resources</id>
                    <phase>validate</phase>
                    <goals>
                        <goal>copy-resources</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${basedir}/target/classes/static/</outputDirectory>
                        <resources>
                            <resource>
                                <directory>${basedir}/src/main/angular4Client/dist/angular4Client</directory>
                            </resource>
                        </resources>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
    <resources>
        <resource>
            <directory>target/angular4Client</directory>
            <targetPath>static</targetPath>
        </resource>
    </resources>
</build>
</project>

Then in your angular package.json change like this:

"scripts": {
"ng": "ng",
"start": "ng serve --proxy-config proxy.conf.json",
"build": "ng build --prod",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
}

Create a proxy.conf.json file in angular project root :

{
"/api": {
    "target": "http://localhost:8080",
    "secure": false
    }
}

And last things to do, move your angular 4 project into : "src/main/" on SpringBoot project.

Good luck according to this demo : http://javasampleapproach.com/java-integration/integrate-angular-4-springboot-web-app-springtoolsuite

Gama_aide
  • 61
  • 4
  • I have tried the above, but my war doesn't created. – Anil Kumar May 17 '19 at 18:17
  • I am able to package the application as jar and war. And able to execute the packaged jar. I am facing another issue. I am unable to access rest point mention in proxy.conf.json. Any idea? – Anil Kumar Jun 06 '19 at 07:34
0

The reference doc contains a detailed description of this. You need <packaging>war</packaging> in both your frontend and backed module pom and some Java code. All described here

With that said, I try to avoid war deploys if not totally necessary. You could just run the built jar file with java -jar your.jar and it will start in an embedded Tomcat.

Pär Nilsson
  • 2,259
  • 15
  • 19