Apache Axis2 2.0.2 Release Notes
Upgrading from 2.0.1
Everything a working 2.0.1 deployment may have to change, in one place. The reasoning for each is further down; this is the checklist.
Defaults that now refuse what they previously allowed. Each is a one-line opt-out in axis2.xml if a deployment genuinely needs the old behaviour.
| Change | Restore the old behaviour with |
|---|---|
| Decoupled WS-Addressing responses are refused (AXIS2-6108) | <parameter name="allowNonAnonymousResponseEndpoints">true</parameter> |
| Service dispatch from the SOAP body namespace is off | <parameter name="allowContentBasedServiceDispatch">true</parameter> |
| Admin console ships with empty credentials, so it is disabled | set userName and password in your own axis2.xml |
The WS-Addressing change is the one most likely to be felt: any client using a non-anonymous ReplyTo or FaultTo stops working until the parameter is set. Deployments that re-enable it should also set httpFrontendHostUrl, because the generated reply address otherwise defaults to the local machine's IP. In this project's own test suite the change touched 17 of 244 integration tests, all decoupled-response cases, and opting those in was the migration – expect the same shape of work.
New ceilings. Requests larger than these are now rejected rather than allocated. Raise them if a deployment legitimately handles bigger messages: multipartMaxRequestSize, multipartMaxFileSize, formUrlEncodedMaxRequestSize, mtomMaxRequestSize, soapMaxRequestSize, and for multiref org.apache.axis2.databinding.multiref.maxDepth.
Classpath and packaging changes. These affect builds and WAR deployments rather than configuration:
axis2-springno longer brings Spring with it. Applications that inheritspring-boot-starter-parentor importspring-boot-dependenciesare unaffected – their dependency management already decided the Spring version. Anyone depending onaxis2-springwithout Spring Boot's dependency management must now declarespring-core,spring-beans,spring-contextandspring-webthemselves.- The JMS and mail transports are no longer bundled in
axis2.war. Both remain inlib/of the binary distribution, so a standalone server is unaffected; a WAR deployment that uses either now adds the transport jar toWEB-INF/lib. jibxis no longer a valid-dvalue forwsdl2java. JiBX was removed in 2.0.1; the option had survived in the tool's help text without a backing implementation.
Metadata exposure. exposeServiceMetadata is now honoured on every anonymous metadata route rather than only the ?wsdl/?xsd queries, and a service with it disabled is answered as though it were not deployed. If you relied on WS-MEX, the /services/ listing, the ping module or the .xsd/.wsdl file routes reaching a service that had metadata exposure turned off, they no longer will.
Distribution Changes
-
axis2-springno longer exports Spring to its consumers. Itsspring-core,spring-beans,spring-contextandspring-webdependencies are nowprovidedrather thancompile. The module is an integration layer: the application already has Spring and decides its version. As compile-scope dependencies they were transitive, so a consumer running an older Spring who did not import the Spring Boot BOM silently got this build's Spring on the classpath beside their own. Applications that inheritspring-boot-starter-parentor importspring-boot-dependencieswere never affected – dependency management already overrode the transitive version – and are unaffected now. Anyone depending onaxis2-springwithout Spring Boot's dependency management must declare their own Spring dependencies, which is the intent. -
Five stray Spring jars dropped from
axis2.warand the binary distribution.spring-beans,spring-context,spring-coreandspring-webhave always been excluded on purpose – a deployment using the Spring integration supplies its own Spring. Spring 7 movedspring-aop,spring-expression,micrometer-observation,micrometer-commonsandjspecifybehindspring-contextandspring-core, and the exclusion lists were never updated, so ~870 KB of Spring fragments shipped that could not work without the four jars deliberately left out. Axis2's ownaxis2-springis unchanged and still shipped. -
google-java-format replaced, dropping ~5.9 MB from the WAR. Codegen tidied its generated Java with google-java-format, a full parse-and-reflow formatter that brought guava and a shaded javac with it – about 6 MB shipped in every
axis2.warto format machine-generated code that a template had already laid out.PrettyPrinternow re-indents with no dependencies. It rewrites leading whitespace and nothing else: it does not reflow lines, reorder imports or alter a character the compiler can see, so the worst it can do is indent badly rather than change what generated code means. Braces inside string literals, character literals and comments are not counted, and text blocks are reproduced verbatim because their leading whitespace is part of the string. A formatting failure now leaves the generated file untouched – the previous code deleted the source before renaming the formatted copy over it, so a failure destroyed it.axis2.wargoes from 36 MB to 30 MB across this and the JMS, mail and Spring changes above. Guava is therefore no longer inlib/orWEB-INF/lib; modules that need it at runtime must ship their own – Rampart 2.0.0 does, because OpenSAML and WSS4J require it. -
The mail transport is no longer bundled in
axis2.wareither. Same reasoning as JMS: no defaultaxis2.xmlenables amailtolistener or sender, and the module is deprecated for removal in 2.0.3. It remains inlib/of the binary distribution. Note thatangus-mailandjakarta.mail-apistay in the WAR and are not mail transport baggage:jakarta.mail-apicarries theMimeBodyPart,MimePartDataSource,InternetHeadersandByteArrayDataSourceclasses that JAX-WS attachment handling uses, andangus-mailsupplies theMETA-INF/services/jakarta.mail.util.StreamProviderimplementation those classes need at runtime. Removing either would break MTOM and SwA, not the mail transport. -
The JMS transport is no longer bundled in
axis2.war.axis2-transport-jmsandjakarta.jms-apishipped in every WAR while no defaultaxis2.xmlenables a JMS listener or sender, so every deployment carried the transport – and its JNDI lookup code – without asking for it. It was never usable as shipped in any case:jakarta.jms-apiis an API with no provider, so enabling JMS always required adding a broker client. The module is unchanged, remains a supported transport, and is still inlib/of the binary distribution, so a standalone server is unaffected. A WAR deployment that uses JMS now addsaxis2-transport-jmstoWEB-INF/libalongside the broker client it already had to add. -
The
dynamicclientsample is removed from the source distribution. It was never part of the build, and its modules declared a parent version that did not match their own aggregator, so it could not be built. Its WSDL 2.0 client also depended on WSDL 2.0 support that is no longer documented.ServiceClientcan still be constructed from a WSDL URL;modules/samples/jaxws-addressbookcovers the JAX-WS Dispatch client. -
More unrunnable samples are removed.
yahoojsonsearchandyahoorestsearchcalled Yahoo search APIs that were shut down in 2011, andgooglespellcheckcalled a Google SOAP API retired in 2009; the two Yahoo samples were still in the binary distribution.jaxws-dynamicwas shipped with no build file and an empty README, andbookdepended on 1.8.0 snapshots and was never built. Three Maven samples whose run instructions could not work are removed as well:transport/https-sampleran on the Jetty 6 plugin, which cannot host a Jakarta webapp;java_first_jaxwswas set up for a javax-based Cargo container; andtransport/jms-samplehad no client. -
The ant-built samples in the binary distribution build again. Since 2.0.1 the binary distribution has placed samples under
modules/samples/, but most samplebuild.xmlfiles still locatedAXIS2_HOMEtwo directories up, soantfailed looking formodules/lib. They now resolveAXIS2_HOMEcorrectly fromAXIS2_HOME/modules/samples/<sample>, andservicelifecycle, which still used a builder class removed in Axiom 2.0, compiles again.
Deprecated for Removal
-
The mail transport (
axis2-transport-mail) is deprecated and is planned for removal in 2.0.3. SOAP over SMTP was specified and profiled, but a request/response exchange that blocks a caller thread on a mailbox poll saw very little use even when SOAP was at its most popular, and it shows: no functional change has been made to this module in over a decade, and every commit touching it since 2015 is either a project-wide sweep (the jakarta rename, the SecurityManager removal, a package move) or a test-dependency bump.It is not enabled by any default
axis2.xml, and as of this release it is no longer bundled inaxis2.wareither – it remains inlib/of the binary distribution for anyone who configures it. Its correlation of responses to requests byIn-Reply-To(SynchronousCallbackand the callback table inAbstractTransportListener) is the only such mechanism in the tree and is used by nothing else; the module's own source carries long-standingFIXMEcomments saying that machinery does not belong where it sits.If you use the mail transport, please say so on the dev list – concrete usage is what would keep it. Otherwise plan to move to an HTTP transport before 2.0.3. Nothing is removed in 2.0.2 and the module continues to work in this release.
Security Hardening
Several defaults changed in this release. Each one closes a surface an unauthenticated caller could reach, and each is listed here with what to set if a deployment genuinely needs the previous behaviour. The full reasoning for each is in SECURITY.md.
-
No default admin console credentials. The published
axis2-webappWAR and theaxis2_default.xmlinsideaxis2-kernel.jarshippedadmin/axis2as the/axis2-adminlogin. That console can upload services, and so execute code. Both now ship empty, which leaves the console disabled: the login rejects empty credentials before comparing, so no request can authenticate until an operator sets bothuserNameandpasswordin their ownaxis2.xml. Deployments that relied on the default login must now set one explicitly. -
Service dispatch from the message body is opt-in. The inflow order is Transport, Addressing, Security, PreDispatch, Dispatch, so a service selected during Dispatch is selected after the Security phase has already run — against no service, because none was bound yet — and Security is not revisited. A request whose URI names no service could therefore pick the service from the namespace of the SOAP body's first element, reaching a service whose engaged security modules never ran.
allowContentBasedServiceDispatchnow defaults tofalse. Dispatch by request URI, SOAPAction and WS-Addressing is unaffected. Set it totrueonly if services are genuinely addressed by body namespace, and not alongside per-service security modules. -
Decoupled WS-Addressing responses are refused by default. A non-anonymous
wsa:ReplyToorwsa:FaultTomakes the server open a connection to an address the caller chose.allowNonAnonymousResponseEndpointsnow defaults tofalse; replies and faults travel back down the inbound connection. Deployments that use decoupled responses — separate-listener “Dual” clients, or a third-party callback endpoint — set it totrue, and should also sethttpFrontendHostUrlso the generated reply address is the real external URL. With the feature enabled,allowedResponseEndpointSchemespermits HTTPS only, the destination is screened at both the header-parsing and transport-selection layers, and redirects are not followed over either the HTTP or the HTTP/2 sender. Wherejmsis among the permitted schemes, a reply endpoint may name a destination but no longer supply the JNDI environment used to resolve it: ajava.naming.*parameter on a reply address is refused, since it would let the caller choose which broker the server connects to. Deployments replying through a particular provider name it in their own transport configuration. -
JMS target addresses are screened more precisely. A JMS address becomes JNDI lookups, and JNDI resolves a name carrying a remote naming scheme (
ldap:,rmi:,iiop:,corbaname:,dns:and friends) through that scheme's URL context factory, which can fetch and deserialise a remote object. Those schemes are refused in the destination name, the reply destination and the JNDI provider URL. This replaces a guard that searched the whole address for those words as substrings and so refused ordinary destinations whose names contained one: a queue calledalarmingcontains “RMI”,dns-eventscontains “DNS”. Such names now work again. -
Multiref resolution is bounded. SOAP multiref references were resolved with no cycle check and no expansion budget, on the anonymous RPC/POJO receiver path. A reference leading back on itself recursed until the stack ended, and a reference graph with no cycle at all could still double at every level – an entity-expansion bomb built from well-formed XML that no parser limit objects to, ending in
OutOfMemoryError. Cyclic element references are now refused, nesting depth and total work are bounded, and the cost of copying a referenced element is charged before the copy is made. A cyclic object graph, which SOAP encoding permits and Axis2 has always accepted, still deserializes. The limits areorg.apache.axis2.databinding.multiref.maxDepth(64),maxResolutions(5000) andmaxExpandedNodes(50000);-1for unbounded. -
Request bodies are bounded. The
multipart/form-dataandapplication/x-www-form-urlencodedbuilders read the transport stream directly, so a servlet container's post-size limit never saw the body.multipartMaxRequestSizeandmultipartMaxFileSize(100 MB),formUrlEncodedMaxRequestSize(2 MB),mtomMaxRequestSize(100 MB, covering the wholemultipart/relatedbody and so MTOM and SwA),soapMaxRequestSize(100 MB, a plain SOAP or POX body) andjsonMaxRequestSize(100 MB, every JSON builder including the Gson, Moshi and HTTP/2 variants) now bound them;-1restores the previous unbounded behaviour, and any may be set per service. All the stream-reading builders are covered, not only the form ones: the caller picks the builder by choosing the Content-Type, so bounding some of them bounds none. The ceilings are enforced against bytes actually read, so a chunked body is bounded on the same terms as a declared one. Multipart temporary files are deleted rather than accumulating. -
exposeServiceMetadatais honoured uniformly. Every anonymous metadata route now respects it: the?wsdl,?wsdl2and?xsdqueries as before, plus the.xsd/.wsdlfile routes on both the servlet and standalone HTTP paths, the named-WSDL route, the OpenAPI/Swagger/MCP generators, the/services/listing on both render paths, WS-MEXGetMetadata, and the ping module's service-level ping. A service with exposure disabled is skipped rather than refused, so it stays indistinguishable from one that is not deployed – the?wsdl,?wsdl2,?xsdand?policyroutes used to answer 403 for a hidden service where an absent one gets 404, which told an anonymous caller which service names exist; both now answer 404 with the same body. If you relied on a hidden service still appearing in the listing, in a WS-MEX response or in a ping response, it no longer will; setexposeServiceMetadatato true on that service. -
The
?xsd=route serves only schema and WSDL documents. It reached a service's packaged META-INF with the request's value, so?xsd=services.xmlreturned the service descriptor – which names keystores and password-callback classes. Only.xsdand.wsdlnames that stay inside META-INF are served now, enforced inside the shared helper so all three callers inherit it. -
Generated output cannot be written outside the output directory. Code generation derives file names from the document it was handed, and a
wsdl:servicename reached the shared file sink verbatim – a QName localPart is not required to be an NCName, so separators and..survived. A WSDL naming its service../../../src/main/resources/apihad the tool write its re-serialized WSDL over a project's real contract file. The sink now refuses a name that resolves outside the output root. -
Schema values are escaped before they reach generated source. Element and attribute default and fixed values, enumeration facets and the numeric range facets were copied out of the schema into generated Java and C inside string literals with no escaping, so a value carrying a quote closed its literal and the remainder became code in a class-level initializer – which runs when the generated bean class loads, on the build machine and in the shipped application. All of these are escaped now, as the pattern facet already was. QName enumerations are unaffected: the argument split the compiler inserts deliberately is preserved.
-
Every WSDL-loading path is screened, not just the client-side one. wsdl4j parses with its own unhardened parser and fetches imports itself, so a DOCTYPE in a WSDL – or in anything it imports – was an XXE in whichever JVM read it. Only the client-side path was screened. The JAX-WS loader, the runtime reload wrapper, the deployment builder's resolver path and the WSDL2Java entry point now screen too, via a locator that refuses a DOCTYPE without changing where documents may be loaded from: a delegate locator keeps its own catalog or archive resolution, and a bare relative path still works.
-
The schema compiler no longer trusts the schema it is compiling.
XSD2Javaand theaxis2-xsd2java-maven-pluginexist to consume contracts written elsewhere, but parsed them with no XXE hardening and dereferencedxs:include/xs:importlocations with whatever scheme they named – so a schema handed to a developer could read local files, exfiltrate them through an external entity, or make the build fetch internal URLs. DOCTYPE and external entities are now refused, and include/import locations resolve from the filesystem only. Sibling schema files, the ordinary case, are unaffected. A build that genuinely resolves schemas over the network passes-aslto the CLI or sets<allowAbsoluteSchemaLocations>true</allowAbsoluteSchemaLocations>on the plugin. -
Context deserialization: a documented allowlist that never existed is now described accurately, and what can be enforced is.
SECURITY.mdclaimed three times thatSafeObjectInputStreamrestricts deserialization to known Axis2 context classes. It does not, and cannot: the feature exists to carry application objects –SelfManagedDataHolderholds whatever a service put there, and aParametervalue may be any serializable object – so such a list would refuse the data it is for. The streams Axis2 creates now refuse dynamic proxies (org.apache.axis2.context.externalize.allowProxies=trueto override), andorg.apache.axis2.context.externalize.serialFilteraccepts a JEP 290 pattern for an integrator who does know their own types. No Axis2 path feeds these streams from the network; if you persist or replicate contexts, restrict the stream you own. -
Swagger UI scripts are integrity-pinned. The page loads swagger-ui from a CDN at a pinned version, which says which release to ask for but not that what came back is that release – and the page is built to drive authenticated API calls. The script tags now carry Subresource Integrity hashes and
crossorigin="anonymous". The hashes are version-specific, so a deployment pinning a different Swagger UI version supplies its own withopenapi.swaggerUi.integrity.bundleandopenapi.swaggerUi.integrity.standalonePreset; without them the page still renders and a warning says integrity is not being enforced. -
Unexpected-error faults no longer name the exception class. An otherwise unhandled error produced a fault reason of
fully.qualified.Class: messagewhateversendStacktraceDetailsWithFaultswas set to, and since that catch-all serves every request the servlet handles, it applied to JSON and REST responses as much as to SOAP faults. The reason is now generic unless details are enabled. The error is logged with its stack as before. -
WSDL2Java no longer lets a remote server retarget its own WSDL fetch. The tool probes an http location for a redirect before parsing, and took the
Locationheader from any response, unresolved and unconstrained: a stray header on a200redirected it, a relative target was used as given, andLocation: file:///etc/passwdpointed the parse at the developer's filesystem. A redirect is now followed only from a 3xx status, only to http or https, and a relative target resolves against the document requested; anything else stops code generation instead of silently parsing something else. Connect and read timeouts are applied and configurable. -
Packaged schema and WSDL documents are served only from the requesting service's own archive.
AxisService.printXSDandprintWSDL2– the?xsd=and?wsdl2=queries – looked a requested name up withgetResourceAsStream, which delegates parent-first, so an anonymous caller could read anyMETA-INF/*.xsdor*.wsdlfrom jars anywhere on the webapp or container classpath and fingerprint what was deployed. The file routes had been fixed for this once (AXIS2-5846); the query routes had not. Both rules – schemas and WSDLs only, own archive only – now live in one kernel helper,MetaInfResources. A service whose classloader is not aURLClassLoadercannot serve this route at all; deployed archives are unaffected. -
The absolute-
schemaLocationguard no longer fails open on malformed input.WSDLToAxisServiceBuilder's default schema resolver classified locations withjava.net.URIand ignoredURISyntaxException. A locationURIrejects butjava.net.URLaccepts – one containing a space,|,{,},^or a backslash – was therefore never classified and was resolved as though relative, fetching the remote schema the guard exists to refuse. Classification is textual now. Relative names thatURIalso rejects still resolve. -
httpFrontendHostUrlis documented as a requirement, not a convenience. Without it (or an explicit servlet-transportport), the port advertised in generated WSDL comes from the first request'sHostheader after startup and is kept for the life of the process. See item 14 ofSECURITY.md; this is a configuration note, not a code change. -
Two threat-model claims made true, and their limits stated. The document said every parser factory the framework creates disables DTDs and external entities, and that the AAR/WAR resolvers block
file:resolution. Neither held. The SAAJ and JAX-WS conversions now use the hardened factory (XMLUtils.toDOM,SAAJUtil.toDOM,SOAPBodyImpl,LogicalMessageImpl,JAXWSRIWSDLGenerator), andfile:is refused by the deployment resolvers – which mattered in one of the four, where an absolutefile:import had been reaching the filesystem.SECURITY.mdnow also names what is not covered: the build-time codegen factories, the deliberate hbm.xml DTD exception, and theTransformerFactoryinstances. -
OpenAPI and Swagger UI output. Request-controlled values are validated and encoded for the context they are written into, the served page carries a Content-Security-Policy with a per-response script nonce, and the published
servers[].urlis relative rather than derived from the request Host.openapi.serverBaseUrlpins an absolute URL where a deployment needs one. -
JSON field filtering only narrows a response. The
?fields=selector read fields by reflection, so it could name one the serializer never writes: the syntheticthis$0of a non-static inner class, which returned the enclosing object, or with Moshi a field marked@Json(ignore = true). Those fields are now skipped at the top level and in dot paths alike, so a filtered response holds only fields the unfiltered one already contains.Release Notes - Axis2 - Version 2.0.2
Task
- [AXIS2-6107] - Remove vestigial context externalization code (SafeObjectInputStream and readExternal)
- [AXIS2-6108] - WS-Addressing decoupled responses are refused by default from 2.0.2
Apache Axis2
