Spring Boot classpath - java

In the Spring Boot's docs here, about serving static content, it says:
By default Spring Boot will serve static content from a directory
called /static (or /public or /resources or /META-INF/resources) in
the classpath.
I found that all the content in the directory:
src/main/resources
will be copied inside the classpath, so I can put my static content in:
src/main/resources/static
and all will work fine and I'm happy since I can have my static content under the src directory.
But, I have some questions about this:
Why the documentation doesn't say to put static content in src/main/resources/static instead of speaking about the classpath (I think this is a bit confusing)?
Is it good to assume that the content in src/main/resources/ will be always copied in the classpath?
Is there some Spring Boot official documentation explaining what I'm supposed to find in the classpath other than Java classes and packages (up to now I only know I can found all the content from src/main/resources/)?

/src/main/resources is a Maven project structure convention. It's a path inside your project where you place resources. During the build step, Maven will take files in there and place them in the appropriate place for you to use them in your runtime classpath, eg in an executable .jar, some physical file system location used in the classpath (with java's -cp option), etc.
I could choose to build my application myself or with a different build tool. In such a case, /src/main/resources would not exist. However, the intention is for the classpath to be the same, ie. to contain the same resources and .class files.
The Spring boot documentation talks about the classpath because it shouldn't make assumptions about how your project is set up.

The classpath also contains additional libraries (JARs), which also can have a static folder, which would then be included for serving static resources. So if the documentation would only state the folder src/main/resources/static, it would be incomplete.
Ad 2: As long as you don't mess with the default Maven configuration, then it's safe to assume this.
Ad 3: Maybe start with the official Oracle documentation: https://docs.oracle.com/javase/8/docs/technotes/tools/windows/classpath.html. Hint: Of course, it's not only the contents of the resources folder, which are in the classpath, but also of course all compiled classes, hence its name.

To add to previous answers, it's the Spring Boot Maven Plugin (spring-boot-maven-plugin in the pom.xml) that that enables you to run the application using Maven. One of its functions is to ensure contents in the app including dependency libraries are available on the runtime classpath, such as within the the executable JAR file.

Related

Classpath in java and spring

I am majorly confused about where the classpath is. I understand when we create a spring mvc, resources folder, or inside web-inf is considered classpath. And we can use "classpath:" inside xml files to declare the folder. However, where is this classpath exactly? How is it set ? I have been reading about it for a long time, i still couldnt manage to get a real clear image in my head how the classpath is initially determined etc.
For example when we create a war file, and deploy it on a tomcat server, all the resource files can still be read via given paths with "classpath:" in the xml files. How does this work?
Thanks.
Ok, if it's web application, the classpath begins in WEB-INF/classes. Also, jar files in WEB-INF/lib are also on the classpath.
The Classpath is where the JVM will look for class files and other resources. Since you are using Spring MVC, I assume you are deploying a Web application (ie WAR file). This means that the classpath is set by the container which is following the Servlet spec.
The classpath for a WAR file includes the WEB-INF/classes and WEB-INF/lib folders. The Java EE/Servlet container where the WAR file is deployed will also include other common folders in the classpath.
Here is how Tomcat works.
You might also want to try this StackOverflow article/answer

Java WAR deployment issue

I've built a basic Java Web Project using Netbeaans, which uses Maven.
The issue is, in my 'dependencies' I see 'javaee-web-api-6.0.jar'. However, when I build the project, in the .war file I don't see this .jar file included anywhere.
Am I missing something, or is there any extra step that I need to take to have all the dependencies be included in the .jar?
Servlet API dependencies should never be in the resulting war file. It is a dependency that is provided by your container. Having it in the war file would only result in a bunch of classloader issues. Most containers would ignore the jar file anyway, if it was present inside the war.
Check the scope of javaee-web-api-6.0.jar dependency. If its provided then it will not be bundled into the resultant war.
javaee-api-6.0.jar and servlet-api-3.jar These jars are already provided by Tomcat(assuming using tomact). To verify this look in <TOMCAT_HOME>\lib to see that these jars are already there.

What is the Maven idiom for accessing configuration files?

