How to serve React built files to Spring Boot application - java

I have a Spring Boot application that has multiple APIs and a standart React application that was created using the create-react-app command. What I want to do is to build the React app using
npm run build
and serve the built files from the Spring Boot application.
Here is my project structure:
Right now, during development I set a proxy to the frontend/package.json in order to send all requests to the backend server but need the same behaviour in production. How do I achieve that?
package.json:
"proxy": "http://localhost:8082/gui",
I also need everything packaged together in my war so in my pom.xml I use a couple of plugins to build the React app and copy the built files to the Spring Boot target folder:
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.6</version>
<configuration>
<workingDirectory>frontend</workingDirectory>
<installDirectory>target</installDirectory>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v12.13.1</nodeVersion>
<npmVersion>6.12.1</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>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>generate-resources</phase>
<configuration>
<target>
<copy todir="${project.build.directory}/classes/public">
<fileset dir="${project.basedir}/frontend/build" />
</copy>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
An important information is that the Spring Boot app has a custom context path:
server.servlet.context-path=/gui
so the homepage should be served from localhost:8080/gui.
I need to know how to serve the frontend from my Spring Boot server. Thank you in advance!

Related

Adding angular as maven module in maven project

I am working in multi maven project which is separated in the following modules:
rest layer
service layer
repository layer
I want to add another module called view layer, ui of the application. The only problem is that ui is angular, and i need somehow to integrate angular app in maven module for this project.
I created a new maven module called view layer. Added the following plugin it maven module pom of view layer like below:
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.3</version>
<configuration>
<nodeVersion>v8.11.3</nodeVersion>
<npmVersion>6.3.0</npmVersion>
<workingDirectory>src/main/web/</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>
<execution>
<id>prod</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run-script build</arguments>
</configuration>
<phase>generate-resources</phase>
</execution>
</executions>
</plugin>
And generated an angular app with angular cli inside src/main/web directory of view module.
Unfortunately the build is failing, it is not finding the package.json.
I will appreciate any help.
Regards,
Darth Bato.
I do it this way to add angular as a maven module, in a multi maven project.
First thing I add a simple maven module by skipping the archetype selection. I modify the pom by adding the following configurations:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.deploy.skip>true</maven.deploy.skip>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>npm install</id>
<goals>
<goal>exec</goal>
</goals>
<phase>install</phase>
<configuration>
<executable>npm</executable>
<arguments>
<argument>install</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>npm build</id>
<goals>
<goal>exec</goal>
</goals>
<phase>install</phase>
<configuration>
<executable>npm</executable>
<arguments>
<argument>run</argument>
<argument>build</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Next, I delete all the content in the module I created only leaving the pom file. I delete the src folder, test folder, etc that are creating when we create a Maven module.
After that, I create a new angular app by using ANGULAR CLI. I move all the content of the angular app(src, dist, nodes_modules, etc) to the maven module project.
In the end, to check if everything is ok, I run a maven build to parent maven project to see if everything compiles successfully.
i think your
<workingDirectory>src/main/web/</workingDirectory>
is not correcte since you've not added the module name
like this
<workingDirectory>frontend-module/src/main/web/</workingDirectory>
thats is why it cannot get your package.json

How to package ReactJs app with Spring Boot Webflux

I am wondering is there any way to combine REST API and UI of Spring boot Webflux application. I use React for the UI part.
In normal Spring MVC application I can use frontend-maven-plugin along with maven-resources-plugin to build and copy the static resources to target directory. Something like this:
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.6</version>
<configuration>
<installDirectory>target</installDirectory>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v10.15.0</nodeVersion>
<npmVersion>6.4.1</npmVersion>
</configuration>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>webpack build dev</id>
<goals>
<goal>npm</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<arguments>run webpack:build</arguments>
<npmInheritsProxyConfigFromMaven>false</npmInheritsProxyConfigFromMaven>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>position-react-build</id>
<goals>
<goal>copy-resources</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<outputDirectory>${project.build.outputDirectory}/static</outputDirectory>
<resources>
<resource>
<directory>${frontendSrcDir}/build</directory>
<filtering>false</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
Everything works fine. But it is maybe because I use embedded Tomcat Server (default for Spring Boot with Spring MVC).
For the second approach, I would like to use Spring Boot Webflux. By default the application will run on Netty. I tried to apply the same maven configuration. But when the application is started it does not handlethe ReactJs application.

