1

My Spring Boot application contains a Java part and an Angular part. The Angular part (with an index.html,etc) is generated into the folder src/main/resources/static. Works fine. I noticed that when building the final JAR often (?) the static part is lost.

How come? What can I do to get the static / HTML part into the final Spring Boot JAR?

My <build> part of the pom.xml is shown below. All not-interesting parts (like unit testing, etc) is removed.

<build>
    ... 
    <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>1.6.0</version>
    <executions>
      <execution>
        <id>npm install</id>
        <goals>
          <goal>exec</goal>
        </goals>
        <phase>initialize</phase>
        <configuration>
          <executable>npm</executable>
          <arguments>
            <argument>install</argument>
          </arguments>
        </configuration>
      </execution>
      <execution>
        <id>build Angular production code</id>
        <goals>
          <goal>exec</goal>
        </goals>
        <phase>compile</phase>
        <configuration>
          <executable>npm</executable>
          <arguments>
            <argument>run</argument>
            <argument>build</argument>
            <argument>--prod</argument>
          </arguments>
        </configuration>
      </execution>
    </executions>
  </plugin>
  ...
</build>
3
  • When I remove the maven-clean-plugin plugin, then everything works. Why is that? I put a file in the resources/static folder as a place holder. I haven't tried so far if that has any influence. Commented Dec 12, 2018 at 21:55
  • Where did you put that angular app? Should be in resources, static, or webapp Commented Dec 12, 2018 at 22:04
  • The angular part is generated info the folder "src/main/resources/static". Commented Dec 13, 2018 at 21:30

2 Answers 2

2

Thank you @Carlos Cavero! You pointed me in the right direction. Thank you so much!

The problem was that the npm build was done in the 'compile' phase. On some machines the 'compile' phase of the Java code was done before that 'compile' with the Angular 'npm build'.

The solution was to put the Angular (typescript) npm phase BEFORE the compile phase. That is: in the generate-resource phase. It could not be the 'validate' phase, because that one is done before the 'install' with the 'npm install'.

This is now the correct Angular / npm build phase.

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>1.6.0</version>
    <executions>
      <execution>
        <id>npm install</id>
        <goals>
          <goal>exec</goal>
        </goals>
        <phase>initialize</phase>
        <configuration>
          <executable>npm</executable>
          <arguments>
            <argument>install</argument>
          </arguments>
        </configuration>
      </execution>
      <execution>
        <id>build Angular production code</id>
        <goals>
          <goal>exec</goal>
        </goals>
        <phase>generate-resources</phase>
        <configuration>
          <executable>npm</executable>
          <arguments>
            <argument>run</argument>
            <argument>build</argument>
            <argument>--prod</argument>
          </arguments>
        </configuration>
      </execution>
    </executions>
 </plugin>
Sign up to request clarification or add additional context in comments.

3 Comments

That's right, I edited the response following @Antoniossss' recomendations about the correct maven lifecycle.
he problem was that the npm build was done in the 'compile' phase. On some machines the 'compile' phase of the Java code was done before that 'compile' with the Angular 'npm build'. how is that even possible? And only on "some machines"? In general maven lifecycle is serialized. Some phases migh run parallel (internally) so its hard to belive you had some sort of racing conditions involved.
I agree - that was what really really amazed me. I don't have an answer for that. BUT the solution of putting the 'npm' (Angular) part in the generate-resources part is the real solution.
1

I am using validate phase to copy the static angular resources to spring:

mvn clean install

Using a parent pom to split angular from Spring project:

<modules>
    <module>phs-frontend</module>
    <module>phs-frontend-web</module>
</modules>

Where phs-frontend project is an angular project with a pom file and maven clean plugin:

<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>v6.10.3</nodeVersion>
                        <npmVersion>5.6.0</npmVersion>
                    </configuration>
                </execution>

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

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

            </executions>
        </plugin>

    </plugins>
</build>

And the phs-frontend-web is the Spring project:

<build>
    <plugins>

        <plugin>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.6</version>
            <executions>
                <execution>
                    <id>copy-resources</id>
                    <phase>validate</phase>
                    <goals>
                        <goal>copy-resources</goal>
                    </goals>
                    <configuration>
        <outputDirectory>${project.build.outputDirectory}/static/</outputDirectory>
                        <encoding>UTF-8</encoding>
                        <nonFilteredFileExtensions>
                            <nonFilteredFileExtension>ttf</nonFilteredFileExtension>
                            <nonFilteredFileExtension>woff</nonFilteredFileExtension>
                            <nonFilteredFileExtension>woff2</nonFilteredFileExtension>
                        </nonFilteredFileExtensions>
                        <resources>
                            <resource>
                                <directory>${project.basedir}/phs-frontend/dist</directory>
                                <filtering>true</filtering>
                                <includes>
                                    <include>**/*</include>
                                </includes>
                            </resource>
                        </resources>
                    </configuration>
                </execution>
            </executions>
        </plugin>           

        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <executable>true</executable>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <configuration>
                <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
        </plugin>
    </plugins>
</build>

2 Comments

I would say that package is doing what you are saying not validate (and thats before install). Validate is even before compile.
@Antoniossss you are completely right. Probably I copied/pasted the example and I called validate phase on purpose after install. I moved the maven-resources-plugin to the Spring project in order to do things properly with mvn clean install. Right now my CI/CD pipeline is much more better. I followed this article: dzone.com/articles/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.