Debugging
Definition
Explain how to perform debugging when something doesn't work in CargoSometimes, it can happen that the container does not start or stop as expected or you might have reasons to believe that Codehaus Cargo is "acting weird". Here is a short list of things you can do to try debugging the problem.
Embedded containers
Remember that Codehaus Cargo supports different types of containers, and particularly pay attention that embedded containers will be ignoring the JVM arguments you provide: as they are embedded, they will by definition simply take over whatever is coming from the host JVM.
In other words, when using an embedded container in your own application, Ant tasks or the Maven 3 Plugin, you actually will have to put your application, Ant or Maven itself in a debug mode to debug the actual container. The best solution is to use an installed container instead, which also provides a much more realistic execution environment.
Debugging the container
Most Java Virtual Machine implementations support remote debugging. Once started in debug mode, you can then remotely connect to your container using any IDE and debug your container and/or application.
In order to do so, add the following arguments to the JVM start arguments configuration property:
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=<suspend>,address=<port> -Xnoagent -Djava.compiler=NONE
where:
- suspend is whether the launch of the container should first wait for a remote debugger to connect. If
y
, the container will wait for you to connect with your remote debugger before starting; ifn
the container will start immediately and at the same time listen on the remote debugging port. - port is the port number to use for remote debugging.
Here is an example for starting a JOnAS 5.x container in Remote Debug on port 8000 without suspend mode using the Maven 3 plugin:
<plugin> <groupId>org.codehaus.cargo</groupId> <artifactId>cargo-maven3-plugin</artifactId> <version>${cargo.version}</version> <configuration> <container> <containerId>jonas5x</containerId> <type>installed</type> <home>${jonas.root}</home> </container> <configuration> <type>existing</type> <home>${jonas.base}</home> <properties> <cargo.servlet.port>${http.port}</cargo.servlet.port> <cargo.start.jvmargs> -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000 -Xnoagent -Djava.compiler=NONE </cargo.start.jvmargs> </properties> </configuration> </configuration> </plugin>
Once the server is started, follow these steps to remotely debug your server and/or application:
- Click Debug - Attach Debugger...
- In the window that appears, type in the remote host name and the port number then click OK
Steps for achieving the same in Eclipse IDE are similar.
About the cargo.start.jvmargs property
The JVM start arguments configuration property only exists since Codehaus Cargo 1.4.18.
With older versions, you'll have to use cargo.jvmargs
and make sure you set the execution property only on the start
goal - Else you will get error messages such as:
[INFO] [talledLocalContainer] FATAL ERROR in native method: JDWP No transports initialized, jvmtiError=AGENT_ERROR_TRANSPORT_INIT(197) [WARNING] [talledLocalContainer] ERROR: transport error 202: bind failed: Address already in use [WARNING] [talledLocalContainer] ERROR: JDWP Transport dt_socket failed to initialize, TRANSPORT_INIT(510) [WARNING] [talledLocalContainer] JDWP exit error AGENT_ERROR_TRANSPORT_INIT(197): No transports initialized [../../../src/share/back/debugInit.c:741]
Redirecting container output to a file and setting the log level of the container
Example using the Java API
The Container.setOutput(File)
API allows you to redirect the container console (stdout
) to a file. This is the first file you should check in case of problem.
Cargo is able to configure containers to generate various levels logs. There are 3 levels defined in o.c.c.container.property.LoggingLevel
: LoggingLevel.LOW
, LoggingLevel.MEDIUM
and LoggingLevel.HIGH
(LoggingLevel.MEDIUM
is the default value). They represent the quantity of information you wish to have in the generated log file. You can tune container logging by using the following API:
configuration.setProperty(GeneralPropertySet.LOGGING, LoggingLevel.HIGH.getLevel());
The generated log files will then be found in the working directory you have specified on the container (through the container.setWorkingDir()
call).
Starting Tomcat 8.x specifying an output console log file:
LocalContainer container = new Tomcat8xLocalContainer( new CatalinaStandaloneLocalConfiguration("target/tomcat8x")); container.setHome("c:/apps/apache-tomcat-8.5.85"); container.setOutput("target/output.log"); container.start();
Use the container.setAppend(true|false)
method to decide whether the log file is recreated or whether it is appended to, keeping the previous execution logs (by default, the file is recreated at every container start or stop).
Example using the Ant API
Starting Tomcat 8.x specifying an output console log file with the highest possible level of logs:
<cargo containerId="tomcat8x" home="c:/apps/apache-tomcat-8.5.85" action="start" output="target/output.log" append="false"> <configuration home="target/tomcat-home"> <property name="cargo.logging" value="high"/> </configuration> </cargo>
Use the append="true|false"
attribute for controlling the log file creation behavior.
Example using the Maven 3 plugin
Starting Tomcat 8.x specifying an output console log file with the highest possible level of logs:
<container> <containerId>tomcat8x</containerId> <home>c:/apps/apache-tomcat-8.5.85</home> <output>target/output.log</output> <append>false</append> </container> <configuration> <properties> <cargo.logging>high</cargo.logging> </properties> </configuration>Â
Use the append="true|false"
attribute for controlling the log file creation behavior.
Debugging Codehaus Cargo itself
To enable the Java debugger on ANT, export the ANT_OPTS
system property using the parameters specified above. For example:
export ANT_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000"
On Maven 3, enabling Java debugger is done using the mvnDebug
executable instead of mvn
.
mvnDebug command on MacOS X
 Note that on MacOS X, mvnDebug
