Collect dependency information from pom.xml - maven-dependency-plugin

I'd like to print a file containing listing of all the dependencies and their versions in my pom.xml. (no need to go inside of each dependency)
My ultimate goal is to have the dependency + version information listing in a file that can be read by the application at runtime and be displayed via "version info" link on a web page.
I found out there is a maven dependecy plugin | dependency:list, which I understand, should be doing pretty much what I want. I also manage it to print an output file, but it contains mainly gibberish. What I can make sense of it, it just has some kind of listing of the packages in the project. (no version info)
Could someone please clarify how to use this plugin correctly, or if it even does what I need it to do.
My configuration is same as in their usage instructions, but if try to use any optional parameters it fails always.

This looks like it is doing the right thing now. A version file is printed in 'target/classes' and I can find it when looking from the app at runtime.
In pom.xml (in build/plugins):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>createVersionInfo</id>
<phase>compile</phase>
<goals>
<goal>list</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.company.project</groupId>
<artifactId>app-name</artifactId>
<version>${project.version}</version>
<type>war</type>
<overWrite>true</overWrite>
</artifactItem>
</artifactItems>
<sort>true</sort>
<includeScope>compile</includeScope>
<outputFile>target/classes/dependency_versions.txt</outputFile>
</configuration>
</execution>
</executions>
</plugin>
The '<excludeScope>test</excludeScope>' does not work as supposed. It excludes everything. I think the explanation for includeScope explains this somehow.
An Empty string indicates all scopes (default).
The scopes being interpreted are the scopes as Maven sees them,
not as specified in the pom. In summary:
runtime - scope gives runtime and compile dependencies,
compile - scope gives compile, provided, and system dependencies,
test - (default) scope gives all dependencies,
provided - scope just gives provided dependencies,
system - scope just gives system dependencies.
And this piece of code on the java side will do pretty much what is needed:
InputStream in = this.getClass().getResourceAsStream("/dependency_versions.txt"); // Finds the file from classpath
String content = "";
// Java7 AutoCloseable
try (Scanner scan = new Scanner(in)) {
scan.useDelimiter("\\Z"); // Found this from another SO-thread, enables to read in the whole file at once
content = scan.next();
}
// Iterate the content and collect the information
// \n = line change
for (String row : content.split("\n")) {
row = row.trim();
// Basically removes the 1st two lines of the file that are not wanted
if (StringUtils.isEmpty(row) || row.endsWith(":")) {
continue;
}
StringTokenizer tokenizer = new StringTokenizer(row, ":");
String package = tokenizer.nextToken();
String dependency = tokenizer.nextToken();
String type = tokenizer.nextToken();
String version = tokenizer.nextToken();
String scope = tokenizer.nextToken();
}
I am actually populating a list of my own TO's there for showing the info in JSF, but I omit that part for simplicity/readability.
... Actually made me think why do I want to read in the whole file at once and not iterate it and read it one row at a time, but I'll leave it for the daily WTF. ;)

Related

Maven Surefire Plugin + Spock 2: additional “test case” in the report

