Where exactly do I put project-defaults.yml? - java

I'm working on a Wildfly Swarm project (using Wildfly Swarm version 2017.8.1, Maven 3.5.0, OpenJDK 1.8.0_141) where users will often upload files WAY bigger than Undertow's default 10485760 bytes (10MB) max-post-size setting.
I see from other questions that what I need to change is the key swarm.undertow.servers.default-server.http-listeners.default.max-post-size.
To try this setting out, I put it on the command line when I start the jar:
java -jar project-swarm.jar -Dswarm.undertow.servers.default-server.http-listeners.default.max-post-size=4000000000
This worked. The following also works if I want to run it using the Wildfly Swarm maven plugin:
mvn wildfly-swarm:run -Dswarm.undertow.servers.default-server.http-listeners.default.max-post-size=4000000000
Using either of the above two commands I can upload files bigger than 10485760 bytes (10MB). The next step is to make this the default so that I don't have to pass it in via command line each time. The official Wildfly Swarm configuration documentation said that I should put the undertow setting in a project-defaults.yml file. This is what that looks like for me:
swarm:
undertow:
servers:
default-server:
http-listeners:
default:
max-post-size: 4000000000
The thing is, none of that documentation says WHERE the file should ultimately end up. Should it end up as part of the war, under WEB-INF/classes, or the root of the war, or somewhere else? From the wildfly-swarm examples repo on github, usually the project-defaults.yml file is insrc/main/resources`, which is where I had it originally. However, it didn't work for me. Any attempts to upload a file bigger than 10485760 bytes (10MB) fail.
I found out that anything in a maven project that is put into src/main/resources gets put into the war file's /WEB-INF/classes (and the war file itself is wrapped by the swarm jar). So, I updated my maven pom so that the project-defaults.yml would be stored in the base directory of the war file itself. This STILL didn't work.
Next, I tried putting project-defaults.yml in the swarm jar itself, rather than the enclosed war. Yet again, I could not break past the 10485760 bytes (10MB) max-post-size default.
Finally, I tried using the command line option to refer to an external yml file, like so:
java -jar project-swarm.jar -s../src/main/root-resources/project-defaults.yml
This loaded the file, but alas I was STILL STUCK at the default max-post-size of 10485760 bytes (10MB).
At this point, I'm stumped. My project-defaults.yml file might be wrong or I'm not putting it in the right location. How do I fix this so I can upload files bigger than 10485760 bytes (10MB) and specify it via the project-defaults.yml file?

For those searching for an answer to this question, you have two alternatives for placing project-defaults.yml in your project.
Use Default Location
src/main/resources/project-defaults.yml
Use Maven Resource Declaration
Place the file somewhere else, for example: src/main/java/project-defaults.yml
Then, declare it as a resource using maven inside of the build section like so:
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>project-defaults.yml</include>
</includes>
</resource>
</resources>
</build>

Related

Cannot get my features files recognized by aws device farm

I am having an issue running my cucumber project with device farm.
I am getting this error:
[TestNG] Caused by: java.lang.IllegalArgumentException: Not a file or directory: /tmp/scratchheDEgq.scratch/test-packagex5ZhYf/src/test/java/cucumber/features
I understand from this message that there is an issue with the path of the features directory in my project but locally it works.
This is how I put it in my code:
#CucumberOptions(features = "src/test/java/cucumber/features", glue = "cucumber.steps")
Should I provide a different path to device farm? What am I missing here?
Thanks
By default the src/test/java/cucmber directory(if it exists in the project) is not included the *-test.jar file. Try putting the feature files in the src/test/resources directory as shown in the Device Farm sample project.
https://github.com/aws-samples/aws-device-farm-appium-cucumber-tests-for-sample-app/tree/master/src/test/resources/LoginTest
Alternatively, you can implement the testResources tags in the pom.xml to explicitly reference another directory besides src/test/resources assuming that we're using maven:
<testResources>
<testResource>
<directory>${project.basedir}/src/test/YOUR_DIRECTORY_HERE</directory>
</testResource>
</testResources>
Check out this link for more info on the testResources tag
https://maven.apache.org/pom.html#Resources
testResources: The testResources element block contains testResource elements. Their definitions are similar to resource elements, but are naturally used during test phases. The one difference is that the default (Super POM defined) test resource directory for a project is ${basedir}/src/test/resources. Test resources are not deployed.
HTH
-James

Modify the content of a file when executing the Maven command in Unix

I'm using the Unix terminal to build Java Projects. And I have created few Shell Script(.sh) files to execute the Jar files. So those sh files contain the version name of the jar file.
So I come across on a new requirement that when I upgrade my version Of the POM by executing a maven command and simultaneously I want to change the sh file's content according to that.
As an example
content of
A.sh
#!/bin/bash
"-jar X.3.16.0.jar"
When I execute the command like
mvn versions:set -DnewVersion= X.3.17.0-SNAPSHOT
I want to change the content of A.sh to be like
#!/bin/bash
"-jar X.3.17.0-SNAPSHOT.jar"
I used to do this change manually. But in the long run it won't be a good idea. So I thought to solve this by two approaches.
Method 1
Implement a mechanism to listen to above mentioned maven command and find the specified text in the sh file and replace it.
Method 2
Implement a new Shell Script with the maven command included and find and replace the text in A.sh file. This newly implemented sh file will have an argument to take the new version.
Question:
What will be the best approach to solve this problem? If none of the above will do it please help me out.
Thank you!
You could use the filter feature of the Maven resources plugin. Usually the resources plugin simply copies files from the resources directory (default src/main/resources) to the output directory (default target/classes) and includes the files into the jar (or whatever packaging you are using). Filtering enhances this process by resolving variables within the copied files while writing them to the target directory. Variables could be all standard Maven properties or any self-defined value that is set in the pom. The current version of the project is referenced with ${project.version}.
Filtering is enabled by declaring a resource directory to be filtered. The easiest case would be to filter all resources:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
Another option is to have a separate directory for resources that should be filtered:
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/filtered_resources</directory>
<filtering>true</filtering>
</resource>
</resources>
If src/main/filtered_resources contains a file with the text
echo Version: ${project.version}
the result would be after the build
echo Version: 0.0.1-SNAPSHOT
If the filtered scripts should not be copied to the target directory but to a separate directory, the copy-resources goal of the resources plugin is useful.

Must I unpack a war file to run a single class? [duplicate]

I have a Java class which has a main and I used to run as a standalone app from the command line e.g.
java -jar myjar.jar params
I needed to repackage the code to run under apache and all my code, including the entry point class from the old jar, has ended up in a WAR file for easy deplyment into the web server.
However, I still want to be able to run it from the command line and the code has not changed and is all in there, I just can't figure out how to get it to run.
Here's what I tried...
I presumed the WAR was just like a jar, so
java -jar mywar.war params
That failed saying there was no main class defined in the manifest.
I manually added a manifest to the war and tried again, with the same effect.
I noticed that in my war I had a folder called META-INF containing a manifest.mf, so I added a line to that declaring my main class as I would to a normal manifest...
Manifest-Version: 1.0
Main-Class: mypackage.MyEntryPointClass
This gave a noClassDefFoundError mypackage.MyEntryPointClass, which is progress of a sort. That led me to believe that it was just a path issue, so I tried
Manifest-Version: 1.0
Main-Class: WEB-INF.classes.mypackage.MyEntryPointClass
I now get the same error, but with a stack trace...
Exception in thread "main" java.lang.NoClassDefFoundError: WEB-INF/classes/mypackage/MyEntryPointClass (wrong name: mypackage/MyEntryPointClass)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$100(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
I've googled for a bit but can't find anything which answers my question, and I read a couple of other questions here which are slightly different, so I thought I would post.
Java 1.5, not that I think that should make any difference.
Similar to what Richard Detsch but with a bit easier to follow (works with packages as well)
Step 1: Unwrap the War file.
jar -xvf MyWar.war
Step 2: move into the directory
cd WEB-INF
Step 3: Run your main with all dependendecies
java -classpath "lib/*:classes/." my.packages.destination.FileToRun
You can do what Hudson (continuous integration project) does.
you download a war which can be deployed in tomcat or to execute using
java -jar hudson.war
(Because it has an embedded Jetty engine, running it from command line cause a server to be launched.) Anyway by looking at hudson's manifest I understand that they put a Main class in the root for the archive. In your case your war layout should be look like:
under root:
mypackage/MyEntryPointClass.class
WEB-INF/lib
WEB-INF/classes
META-INF/MANIFEST.MF
while the manifest should include the following line:
Main-Class: mypackage.MyEntryPointClass
please notice that the mypackage/MyEntryPointClass.class is accessable from the command line only, and the classes under WEB-INF/classes are accessable from the application server only.
HTH
A war is a webapp. If you want to have a console/standalone application reusing the same classes as you webapp, consider packaging your shared classes in a jar, which you can put in WEB-INF/lib. Then use that jar from the command line.
Thus you get both your console application, and you can use the same classes in your servlets, without making two different packages.
This, of course, is true when the war is exploded.
If you're using Maven, just follow the maven-war-plugin documentation about "How do I create a JAR containing the classes in my webapp?": add <attachClasses>true</attachClasses> to the <configuration> of the plugin:
<project>
...
<artifactId>mywebapp</artifactId>
<version>1.0-SNAPSHOT</version>
...
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<attachClasses>true</attachClasses>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
The you will have 2 products in the target/ folder:
The project.war itself
The project-classes.jar which contains all the compiled classes in a jar
Then you will be able to execute a main class using classic method: java -cp target/project-classes.jar 'com.mycompany.MainClass' param1 param2
To execute SomeClass.main(String [] args) from a deployed war file do:
Write class SomeClass.java that has a main method method i.e. (public static void main(String[] args) {...})
Deploy your WAR
cd /usr/local/<yourprojectsname>/tomcat/webapps/projectName/WEB-INF
java -cp "lib/jar1.jar:lib/jar2.jar: ... :lib/jarn.jar" com.mypackage.SomeClass arg1 arg2 ... arg3
Note1: to see if the class SomeOtherClass.class is in /usr/tomcat/webapps/<projectName>/WEB-INF/lib run:
cd /usr/tomcat/webapps/projectName/WEB-INF/lib &&
find . -name '*.jar' | while read jarfile; do if jar tf "$jarfile" | grep SomeOtherClass.class; then echo "$jarfile"; fi; done
Note2: Write to standard out so you can see if your main actually works via print statements to the console. This is called a back door.
Note3: The comment above by Bozhidar Bozhanov seems correct
The rules of locating classes in an archive file is that the location of the file's package declaration and the location of the file within the archive have to match. Since your class is located in WEB-INF/classes, it thinks the class is not valid to run in the current context.
The only way you can do what you're asking is to repackage the war so the .class file resides in the mypackage directory in the root of the archive rather than the WEB-INF/classes directory. However, if you do that you won't be able to access the file from any of your web classes anymore.
If you want to reuse this class in both the war and outside from the java command line, consider building an executable jar you can run from the command line, then putting that jar in the war file's WEB-INF/lib directory.
In Maven project, You can build jar automatically using Maven War plugin by setting archiveClasses to true. Example below.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archiveClasses>true</archiveClasses>
</configuration>
</plugin>
the best way if you use Spring Boot is :
1/ Create a ServletInitializer extends SpringBootServletInitializer Class
. With method configure which run your Application Class
2/ Generate always a maven install WAR file
3/ With this artefact you can even :
. start application from war file with java -jar file.war
. put your war file in your favorite Web App server (like tomcat, ...)
Well, according to Wikipedia, with a WAR file, the classes that get loaded into the classpath are in the "/WEB-INF/classes" and "/WEB-INF/lib" directory.
You could try simply putting a copy of the classes on the root file system of the zip file (which is what a war/jar is). I'm not sure if that would work though.
You can always just create two separate files.
As an alternative option, include into the war file, the rest service to trigger the application logic via url. Deploy the war file onto any web/application server you want.
Then you can start your application via any command-line based HTTP client like curl on Linux.
The disadvantage: usually these HTTP clients are different on different OSs. Which is not critical for a lot of cases. Also you can install curl on Windows.
It's not possible to run a java class from a WAR file. WAR files have a different structure to Jar files.
To find the related java classes, export (preferred way to use ant) them as Jar put it in your web app lib.
Then you can use the jar file as normal to run java program. The same jar was also referred in web app (if you put this jar in web app lib)

Use a custom database.properties file only in production in a resthub bootstrapped maven java project running in Intellij

I am using resthub to bootstrap my spring-backbone webapp.
https://github.com/resthub/resthub.github.io/blob/master/docs/spring/layout.md#environment-specific-properties
According to https://github.com/resthub/resthub.github.io/blob/master/docs/spring/mongo.md . They already have a default database properties file.
Things work fine so far, but I have to deploy the project on heroku, which has different dbname, port & other settings.
To override default db properties provided by resthub, a file named database.properties can be created in the classpath. But I want that file to be picked only for deployment on heroku.
How shall I proceed about configuring it such that it works locally on intellij with default db properties but takes up database.properties for heroku.
I have already read about Maven Profiles, but it talks about how to have different files for different environments and I'm looking for not to have a particular file for a particular environment, instead use the default one provided in one of the resthub jars.
Update
Just went through
What is the order of precedence when there are multiple Spring's environment profiles as set by spring.profiles.active
resthub-mongodb profile is always olded, in case of production (identified by -Dprod=true), a new profile called heroku is loaded which in turns loads prod\database.properties
<context:property-placeholder location="classpath*:prod/database.properties"/>
But I guess the mongo related beans are already defined using properties defined in resthub-mongodb & hence, loading loading heroku profile to change the db properties doesn't work.
What is the solution in such a case ?
Possible Solution
For now, I ended up using one of the profile - heroku or resthub-mongodb depending on the system property.
Is there any other way ?
You can let maven handling your environements with resource configuration.
Add in your pom or parent pom :
<env>local</env>
...
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>false</filtering>
</resource>
<resource>
<directory>${basedir}/src/main/config/${env}</directory>
<filtering>false</filtering>
</resource>
</resources>
This allows you to provide multiple configuration directories ; one for each your environment : local, heroku ...
With this conf, you will be able to provide a specific database.properties file for your heroku environment while keeping resthub defaults locally (not providing custom database.properties in config/local):
src/
main/
config/
local/
heroku/
database.properties
Adding -Denv=heroku option to any of your maven command run will add all config/ directory content in your classpath. local is the default environement and used if no option is given.

Eclipse: project version as a parameter in multiple files

I am developing a project which uses versioning:
version name is typed in POM file
It is also used as a part of to-be-created .msi file name : file_[version].msi
It is used in a service name, after this project is installed from .msi
Those params are kept in locations as follows:
a).properties file as a Spring param: version=0340
b)in pom.xml <package-version>0340</package-version>
c)as a <filename><version>.wxs file, used by build.xml
d) also in the abovementioned .wxs file as a MsiProductVersion = "3.4.0" (notice the dots)
Is there a way to define a parameter in some other config file, that would populate those files with proper data, as to keep the version in one place only. Now it is easy to overlook one param, and build a 340.msi which will display 330 Service as its name. I find it difficult since not all files belong to one model (like Spring).
You can configure Maven to replace "variables" in resources. Add this to your POM:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
</build>
Now you can use ${project.version} and it will be replaced with the version from the POM in all files below src/main/resources and src/test/resources.
As for the other files, you can either use an embedded Ant task in your POM or write a small script (Ant, bash, whatever you like) that reads the POM and creates the other three files from templates.
Another option is to write a unit tests which reads all files and makes sure that they contains the correct values. That way, the version won't be updated automatically but a) the version doesn't change that often (which probably causes your problem) and b) the tests are much more powerful than what you can do in a script (they can, for example, read&update binary files).

Categories

Resources