is not on the default path. To run it, execute the command:Â /usr/share/maven/bin/mvnDebug
Redirecting Codehaus Cargo logs to a file
Example using the Java API
Some Cargo classes support generation of logs. This is implemented through the notion of Logger
and levels are managed using LogLevel
. There are 3 levels defined in o.c.c.util.log.LogLevel
: LogLevel.DEBUG
, LogLevel.INFO
and LogLevel.WARN
(LogLevel.INFO
is the default value).
For example to turn on logging monitoring on a Container
class, you can use:
Logger fileLogger = new FileLogger(new File("c:/tmp/cargo.log"), true); fileLogger.setLevel(LogLevel.DEBUG); container.setLogger(fileLogger);
There are several Loggers that are readily available in the Cargo distribution:
- FileLogger: logs messages to a file
- SimpleLogger: logs messages to the console (stdout)
- AntLogger: logs messages using Ant's logging mechanism
Example using the Ant API
When using the Ant tasks, Codehaus Cargo will by default use the AntLogger. You can specify the log level using the logLevel
attribute (where the accepted values are debug
, info
and warn, the default being info
), and the log file by using the log
attribute. For example:
<cargo containerId="tomcat8x" home="c:/apps/apache-tomcat-8.5.85" action="start" logLevel="debug" log="target/cargo.log"/>
Example using the Maven 3 plugin
When using the Maven 3 plugin, Codehaus Cargo will by default use the MavenLogger.
When you use mvn
with the -e
option, both Maven itself and the Codehaus Cargo plugin will log everything in debug mode.
If you want to use the plugin in debug mode without having Maven itself in debug mode, you can specify the log level using the logLevel
attribute (where the accepted values are debug
, info
and warn, the default being info
), and the log file by using the log
attribute. For example:
<container> <containerId>tomcat8x</containerId> <home>c:/apps/apache-tomcat-8.5.85</home> <log>target/cargo.log</log> <logLevel>debug</logLevel> </container>
Debugging your application(s) on the container
The hints above to start the container in debug mode would obviously also allow you to debug your application(s) running on that container.
Nevertheless, what you might experience is that your application's log levels do not follow what you defined as container log level. Sadly, there is little Codehaus Cargo can do in this case: you will have to look into your application's distribution, and find existing logger definitions, to update them.