How to dynamically find and assign free ports within maven build. Running local clients and servers in parallel. With selenium exampleBy neokrates, written on May 28, 2010 |
howto |
- neokrates
- Email: uwarov@yahoo.com
- Website: http://www.thinkplexx.com
- Join date: 05-31-09
- Posts: 20
What build management tool does your project or firm use?
- Buildr (47%, 15 Votes)
- Maven 2 (6%, 2 Votes)
- Ant (6%, 2 Votes)
- Maven (3%, 1 Votes)
- Maven 3 (3%, 1 Votes)
- Ivy (0%, 0 Votes)
- GAnt (0%, 0 Votes)
- Gradle (0%, 0 Votes)
- Rake (0%, 0 Votes)
- Raven (0%, 0 Votes)
- Any Make Type Tool (0%, 0 Votes)
Total Voters: 32
Loading ...
We have Hudson. It has some slaves per server. And we have selenium grid, which in our case has hard-coded ports for hub and for agents. There is a simple way to assign free ports and avoid conflict. Selenium is just an example, ports could be made available for any client – server running under maven.
Software:
Selenium grid
Maven
Ant
Linux
Should also work for:
Any other OS which supports those tools
Preconditions:
In this example selenium grid is used. To run it system must be configured first. Like being able to run browser from command line.
If you want to setup jetty, db etc… something lightweight, then they will likely have no special environment needs.
Here, no complete solution and example to run selenium under maven and ant is given. You can find it elsewhere. The only point is to show how the free ports can be picked and propagated to the server instance, ensuring there will be no port conflict ever.
| 1 |
Find free ports, make them available
build-helper-maven-plugin:reserve-network-port (http://mojo.codehaus.org/build-helper-maven-plugin/) does two things:
find the free port;
make it available for the maven.
Here, we get 3 free ports seleniumHubPort, seleniumAgentPort1, seleniumAgentPort2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <executions> <execution> <id>reserve-ports</id> <phase>initialize</phase> <goals> <goal>reserve-network-port</goal> </goals> <configuration> <portNames> <portName>seleniumHubPort</portName> <portName>seleniumAgentPort1</portName> <portName>seleniumAgentPort2</portName> </portNames> </configuration> </execution> </executions> </plugin> |
| 2 |
Use generated ports to start the (selenium) server
Selenium may be started from ant script, ant will run inside maven.
We bind the call to start selenium hub and remote controls to the test maven lifecycle phase.
In your pom.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <plugins> .... <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.3</version> <executions> <execution> <id>start-selenium</id> <phase>test</phase> <configuration> <tasks> <ant antfile="build.xml"> <property name="seleniumHubPort" value="${seleniumHubPort}" /> <target name="start-hub" /> </ant> <ant antfile="build.xml"> <property name="seleniumHubPort" value="${seleniumHubPort}" /> <property name="seleniumAgentPorts" value="${seleniumAgentPort1},${seleniumAgentPort2}" /> <target name="launch-selenium-agents" /> </ant> </tasks> </configuration> <goals> <goal>run</goal> </goals> </execution> </executions> </plugin> .... </plugins> |
build.xml in the same directory (showing only the code part which illustrates port propagation):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | <?xml version="1.0"?> <project name="Run Selenium instances" basedir="."> <!-- ... --> <taskdef resource="net/sf/antcontrib/antcontrib.properties" classpath="${basedir}/lib/ant-contrib-1.0b3.jar" /> <!-- ... --> <target name="start-hub" description="Start the Hub"> <echo>Selenium hub will listen on port ${hubPort}</echo> <java taskname="launch-hub" classname="com.thoughtworks.selenium.grid.hub.HubServer" classpathref="hub.classpath" fork="true" spawn="true"> </java> </target> <!-- ... --> <target name="launch-remote-control" description="Launch A Remote Control"> <java taskname="launch-remote-control" classpathref="remote-control.classpath" classname="com.thoughtworks.selenium.grid.remotecontrol.SelfRegisteringRemoteControlLauncher" fork="true" spawn="true"> <!-- ... --> <arg value="-port" /> <arg value="${port}" /> <!-- ... --> </java> </target> <!-- ... --> <property name="ports" value="${seleniumAgentPorts}" /> <target name="launch-selenium-agents" description="Launch Remote Controls"> <echo>Celenium agents will take ports: ${ports}</echo> <foreach list="${ports}" delimiter="," param="port" target="launch-remote-control" inheritall="true" parallel="true" /> </target> <!-- ... --> </project> |
| 3 |
Selenium hub will also use grid_configuration.yml
Selenium needs grid_configuration.yml. It should be located in the directory where selenium is being started (selenium home dir).
In our case it must also always have the correct port, put there dynamically.
We will use the maven filtering to write the port into .yml file.
Put the .yml file into maven resources src/main/resources/grid_configuration.yml:
1 2 3 4 5 6 7 | hub: port: ${seleniumHubPort} environments: - name: "Firefox on Windows" browser: "*firefox" - name: "Firefox on OS X" browser: "*firefox" |
Then, in maven’s pom add:
1 2 3 4 5 6 7 8 9 10 11 12 | <resources> <!-- ... --> <resource> <directory>src/main/resources</directory> <includes> <include>**/grid_configuration.yml</include> </includes> <filtering>true</filtering> <targetPath>../..</targetPath> </resource> <!-- ... --> </resources> |
| 4 |
Conclusion
After the test maven phase, server (selenium) and agents are running. Also second instance of this maven project, i.e. with different test scenarios, can be started. Done.
REMARKS:
- Selenium is very greedy, so if you run many hubs (selenium grid) in parallel, it will need large memory space, swap, good CPU, etc. Watch for the resource usage, you can use the unix top command to do that.
- I don’t know if reserve-network-port itself can handle a race condition. So, if it happens that some reserve-network-port search for free ports in the same time, there is a tiny chance they take the same port.
Have fun!
|
LEARN MORE (amazon bookstore)
|
|
TAGS
|
|
SOCIAL
|


















