How do I add a directory in /target to the resulting JAR with Spring Boot? - maven

I'm using Enunciate to generate REST documentation upon building a REST application. Enunicate outputs documentation to /target/docs. I would like to add the /docs directory to the resulting JAR file (and rename it) to be able to serve docs as static content.
How do I do this? I can't figure out how to get these static files (which are generated upon build) into the JAR.

I guess you can solve this by configuring the Maven plugin for enunciate and wiring it up to be run in the 'generate-resources' lifecycle phase.
Also, make sure you set the output-dir to a subdirectory of src/main/resources/static, as commented by Rob above.

I added this to my enunciate.xml to force the docs directory to be generated in a custom location which will be packaged with the .war file
<docs docsDir="target/<app_name>/docs"/>
and then maven will put the entire contents of target/ into the resulting war file package

Related

spring boot loading property file from custom folder

I need to load a property file from src/main/resources/config folder. The loading part is written in a common dependency project where we dont have any control. We are just passing the file name expressed through a dependency. The code snippet in the dependent jar is like below, the standard resource loading.
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(propertyFileName);
Spring will always look for recources under recources folder directly, in this case its unable to load the file as its in the custom folder and its not under classpath.
How do we explicitly set the custom folder as additional classpath folder?
With maven we could do something like below which works fine. Is there any OOTB way to achieve this with annotation in spring boot?
`<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/resources/config</directory>
</resource>
</resources>`
Updated
`// This works if config.properties is directly under resource folder
// What if config.properties is under resources/config folder.
// Dont say to pass argument as /config/config.properties, there are some other limitations.
// So in that case with the same approach, config should come under classpath, so that the below
// method will work always when the property name is passed.
// As mentioned earlier, we can use maven resource settings to achieve this.
// The question here is, is there any way to explicitely advise spring to load property from this folder.
// I have seen something like loader.path config, not sure that helps!
InputStream stream = SpringBootStarter.class.getResourceAsStream("/config.properties");`
Before answering, when you say: Spring will always look for recources under recources folder directly, in this case its unable to load the file as its in the custom folder and its not under classpath., this is not correct.
Spring can look anywhere on your system. Here is how you can load different properties file with Spring and Spring boot:
#PropertySource("classpath:config/common.properties") => Will look under the class path for a file located under the config folder, at the root of your classpath.
#PropertySource("file:/config/common.properties") => Will look for the file common.properties at the root of your filesystem, here under /config/common.properties.
Now, there is the question of "what is the classpath", it seems like it is worth more explanation.
The classpath is for the JVM what the filesystem is for your OS. When you execute some java code (.jar file for instance), the JVM stores all the files you specify. You can specify files when executing java -classpath /a/shared/folder,/a/dependency/app.jar,myApp.jar MainClass. (See this for some others ways: https://javarevisited.blogspot.com/2012/10/5-ways-to-add-multiple-jar-to-classpath-java.html).
Quite often, what happens for developers (before we use Spring) was this:
We develop our application, and use maven for managing the dependencies
We execute our app with the IDE, everything works just as fine, life is wonderful
We are ready to go live (in production). We generate the famous myApp.jar and try executing the application java -jar myApp.jar and... Nothing works. You have issues with java (I assume you setup the main-class in the Manifest...) and you get something like Caused by: java.lang.ClassNotFoundException: my.dependency.OtherClass...
Finally, you realize life is hard and you are not ready to go live right now. You need to have something you can execute easily.
One possible solution to this, to avoid having classpath issues is to put everything in your JAR (called in spring-boot the FAT jar) and you use java -jar myApp.jar and it is working fine.
By default, when you generate a maven project, automatically you have some folders included like:
src/main/java => your java files and packages
src/main/resources => your config files (like .properties)
src/test/java => Your java test files
src/test/resources => the resources handy for your tests
When you generate your jar (more or less every configuration you added to your maven project, but let's say it is okay), what happens is the compiler takes all the folders and files under src/main/java and src/main/resources and put them at the root of your jar. (Don't hesitate to have a look inside your jar files. This is just a Zip, you can open it, browse it, and see for yourself).
With that said, when you say How do we explicitly set the custom folder as additional classpath folder?, and you talk about a custom folder located under src/main/resources, then when you generate your Jar, the custom folder will be in jar, and therefor, in your classpath.
If you still have troubles, this actions will help you:
Unzip your jar files and check what is inside. If you don't see any config/ folder in it, maybe your Jar generation is wrong
Try using #PropertySource(...) to load properties file, in your classpath and in your filesystem, to see how it works and what you achieve
Have also a look to this:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
Don't hesitate to migrate more and more of your old code to Spring-boot, will be a lot easier for you.

What does Gradle do with the files, which are located in src/main/resources directory?

I'm trying to figure out, what Gradle does with the files, which are located in src/main/resources directory.
The processResources task, added by the java plugin to the project, copies them to the build/resources/main directory.
The content of this directory is bundled into the jar file created by the jar task that is also added by the java plugin, and the resources can thus be loaded, at runtime, by the ClassLoader.
See the documentation of the java plugin.
it might do nothing with them, but ignore them - per default (with the Android plugin) that directory is called res, only the Java plugin would take the resources directory into account (the question does not indicate which plugin is used). otherwise it would run a processResources task on them; only res/raw is not being processed (copied 1:1).

Read files within maven plugin

I am trying to create a maven-plugin that generates new files based on a template file (basically using the FreeMarker language). I can successfully generate the files if I run the maven plugin from the directory of my maven-plugin project since my plugin accesses the template file based on a relative path.
However, if I try to run the plugin in some other java project directory, I cannot find the template file. I do not want to copy the templated file into the new java project.
I searched around to see if the maven plugin can access files within itself when another project is using the plugin but wasn't successful. Most of the documentation refers to accessing the java project files, and not the maven-plugin files.
Is this even possible or is there a better approach/workaround to tackle the problem?
Edit (Directory structure):
Maven-Plugin (FileGenerator):
src
--main
--java
--FileGenerator.java (references the TemplateFile based on the path to the root project)
TemplateFile
If I run the plugin as a standalone, I am able to generate new files based on the TemplateFile. I achieve the following structure
Maven-Plugin (FileGenerator):
src
--main
--java
--FileGenerator.java
TemplateFile
NewFile1
NewFile2
However, if I run the plugin in another directory (such as part of another java project) with the command mvn myplugin:mypluginplugin:1.0-SNAPSHOT:build
Another Java Project
src
--main
--java
--AnotherFile.java
pom.xml
I get an error mentioning that the TemplateFile cannot be found. Is there a way for the plugin to reference the TemplateFile regardless of where it is run at?
Ideal Output After running plugin
Another Java Project
src
--main
--java
--AnotherFile.java
pom.xml
NewFile1
NewFile2

Deploy a embedded Jetty&Jersey war to jetty9,only can see static file?

I cteate a jetty&jersey embedded project with IDEA and Maven,I put it in Github https://github.com/Mengqi777/JettyProject. Run JettyServerStart.java start the server, in the browser address bar enter localhost:8080/dynamic, show OK, enter localhost:8080/static, show static resource file
Now I package it to a war file,and put it in jetty webapps directory. But only can see static file in brower with enter localhost:8080/static.404 Not Found Error when in brower with enter localhost:8080/dynamic
What happend?
What should I do to package this project into a war file or jar file and run it in jetty successfully?
You are doing things in your embedded-jetty usage in JettyServerStart.java that you do not declare/configure in your webapp or war file.
It's a maven project, but not declared as a webapp or war project (in the pom.xml)
Its doesn't have its WEB-INF in the right place (maven directory structure wise), which means your built war file is invalid.
The dependencies are not declared correctly for a webapp or war project (you cannot include jetty-server in a war file)
Your badly located WEB-INF/web.xml does not perform the same configuration steps as your JettyServerStart.java
You don't specify how you created your ${jetty.base} directory to support this war file?
You didn't specify what version of jetty-distribution or jetty-home you downloaded, or are attempting to work with.
The statement "and put it in jetty webapps directory" is unclear, which one? (using jetty-distribution/webapps is invalid and will cause many errors and warnings if you attempt to use it for your own webapps, there's no jetty-home/webapps, and you didn't identify your jetty-base configuration)
The way your project is declared right now, even if manually assembled, skipping maven entirely, you have no servlets, no filters, no listeners, no intializers, only a servlet spec mandated DefaultServlet on url-pattern / giving you static content. That's why accessing http://localhost:8080/static/ works, but nothing else.

CMYKJPEGImageReaderSpi not loading

I was having an issue of reading CMYK JPEG images , and have used below url as reference for solving the issue.
http://www.randelshofer.ch/blog/2011/08/reading-cmyk-jpeg-images-with-java-imageio/
I have given the configuration org.monte.media.jpeg.CMYKJPEGImageReaderSpi in the file javax.imageio.spi.ImageReaderSpi under path /META-INF/services/javax.imageio.spi.ImageReaderSpi.
This works perfectly inside eclipse and the image reader is loaded successfully.
This file is not loading when deployed , i can find the folder and the file in the generated war file in my desired jar file inside lib folder, i guess i need to add it to java classpath.
Please help me to add to classpath or if there is any other issue with it.
You need to add this file as a static resource to your build lifecycle.
For Ant or Gradle you just need to write a simple copy task (Ant task, Gradle task), for Maven you can use Maven Resources Plugin.
After that your file should appears in your app package.

Resources