With Spock upgrade to 2.4-M1-groovy-3.0 we found out that test reports for our data driven tests (= using #Unroll Spock annotation) contain an additional "test case" and also counts the time of this "test case" to the total which means the total time doubles.
I searched the docs and it seems to be Spock 2's default feature to show the test results for data driven tests in a tree (e.g. when run in IDE) showing the tests hierarchy while Maven Surfire can probably show only a flat list:
Hence there is this umbrella "test case" which is quite confusing. Would anyone know how the get rid of the additional line in the report?
If I remember correctly you have to use this bit of config in your pom.xml
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<statelessTestsetReporter implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5Xml30StatelessReporter">
<disable>false</disable>
<version>3.0</version>
<usePhrasedFileName>false</usePhrasedFileName>
<usePhrasedTestSuiteClassName>true</usePhrasedTestSuiteClassName>
<usePhrasedTestCaseClassName>true</usePhrasedTestCaseClassName>
<usePhrasedTestCaseMethodName>true</usePhrasedTestCaseMethodName>
</statelessTestsetReporter>
</configuration>
</plugin>

Cannot set pagecache size with embedded Neo4J/Gremlin

I am writing a Java program that uses an embedded Neo4j graph with TinkerPop. Here's the relevant section of my pom
<dependency>
<groupId>org.apache.tinkerpop</groupId>
<artifactId>neo4j-gremlin</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-tinkerpop-api-impl</artifactId>
<version>0.7-3.2.3</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-tinkerpop-api</artifactId>
<version>0.1</version>
</dependency>
I want to add a configuration option to set the page cache size when initializing the graph. My PS Old Gen heap space is filling up.
Currently, I'm opening the Neo4j graph by passing it a org.apache.commons.configuration.Configuration object. I’m trying to set two properties, the directory and the pagecache. When I run my program, the "gremlin.neo4j.directory" property is processed, but the "dbms.memory.pagecache.size" is not, according to the graph's log file. The log file's first line is this:
2019-03-20 14:38:36.155+0000 WARN [o.n.i.p.PageCache] The
dbms.memory.pagecache.size setting has not been configured. It is
recommended that this setting is always explicitly configured, to
ensure the system has a balanced configuration. Until then, a computed
heuristic value of 8310519808 bytes will be used instead.
Using jvisualvm and jconsole, I can see that the memory in the PS Old gen is filling up with objects related to page caching so I'm trying to throttle how much data is cached by Neo4j.
Here's my code:
Configuration configuration = new BaseConfiguration();
configuration.addProperty("gremlin.neo4j.directory", "tmp/mygraph");
configuration.addProperty("dbms.memory.pagecache.size", "500m");
myGraph = Neo4jGraph.open(configuration);
Any idea what I'm doing wrong?
I think that you need to prefix your configuration keys that are Neo4j specific with gremlin.neo4j.conf thus:
Configuration configuration = new BaseConfiguration();
configuration.addProperty("gremlin.neo4j.directory", "tmp/mygraph");
configuration.addProperty("gremlin.neo4j.conf.dbms.memory.pagecache.size", "500m");
myGraph = Neo4jGraph.open(configuration);

How to override 'org.apache.cxf.stax.maxChildElements' property value inside a TomEE container?

I've got a JAX-WS web service endpoint configured purely via annotations running in TomEE 7 environment. Basically, the method being called has to return a List<String> of all node names contained in a graph data structure. The response of such a request can contain more thank 50k elements.
With CXF 2.6.x this worked fine. However, when I call the WS-method under CXF 3.x (bundled in TomEE 7.x), the following exception is thrown on the server side:
org.apache.cxf.interceptor.Fault: Unmarshalling Error: Maximum Number of Child Elements limit (50000) Exceeded
at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:906)
at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:712)
at org.apache.cxf.jaxb.io.DataReaderImpl.read(DataReaderImpl.java:179)
at org.apache.cxf.wsdl.interceptors.DocLiteralInInterceptor.handleMessage(DocLiteralInInterceptor.java:109)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:801)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1680)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1559)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1356)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:653)
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:514)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:423)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:324)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:277)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:139)
at com.sun.proxy.$Proxy51.getAllNodeNames(Unknown Source)
Caused by: javax.xml.bind.UnmarshalException
- with linked exception:
[javax.xml.stream.XMLStreamException: Maximum Number of Child Elements limit (50000) Exceeded]
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(UnmarshallerImpl.java:485)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:417)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:394)
at org.apache.cxf.jaxb.JAXBEncoderDecoder.doUnmarshal(JAXBEncoderDecoder.java:855)
at org.apache.cxf.jaxb.JAXBEncoderDecoder.access$100(JAXBEncoderDecoder.java:102)
at org.apache.cxf.jaxb.JAXBEncoderDecoder$2.run(JAXBEncoderDecoder.java:894)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.cxf.jaxb.JAXBEncoderDecoder.unmarshall(JAXBEncoderDecoder.java:892)
... 21 more
Caused by: javax.xml.stream.XMLStreamException: Maximum Number of Child Elements limit (50000) Exceeded
at com.ctc.wstx.sr.InputElementStack.push(InputElementStack.java:340)
at com.ctc.wstx.sr.BasicStreamReader.handleStartElem(BasicStreamReader.java:2951)
at com.ctc.wstx.sr.BasicStreamReader.nextFromTree(BasicStreamReader.java:2839)
at com.ctc.wstx.sr.BasicStreamReader.next(BasicStreamReader.java:1073)
at com.sun.xml.bind.v2.runtime.unmarshaller.StAXStreamConnector.bridge(StAXStreamConnector.java:196)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:415)
... 27 more
Error: Maximum Number of Child Elements limit (50000) Exceeded
So far, I've read the official CXF documentation on this issue, checked a HowTo at the TomEE website and read many related, yet older posts in forums.
I tried to set the properties - as advised by the TomEE documentation - via openejb-jar.xml in the webservice's WEB-INF folder:
<?xml version="1.0" encoding="UTF-8"?>
<openejb-jar>
<ejb-deployment ejb-name="MyWebService">
<properties>
org.apache.cxf.stax.maxChildElements = 100000
</properties>
</ejb-deployment>
</openejb-jar>
I also tried with the shorter property cxf.stax.maxChildElements to check whether this would be accepted, yet without success.
For testing/debugging, I start the TomEE instance via the tomee-maven-plugin, Therefore, I tried the set the maxChildElement property as an environment property like so:
<plugin>
<groupId>org.apache.tomee.maven</groupId>
<artifactId>tomee-maven-plugin</artifactId>
<version>${tomee.plugin.version}</version>
<configuration>
<tomeeVersion>${tomee.version}</tomeeVersion>
<tomeeClassifier>plus</tomeeClassifier>
<debug>false</debug>
<tomeeHttpPort>8181</tomeeHttpPort>
<debugPort>5005</debugPort>
<args>-Dfoo=bar</args>
<skipCurrentProject>true</skipCurrentProject>
<webapps>
<webapp>my.ws:${webservice.artifact.name}:${webservice.artifact.version}?name=ws-endpoint</webapp>
</webapps>
<libs>
<!-- Third party libraries needed in the global lib folder of TomEE -->
<lib>log4j:log4j:${log4j.version}</lib>
</libs>
<systemVariables>
<!--
special property needed to allow for more childElements in StAX Parser
-->
<org.apache.cxf.stax.maxChildElement>100000</org.apache.cxf.stax.maxChildElement>
</systemVariables>
</configuration>
</plugin>
Sadly, it has no effect on the runtime configuration of CXF/StAX (Woodstox).
Question
How can we override the maxChildElements property via a configuration in openejb-jar.xml or as an external property at TomEE startup.
Finally, I got it working with the help of Romain Manni-Bucau (credits to him for pointing me into the right direction). Yet, his original answer is not the final solution. Therefore, I give the working configuration here.
1.) Put the following openejb-jar.xml to the WEB-INF folder:
<?xml version="1.0" encoding="UTF-8"?>
<openejb-jar>
<ejb-deployment ejb-name="MyWebService">
<properties>
cxf.jaxws.properties = cxfConfig
</properties>
</ejb-deployment>
</openejb-jar>
2.) Provide a new (or add to an existing) resources.xml file, again via WEB-INF:
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<Service id="cxfConfig" class-name="org.apache.openejb.config.sys.MapFactory" factory-name="create">
org.apache.cxf.stax.maxChildElements = 100000
</Service>
</resources>
Note well the configuration link via the MapFactory object with the id cxfConfig.
3.) Configure JAX-WS clients to set corresponding property as well. For instance, given a Spring client, this can be configured like so:
<bean id="wsClientProxy" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
<property name="serviceClass" value="com.acme.ws.jaxb.MyWebservice"/>
<property name="address" value="${ws.endpoint.url}"/>
<property name="properties">
<map>
<entry key="org.apache.cxf.stax.maxChildElements" value="100000" />
</map>
</property>
</bean>
In general, this might also be useful for people trying to set other CXF-related properties as listed in the XML section of the CXF security guideline, in particular to increase or decrease conservative default values.
I tested the above configuration steps successfully under a TomEE 7.0.3 and 8.0.9 environment, yet this should also reliably work with all 7.0.x and 8.0.x releases.
For other use cases, this blog post by Romain might also be worth reading, as it covers basic configuration concepts quite well.
Hope this helps others.
You can try
-Dorg.apache.cxf.stax.maxChildElements=100000
It should also work
I think you need to define a resources.xml with a Service of type (class-name) java.util.Properties and the properties inside:
openejb-jar.xml would get this property:
cxf.jaxws.properties = cxfConfig
resources.xml would get
org.apache.cxf.stax.maxChildElements = 1
This test does it programmatically: https://github.com/apache/tomee/blob/master/server/openejb-cxf/src/test/java/org/apache/openejb/server/cxf/MaxChildTest.java