For example suppose I'm using the standard project structure and have
src/main/config/config.xml
To access this I presume
new File("src/main/config/config.xml");
would be incorrect
There is no "Maven Idiom" for accessing configuration files. Maven is a build platform, not an execution platform. So the conventions for accessing configuration files that apply are really just the conventions of the Java platform that you are using; e.g.
the plain J2SE way of doing it, or
the J2EE and/or webapp way of doing it, or
the J2ME way of doing it, or
...
Maven only comes into the picture because you (presumably) have resource files in your project / version control that need to be included in the JAR or WAR or whatever artifacts that you are building. To get this to work in Maven, you simply need to understand how Maven copies non-Java files into the artifacts.
In the simple (JAR) case, the default behavior is to copy anything in src/main/resources/ into the JAR, with the same relative name; e.g. src/main/resource/foo/bar.xml becomes /foo/bar.xml in the JAR file.
For WAR files, the default is to copy anything src/main/webapp to into the WAR file. So if you wanted a file to be accessible in the webapp as a classpath resource with the name /foo/bar.xml you would put it in src/main/webapp/WEB-INF/classes/foo/bar.xml. (I'm assuming that you know how webapp classpaths work ... or that this isn't your use-case.)
A config file is just a resource on your classpath like any other, so use:
URL resource = getClass().getResource("config.xml");
You'll need to do the usual Use as Source Folder on your src/main/config folder for this to work in Eclipse with m2e.
I think config files should be in src/main/resources by default.

How to access a XML file in a maven project so it stays available when packaged

I currently started working on a maven web-app project that needs to be launched with the jetty:run-exploded goal for development/debugging in eclipse.
Now, I have an XML file which contents I need to access at runtime. My problem is: where to put the file so that the code that does the reading works both in "exploded" and packaged (i.e. in the WAR) mode?
Putting the file in src/main/java (so as to be in the classpath) won't cut it since maven filters out all non-java files on packaging.
When the file is in src/main/resources, one mean would be to figure out the root path of the project (during eclipse development) and look into that directory - but this won't be the case anymore when the project will be packaged.
Of course I could go into writing code that tries to read the file from both locations, but this seems rather cumbersome. Any suggestions?
Files in src/main/resources are copied to the target/classes directory and are available on the class path. Just read them from the class path. As explained in How do I add resources to my JAR? from the maven documentation (with a test resource here):
In a unit test you could use a simple
snippet of code like the following to
access the resource required for
testing:
...
// Retrieve resource
InputStream is = getClass().getResourceAsStream("/test.properties" );
// Do something with the resource
...
In such case I put the file under src/main/resources directory and use Spring's ClassPathResource. This way the file is accessible in IDE, during Maven build process and in runtime.

What are some additional directory conventions for Maven projects?

Maven 2 uses a standard directory layout for projects, documented here:
http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html
What I'm wondering is: are there recommended conventions for other projects besides the plain-vanilla Java library, Java EE and WebApp projects? Specifically, where to place ant files, start scripts, configuration files, sample applications, etc.
In addition, what is the convention for placing files outside of the src/ directory tree? For example, is it common to place documentation under doc/ (as sibling of src)?
Is there a page where these conventions are compiled? If not, can other readers provide examples from their own projects?
The main folder I place extra config files in is under src/main/java/resources. Usually I created sub directories under there. The tests can have their own config files src/test/resources.
You can use directives in the build section of the pom.xml to specify additional resources directories and where to copy files to specific places in the target directory. Usually a convention arises for the language or framework you are trying to use. In which case the mess can be hidden in a parent pom.xml
See http://maven.apache.org/pom.html#Resources
I don't think there is an official layout for desktop applications, but this is the layout we use for ours.
src/main/config - Config files, copied and filtered to ${project.build.directory}/config.
src/main/scripts - sh, bat, README and other plain-text files that are copied and filtered to ${project.build.directory}.
src/main/bin - Binary files that are not filtered and copied to ${project.build.directory}.
src/main/build - Any additional scripts, ant files, or resources used by the build process but not included in the application.
src/main/assembly - Assembly descriptor to create application assembly.
Copy dependencies to ${project.build.directory}/lib using maven-dependency plugin.
Bonus points if you use a shared assembly descriptor jar which includes the config and lib directories along with standard file types to share with all your projects. A good set of default file types to include is .sh, .bat, and .exe with executable permissions; .jar, .zip, .txt, .pdf, .xml, .properties, .conf, .ico, .png, .jpg with standard permissions.
Add the config directory and lib/ prefix to the classpath using the maven-jar plugin to make a runnable jar.
Add a installer profile that builds an assembly of your application using the maven-assembly plugin and your assembly descriptor. This assembly can then be consumed by a separate installer project if needed.
Avoid putting anything else at the src/ level. Instead put documentation inside the src/site/ directory (eg. src/site/sphinx) or src/doc if you really need to.
Put all the above configuration in a parent/corporate pom to share with all your projects. Simply reference the maven-dependency, maven-resources, maven-jar, and maven-assembly plugins in you project to build an entire application with almost no configuration (don't forget to set the main-class for the maven-jar plugin).

Categories

Resources