How to find resource path in maven multimodule application - java

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;
}

Related

Use Maven Replace Plugin to replace a phrase on a generated Java file inside Target/generated-sources

I spent hours on this problem, searching several Google and SO entries, I have some ideas but not getting the result.
I have a maven file that does something like this:
grab a jar containing JSON schemas, and unpack them.
Using the Maven Replacer plugin (v 1.5.3), replace a line in a schema file called “MySchema.json” as such:
”Hello” :
”HelloWorld” :
then Maven would use another plugin to compile a class called “converter.java” and runs this class to output a Java file based on “MySchema.json”. let’s call the generated Java file “MyPojo.java”.
Now, I want Maven to replace a line in “MyPojo.java”, but no matter what I do I cannot achieve this.
I tried:
include a separate replace plugin entry for step 4 after the plugin that converts schemas to Java, but ofcourse this caused Maven to complain about existing replace plugin with same artifact/group id from step 2.
Tried adding a separate execution id to the goal “replace” for second plugin, this is invalid for this plugin.
There is a parent project to my current project folder, I tried putting another replacer plugin in the parent POM and make the phase to be any of the “package”, “generate-resources”, “compile”, etc. did not work. Note: the phase for replacements inside “MySchema.json” (in my current project POM) is generate-sources.
give absolute path to the Java, it kept complaining that path does not exist. But I copied and pasted the path to the Java inside windows explorer address bar after it was generated and could read it from Windows explorer. Note that the generated Java file “MyPojo.java”, went under “target/generated-sources” which is sourced by a parent POM above this project using a Maven Helper plugin in parent POM, so this folder should be visible as a source for further compilation. That Maven Helper plugin has phase generate-sources.
Use with same result as above
In my current project (non-parent one) this is the POM code:
<build>
<!—execute a plugin grab schemas jar and unpack schemas-->
...
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.3</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>${project.basedir}/target/schemas/MySchema.json</include>
</includes>
<replacements>
<replacement>
<token>"Hello":</token>
<value>"Hello World":</value>
</replacement>
</replacements>
</configuration>
</plugin>
<!-- execute a Plugin for converting shcemas to POJO -->
. . .
</plugins>
</build>
</project>
You should be able to declare the plugin only once and run two replace execution at different Maven Build Lifecycle phases:
Before the Json -> POJO conversion
After the Json -> POJO conversion
So, translating that into could would result in something like:
<plugin>
<!-- (unique) plugin declaration -->
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>maven-replacer-plugin</artifactId>
<version>1.3.5</version>
<executions>
<!-- first execution: replace on json file -->
<execution>
<id>replace-for-json</id>
<phase>some-phase-before-conversion</phase>
<goals>
<goal>replace</goal>
</goals>
<configuration>
<filesToInclude>${project.basedir}/target/schemas/MySchema.json</filesToInclude>
<preserveDir>true</preserveDir>
<outputDir>target</outputDir>
<replacements>
<replacement>
<token>"Hello":</token>
<value>"Hello World (Json)":</value>
</replacement>
</replacements>
</configuration>
</execution>
<!-- second execution: replace on java file -->
<execution>
<id>replace-for-pojo</id>
<phase>some-phase-after-conversion</phase>
<goals>
<goal>replace</goal>
</goals>
<configuration>
<filesToInclude>${project.basedir}/target/generated-sources/MyPojo.java</filesToInclude>
<preserveDir>true</preserveDir>
<outputDir>target</outputDir>
<replacements>
<replacement>
<token>"Hello":</token>
<value>"Hello World (Java)":</value>
</replacement>
</replacements>
</configuration>
</execution>
</executions>
</plugin>
Source: Configuration for the maven-replacer-plugin on two separate executions

How to start java app from Maven in non-base project folder?

