I'm trying to create a simple web application using create-react-app and Spring Boot, but spring can't find index.html in resources.
React's build folder is copied to target by maven-resources-plugin:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
...
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
...
<outputDirectory>${basedir}/target/classes</outputDirectory>
<resources>
<resource>
<directory>src/main/app/build</directory>
<filtering>true</filtering>
</resource>
</resources>
...
</plugin>
This is my project structure:
Controller:
#Controller
public class BasicController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public String index() {
return "index";
}
}
Get request to localhost:8080 returns 404. Could you please point me where am i mistaken.
UPDATE:
Managed to make it working by changing React's build output directory in maven plugin to
${basedir}/src/main/resources/META-INF/resources
and return "index" to return index.html.
Well, it's maybe not the precise answer your question, but I would try example from the docs.
Spring Boot will automatically add static web resources located within any of the following directories:
/META-INF/resources/
/resources/
/static/
/public/
In the case of the Consuming a RESTful Web Service with jQuery guide, we included index.html and hello.js files in the /public/ folder. This means that not only does Spring Boot offer a simple approach to building Java or Groovy apps, you can also use it to easily deploy client-side JavaScript code and test it within a real web server environment!
Just copy the content of CRA build directory to Spring Boot public directory (make sure index.html is at the /public/index.html).
If this works then try to automate the process.
I had the same issue. Spring boot backend with reactjs frontend. I solved it by adding a view resolver (thymeleaf) and copying the generated react build resources to outputDirectory/templates directory like below
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>generate-resources</phase>
<configuration>
<target>
<copy todir="${project.build.outputDirectory}/templates">
<fileset
dir="${project.basedir}/src/main/javascript/build" />
</copy>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
Related
I am working with Spring Boot 2.2.5 and Java 8.
I have a Spring Boot webservice that I deploy and run as a linux service using the embedded Tomcat in Spring Boot.
During my Maven build, I generate code coverage metrics using the JaCoCo Maven plugin, and I would like to package and host these static HTML pages when I deploy to my server.
The output for these files is target/site/jacoco/index.html.
I know that you can deploy and host webpages through Spring Boot, but I have never accomplished it, and everything I lookup online seems to be more complicated than what im actually trying to do. The only thing i seem to have gathered so far, is that it need to get the html into my /resources directory.
Does anyone know how I can package all of the JaCoCo generated html pages into my .jar file, and host it on my webserver so that I can access it in a similar fashion to how I access any other API in the app?
I build and deploy the app with Jenkins. So if there is some nifty Jenkins way of doing it through my Jenkins.groovy script, that would be nice too.
I would like to be able to access something like: localhost:8080/my-app-context/coverage
Well, after some more digging and the right google questions, the solution was simpler than I thought. I stumbled across this article from Baeldung.
The goal:
get target/site/jacoco into the src/main/resources/static directory
get target/apidocs into the src/main/resources/static directory
The challenge:
Do it during a Maven/Jenkins build only.
The solution:
Use a Maven plugin to move the files after successful build
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<id>copy-javadocs</id>
<phase>install</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/src/main/resources/static/apidocs</outputDirectory> <!-- output directory -->
<resources>
<resource>
<directory>${basedir}/target/apidocs</directory> <!-- source directory -->
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
<execution>
<id>copy-jacoco</id>
<phase>install</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/src/main/resources/static/jacoco</outputDirectory> <!-- output directory -->
<resources>
<resource>
<directory>${basedir}/target/site/jacoco</directory> <!-- source directory -->
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
After putting the above code in my pom.xml, once the app is deployed to my server, both my JaCoCo coverage and my JavaDoc static html pages can be accessed at:
<context-root>/apidocs/index.html
<context-root>/jacoco/index.html
I hope this simplifies it for others looking to do the same.
We have to customize hosts file in our dynamically generated Elastic Beanstalk instance of our Spring Boot application during our GitLab CI/CD pipeline. To do this, we need to provide a .ebextensions directory with a config file that looks like this:
commands:
01_add_hosts:
command: echo 123.12.12.123 myhost.com >> /etc/hosts
Since we have a spring boot application, we have to package .ebextensions at the root level of our fat jar. So, basically we unzip the jar, add the ebextensions directory and zip it back. This way we successfully achieve the Beanstalk customization in our Gitlab pipelines.
However, to make this process we use maven-antrun-plugin like this:
<!-- Bundle .ebextensions inside jar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>prepare</id>
<phase>package</phase>
<configuration>
<tasks>
<unzip src="${project.build.directory}/${project.build.finalName}.jar" dest="${project.build.directory}/${project.build.finalName}" />
<copy todir="${project.build.directory}/${project.build.finalName}/" overwrite="false">
<fileset dir="./" includes=".ebextensions/**"/>
</copy>
<zip compress="false" destfile="${project.build.directory}/${project.build.finalName}.jar" basedir="${project.build.directory}/${project.build.finalName}"/>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
The problem is that maven-antrun-plugin is and old plugin from 2014 and this looks like not the proper way to achieve this bundle jar.
Do you how or what it is the spring boot way to create this bundle jar? I mean add directories/files at the root level of the jar in spring boot? Bear in mind that we bundle this at our pipeline job time that deploys through AWS Beanstalk maven plugin.
The Build Helper Maven Plugin can be used for this. Create a folder .ebextensions in the project's root and add the plugin to the <build><plugins> section of the pom.xml:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-resource-ebextensions</id>
<phase>generate-resources</phase>
<goals>
<goal>add-resource</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>${basedir}/.ebextensions</directory>
<targetPath>.ebextensions</targetPath>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
Is it required that you upload only a jar to elastic beanstalk? The way we do it is that we upload a zipfile, containing our fat jar, a .ebextensions directory and a Procfile. This way the ebextensions get applied and the Procfile contains the command to start the java process.
So for example you could upload hello-world.zip containing:
.ebextensions:
hosts.config
hello-world.jar
Procfile
With Procfile being a text file containing:
web: java -jar hello-world.jar
If you do it like this, there's no need to embed your ebextension files in your application jar, which makes things a whole lot easier in my opinion.
Procfile documentation
I have a multimodule maven application that has the following structure:
main-project
->submodule1
->src->main
->java
->MainClass.java
->resource
->php
index11.php
file12.php
file13.php
->submodule2
->src->main
->java
MainClass.java
->resource
->php
index21.php
file22.php
file23.php
->submodule3
->src->main
->java
MainClass.java
->resource
->php
index31.php
file32.php
file33.php
->web-app
->src->main
->webapp
Java classes from submodules should access the php files in their resource directories and execute it using Quercus Resin. However, when the project is packed in war, submodules are packed into jar file that are stored in web-app/WEB-INF/lib, which makes it impossible to execute php files. As workaround for this problem, I found solution to copy all php files from the submodules into the web-app, so when it's extracted in Tomcat, it's not inside jar file and could be executed. For that purpose, I'm using maven-remote-resources-plugin, and all php files are stored to web-app/src/main/webapp/php.
The problem I have now is how to properly provide path to these php files from java classes inside submodules.These java classes are inside jar files when application is deployed to Tomcat, but during development I'm using embedded Jetty server, so I need solution that would work in both cases.
If I use class loader to get resource,e.g. getClass().getClassLoader().getResource("/php/index11.php").getPath() it returns absolute path to the submodule1.jar file.
Any idea how to solve this issue?
I managed to solve this problem, so I will post solution here if it might help someone else.
In each submodule I have a maven-remote-resources-plugin bundle to collect all resources I need
<build>
<plugins>
<plugin>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<goals>
<goal>bundle</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>**/*.php</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
Then, in web-app submodule I'm using maven-remote-resources-plugin process to copy these php files to resource directories called WEB-INF/php/submodule-name
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.5</version>
<configuration>
<resourceBundles>
<resourceBundle>org.au.morph.offline:morph-sample:${project.version}</resourceBundle>
<resourceBundle>org.au.morph.offline:morph-project:${project.version}</resourceBundle>
</resourceBundles>
<outputDirectory>src/main/webapp/WEB-INF</outputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
</execution>
</executions>
</plugin>
Finally, I created a utility method that resolves the correct path to this directory both when I run application from IDE or in the Tomcat:
public static String getWebContentPath(String contextPath) throws UnsupportedEncodingException {
String path = PathUtils.class.getClassLoader().getResource("").getPath();
String fullPath = URLDecoder.decode(path, "UTF-8");
if(fullPath.contains("/WEB-INF/classes")){
String pathArr[] = fullPath.split("/classes/");
fullPath=pathArr[0];
}
String reponsePath = "";
reponsePath = new File(fullPath).getPath() + File.separatorChar + "php"+File.separatorChar+contextPath;
return reponsePath;
}
My app uses Spring Boot on the back end and a SPA (Angular) site on the front end. Currently I am serving the index.html page from the webapp folder, which works automatically no configuration needed. Now I integrated a build process for the front end using gulp and all the created sources are "copied" into a build directory. Now I would like to serve the index.html file from the build directory as my main page.
I tried spring.application.index=build/index.htmland some other spring boot settings, but nothing worked. I believe no code is needed from my current code base but if anything is missing let me know.
Is there a way to configure this in the applications.properties file? Do I need to create a controller for the index page? Or is there any other way to change the default behavior?
thanks
Going by the common Spring Boot properties, you should be able to modify this property:
spring.application.index=
Admittedly, I do tend to create a minimal 'home' controller with a #RequestMapping("/") anyway. :)
It's worth noting that the build directory will only be on the classpath if it's under src/main/resources. It's also worth mentioning that the contents of src/main/webapp don't get bundled into the jar automatically. src/main/resources/static is where Spring Boot will look for your static web files. As such, there are a couple of alternatives for you.
Option 1: Configure your Grunt build to output to a directory under src/main/resources/static.
Option 2: Configure your Java build tool to take the Grunt output and put it in your resources directory, so that it's on the classpath. For example, using Maven, the following would move the contents of a directory called build into your src/main/rescources/static.
<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>${basedir}/target/classes/static</outputDirectory>
<resources>
<resource>
<directory>build</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
I am using gwt-maven-plugin and eclipse to create GWT+Spring webapp. In the end I want to get .war file to be deployed to some application server(tomcat etc). The problem is that the generated .war file has strange structure.
And then I run in on Tomcat the application doesn't work - SimpleGWT.html page has a link to javascript file which does all the job
<script type="text/javascript" language="javascript" src="SimpleGWT/SimpleGWT.nocache.js"></script>
My guess is that since the SimpleGWT.nocache.js in located inside SimpleGWT folder which is not inside WEB-INF - it is not accessible
Is there any way to alter options of gwt-maven-plugin in order to get normal webapp structure? Here is part of my pom.xml
<!-- GWT Maven Plugin -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>2.6.0</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<!-- Plugin configuration. There are many available options, see
gwt-maven-plugin documentation at codehaus.org -->
<configuration>
<inplace>true</inplace>
<runTarget>SimpleGWT.html</runTarget>
<hostedWebapp>${webappDirectory}</hostedWebapp>
<i18nMessagesBundle>com.javacodegeeks.gwtspring.client.Messages</i18nMessagesBundle>
</configuration>
</plugin>
Its the issue that is mostly related to access static resources in an HTML page.
You are using relative path that does not have a "/" prefix. That is an absolute path
pointing to the root of the web-server.
In Spring MVC application org.springframework.web.servlet.DispatcherServlet is responsible fore serving all the contents for web apps.
What have you defined as url-pattern for above servlet mapping? Please try with *.html or /* as url-pattern.
For more information read about Unable to load java script files in Jetty webapplication.