Angular and spring boot are not binding together so they run on same port 8080

my angular is running on 4200 port and my spring boot is running in 8080 port. Here I have build the angular project by ng build --prod and dist folder is produced. and they are in same directory inside eclipse-workspace
And i have added plugin inside the pom.xml file as
<plugin>
<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}/../Angular6SpringBoot-Client/dist/Angular6SpringBoot</directory >
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
Inside the dist folder is:
i have updated the project inside eclipse and also cleaned and build the project and when i run the project the output is not coming in localhost:8080 as it shwows:
I need to integrate both angular and spring project and run at port 8080
You are wanting to bundle the Spring Boot app and the Angular SPA (single page app) in a single deployable unit. This deployable unit will finally become a war or a jar depending on your packaging. Assuming you have all these mechanics figured out, here's how to go about meeting your objectives:
First ensure that the AngularJS SPA is built properly and it does produce your index.html, css and js files and any other assets. Easiest (and would be handy) would be to use the frontend-maven-plugin. Here's parts of a sample pom.xml:
<artifactId>xxxxx</artifactId>
<name>Angular UI</name>
<description>Some AngularJS UI project</description>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.6</version>
<configuration>
<nodeVersion>v7.10.1</nodeVersion>
<npmVersion>4.2.0</npmVersion>
<installDirectory>nodejs</installDirectory>
</configuration>
<executions>
<execution>
<id>Install node and npm if needed</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<phase>validate</phase>
</execution>
<execution>
<id>List current node and npm config</id>
<goals>
<goal>npm</goal>
</goals>
<phase>validate</phase>
<configuration>
<arguments>run config</arguments>
</configuration>
</execution>
<execution>
<id>Install all node packages requested by this app</id>
<goals>
<goal>npm</goal>
</goals>
<phase>validate</phase>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>Run tests</id>
<goals>
<goal>npm</goal>
</goals>
<phase>test</phase>
<configuration>
<arguments>run test</arguments>
</configuration>
</execution>
<execution>
<id>Build distributable</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run deploy:prod</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>woff</nonFilteredFileExtension>
<nonFilteredFileExtension>ttf</nonFilteredFileExtension>
<nonFilteredFileExtension>woff2</nonFilteredFileExtension>
<nonFilteredFileExtension>eot</nonFilteredFileExtension>
<nonFilteredFileExtension>swf</nonFilteredFileExtension>
<nonFilteredFileExtension>ico</nonFilteredFileExtension>
<nonFilteredFileExtension>png</nonFilteredFileExtension>
<nonFilteredFileExtension>svg</nonFilteredFileExtension>
<nonFilteredFileExtension>jpg</nonFilteredFileExtension>
<nonFilteredFileExtension>jpeg</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>dist</directory>
<targetPath>static</targetPath>
<filtering>true</filtering>
</resource>
</resources>
</build>
You can use the above as an example and tailor for your own needs. But the resoult should be that, this should produce a jar such that there is a static folder under target\classes. In that static folder you would see your index.html and other assets. This is the first step to complete. If you have gotten this far correctly, your SPA jar that you just produced, can be added as a dependency in a Spring Boot application.
Next add the dependency of the above module you just produced in the pom.xml of your Spring Boot App.
Next you need to tell Spring Boot how to locate the index.html in response to requests for /. For this, you can add a configuration class as follows.
#Configuration
#Order(Ordered.HIGHEST_PRECEDENCE)
public class YourWebConfiguration extends WebMvcConfigurerAdapter{
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("forward:index.html");
}
}
Now you could start your Spring Boot app let's say using mvn spring-boot:run. Let's also assume that your server port is 8080. Now point your browser to http://localhot:8080/. You will see your index.html in the browser.

