Arquillian and Open Liberty requires existing installation? - testing

I'm familiar with Tomcat/TomEE and testing applications using Arquillian. Now were are switching to Open Liberty. I see there is a module for Arquillian using embedded Open Liberty but it seems to require an existing Open Liberty installation whose path is provided in the configuration. This makes it non-portable and therefore unsuitable for automated testing since the installation has to be present at the exact same path. Arquillian and TomEE are self-contained, no installation required. Therefore my question is why this isn't also possible with Open Liberty? And is this planned for the future?
For reference this is how you use Arquillian with TomEE/Tomcat:
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://jboss.org/schema/arquillian"
xsi:schemaLocation="http://jboss.org/schema/arquillian http://www.jboss.org/schema/arquillian/arquillian_1_0.xsd">
<container qualifier="tomee" default="true">
<configuration>
<property name="httpPort">-1</property>
<property name="stopPort">-1</property>
<property name="users">user=pass</property>
</configuration>
</container>
</arquillian>
As you can see, there is no path to a local installation required to run the tests. The only thing you need to do is a add a couple of Maven dependencies in test scope that pull in TomEE (embedded). If the same would work for Open Liberty that would be great.

Going further..so the above is how we do automated testing
but it still uses the location.
I see, regarding not needing any location specified at all, you say:
"The only thing you need to do is a add a couple of Maven dependencies in test scope that pull in TomEE (embedded). If the same would work for Open Liberty that would be great."
So, thinking, maven will put a bunch of classes on the classpath due to the TomEE
dependancies and then the test run will find the appropriate container to
run the tests on.
I will raise an issue over on
https://github.com/OpenLiberty/liberty-arquillian/issues/39
to cover the requirement please feel free to add remarks etc.

If you have a look at https://github.com/OpenLiberty/open-liberty/blob/integration/dev/com.ibm.ws.microprofile.config.1.2_fat_tck/publish/tckRunner/tck/src/test/resources/arquillian.xml
you will see an example arquillian.xml that sets $wlpHome
<property name="wlpHome">${wlp}</property>
from an environment variable $wlp.
('wlp' is short for Websphere Liberty Profile)
The wlpHome variable is used in the managed/local container here:
https://github.com/OpenLiberty/liberty-arquillian/blob/42cb523b8ae6596a00f2e1793e460a910d863625/liberty-managed/src/main/java/io/openliberty/arquillian/managed/WLPManagedContainer.java#L224
An example that does this dynamically is the setting of the
system property ${wlp} here:
https://github.com/OpenLiberty/open-liberty/blob/95c266d4d6aa57cf32b589e7c9d8b39888176e91/dev/fattest.simplicity/src/componenttest/topology/utils/MvnUtils.java#L161
If you have any more queries please post them...
and hope you love OpenLiberty - it rocks!
Gordon

The result you seem to be trying to achieve is a embedded runtime for liberty using arquillian. However, all as far as I can see, the openliberty team only provides a remote container adapter and a managed container adapter at the moment.
With us having a similar need, wanting to run automated integration tests where we wouldnt necessarily have a Openliberty server in-place. We managed to work-around this using liberty-maven-plugin.
The build/testing process would then be:
Running mvn verify, liberty-maven-plugin would generate the specified openliberty which we want to run our tests against.
<plugin>
<groupId>net.wasdev.wlp.maven.plugins</groupId>
<artifactId>liberty-maven-plugin</artifactId>
<version>${version.liberty-maven-plugin}</version> <!-- plugin version -->
<configuration>
<assemblyArtifact> <!-- Liberty server to run test against -->
<groupId>io.openliberty</groupId>
<artifactId>openliberty-runtime</artifactId>
<version>18.0.0.4</version>
<type>zip</type>
</assemblyArtifact>
<configDirectory>src/liberty/${env}/</configDirectory>
<configFile>src/liberty/server.xml</configFile>
<serverName>defaultServer</serverName>
</configuration>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>create-server</goal>
</goals>
</execution>
</executions>
</plugin>
As liberty-maven-plugin per default adds the Liberty server to the target/folder
<arquillian xmlns="http://jboss.org/schema/arquillian">
<container qualifier="liberty-managed" default="true">
<configuration>
<property name="wlpHome">target/liberty/wlp</property>
<property name="serverName">defaultServer</property>
</configuration>
</container>
</arquillian>
This way we can assure that a runnable liberty server according to our liking is always existant in our local environment or e.g. our Jenkins CI/CD Server, essentially getting the same effect as having a embedded container.

