I am creating a batch multiple test suites for a project. I have a regression test and a smoke test. I need to call it from the batch file, so regression I need to run after a release but smoke every day. However when I run
cd %projectLocation%
call mvn clean test -DsuiteXmlFile=smokeTestRunner.xml
in a file it still jumps to the regression test first. Here is my surefire plugin config:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<suiteXmlFiles>
<!-- TestNG suite XML files -->
<suiteXmlFile>regressionTestRunner.xml</suiteXmlFile>
<suiteXmlFile>smokeTestRunner.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
How do I make it run only smoke test or regression test separately? Both runner.xml files and pom.xml are in the same directory
Try this in pom:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>{suite}.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
And then run in terminal:
mvn clean test -Dsuite=smokeTestRunner
or
mvn clean test -Dsuite=regressionTestRunner
I'm following the documentation is https://spring.io/guides/tutorials/react-and-spring-data-rest/ to build a React app that uses Spring. The spring part was fine until it gets to the part where recommends to install the node and npm modules with a plugin. I have the problem that this plugin does not do what it supposed to do. I've checked the documentation and it establish some executions (I don't really know how the plugins work). I introduce those executions, but I still can't see the React app render in the brower at localhost:8080.
This is the plugin that they use in the spring documentation. Just like that. I hope anybody who has followed this tutorial could help me.
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
</plugin>
You can run React Frontend and SpringBoot Backend on the same port and Package them as a single artifact !!
Here is the Github link of the demo project that I am going to
explain here
Spring Boot can serve static content from src/main/resources/static folder. We will exploit the above mentioned feature of Spring Boot to serve the single page of the react project. We will serve a html page from the static folder in the target directory, not in the source directory.
The Project structure-
First, create a spring boot project with https://start.spring.io. Add the Web dependency. Set the groupId and artifactId to whatever you want. Generate the project and unzip it into your project directory.
Or, if you are using Spring Tools Suite you can simply click
File->New->Spring Starter Project and mention the required details to create a spring boot project.
The frontend folder inside src/main should have your react application build using create-react-app.
So, there are two steps-
create a production build of the frontend.
copy the production build into ${target/classes/}.
We we will use two maven plugins and Thymleaf for that.
frontend-maven-plugin for step 1.
maven-resources-plugin for step 2.
For frontend-maven-plugin at Step 1-- If you closely look at the pom.xml there I have mentioned the src directroy from where frontend-maven-plugin will take the files, create the production build and place the contents inside the output directory mentioned(inside src/main/frontend/build).
<workingDirectory>${frontend-src-dir}</workingDirectory>
<installDirectory>${project.build.directory}</installDirectory>
For maven-resources-plugin at step 2-- It will take the production build that was just created by frontend-maven-plugin and place it inside your root directory then target/classes/static.
Then we will use Thymleaf to serve the static content from the target/classes/static using a rest endpoint in the controller. Or else you have to type in the name of the html file, like http://localhost:8080/index.html
Your pom.xml should look like this-
<?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.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.springreact</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Run React Frontend and SpringBoot Backend on the same port.</description>
<properties>
<java.version>1.8</java.version>
<frontend-src-dir>${project.basedir}/src/main/frontend</frontend-src-dir>
<node.version>v14.15.4</node.version>
<yarn.version>v1.16.0</yarn.version>
<frontend-maven-plugin.version>1.7.6</frontend-maven-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>${frontend-maven-plugin.version}</version>
<configuration>
<nodeVersion>${node.version}</nodeVersion>
<yarnVersion>${yarn.version}</yarnVersion>
<workingDirectory>${frontend-src-dir}</workingDirectory>
<installDirectory>${project.build.directory}</installDirectory>
</configuration>
<executions>
<execution>
<id>install-frontend-tools</id>
<goals>
<goal>install-node-and-yarn</goal>
</goals>
</execution>
<execution>
<id>yarn-install</id>
<goals>
<goal>yarn</goal>
</goals>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>build-frontend</id>
<goals>
<goal>yarn</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<arguments>build</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<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>${frontend-src-dir}/build</directory>
<filtering>false</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Here is the Controller code.
package com.springreact.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class IndexController {
#GetMapping("")
public ModelAndView home() {
ModelAndView mav=new ModelAndView("index");
return mav;
}
}
If you follow the above mentioned steps , you should see your React App being spun up on http://localhost:8080/.
If you still have some doubts then you can checkout the comprehensive blog that I have written on it. Here are the links of the blog on two different platforms, you can choose whichever you are comfortable with.
Dev Community- https://dev.to/arpan_banerjee7/run-react-frontend-and-springboot-backend-on-the-same-port-and-package-them-as-a-single-artifact-14pa
Medium- https://arpan-banerjee7.medium.com/run-react-frontend-and-springboot-backend-on-the-same-port-and-package-them-as-a-single-artifact-a790c9e10ac1
If your project structure looks like the following:
frontend/ -> React application
src/ -> Spring Boot application
You can bundle the React application with the frontend-maven-plugin with the following configuration:
<build>
<resources>
<resource>
<directory>${project.basedir}/frontend/build</directory>
<filtering>false</filtering>
<targetPath>public/</targetPath>
</resource>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<filtering>false</filtering>
</resource>
</resources>
<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.8.0</version>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<phase>generate-resources</phase>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>npm build</id>
<goals>
<goal>npm</goal>
</goals>
<phase>generate-resources</phase>
<configuration>
<environmentVariables>
<CI>true</CI>
</environmentVariables>
<arguments>run build</arguments>
</configuration>
</execution>
</executions>
<configuration>
<workingDirectory>frontend</workingDirectory>
<nodeVersion>v12.18.0</nodeVersion>
</configuration>
</plugin>
</plugins>
</build>
If your project structure differs, you have to adjust the workingDirectory and the first resources configuration and point it to your folder.
This plugin basically executes several npm commands to test and build your React application and with the resources configuration, you extend the standard directory to include inside your .jar. Your frontend application is then accessible at http://localhost:8080.
You can find a running example for this here.
I followed the same tutorial and stuck at the same point: the frontend-maven-plugin seems not working. In addition, the codebase that author provided looks not well organized to me, e.g. two pom.xml files, one in project root folder, the other in basic folder.
Here is what I figured out, and finally worked:
In pom.xml add the frontend-maven-plugin in plugins along with the scripts you want it to execute. Make sure you include the version tag and supply the latest version (you can find the version information in Maven Repository), otherwise the plugin won't be resolved.
<build>
<plugins>
<!-- For the sake of simplicity, -->
<!-- other plugins are omitted. -->
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.12.0</version>
<configuration>
<installDirectory>target</installDirectory>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v14.17.3</nodeVersion>
<npmVersion>7.18.1</npmVersion>
</configuration>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<execution>
<id>webpack build</id>
<goals>
<goal>webpack</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Create package.json file in the project root folder, i.e. same location as pom.xml and paste following content:
{
"name": "spring-data-rest-and-reactjs",
"version": "0.1.0",
"description": "Demo of ReactJS + Spring Data REST",
"repository": {
"type": "git",
"url": "git#github.com:spring-guides/tut-react-and-spring-data-rest.git"
},
"keywords": [
"rest",
"hateoas",
"spring",
"data",
"react"
],
"author": "Greg L. Turnquist",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/spring-guides/tut-react-and-spring-data-rest/issues"
},
"homepage": "https://github.com/spring-guides/tut-react-and-spring-data-rest",
"dependencies": {
"react": "^16.5.2",
"react-dom": "^16.5.2",
"rest": "^1.3.1"
},
"scripts": {
"watch": "webpack --watch -d --output ./target/classes/static/built/bundle.js"
},
"devDependencies": {
"#babel/core": "^7.1.0",
"#babel/preset-env": "^7.1.0",
"#babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.2",
"webpack": "^4.19.1",
"webpack-cli": "^3.1.0"
}
}
Create webpack.config.js file in project root folder, i.e. the same location as pom.xml and paste following content:
var path = require('path');
module.exports = {
entry: './src/main/js/app.js',
devtool: 'sourcemaps',
cache: true,
mode: 'development',
output: {
path: __dirname,
filename: './src/main/resources/static/built/bundle.js'
},
module: {
rules: [
{
test: path.join(__dirname, '.'),
exclude: /(node_modules)/,
use: [{
loader: 'babel-loader',
options: {
presets: ["#babel/preset-env", "#babel/preset-react"]
}
}]
}
]
}
};
Copy client.js and the whole api folder in the same directory to your project. The app.js uses client.js which uses the two .js files in the api folder. You can find the source code of the three files in the tutorial repository.
Now you should have everything in order to make React work in this project. While depending on what IDE you're using, it may still "NOT WORK". Let me explain more about what I mean:
if you are using command line to run the project, then simply type ./mvnw spring-boot:run in the project root folder and it should work like a charm.
if you are using the little green triangle to run application in IntelliJ like me, you have to edit run/debug configuration in order to make it work; otherwise the application can run successfully but there is no bundle.js generated whatsoever:
First, open IntelliJ -> Run -> Edit Configurations
Secondly, click on the + button in Before Launch section and select Run Maven Goal
Thirdly, type generate-resources in command line and click OK. We choose this command as mentioned in frontend-maven-plugin git repo, if not sepecified, the goal is executed in generate-resources phase.
Finally, you can create a maven goal to clean everything before build. Here is what Before launch looks like:
Now click on the green triangle to run application and you will get the same result as mentioned in the tutorial (except there is no boarders in the employee list since we don't have the .css file).
Some final thoughts:
You add frontend-maven-plugin to use node and npm in your project.
You add package.json to install necessary JavaScript modules, e.g. React.js.
You add webpack.config.js to instruct webpack to transpile the javascript files into a single file named bundle.js and output it to the static folder of the project
You add many execution and goal tags in pom.xml to automate step 2 and 3.
You execute the maven goals to start the automation process.
We develop a web application that uses Java on the back-end and Angular for the UI, with Maven as the build system.
I've been trying to set up automated integration testing with Protractor, and after loads of Googling/StackOverflowing still can't figure out how the end-2-end configuration can be achieved.
Node.js/NPM installation (failed)
I've tried using frontend-maven-plugin to handle Node.js and NPM installation, but since we're behind a corporate firewall, it doesn't seem possible to download anything directly. It could download Node from our Artifactory though, but then failed on NPM download (I don't understand why it even downloads it as it's a part of Node package). Anyway, I gave up on this idea and decided to use Node installed locally.
Starting Tomcat
Starting/stopping a Tomcat instance for e2e testing is handled nicely by
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<url>${tomcat.manager.url}</url>
<path>/</path>
<server>Tomcat</server>
</configuration>
<executions>
<!-- Starting Tomcat -->
<execution>
<id>start-tomcat</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<!-- Fork the process, otherwise the build will be blocked by the running Tomcat -->
<fork>true</fork>
<port>${tomcat.port}</port>
<systemProperties>
<!-- We want to use the 'e2e' profile for integration testing -->
<spring.profiles.active>e2e</spring.profiles.active>
</systemProperties>
</configuration>
</execution>
<!-- Stopping Tomcat -->
<execution>
<id>stop-tomcat</id>
<phase>post-integration-test</phase>
<goals>
<goal>shutdown</goal>
</goals>
</execution>
</executions>
</plugin>
Using WebDriver (failed)
I managed to start WebDriver, but the problem is it's blocking any further execution:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<!-- Start webdriver -->
<execution>
<id>start-webdriver</id>
<phase>pre-integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>webdriver-manager</executable>
<arguments>
<argument>start</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
Running Protractor
Given that Node.js is installed and WebDriver is running, this shouldn't be a problem. But as I failed to start WebDriver so that it continues execution, this is blocked.
Any advice how the WebDriver can be managed (started/stopped)?
Adding directConnect: true to the Protractor config file solves the issue of starting/stopping the WebDriver (as suggested by Nick). In that case any explicit control of the WebDriver has to be removed from the POM.
Available parameters are explained in detail in the reference configuration file.
I'm trying to integrate Karma with Maven using the 1.6 plugin but it fails and states that:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Results :
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] --- maven-karma-plugin:1.6:start (default) # amm ---
[INFO] Executing Karma Test Suite ...
cmd /C C:\Dev\Workspaces\projectname\subname/src/main/webapp/node_modules/.bin/kar
ma start C:\Dev\Workspaces\projectname\subname\src\main\webapp\karma.conf.js --bro
wsers Chrome, Firefox --single-run --no-auto-watch --colors true
The system cannot find the path specified.
Here are my settings in the maven pom.xml:
<plugin>
<groupId>com.kelveden</groupId>
<artifactId>maven-karma-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
</executions>
<configuration>
<karmaExecutable>${ammWorkspaceDir}/src/main/webapp/node_modules/.bin/karma</karmaExecutable>
<configFile>${ammWorkspaceDir}/src/main/webapp/karma.conf.js</configFile>
<browsers>Chrome, Firefox</browsers>
<autoWatch>false</autoWatch>
<singleRun>true</singleRun>
<colors>true</colors>
<skipKarma>false</skipKarma>
<skipTests>false</skipTests>
<karmaFailureIgnore>false</karmaFailureIgnore>
<!-- <reporters>dots,junit</reporters> -->
</configuration>
</plugin>
I did a check using the cmd dir to see if the node_modules folder contains the .bin folder but it only contains:
karma
karma-chrome-launcher
karma-firefox-launcher
karm-jasmine
Where is the .bin folder? Note that I can run all the normal tests but I have to navigate to where the karma.conf.js file is to run them and can run the tests using karma start (they all pass).
So why is this failing? Is karma installed in the wrong place? Should node and such be present as a System variable?
Thanks
I figured out the problem. What was causing the build issue was the fact that the karma node_modules was interfering with the build. To get around this I had to remove the node_modules from the webapp folder and move it into the root directory of the project, as well as the karma.conf.js file.
That was the first part - the second part was to install karma globally using this command:
npm install -g karma && npm install -g karma-cli
By doing this you should beable to run karma from anywhere but that wasn't the case for me and I still don't know why (elaborate anyone?). The final part was in the actually maven pom.xml:
<plugin>
<groupId>com.kelveden</groupId>
<artifactId>maven-karma-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
</executions>
<configuration>
<configFile>karma.conf.js</configFile>
<browsers>Chrome</browsers>
<autoWatch>false</autoWatch>
<singleRun>true</singleRun>
<colors>true</colors>
<skipKarma>false</skipKarma>
<skipTests>false</skipTests>
<karmaFailureIgnore>false</karmaFailureIgnore>
</configuration>
</plugin>
The key point above is that I haven't included the <karmaExecutable> command here because if you include that then it will break - by keeping it out it will turn to the global karma install to run the tests in the Maven build. This worked for me - hope it works for you.
Here is what my build plug in stanza looks like:
<plugin>
<groupId>com.pyx4me</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.0.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<options>
<option>-dontshrink</option>
<option>-dontnote</option>
<option>-allowaccessmodification</option>
<option>-dontskipnonpubliclibraryclasses</option>
<option>-dontskipnonpubliclibraryclassmembers</option>
</options>
<libs>
<lib>${java.home}/lib/rt.jar</lib>
<lib>${java.home}/lib/jsse.jar</lib>
</libs>
</configuration>
</plugin>
Here is what I get from execution of mvn clean package
[proguard] Error: You have to specify '-keep' options for the shrinking step.
How do I specify the keep options for a library where I just want obfuscation?
You must define with the -keep option the entry points of your application, because you can't obfuscate it. For example if your main class is obfuscated it will be renamed and you won't be able to launch it. The same for public interfaces of your APIs.