How to run embedded TomEE for integration tests with test resources

I have J2EE project based on maven. This project contains connection to database, which is set up via resources.xml and persistence.xml. Connection works fine for normal deployment.
My problem is, that i would like to run embedded TomEE server for integration tests. For these tests i need use inmemory database.
To start TomEE i use combination of maven plugins showed below.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.13</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.tomee.maven</groupId>
<artifactId>tomee-maven-plugin</artifactId>
<version>7.0.4</version>
<executions>
<execution>
<id>start</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
<configuration>
<checkStarted>true</checkStarted>
</configuration>
</execution>
<execution>
<id>stop</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
<configuration>
<simpleLog>true</simpleLog>
</configuration>
</plugin>
When i start maven goal mvn install, server runs as expected, but with wrong DB connection. I did not find way, how to set up, that i need use src/test/resources instead of src/main/resources.
Do you know how to set up this plugin in way? I'am open to suggestions of similar solutions, which is simple and do not contains 'lot of' frameworks.
Thank you in advance.
After some investigation i found solution described below.
Three plugins were added into pom.
First plugin will start TomEE server for us.
<plugin>
<groupId>org.apache.tomee.maven</groupId>
<artifactId>tomee-maven-plugin</artifactId>
<version>7.0.4</version>
<executions>
<execution>
<id>start</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
<configuration>
<checkStarted>true</checkStarted>
</configuration>
</execution>
<execution>
<id>stop</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
<configuration>
<simpleLog>true</simpleLog>
</configuration>
Second one will replace proper resources and persistence files.
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>copy-test-persistence</id>
<phase>process-test-resources</phase>
<configuration>
<tasks>
<!--backup the "proper" files-->
<copy file="${project.build.outputDirectory}/META-INF/resources.xml" tofile="${project.build.outputDirectory}/META-INF/resources.xml.proper"/>
<copy file="${project.build.outputDirectory}/META-INF/persistence.xml" tofile="${project.build.outputDirectory}/META-INF/persistence.xml.proper"/>
<!--replace the "proper" files with the "test" version-->
<copy file="${project.build.testOutputDirectory}/META-INF/resources.xml" tofile="${project.build.outputDirectory}/META-INF/resources.xml"/>
<copy file="${project.build.testOutputDirectory}/META-INF/persistence.xml" tofile="${project.build.outputDirectory}/META-INF/persistence.xml"/>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>restore-persistence</id>
<phase>prepare-package</phase>
<configuration>
<tasks>
<!--restore the "proper" files -->
<copy file="${project.build.outputDirectory}/META-INF/resources.xml.proper" tofile="${project.build.outputDirectory}/META-INF/resources.xml"/>
<copy file="${project.build.outputDirectory}/META-INF/persistence.xml.proper" tofile="${project.build.outputDirectory}/META-INF/persistence.xml"/>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
Last plugin force 'clean' before install. Without this i had problem in case, when i forget clean project before install.
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.4.1</version>
<executions>
<execution>
<id>auto-clean</id>
<phase>initialize</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>

Deploying war to remote tomcat server without breaking the integration tests execution

I am using tomcat7-maven-plugin for running my integration tests on my localhost Tomcat using mvn verify command. However, when I run mvn tomcat7:redeploy I want to deploy the war to my remote tomcat server instead of localhost tomcat. How can I achieve this? Please guide.
pom.xml
<!-- Embedded integration testing with localhost Tomcat -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<id>start-tomcat</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run-war</goal>
</goals>
<configuration>
<fork>true</fork>
</configuration>
</execution>
<execution>
<id>stop-tomcat</id>
<phase>post-integration-test</phase>
<goals>
<goal>shutdown</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Integration tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>

Categories

Resources