I'm using Intellij Idea 14 and start learning embedded Maven installation.
At now Maven compile sources, generate JAR with MANIFEST.MF inside (with 'lib/' prefixes in 'Class-Path') to 'target/', copy dependencies at 'target/lib/' folder, copy folder 'src/main/resources/cfg' to 'target/cfg'.
If i manually go to folder 'target' and start app with 'java -jar app.jar' then it works fine and successfully find folder 'cfg', but if i start app from Idea then app triyng to search folder 'cfg' in base project folder.
There is some POM piece:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable>
<workingDirectory>${project.build.directory}\</workingDirectory>
<mainClass>app.Main</mainClass>
</configuration>
</plugin>
I looked at workingDirectory parameter [ http://www.mojohaus.org/exec-maven-plugin/exec-mojo.html ]. This won't work.
How can i change working folder to 'target'? This is for comfort app develop and run/debug right from Idea.
I need to get that result application structure:
/app.jar
/cfg
/cfg/application.cfg

Maven Shade External Properties file relative to final Jar

Hi all!!
Sorry if this is a dumb question, but I'm new to Maven and have reached an impasse!
I have a project which uses MyTest.properties, MoreMyTest.properties.
I use the Maven Shade plugin to build this project into a .jar file, which is working fine! Unfortunately, the shade plugin is packaging MyTest.properties inside my jar file.
Then, I get this error when I try to execute the jar.
java.io.FileNotFoundException: Unable to locate: properties/MyTest.properties at file:\C:\Dev\test.jar!\properties\MyTest.properties
at ...
I'm wanting to access my properties both inside my IDE, and by running the jar from the command line when I deploy. I was thinking of having my properties files in a relative folder ../lib/ above the location of my jar file.
Inside my program I want to access the properties like so:
File testProperties = new File(
ClassLoader.getSystemResource("properties/MyTest.properties").getFile()
);
I tried adding this to my POM.xml
<transformer
implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
<resource>*.properties</resource>
<file>../*properties</file>
</transformer>
(Sorry the formatting got messed on the above code snippet!)
But, it's not working. I'd really appreciate any help in this. I've not posted all code as the code is really big, but I hope you can get an idea of what I'm trying to achieve.
Many thanks,
Paul
Ok, I have a solution. Always the way, just after posting! But thanks for your reply.
<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>../lib</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>

Include the external jar files in my project

I'm developing a Java SE application with Netbeans IDE.
I added external jar files to the project.
After my project is compiled, these external jar files will be in the lib folder, next to the jar file.
I want to use jar in jar solution. So the external jar files are included in my project's runnable jar file.
Is any standard method to solve this problem? Or this is not a good solution?
Thank you!
I'm pretty sure that Java doesn't support embedded Jars. I'd recommend moving the lib out to the file system (so that it creates a sub folder ./lib within the same drctory as your executable Jar & see if that makes a difference.
If you really want to use embedded Jars, you could take a read of One-Jar
You should have a directory structure of
Example below
.\JarTest2.jar
.\lib\log4j-1.2.17.jar
You might wanna try One-JAR™; and if your project is Maven-based:
<build>
<plugins>
<!-- other plugins omitted for brevity -->
<plugin>
<groupId>org.dstovall</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<executions>
<execution>
<configuration>
<attachToBuild>true</attachToBuild>
</configuration>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

maven: how to include annotation-generated .java files in the .jar

I have some java 7 annotation processors (for xtend) on my class-path. Via some annotations they create java files.
This works great, in Elipse and in the Maven build.
The generated files end up in target/generated-sources/annotations as expected.
The corresponding generated .class files also end up where expected and are thus part of the final jar file.
Since I need to also include all java source files in my .jar file (there should be only one .jar file with the sources and classes) for GWT,
I have specified src/main/java as a resources dir (so that Maven copies the files to the classes dir and they end up in the jar file).
the trick with the resources directory does not really work for my generated files, because Maven will first copy all resources and then start the compilation (which in turn will generate the .java files via the annotation processors).
How can I tell Maven to copy also include the generated .java files in the .jar?
You can bind the maven-resources-plugin to the prepare-package phase to achieve copying annotation sources before packaging proper:
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-annotations</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>target/generated-sources/annotations</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
I hope that helps.
Cheers,

Categories