The axis jar files are built in the xml-axis/java/build/lib
directory. Here is an example CLASSPATH, which I use when developing
code:
If you access the internet via a proxy server, you'll need to set an environment variable so that the Axis tests do the same. Set ANT_OPTS to, for example:D:\\xerces\\xerces-1_4_2\\xerces.jar
G:\\junit3.7\\junit.jar
G:\\xml-axis\\java\\build\\lib\\commons-discovery.jar
G:\\xml-axis\\java\\build\\lib\\commons-logging.jar
G:\\xml-axis\\java\\build\\lib\\wsdl4j.jar
G:\\xml-axis\\java\\build\\lib\\axis.jar
G:\\xml-axis\\java\\build\\lib\\log4j-1.2.4.jar
G:\\xml-axis\\java\\build\\classes
-Dhttp.proxyHost=proxy.somewhere.com -Dhttp.proxyPort=80 -Dhttp.nonProxyHosts="localhost"
org.apache.axis.components.logger.LogFactory
is the factory,
or discovery mechanism, for the logger component/service.
The org.apache.axis.components.image
package demonstrates
both a factory, and supporting classes for different image tools used
by AXIS. This is representative of a pluggable component that uses
external tooling, isolating it behind a 'thin' wrapper to AXIS that
provides only a limited interface to meet AXIS minimal requirements.
This allows future designers
and implementors to gain an explicit understanding of the AXIS's
specific requirements on these tools.
To use the JCL SPI from a Java class, include the following import statements:
import org.apache.commons.logging.Log;
import org.apache.axis.components.logger.LogFactory;
log
attribute as follows:
public class CLASS
{
private static Log log = LogFactory.getLog(CLASS.class);
...
Messages are logged to a logger, such as log
by invoking a method corresponding to priority:
The Log
interface defines the following methods for use
in writing log/trace messages to the log:
log.fatal(Object message);
log.fatal(Object message, Throwable t);
log.error(Object message);
log.error(Object message, Throwable t);
log.warn(Object message);
log.warn(Object message, Throwable t);
log.info(Object message);
log.info(Object message, Throwable t);
log.debug(Object message);
log.debug(Object message, Throwable t);
log.trace(Object message);
log.trace(Object message, Throwable t);
In addition to the logging methods, the following are provided:
log.isFatalEnabled();
log.isErrorEnabled();
log.isWarnEnabled();
log.isInfoEnabled();
log.isDebugEnabled();
log.isTraceEnabled();
Configuration of the behavior of the JCL ultimately depends upon the logging toolkit being used. The JCL SPI (and hence AXIS) uses Log4J by default if it is available (in the CLASSPATH).
Configure Log4J using system properties and/or a properties file:
Use this system property to specify the name of a Log4J configuration file.
If not specified, the default configuration file is log4j.properties.
A log4j.properties file is provided in axis.jar
.
This properties file can sometimes be overridden by placing a file of
the same name so as to appear before axis.jar
in the CLASSPATH.
However, the precise behaviour depends on the classloader that is in use
at the time, so we don't recommend this technique.
A safe way of overriding the properties file is to replace it in axis.jar. However, this isn't very convenient, especially if you want to tweak the properties during a debug session to filter out unwanted log entries. A more convenient alternative is to use an absolute file path to specify the properties file. This will even ignore web app's and their classloaders. So, for example on Linux, you could specify the system property:
log4j.configuration=file:/home/fred/log4j.props
LogFactory.getLog(logger.name)
,
used to create the logger instance. Priorities are:
DEBUG
,
INFO
,
WARN
,
ERROR
,
or FATAL
.
Log4J understands hierarchical names,
enabling control by package or high-level qualifiers:
log4j.logger.org.apache.axis.encoding=DEBUG
will enable debug messages for all classes in both
org.apache.axis.encoding
and
org.apache.axis.encoding.ser
.
Likewise, setting
log4j.logger.org.apache.axis=DEBUG
will enable debug message for all AXIS classes,
but not for other Jakarta projects.
A combination of settings will enable you to see the log events that you are interested in and omit the others. For example, the combination:
log4j.logger.org.apache.axis=DEBUG log4j.logger.org.apache.axis.encoding=INFO log4j.logger.org.apache.axis.utils=INFO log4j.logger.org.apache.axis.message=INFOcuts down the number of a log entries produced by a single request to a manageable number.
For example: one can capture DEBUG (and higher) level information in a logfile, while limiting console output to INFO (and higher).
System.getProperty()
,
and instead call AxisProperties.getProperty
.
AxisProperties.getProperty
will
call System.getProperty
, and will (eventually)
query other sources of configuration information.
Using this central point of access will allow the global configuration system to be redesigned to better support multiple AXIS engines in a single JVM.
These guidelines are fundamentally independent of programming language. They are based on experience, but proper credit must be given to More Effective C++, by Scott Meyers, for opening the eyes of the innocent(?) many years ago.
Finally, these are guidelines. There will always be exceptions to these guidelines, in which case all that can be asked (as per these guidelines) is that they be logged in the form of comments in the code.
There are a few corrollaries to this rule.
main
method or program.
For a middleware component, this is the entry point(s) into the component.
For AXIS this is AxisServlet
or equivalent.
After catching specific exceptions which can be resolved internally, the outermost code must ensure that all internally generated exceptions are caught and handled. While there is generally not much that can be done, at a minimum the code should log the exception. In addition to logging, the AXIS Server wraps all such exceptions in AxisFaults and returns them to the client code.
This may seem contrary to the primary rule, but in fact we are claiming that AXIS does know what to do with this type of exception: exit gracefully.
When in doubt, log the exception.
When in doubt, log the exception and any related local information that can help to identify the complete context of the exception.
Log the exception as an error (log.error()
)
if it is known to be an unresolved or unresolvable error,
otherwise log it at the informative level (log.info()
).
e
is caught and wrapped
by a new exception w
,
log exception e
before throwing w
.
Log the exception as an error (log.error()
)
if it is known to be an unresolved or unresolvable error,
otherwise log it at the informative level (log.info()
).
e
is caught and resolved,
logging of the exception is at the discretion of the coder and reviewers.
If any comments are logged, the exception should also be logged (log.info()
).
Issues that must be balanced are performance and problem resolvability.
Note that in many cases, ignoring the exception may be appropriate.
Exceptions raised in the business logic (this includes the server and AXIS handlers) must be delivered to the client code.
handlers
, providers
and other
user controllable hook-points must be guarded
by catch(Exception ...)
.
Exceptions generated by user code and caught by system code should be:
cd xml-axis/javaTo run the tests:
ant compile
cd xml-axis/javaNote: these tests start a server on port 8080. If this clashes with the port used by your web application server (such as Tomcat), you'll need to change one of the ports or stop your web application server when running the tests.
ant functional-tests
Please run ant functional-tests and ant all-tests before checking in new code.
sample00=My name is {0}, and my title is {1}.
Messages.getMessage("sample00", "Rich Scheuerle",
"Software Developer");
if ( operationName == null )
throw new AxisFault( "No operation name specified" );
We will add an entry into org/apache/axis/i18n/resource.properties:
noOperation=No operation name specified.
And change the code to read:
if ( operationName == null )
throw new AxisFault(Messages.getMessage("noOperation"));
java.util.ResourceBundle
to access property files and message strings,
and uses java.text.MessageFormat
to format the strings using variables.
AXIS provides a single class org.apache.axis.i18n.Messages
that manages both ResourceBundle and MessageFormat classes.
Messages methods are:
public static java.util.ResourceBundle getResourceBundle();
public static String getMessage(String key) throws java.util.MissingResourceException;
public static String getMessage(String key, String var) throws java.util.MissingResourceException;
public static String getMessage(String key, String var1, String var2) throws java.util.MissingResourceException;
public static String getMessage(String key, String[] vars) throws java.util.MissingResourceException;
AXIS programmers can work with the resource bundle directly via a call
to Messages.getResourceBundle()
,
but the getMessage()
methods should be used instead for two reasons:
Messages.getMessage("myMsg00");
Messages.getResourceBundle().getString("myMsg00");
getMessage
methods enable messages with variables.myMsg00=This is a string.
Messages.getMessage("myMsg00");
If you have a message with variables, use the syntax
"{X}"
where X
is
the number of the variable, starting at 0. For example:
myMsg00=My {0} is {1}.
Messages.getMessage("myMsg00","name", "Russell");
You could also call the String array version of getMessage:
Messages.getMessage("myMsg00", new String[] {"name", "Russell"});
The String array version of getMessage
is all that is necessary, but the vast majority of messages will have 0,
1 or 2 variables, so the other getMessage
methods are provided as a convenience to avoid the complexity of the String
array version.
Note that the getMessage methods throw MissingResourceException if the resource cannot be found. And ParseException if there are more {X} entries than arguments. These exceptions are RuntimeException's, so the caller doesn't have to explicitly catch them.
The resource bundle properties file is org/apache/axis/i18n/resource.properties.
See Also: Test and Samples Structure
Editor's Note: We need more effort to streamline and simplify the addition of tests. We also need to think about categorizing tests as the test bucket grows.If you make changes to Axis, please add a test that uses your change. Why?
Some general principles:
One way to build a test is to "cut and paste"
and existing tests, and then modify the test to suit your needs.
This approach is becoming more complicated as the different kinds of tests
grow.
A good "non-wsdl" test for reference is test/saaj.
java org.apache.axis.wsdl.Wsdl2java -t -s
SequenceTest.wsdl
<!--
Sequence Test -->
<wsdl2java url="${axis.home}/test/wsdl/sequence/SequenceTest.wsdl"
output="${axis.home}/build/work"
deployscope="session"
skeleton="yes"
messagecontext="no"
noimports="no"
verbose="no"
testcase="no">
<mapping namespace="urn:SequenceTest2" package="test.wsdl.sequence"/>
</wsdl2java>
As of Axis 1.0, RC1, we have moved to a "componentized" test structure. Instead of having one high-level large recursive function, there are smaller, simple "component" build.xml files in the leaf level of the test/** and samples/** trees.
These "component" files have a common layout. Their primary targets are:
A "sample" test xml file can be found in test/templateTest
If a convention can be reduced to a regular expression match, it can be enforced at build time by updating java/test/utils/TestSrcContent.java.
All that is necessary is to add a pattern to the static FileNameContentPattern array. Each pattern has three parameters:
A reasonable summary of the regular expression notation is provided in the Jakarta ORO javadocs.
tcpmon
to Monitor Functional Tests.
Here is an easy way to monitor the messages while running
functional-tests
(or all-tests
).
Start up tcpmon listening on 8080 and forwarding to a different port:
java org.apache.axis.utils.tcpmon 8080 localhost 8011Run your tests, but use the forwarded port for the SimpleAxisServer, and indicate that functional-tests should continue if a failure occurs.
ant functional-tests -Dtest.functional.SimpleAxisPort=8011 -Dtest.functional.fail=noThe SOAP messages for all of the tests should appear in the tcpmon window.
tcpmon
is described in more detail in the
AXIS User's Guide.
SOAP Monitor
to Monitor Functional Tests.
If you are debugging code that is running as a web application using
a web application server (such as Tomcat) then you may also use the
SOAP Monitor utility to view the SOAP request and response messages.
Start up the SOAP monitor utility by loading the SOAP monitor applet
in your web browser window:
http://localhost:<port>/axis/SOAPMonitor. As you run your tests, the SOAP messages should appear in the SOAP monitor window.
SOAP Monitor
is described in more detail in the
AXIS User's Guide.
java org.apache.axis.transport.http.SimpleAxisServer -p 8080In another window, first deploy the service you're testing:
java org.apache.axis.client.AdminClient deploy.wsddThen bring up the JUnit user interface with your test. For example, to run the the multithread test case:
java junit.swingui.TestRunner -noloading test.wsdl.multithread.MultithreadTestCase
log4j.properties
file
is packaged in axis.jar
with reasonable
default settings.
Subsequent items presume changes to these settings.
There are multiple options open to the developer,
most of which involve
extracting log4j.properties
from axis.jar
and modifying as appropriate.
java
programs from
a command line or script file,
include the JVM option
-Dlog4j.configuration=yourConfigFile
.
CLASSPATH
such that
your version of log4j.properties
appears
prior to axis.jar
in the CLASSPATH
.
ant
(this includes building AXIS and running it's tests),
set the environment variable ANT_OPTS
to -Dlog4j.configuration=yourConfigFile
.
src/log4j.properties
directly. Be sure NOT to commit your change(s).
log4j.rootCategory
priority to
DEBUG
.
DEBUG
(The log4j.properties
file in AXIS defines two appenders:
CONSOLE
and LOGFILE
).
log4j.rootCategory
priority to
INFO
or higher.
log4j.logger.logger.name
priority to
DEBUG
for the loggers that you are interested in.
DEBUG
(The log4j.properties
file in AXIS defines two appenders:
CONSOLE
and LOGFILE
).
grep
to
search for them in log messages.
System.out.println
or
System.err.println
should be avoided.
Developers may be tempted to use System.out.println
while debugging or analyzing a system.
If you choose to do this, you will need to disable the
util/TestSrcContent
test,
which enforces avoidance of
System.out.println
and System.err.println
.
It follows that you will need to remove your statements
before checking the code back in.
As an alternative,
we strongly encourage you to
take a few moments and introduce debug statements:
log.debug("reasonably terse and meaningful message")
.
If a debug message is useful for understanding a problem now,
it may be useful again in the future to you or a peer.
The kit comes as a zip file which you should unzip into a directory of your choosing. The installation instructions are in the JAX-RPC Release Notes document which is stored in the docs directory. If you open the index.html file in the docs directory using a web browser, you'll see a list of all the documents supplied with the kit.
Note that the kit includes the JavaTest test harness which is used for running the compatibility tests.
If any more information is needed about running these tests, please add it here!