How to configure File[] on Maven plugin? - java

I have a Maven plugin that expects File[] for one of its config parameters (docs: maven-failsafeplugin). How do you configure such parameter in pom.xml? Ideally, I would like to say "include all files in directory X" or "my-test-output/*.xml".

<executions>
<execution>
<configuration>
<summaryFile>path/to/file</summaryFile>
<summaryFile>path/to/file2</summaryFile>
<summaryFile>...</summaryFile>
</configuration>
<execution/>
<execution>
....
<execution/>
</executions>
Look at the usage page for more info and samples

The File[] should be reflected by some collection type element in which you can nest.
For example summaryFiles:
<summaryFiles>
<summaryFile>/topping/*.xml</pizza>
<summaryFile>/topping/special/cheese.xml</pizza>
</summaryFiles>

Related

Maven resource plugin doesn't filter out customized delimiters nested in ${}

I have a properties file:
property.a=$[value]
I am using maven-resources-plugin with filtering on this property file enabled in order to substitute build variables in there:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<delimiters>
<delimiter>$[*]</delimiter>
</delimiters>
</configuration>
</plugin>
Everything works flawlessly, until $[*] token is not nested into ${*} one, like below:
property.a=${VALUE:$[value]}
Assuming value=XXX in Maven properties, I expected to get:
property.a=${VALUE:XXX}
However, Maven resources plugin doesn't substitute $[value] in there, leaving filtered contecnts as-is. I tried enabling supportMultiLineFiltering but it changed nothing. It feels like despite <delimiters> option is set explicitly, plugin treats ${*} as a valid delimiter either, and tries to filter it, without success.
How should I configure maven resources plugin so that it filters the property file contents as expected?
I just realized I missed a configuration option in maven resource plugin, designed specially for controlling default delimiters - useDefaultDelimiters, which is true by default. The configuration below solved the issue:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<delimiters>
<delimiter>$[*]</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>

How to share/pass a variable with application properties and pom file

I have a multi module spring-boot project, before integration tests of my app, I start another child module (which is Stub made by another spring boot app) You can see it is attached to "pre-integration-test" and it is working fine finally.
Parent Pom
|
|----myRealApp module(spring boot app)
|----stub module(This is also a spring-boot app)
My question is, is there a way to randomize And share this port (not fixed to 8090), so concurrent builds on Jenkins server can run tests and not fail because address is in use already.
I know I can generate random numbers/ports in spring properties file. But couldn't find a way to pass it to Pom.
application-test.properties of myRealApp:
stub.port=8090
stub.url=http://localhost:${stub.port}/stub/api/v1/domains/
Pom of myRealApp:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>${spring.boot.mainclass}</mainClass>
</configuration>
<executions>
<execution>
<id>start-stub</id>
<configuration>
<arguments>
<argument>--server.port=8090</argument>
</arguments>
<mainClass>io.swagger.Stub</mainClass>
<classesDirectory>../my-stub/target/classes</classesDirectory>
</configuration>
<goals>
<goal>start</goal>
</goals>
<phase>pre-integration-test</phase>
</execution>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
You can do that via jenkins Port Allocator Plugin
Once you assign the port (lets say HTTP_PORT), then you can pass this as command line
-Dstub.port=$HTTP_PORT
I recommend you not to randomize at all. My suggestion is to parametrize the server port in the POM and application-test.properties files, and set a value based upon some Jenkins-provided variable: For example, BUILD_NUMBER, which is incremented on every build and thus uniqueness is guranteed.
However, there is a problem about this: You also need to enclose the port number within valid boundaries: TCP ports must be within 1024 and 65535, however BUILD_NUMBER is not limited at all.
How to cope with this? I think a simple Ant task bound to the initialize phase could read the BUILD_NUMBER value, apply it a simple formula 1024+(BUILD_NUMBER % 64512), and set it as the definitive port number variable, which is the one you will reference in the POM and application-test.properties files.

JAXB Maven generate classes using multiple episodes

Using this maven plugin, I was able to generate my classes and reused them in another schema; which is really great!
Now I find myself with a schema needing two episodes (two different packages generated from schemas). I simply tried to add another arg in XJC, but it didn't work.
Then I changed the order of the two args, and the error targetted the other schema. I then understood that both episodes were OK, but it might not be the way of doing things.
Here is some of my pom:
<execution>
<id>business</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
..
<extension>true</extension>
<args>
<arg>-b</arg>
<arg>${project.basedir}/target/episodes/x.episode</arg>
<arg>${project.basedir}/target/episodes/y.episode</arg>
<arg>${project.basedir}/target/episodes/z.episode</arg>
</args>
..
</configuration>
</execution>
And here is what I get:
org.xml.sax.SAXParseException; systemId: file:/****.episode; lineNumber: 2; columnNumber: 65; s4s-elt-schema-ns: namespace element 'bindings' must be from 'http://ww.w3.org/2001.XMLSchema'.
From what I understand (after swapping their call in ), the three schemas/episodes are good, but I cannot use them both at the same time. Any way to do that?
Newbie here, any help much appreciated :).
Author of the maven-jaxb2-plugin here.
Why do you use args, why not just add your episodes in the configuration?
<episodes>
<episode>
<groupId>com.acme.foo</groupId>
<artifactId>package1</artifactId>
<!-- Version is not required if the artifact is
configured as dependency -->
</episode>
<episode>
<groupId>com.acme.foo</groupId>
<artifactId>package2</artifactId>
<!-- Version is not required if the artifact is
configured as dependency -->
</episode>
</episodes>
The whole idea of episodes is that you can point to the JAR (containing the episode file) and XJC will find out and use the binding from the contained episode. Using arg with -b is not what it was inteded for. :)
Concerning the error you're seeing, I guess the way you configure arg makes XJC think that your second and further episodes are actually schemas. I'd try to put intermediate -b arguments or configure all the episodes you refer to in one arg.
But I still think it is not the right way to use episodes. Compile your episodes as separate JARs/separate Maven modules, use them as dependencies and either configure them as episodes or just turn on the useDependenciesAsEpisodes option.
I have done this before on another project. I think you're using the wrong syntax:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>jaxb-Generic-XSD</id>
<phase>generate-sources</phase>
<goals>
<goal>xjc</goal>
</goals>
<configuration>
<enableIntrospection>false</enableIntrospection>
<schemaFiles>Generic.xsd</schemaFiles>
<schemaDirectory>${jaxb.schema.folder}</schemaDirectory>
<packageName>you.package.name.here</packageName>
<outputDirectory>${jaxb.output.folder}</outputDirectory>
<extension>true</extension>
<arguments>-b ${core.episode.file} -b ${containers.episode.file}</arguments>
</configuration>
</execution>
</executions>
</plugin>
Note the: <arguments>-b ${core.episode.file} -b ${containers.episode.file}</arguments> line.
I think you're using the same maven plugin, but if not, then take note of the plugin version groupId, artifactId, and use it instead.

Onejar and resource loading

I have a maven project which I would like to package in an executable jar.
It's using quite a few dependencies, like spring and so on.
It was suggested in a few posts to use OneJar, to avoid a lot of headaches.
This is what I have currently in my pom.xml:
<plugin>
<groupId>org.dstovall</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<executions>
<execution>
<configuration>
<mainClass>com.cool.project.Application</mainClass>
<onejarVersion>0.97</onejarVersion>
<attachToBuild>true</attachToBuild>
<classifier>coolproject</classifier>
</configuration>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
In my Spring configuration one of the classes needs to pass the a resource (src/main/resources/coolfile.bin) path to an external library (jsch) method:
String resource = ConfigurationClass.class.getClassLoader().getResource("coolfile.bin").getFile();
jsch.addIdentity(resource);
When I run Application.java from the IDE (eclipse), the entire application loads successfully.
Although when I run mvn clean install, the onejar jar is built under the target folder, but when I try to run it with java -jar coolproject.one-jar.jar the following error is displayed:
...
Caused by: java.io.FileNotFoundException: file:/target/coolproject.one-jar.jar!/main/coolproject.jar!/coolfile.bin (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:97)
at com.jcraft.jsch.IdentityFile.newInstance(IdentityFile.java:83
If I inspect coolproject.one-jar.jar, I can find the coolproject.jar under the main folder, and if I inspect that, I can see coolfile.bin in its root.
So in theory the resource should be found? What am I missing?
Turns out that FileInputStream would not find the path specified by resource.
Luckily jsch provides another method where you can pass the byte array of the file rather than its location:
jsch.addIdentity("coolfile.bin", toByteArray(ConfigurationClass.class.getResourceAsStream("/coolfile.bin")), null, null);

Injecting Maven project information into Swing Application Framework resources?

I have a Maven project using the Swing Application Framework and would like to inject project information from the pom.xml into my application's global resources to avoid duplication.
The base application (provided via netbeans) uses Application.title, Application.version, Application.vendor, Application.description resources etc for Window titles and about box configuration but I can't find a way to set these values programatically at run time and I'm not a maven maven so don't have the skills to inject them at build time.
Anyone have any recommendations on how best to achieve the desired result?
You could try using filtered resources. If you create a property file, say src/main/resources/com/myapp/app.properties that looks like this:
version=${project.version}
name=${project.name}
id=${project.artifactId}
Them you need to enable filtering in your pom.xml:
<build>
<resources>
<resource>src/main/resources</resource>
<filtering>true</filtering>
</resources>
</build>
Now when maven builds your project, it'll expand the property file, and place it on the classpath. Then you can just call getResourceAsStream("/com/myapp/app.properties") to read it into your app.
Whist maven does automatically create a file /META-INF/maven/$groupId/$artifactId/pom.properties, this may not have all the information you need.
You can keep those in separte property file and read it from both pom.xml and your application.
Another option is to read pom.xml file from classpath (mvn will put it in META-INF folder) and parse it from there as plain xml file.
I would go with first option.
I would try using the maven-antrun-plugin. Pass the necessary maven properties to ant and create an ant build script which modifies an application properties file or the spring context configuration directly.
Another way would be to generate a separate properties file with the properties-maven-plugin and then add this properties file to the application bundle names:
For the pom.xml to write application.properties file:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>write-project-properties</goal>
</goals>
</execution>
</executions>
<configuration>
<outputFile>${project.build.outputDirectory}/application.properties</outputFile>
</configuration>
</plugin>
...
</plugins>
...
</build>
For including the application.properties into your application:
public class MyApplication extends SingleFrameApplication
public MyApplication() {
super();
addGeneratedApplicationProperties();
}
private void addGeneratedApplicationProperties() {
ResourceManager resourceManager = getContext().getResourceManager();
getContext().setApplicationClass(MyApplication.class);
List<String> bundleNames = new LinkedList<String>(resourceManager.getApplicationBundleNames());
bundleNames.add(0, "application");
resourceManager.setApplicationBundleNames(bundleNames);
}
...
}
However, I find the maven-filter-solution way more elegant.

Categories

Resources