How to fork a Maven lifecycle (in the proper sense) from a plugin?

General Problem: I'm testing a web application at a large company with a service oriented architecture. External services often fail in our test environment due to background noise. This prevents integration tests for our service from running properly since our service won't work unless calls to these external services are succeeding. For this reason we'd like the ability to mock responses from external services so that we don't have to depend on them and can test our own service in isolation.
There's a tool for this called Mockey which we are hoping to use. It's a Java program that runs through an embedded Jetty server and acts as a proxy for service calls. Our web application is re-configured to call Mockey instead of the external services. Mockey is then configured to provide dynamically mocked responses to these calls depending on the URL and header data that get passed in.
In order to utilize this tool we'd like the ability to start Mockey during the pre-integration-test phase of a Maven lifecycle so that it will be available for use during the integration-test phase.
Specific Problem: In order to start and shutdown Mockey during the pre-integration-test and post-integration-test phases of the Maven lifecycle I've written a Maven 3 plugin called mockey-maven-plugin:
The mockey-maven-plugin pom.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.mockey</groupId>
<artifactId>mockey-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<version>1.3</version>
<dependencies>
<!-- Maven plugin dependencies -->
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.4</version>
<scope>provided</scope>
</dependency>
<!-- Mockey dependency -->
<dependency>
<groupId>com.mycompany.mockey</groupId>
<artifactId>Mockey</artifactId>
<version>1.16.2015</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- This plugin is used to generate a plugin descriptor
xml file which will be packaged with the plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.4</version>
</plugin>
</plugins>
</build>
</project>
The mockey-maven-plugin StartMockey class:
#Mojo(name="start-mockey")
#Execute(phase= LifecyclePhase.PACKAGE) // Not sure about this annotation
public class StartMockey extends AbstractMojo
{
/**
* Flag which controls Mockey startup.
*/
#Parameter(property="mockey.skipStartup", defaultValue="false", required=true)
private Boolean skipStartup;
// Do I need these getters and setters or does Maven ignore them?
public Boolean getSkipStartup()
{
return skipStartup;
}
public void setSkipStartup(Boolean skipStartup)
{
this.skipStartup = skipStartup;
}
// *SNIP* Defining Mockey parameters...
// Maven will call this method to start the mockey-maven-plugin
public void execute()
{
if(skipStartup)
{
getLog().info("Skipping Mockey startup");
return;
}
getLog().info("Starting Mockey");
// Load specified parameters into array
List<String> argsList = new ArrayList<>();
// *SNIP* Adding Mockey parameters to argList...
String[] args = new String[argsList.size()];
argsList.toArray(args);
// Start Mockey with specified parameters and wait for it to return
try
{
JettyRunner.main(args);
}
catch(Exception e)
{
getLog().error("Mockey died... :(");
}
getLog().info("mockey-maven-plugin now exiting");
}
}
The mockey-maven-plugin ShutdownMockey class:
#Mojo(name="shutdown-mockey")
public class ShutdownMockey extends AbstractMojo
{
/**
* Flag which controls Mockey shutdown.
*/
#Parameter(property="mockey.skipShutdown")
private Boolean skipShutdown;
// Again, Do I need these getters and setters or does Maven ignore them?
public Boolean getSkipShutdown()
{
return skipShutdown;
}
public void setSkipShutdown(Boolean skipShutdown)
{
this.skipShutdown = skipShutdown;
}
public void execute()
{
if(skipShutdown)
{
getLog().info("Skipping Mockey shutdown");
return;
}
getLog().info("Shutting down Mockey");
JettyRunner.stopServer();
getLog().info("mockey-maven-plugin now exiting");
}
}
Plugin entry for mockey-maven-plugin in my team project's pom.xml file:
<plugin>
<groupId>com.mycompany.mockey</groupId>
<artifactId>mockey-maven-plugin</artifactId>
<version>1.3</version>
<configuration>
<skipShutdown>${keepMockeyRunning}</skipShutdown>
<skipStartup>${skipMockey}</skipStartup>
<!-- *SNIP* Other Mockey parameters... -->
</configuration>
<executions>
<execution>
<id>start-mockey</id>
<goals>
<goal>start-mockey</goal>
</goals>
<phase>pre-integration-test</phase>
</execution>
<execution>
<id>shutdown-mockey</id>
<goals>
<goal>shutdown-mockey</goal>
</goals>
<phase>post-integration-test</phase>
</execution>
</executions>
</plugin>
This plugin works fine for starting Mockey in the pre-integration-test phase, but blocks the build until Mockey has exited. I'm not sure why this is occurring since I added this annotation specifically to prevent that issue:
#Execute(phase= LifecyclePhase.PACKAGE)
I actually copied this annotation from another plugin which does exactly what I'm trying to do here (We use the maven-tomcat7-plugin for launching our web application locally in the pre-integration-test phase and shutting it down in the post-integration-test phase). I thought this would work the same way, but I'm seeing a different behavior.
Here's what I want to see happen:
Maven build begins on a single thread.
This thread runs through all of the lifecycle phases from validate to package (reference) and executes all of the plugins with goals that are bound to those phases.
The thread gets to the pre-integration-test phase, sees that the mockey-maven-plugin's start-mockey goal is bound to the pre-integration-test phase, and attempts to execute the start-mockey goal.
The start-mockey goal is annotated to execute on a second thread (not the first thread) without running any other goals for any other lifecycle phases beforehand or afterwards on the new thread. The second thread starts Mockey's Jetty server by calling JettyRunner.main(args) and blocks on that method for the time being (it's running Mockey).
The first thread continues on to other goals and phases (IE: run integration tests).
The first thread gets to the post-integration test phase, sees that the mockey-maven-plugin's shutdown-mockey goal is bound to the post-integration-test phase, and executes the shutdown-mockey goal.
The shutdown-mockey goal calls JettyRunner.stopServer() which hooks into a static object inside the JettyRunner class and signals the first thread to shutdown Jetty. Meanwhile the first thread waits for a signal from the second thread (or maybe it's polling, I don't really know) that Jetty has shut down.
The second thread finishes shutting down Jetty, signals to the first thread that it can continue, and kills itself.
The first thread continues on to any additional goals and Maven lifecycle phases.
Here's what I'm actually seeing happen:
Maven build begins on a single thread.
This thread runs through all of the lifecycle phases from validate to package (reference) and executes all of the plugins with goals that are bound to those phases.
The thread gets to the pre-integration-test phase, sees that the mockey-maven-plugin's start-mockey goal is bound to the pre-integration-test phase, and attempts to execute the start-mockey goal.
The start-mockey goal is annotated to execute on a second thread. The second thread starts the entire Maven lifecycle over again beginning in the validate phase.
The first thread blocks while waiting for the second thread to exit.
The second thread runs all the way through the package phase and then kills itself.
The first thread is unblocked and picks up where it left off. It executes the start-mockey goal on its own (never run by the second thread). This calls JettyRunner.main(args) and the thread then blocks while running Mockey's Jetty server.
The thread remains blocked until the Jetty server is manually killed (along with the rest of the Maven lifecycle).
This confuses me primarily because Maven seems to have a different concept of forking than what I'm familiar with. To me forking means to diverge at a particular point, not to start over, and not to affect the original process. When we fork a process in Unix it copies the stack and function pointer of the first process. It does not start over from the beginning of the program. Similarly, when we fork a code repository we start with all of the files and directories that are currently in the original repository. We don't start over with a blank slate. So why, when we "fork" a Maven lifecycle does it abandon everything, start over, and block the original thread? That doesn't seem at all like forking to me. Here's some of the documentation I've read that describes "forking" in Maven:
"Running the ZipForkMojo will fork the lifecycle"
"Any plugin that declares #execute [phase] will cause the build to fork"
"goal=goal to fork... lifecycle=lifecycle id to fork... phase=lifecycle phase to fork..."
Remaining Questions:
How can I get Maven to fork in the sense that I'm familiar with?
What does it mean to fork a Maven lifecycle to a phase that takes place before the one that you're forking from? For instance, what does it mean to fork to the package phase from the pre-integration-test phase?
Why do you think the Tomcat7 plugin is doing this (forking to the package phase from the pre-integration test phase)?
What could be different about the Tomcat7 plugin that causes the same annotation to behave differently in my plugin?
Answered Question (see below):
- Is there another phase which I should specify in the annotation for my plugin to get it to behave as desired or should I be using the execute annotation in a fundamentally different manner?
See https://books.sonatype.com/mvnref-book/reference/writing-plugins-sect-plugins-lifecycle.html
The docs seem to indicate that you should create a custom lifecycle that only includes the start-mockey goal. Then your #Execute annotation should specify the goal and the lifecycle. That should fork off the execution but only execute your start-mockey. I think then you can run the end-mockey as normal.
I still don't understand what Maven is doing, but I did find a way to work around it:
I removed the #Execute annotation from the StartMockey class.
I forked the process myself in Java.
A snippet of the new code inside StartMockey.execute():
// Start Mockey with the specified parameters on a new thread.
MockeyRunner mockeyRunner = new MockeyRunner(args);
mockeyRunnerThread = new Thread(mockeyRunner);
mockeyRunnerThread.start();
The new MockeyRunner class:
public class MockeyRunner implements Runnable
{
private String[] args;
private Exception exception;
/**
* We cannot throw the Exception directly in run() since we're implementing the runnable interface which does not
* allow exception throwing. Instead we must store the exception locally and check for it in whatever class is
* managing this MockeyRunner instance after the run method has returned.
* #return Exception thrown by Mockey
*/
public Exception getException()
{
return exception;
}
/**
* Constructor
* #param args The arguments to pass to Mockey on startup
*/
public MockeyRunner(String[] args)
{
this.args = args;
}
/**
* This method starts Mockey from inside a new Thread object in an external class. It is called internally by Java
* when the Thread.start() method is called on that object.
*/
#Override
public void run()
{
try
{
JettyRunner.main(args);
}
catch(Exception e)
{
exception = e;
}
}
}
I'm not going to accept this solution as an answer. Although it solves my problem I'd still like to know what Maven "forking" is all about!

