I am using JNDI to read database configuration from my application's context.xml. The way I currently have this setup is to have [appname].xml in conf/Catalina/localhost. However, when I redeploy the app, this file gets overridden with an empty context file, and I have to copy the custom one back to the conf/Catalina/localhost directory. I have different database settings, etc. for my test and production servers, and so don't want to put the context file in META-INF in the WAR file, but would like to just keep it in the conf/Catalina/localhost directory. Is this possible?
Is there somewhere better to put the database configuration?
I'd also like to avoid putting the configuration in the server.xml file, although I know this is possible.
Thanks!
I would say look into using maven profiles (one for prod, one for test), and having different resource definitions for each profile. You can keep your common files in src/main/resources and then have a folder for each profile type to keep specific config files in:
src/test/resources
src/prod/resources
Then you can amend your pom to define each profile and its associated resources:
<project>
<profiles>
<profile>
<id>prod</id>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<targetPath>${project.build.outputDirectory}</targetPath>
</resource>
<resource>
<directory>src/prod/resources</directory>
<targetPath>${project.build.outputDirectory}</targetPath>
</resource>
</resources>
</build>
</profile>
<profile>
<id>test</id>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<targetPath>${project.build.outputDirectory}</targetPath>
</resource>
<resource>
<directory>src/test/resources</directory>
<targetPath>${project.build.outputDirectory}</targetPath>
</resource>
</resources>
</build>
</profile>
</profiles>
</project>
finally you can build the war using the -Pprod or -Ptest profile argument to mvn
mvn -Pprod package
Problem is that undeploy removed the webapp specific context.xml file that was installed in Catalina/localhost/.xml
If you don't want to have the file removed, you'll have to just redeploy it, not undeploy/deploy
Related
I'm trying to configure my application to have 2 build profiles: development and production. In order to do that, I created two subdirectories under the src/main/resources folder: src/main/resources/development and src/main/resources/production. Each subdirectory has its own .properties files.
<profiles>
<profile>
<id>development</id>
<build>
<resources>
<resource>
<directory>src/main/resources/development</directory>
</resource>
</resources>
</build>
</profile>
<profile>
<id>production</id>
<build>
<resources>
<resource>
<directory>src/main/resource/production</directory>
</resource>
</resources>
</build>
</profile>
</profiles>
I build the app with the command mvn install -P ${profile_here}
Maven copies the content of the folder related to the chosen profile to the WEB-INF/classes output directory, however the development and production folders are copied as well.
WEB-INF/classes
WEB-INF/classes/development
WEB-INF/classes/production
How can I solve this problem?
Thanks in advance.
The maven-war-plugin is rather limited when it comes to resources. However, you could use the maven-resources-plugin to include/exclude resources like described here: https://maven.apache.org/plugins/maven-resources-plugin/examples/include-exclude.html
I manually set the tag value in my pom.xml before I packaged my Spring web app to .war and then I manually deploy my .war file on JBOSS.
I have an test.html file in webapp folder which is sending an POST request to test if #RequestMapping methods inside my controller class are working as expected or not. I want to store the value of tag in the JavaScript variable (in test.html).
How can I fetch the value from pom.xml and store in the JavaScript variable?
Make a filtered property resource file that has ${finalName} in it, and then read that in from your classpath.
src/main/resources/config.properties:
finalName=${propContainingFinalName}
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>config.properties</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
I have a test.properties file located in: $PROJECT_HOME/src/test/resources with the following content:
hostname=${host}
I also have a main.properties file located in: $PROJECT_HOME/src/main/resources with the same content.
Then I specified the followinging lines in the pom-file of my project.
<properties>
<host>localhost</host>
</properties>
<build>
<resources>
<!-- Filter resource files -->
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
....
</build>
After executing a mvn clean install I see that the main.properties in my target folder is replaced with the localhost value. However the property in my test.properties is not...
My first idea was to adapt the resources as this:
<properties>
<host>localhost</host>
</properties>
<build>
<resources>
<!-- Filter resource files -->
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
....
</build>
When building now, the test.properties file is replaced with the localhost value, but is placed into the classes folder in the target. In test-classes, there is still the test.properties file without the replaced value...
Is there a way to also replace the value in the test-classes folder?
My idea is to work on my local server with the localhost value without specifying it as a parameter and to overwrite this value with an alternate host when performing integration tests against a test server. In this case I specify the value -Dhost=<> on our continuous integration system.
This should work (although test.properties will not end up in your classes folder and test-classes would have both test.properties and main.properties with the replaced value which I think was what you wanted but wasn't sure).
<resources>
<!-- Filter resource files -->
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<testResources>
<!-- Filter test resource files -->
<testResource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
</testResource>
</testResources>
Also, you may want to have two properties, ${host} (referenced in host.properties) and ${test.host} (referenced in test.properties), otherwise if you specify -Dhost during an integration build it will replace the value in both the host.properties and the test.properties. This way you can specify -Dtest.host to change which host you are using for integration tests but not the host that is set when you deploy.
we have a project which initially was developed to run on a linux platform, we want to customize it and use it under windows platform. It is hosted on github. Any advice on how to manage files that are shared between the two platforms but have some specificity for each one. for example configuration files that contains paths, environment variables and the like.
thanks for suggestion.
Since you have tagged maven here is the solution, use profiles to differentiate between linux and windows.
<profiles>
<profile>
<id>linux</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<envName>linux</envName>
</properties>
</profile>
<profile>
<id>windows</id>
<properties>
<envName>windows</envName>
</properties>
</profile>
</profiles>
<build>
<outputDirectory>${project.basedir}/target/classes</outputDirectory>
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
<resources>
<resource>
<directory>${basedir}/src/main/java</directory>
<includes>
<include>**/*.class</include>
</includes>
</resource>
<resource>
<targetPath>${project.basedir}/target/classes/configurations</targetPath>
<directory>${basedir}/src/main/resources/configurations/${envName}</directory>
</resource>
</resources>
<plugins>
</build>
Say suppose you have some configuration files specific to OS. and when you want to build based on the enivronment you want the file to copied to configurations directory inside class, the above code snippet copies that. For that to work you need to create 2 directories inside src/main/resoruces/configurations/linux and src/main/resources/configurations/windows. when you run maven you need to use profile like mvn package -Plinux or mvn package -Pwindows.
Summary
My JUnit tests are not finding the files they require during execution.
I'm using Maven for dependency management and compilation.
Details
All files required by the test cases are located in: src/test/resources.
For example, src/test/resources/resourceFile.txt.
To access a resource I use the following code:
URL url = getClass().getResource("/resourceFile.txt").getFile();
File file = new File(url);
But then file.exists() returns false. And the error I get is:
Tests in error:
myJUnitTestCase(tests.MyJUnitTestClass): /home/me/workspace/Project%20Name/target/test-classes/resourceFile.txt (No such file or directory)
Note, the following gives the same error (notice the removed / prefix):
URL url = getClass().getClassLoader().getResource("resourceFile.txt").getFile();
File file = new File(url);
It seems as though the files from src/test/resources are not getting copied into target/test-classes.
Any ideas?
The following questions did not help
Why Can't I access src/test/resources in Junit test run with Maven?
Loading Properties File In JUnit #BeforeClass
How to deal with the test data in Junit?
Software Versions
Ubuntu 12.04
Apache Maven 2.2.1
Java 1.7.0
Eclipse (Java EE IDE for Web Developers) Indigo Service Release 2
(truncated) Maven POM
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.groupId</groupId>
<artifactId>artifactId</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>name</name>
<build>
<finalName>name</finalName>
<directory>target</directory>
<outputDirectory>target/classes</outputDirectory>
<testOutputDirectory>target/test-classes</testOutputDirectory>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
My mistake, the resource files WERE actually copied to target/test-classes. The problem seemed to be due to spaces in my project name, e.g. Project%20Name.
I'm now loading the file as follows and it works:
org.apache.commons.io.FileUtils.toFile(myClass().getResource("resourceFile.txt"));
Or, (taken from Java: how to get a File from an escaped URL?) this may be better (no dependency on Apache Commons):
myClass().getResource("resourceFile.txt").toURI();
You know that Maven is based on the Convention over Configuration pardigm? so you shouldn't configure things which are the defaults.
All that stuff represents the default in Maven. So best practice is don't define it it's already done.
<directory>target</directory>
<outputDirectory>target/classes</outputDirectory>
<testOutputDirectory>target/test-classes</testOutputDirectory>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
</testResources>
This is actually redundant except in cases where you want to override the defaults. All of these settings are implied defaults.
You can verify that by checking your effective POM using this command
mvn help:effective-pom
<finalName>name</finalName>
<directory>target</directory>
<outputDirectory>target/classes</outputDirectory>
<testOutputDirectory>target/test-classes</testOutputDirectory>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
</testResources>
For example, if i want to point to a different test resource path or resource path you should use this otherwise you don't.
<resources>
<resource>
<directory>/home/josh/desktop/app_resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>/home/josh/desktop/test_resources</directory>
</testResource>
</testResources>
You may have defined:
<packaging>pom</packaging>
If you did this, the resources won't be present in the target directory when you will launch your tests. And mvn package won't create it either.
At the contrary, if you define:
<packaging>jar</packaging>
Or nothing as the default value is jar. As Maven is based on Convention over Configuration. You will end up with:
src/main/resources => target/classes
src/test/resources => target/test-classes
Main classes should be under src/main/java
and
test classes should be under src/test/java
If all in the correct places and still main classes are not accessible then
Right click project => Maven => Update Project
Hope so this will resolve the issue
The test Resource files(src/test/resources) are loaded to target/test-classes sub folder. So we can use the below code to load the test resource files.
String resource = "sample.txt";
File file = new File(getClass().getClassLoader().getResource(resource).getFile());
System.out.println(file.getAbsolutePath());
Note : Here the sample.txt file should be placed under src/test/resources folder.
For more details refer options_to_load_test_resources
Make 'maven.test.skip' as false in pom file, while building project test reource will come under test-classes.
<maven.test.skip>false</maven.test.skip>