Related

How to set context.xml in tomcat run configuration in Idea

I'm trying to deploy a war file for local development and I want to modify tomcat's context.xml to provide datasource via jndi. This works when using tomcat7-maven-plugin:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<contextFile>../../tomcat-test-context.xml</contextFile>
</configuration>
</plugin>
The problem is, that tomcat7-maven-plugin doesn't work with overlays which I use in the project, so I have to use another approach. I can deploy the war artifact in intellij idea, but I don't see any option to specify the contextFile like in the tomcat7-maven-plugin. Is there some option to do similar thing in intellij idea tomcat configuration?
Of course I can modify the context.xml under the catalina home, but I'd like to have it configured per project and don't want to have many tomcats.
The application is deployed on weblogic in production and I use tomcat only locally for testing.

How to override maven-release-plugin config in one child module

I have a multi-module maven build where one of the child modules requires an extra goal to be executed as part of a release. But it looks as though any configuration of the maven-release-plugin in the child module is ignored in favour of the default configuration in the parent module.
This is the snippet from the child module. The plugin configuration is the same in the pluginManagement section of the parent pom, but without the custom element.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.1</version>
<configuration>
<tagBase>http://mycompany.com/svn/repos/myproject/tags</tagBase>
<goals>deploy myCustomPlugin:myCustomGoal</goals>
</configuration>
</plugin>
So is it possible for a child module to override the parent's configuration and add extra goals?
Maven version 2.2.1
Use combine.children="append" combine.self="override"
Parent POM
<configuration>
<items>
<item>parent-1</item>
<item>parent-2</item>
</items>
<properties>
<parentKey>parent</parentKey>
</properties>
</configuration>
Child pom
<configuration>
<items combine.children="append">
<!-- combine.children="merge" is the default -->
<item>child-1</item>
</items>
<properties combine.self="override">
<!-- combine.self="merge" is the default -->
<childKey>child</childKey>
</properties>
</configuration>
Result
<configuration>
<items combine.children="append">
<item>parent-1</item>
<item>parent-2</item>
<item>child-1</item>
</items>
<properties combine.self="override">
<childKey>child</childKey>
</properties>
</configuration>
See this blog for further details
Yes and no. Certainly a child pom can override the configuration of a plugin specified by its parent, and I have to assume you've done so correctly because there's nothing really hard about it. If you check the output of mvn help:effective-pom, you should be able to see plainly that this module has different settings for the release plugin.
The problem you're having is with the behavior of the release plugin. Typically, if you run a goal or phase--mvn compile, for example--from the root module of your project, it first runs that goal/phase on the root module, then on all the modules in reactor order, almost as if you'd run it in each module yourself. Any customizations you've added to child modules take effect as expected. When you run the release plugin, it runs only at the root module. It doesn't run in any of the child modules. Instead, running it at the root module forks a new build using the same settings as the root module, which runs for all the other modules in nearly the same way, except that it uses the root module's configuration for all the modules. I don't know the exact semantics, but I believe this is analogous to you manually running the release goals in each child and specifying the configuration options as system properties at the command line: regardless of how a child module configures the release plugin, the command line args win.
I've never dealt with this problem myself, and it's hard to say without knowing exactly what you're trying to accomplish. Perhaps if you can express what you want to do in this special module as a profile, then you could add a profile to your goals and or preparationGoals. Alternately, there's an arguments option to both the prepare and perform goals that you might be able to pull some tricks with.

How to run jetty:run-war using a war defined by maven coordinates?