"Can not initialize the default wsdl from..." -- Why?

My pom.xml contains the following to auto generate a client for a working web service having the WSDL specified below:
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<id>generate-sources</id>
<configuration>
<sourceRoot>${basedir}/target/generated/src/main/java</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>${basedir}/src/main/wsdl/myclient.wsdl</wsdl>
<extraargs>
<extraarg>-client</extraarg>
<extraarg>-verbose</extraarg>
</extraargs>
<wsdlLocation>wsdl/myclient.wsdl</wsdlLocation>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
The project builds fine, without any errors or warnings and I can see the the file myclient.wsdl in the JAR file right under a wsdl folder.
But when I try running that JAR:
java -Xmx1028m -jar myclient-jar-with-dependencies.jar
It complains that "Can not initialize the default wsdl from wsdl/myclient.wsdl"
Why?
What am I missing?
How can I find out what path that wsdl/myclient.wsdl in pom.xml translates into, that makes the client's JAR complain at run time?
Update: I am aware of some solutions/workarounds that involve modifying the auto-generated code:
Pass "null" for the wsdl URL and then use the ((BindingProvider)port).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://example.com/....") to set the address.
load the WSDL as a Java resource and pass its location into your service's constructor.
But I am more interested in a solution that requires entering the right values into the pom.xml like the classpath approach (but unfortunately classpath didn't work for me for some reason).
Any ideas what I should be typing there instead? Apparently this is a very simply case of figuring out the correct path rules for that particular plugin, but I am missing something and I don't know what it is.
The error comes from the static initializer of your generated service class (which is annotated by #WebServiceClient). It tries to load the wsdl file as resource. The generator uses the value which you have provided by the parameter wsdlLocation. You should leave away the "wsdl/" prefix:
<wsdlLocation>myclient.wsdl</wsdlLocation>
because the wsdl is located directly in the root of the classpath folder.
BTW: If you omit the parameter <wsdlLocation> the value of the param <wsdl> is used (which is not correct at runtime in your case, but would be correct if the provided URL would be a remote URL address, i.e. directly fetched from the webservice server).
BTW2: Your workaround 2 is in fact +/- what the generated code of the service class does if you use the parameterless constructor.
I notice the cfx examples use slightly different locations for sourceRoot, wsdl and wsdlLocation.
Remember that typically, files in src/main/resources are included in the produced artifact. In order for files in src/main/wsdl to be included, it needs to be added as a resource in the pom.xml:
<resources>
<resource>
<directory>src/main/wsdl</directory>
</resource>
</resources>
Tips:
Set the paths you suspect to known bad paths and see if you get the same error-message.
Unzip the produced *.jar-file(s) and check if the wsdl is included, and what the path is.

Resources