Background: I'm setting up a functional tests module in a maven project. We use the maven-jetty-plugin for testing.
I've got the jetty plugin set up as described here (to play nicely with the Failsafe plugin), but what I'd like to do is deploy the war artifact from our main web module using jetty (which has just been installed into the local maven repo by the time the functional test module is running).
The jetty plugin's run-war goal has a <webApp> element which takes a string path to a war to deploy. I'd much rather specify the war to deploy using the maven coordinates defined by our web module. Is there any way to do this?
Possible workarounds:
Section 4.13 of "Better Builds with Maven" describes using cargo to deploy a war specified using maven coordinates, but that's serious overkill given that we're using jetty.
More reasonable IMO is using dependency:copy to copy the just-built-and-installed war artifact to a fixed path in the functional tests module's target directory, which I can then provide in the jetty plugin's <webApp> configuration element.
The jetty plugin's run-war goal has a element which takes a string path to a war to deploy. I'd much rather specify the war to deploy using the maven coordinates defined by our web module. Is there any way to do this?
This is not really the maven jetty plugin is supposed to be used, the plugin deploys the war of the current module, what you want to do is not supported by default.
Section 4.13 of "Better Builds with Maven" describes using cargo to deploy a war specified using maven coordinates,
Yes, Cargo can do this in a clean way.
but that's serious overkill given that we're using jetty.
I don't agree. First, the jetty plugin doesn't support what you want to do out of the box (so it may not be the right tool). Second, serious overkill is highly exaggerated, a misconception actually, especially given that cargo requires very little configuration (zero?) for an embedded Jetty.
More reasonable IMO is using dependency:copy to copy the just-built-and-installed war artifact to a fixed path in the functional tests module's target directory
No offense but your whole question sounds a bit like: I have a hammer, it was fine for a nail, can I use it for a screw given that getting a screw driver seems a serious overkill? To answer this question (which is somehow what you are saying), you can use dependency:copy and get the whole thing working with the maven jetty plugin, but this is a hack (and since you're actually not asking any question, I guess you wanted an opinion on this). Of course the final decision belongs to you :)
Just in case, here is how I would implement this with Cargo:
<dependencies>
<dependency>
<groupId>war group id</groupId>
<artifactId>war artifact id</artifactId>
<type>war</type>
<version>war version</version>
</dependency>
...
</dependencies>
...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<!-- Container configuration -->
<container>
<containerId>jetty6x</containerId>
<type>embedded</type>
</container>
<!-- Configuration to use with the container or the deployer -->
<configuration>
<deployables>
<deployable>
<groupId>war group id</groupId>
<artifactId>war artifact id</artifactId>
<type>war</type>
<properties>
<context>war context</context>
</properties>
</deployable>
</deployables>
</configuration>
<!-- Don't wait, execute the tests after the container is started -->
<wait>false</wait>
</configuration>
<executions>
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-container</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
And I don't think that this can be objectively qualified as a "serious overkill".

Maven2: Cargo plugin hot deployment & Jonas support

I am trying to get the Cargo plugin works on my maven project in order to benefit from war hot-deployment targetting the Jonas server.
The official documentation is not that clear on what is supported and what is not (for example you can find this: http://cargo.codehaus.org/Hot+Deployment but also this http://cargo.codehaus.org/JOnAS+4.x).
Anyway I have the following coniguration in for my war's POM:
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.0</version>
<configuration>
<container>
<containerId>jonas4x</containerId>
<home>C:\JOnAS-4.8.4\nt\bin</home>
</container>
<configuration>
<type>existing</type>
<home>C:\JOnAS-4.8.4</home>
</configuration>
</configuration>
</plugin>
And when I run
mvn cargo:deploy
on my project, the war is copied to the Jonas webapps folder but there is no hot deployment. The file is only copied but the hot deploy Jonas command is not called so that my modifications are not available immediatly.
EDIT: I also tried to add a deployer configuration as suggested on the answers but the behaviour is the same (ie: war is copied but the Jonas hot deploy command is not called so that the war is not reloaded in Jonas).
Am I missing something or am I right saying the Cargo Maven plugin does not support Jonas Hot Deployement?
Thanks in advance!
The cargo page on deploying to a running container links to a table listing the version where hot deployment was introduced for that container. According to the table, JOnAS 4.x is supported from version 1.0 (which you are using), so it should work.
On that page it also has some guidelines for configuring the plugin for deployment, I've attempted to interpret them below.
From the home element in your configuration I assume you are attempting a local deployment. The configuration in the running container page implies that the hot-deployment should be automatic in this line at the end:
Just type mvn cargo:deploy. Notice that we haven't specified a element nor a one. This is because the plugin is smart enough to create default instances for you. Cool, isn't it?
However the earlier configuration block indicates you should configure the deployer section to make the cargo plugin aware of the war to be deployed. The configuration for the deployer would be something like this:
<deployer>
<type>local</type>
<deployables>
<deployable>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<type>war</type>
<properties>
<context>optional root context</context>
</properties>
<pingURL>optional url to ping to know if deployable is done or not</pingURL>
<pingTimeout>optional timeout to ping (default 20000 milliseconds)</pingTimeout>
</deployable>
</deployables>
</deployer>
If the automatic option isn't working for you, consider declaring the configuration for your war.

Maven copy local file to remote server using SSH

Can Maven copy local file to a remote server using SSH?
I want to specify location in maven configuration file and to copy that file (or files) to server each time deploy phase is executed.
The maven-deploy-plugin allows you to configure the deploy phase to deploy to a server using scp. There is a page in the documentation that describes how it can be done.
I believe this will replace the normal deployment instead of add to it, so it may not be what you're after.
If you need to deploy to a traditional Maven repository as well as deliver the file to the remote server, you will need to use the scp task as the other answers suggest.
In this answer I've described how to configure the ftp task, the scp task is almost identical except you may need to add the keyfile and passphrase attributes (and change the task name from ftp to scp obviously).
Have a look at Maven Wagon plugin
To try it manually with a simple command line: mvn org.codehaus.mojo:wagon-maven-plugin:1.0:upload -Dwagon.url=scp://username:userpassword#myserver -Dwagon.fromDir=target -Dwagon.includes=*.ear -Dwagon.toDir=/home/elisabetta
In both cases, be sure to add the SSH extension for Wagon to your pom.xml:
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>2.8</version>
</extension>
</extensions>
Why not use the Ant SCP task, which you can run within Maven?
Same idea as PaoloC, using Maven Wagon plugin with the wagon-ssh extension, but configuration in pom file and run it on specified phase, this examples copies the war file to a remote server with SSH:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>upload-to-myserver</id>
<phase>deploy</phase>
<goals>
<goal>upload-single</goal>
</goals>
<configuration>
<fromFile>${project.build.directory}/${project.build.finalName}.war</fromFile>
<url>scp://username#myserver/path</url>
</configuration>
</execution>
</executions>
</plugin>
<!-- other plugins ... -->
</plugins>
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>2.8</version>
</extension>
</extensions>
</build>
The <phase> tag is optional. You can run just the upload execution with the command:
mvn wagon:upload-single#upload-to-myserver
Maven is not a generic tool, it's a tool to make your build process reusable. I suggest to use an embedded antrun build step. In this step, you can do anything using the normal ant syntax which you'd use in build.xml.
Although this question is not exactly new, I found myself in a similar situation today. My goal is to upload files and run commands on a remote server to which I have to tunnel (through another server). I managed to forge a solution for that with ant (which again can be triggered from maven as mentioned here).
Ants sshsession task only creates a tunnel that you can use for the tasks within. The tasks within are not automatically run on the remote server but you can use the sshexec task together with the tunnel to achieve that. Also the scp task can now upload through the tunnel to the remote server. Here is an example:
<sshsession host="${jumphost}" port="22" username="${user}" password="${password}" trust="true">
<localtunnel lport="${localTunnelPort}" rhost="${targethost}" rport="22"/>
<sequential>
<!-- run a command on the remote server (here mkdir) -->
<sshexec host="localhost" port="${localTunnelPort}" username="${user.param}" password="${password.param}" command="mkdir ${home}/foobar" trust="true" />
<!-- upload a file to the remote server -->
<scp port="${localTunnelPort}" file="test_file.txt" todir="${user.param}:${password.param}#localhost:${home}/foobar/" trust="true" />
</sequential>
</sshsession>