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-spring` no longer brings Spring with it. Applications that inherit
  `spring-boot-starter-parent` or import `spring-boot-dependencies` are
  unaffected -- their dependency management already decided the Spring version.
  Anyone depending on `axis2-spring` **without** Spring Boot's dependency
  management must now declare `spring-core`, `spring-beans`, `spring-context` and
  `spring-web` themselves.
- The JMS and mail transports are no longer bundled in `axis2.war`. Both remain in
  `lib/` of the binary distribution, so a standalone server is unaffected; a WAR
  deployment that uses either now adds the transport jar to `WEB-INF/lib`.
- `jibx` is no longer a valid `-d` value for `wsdl2java`. 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-spring` no longer exports Spring to its consumers.** Its `spring-core`,
  `spring-beans`, `spring-context` and `spring-web` dependencies are now `provided`
  rather than `compile`. 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 inherit `spring-boot-starter-parent` or import `spring-boot-dependencies` were
  never affected -- dependency management already overrode the transitive version --
  and are unaffected now. Anyone depending on `axis2-spring` **without** Spring Boot's
  dependency management must declare their own Spring dependencies, which is the
  intent.

- **Five stray Spring jars dropped from `axis2.war` and the binary distribution.**
  `spring-beans`, `spring-context`, `spring-core` and `spring-web` have always been
  excluded on purpose -- a deployment using the Spring integration supplies its own
  Spring. Spring 7 moved `spring-aop`, `spring-expression`, `micrometer-observation`,
  `micrometer-commons` and `jspecify` behind `spring-context` and `spring-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 own
  `axis2-spring` is 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.war` to format
  machine-generated code that a template had already laid out. `PrettyPrinter` now
  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.war` goes from 36 MB to 30 MB across this and the JMS, mail and
  Spring changes above. Guava is therefore no longer in `lib/` or `WEB-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.war` either.** Same reasoning
  as JMS: no default `axis2.xml` enables a `mailto` listener or sender, and the module
  is deprecated for removal in 2.0.3. It remains in `lib/` of the binary distribution.
  Note that `angus-mail` and `jakarta.mail-api` stay in the WAR and are **not** mail
  transport baggage: `jakarta.mail-api` carries the `MimeBodyPart`,
  `MimePartDataSource`, `InternetHeaders` and `ByteArrayDataSource` classes that
  JAX-WS attachment handling uses, and `angus-mail` supplies the
  `META-INF/services/jakarta.mail.util.StreamProvider` implementation 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-jms`
  and `jakarta.jms-api` shipped in every WAR while no default `axis2.xml` enables 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-api` is 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 in `lib/` of the binary distribution, so a standalone server is
  unaffected. A WAR deployment that uses JMS now adds `axis2-transport-jms` to
  `WEB-INF/lib` alongside the broker client it already had to add.

- **The `dynamicclient` sample 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. `ServiceClient` can
  still be constructed from a WSDL URL; `modules/samples/jaxws-addressbook` covers the
  JAX-WS Dispatch client.

- **More unrunnable samples are removed.** `yahoojsonsearch` and `yahoorestsearch`
  called Yahoo search APIs that were shut down in 2011, and `googlespellcheck` called a
  Google SOAP API retired in 2009; the two Yahoo samples were still in the binary
  distribution. `jaxws-dynamic` was shipped with no build file and an empty README, and
  `book` depended on 1.8.0 snapshots and was never built. Three Maven samples whose
  run instructions could not work are removed as well: `transport/https-sample` ran
  on the Jetty 6 plugin, which cannot host a Jakarta webapp; `java_first_jaxws` was
  set up for a javax-based Cargo container; and `transport/jms-sample` had 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 sample
  `build.xml` files still located `AXIS2_HOME` two directories up, so `ant` failed
  looking for `modules/lib`. They now resolve `AXIS2_HOME` correctly from
  `AXIS2_HOME/modules/samples/<sample>`, and `servicelifecycle`, 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 in `axis2.war` either -- it remains in `lib/` of the binary distribution for
  anyone who configures it. Its correlation of responses to requests by `In-Reply-To`
  (`SynchronousCallback` and the callback table in `AbstractTransportListener`) is the
  only such mechanism in the tree and is used by nothing else; the module's own source
  carries long-standing `FIXME` comments 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-webapp` WAR and
  the `axis2_default.xml` inside `axis2-kernel.jar` shipped `admin`/`axis2` as the
  `/axis2-admin` login. 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 both `userName` and `password` in their own `axis2.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. `allowContentBasedServiceDispatch` now defaults to
  `false`. Dispatch by request URI, SOAPAction and WS-Addressing is unaffected.
  Set it to `true` only 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:ReplyTo` or `wsa:FaultTo` makes the server open a connection to an address
  the caller chose. `allowNonAnonymousResponseEndpoints` now defaults to `false`;
  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 to `true`, and should also set `httpFrontendHostUrl` so the
  generated reply address is the real external URL. With the feature enabled,
  `allowedResponseEndpointSchemes` permits 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. Where `jms` is among the
  permitted schemes, a reply endpoint may name a destination but no longer supply
  the JNDI environment used to resolve it: a `java.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 called
  `alarming` contains "RMI", `dns-events` contains "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 are
  `org.apache.axis2.databinding.multiref.maxDepth` (64),
  `maxResolutions` (5000) and `maxExpandedNodes` (50000); `-1` for unbounded.

- **Request bodies are bounded.** The `multipart/form-data` and
  `application/x-www-form-urlencoded` builders read the transport stream directly,
  so a servlet container's post-size limit never saw the body.
  `multipartMaxRequestSize` and `multipartMaxFileSize` (100 MB),
  `formUrlEncodedMaxRequestSize` (2 MB), `mtomMaxRequestSize` (100 MB, covering the
  whole `multipart/related` body and so MTOM and SwA), `soapMaxRequestSize`
  (100 MB, a plain SOAP or POX body) and `jsonMaxRequestSize` (100 MB, every JSON
  builder including the Gson, Moshi and HTTP/2 variants) now bound them; `-1` restores 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.

- **`exposeServiceMetadata` is honoured uniformly.** Every anonymous metadata route
  now respects it: the `?wsdl`, `?wsdl2` and `?xsd` queries as before, plus the
  `.xsd`/`.wsdl` file 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-MEX `GetMetadata`, 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`, `?xsd` and
  `?policy` routes 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; set `exposeServiceMetadata` to 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.xml` returned the
  service descriptor -- which names keystores and password-callback classes. Only
  `.xsd` and `.wsdl` names 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:service` name 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/api` had 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.** `XSD2Java`
  and the `axis2-xsd2java-maven-plugin` exist to consume contracts written
  elsewhere, but parsed them with no XXE hardening and dereferenced
  `xs:include`/`xs:import` locations 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 `-asl` to 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.md` claimed three
  times that `SafeObjectInputStream` restricts deserialization to known Axis2
  context classes. It does not, and cannot: the feature exists to carry application
  objects -- `SelfManagedDataHolder` holds whatever a service put there, and a
  `Parameter` value 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=true` to override), and
  `org.apache.axis2.context.externalize.serialFilter` accepts 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 with `openapi.swaggerUi.integrity.bundle` and
  `openapi.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: message`
  whatever `sendStacktraceDetailsWithFaults` was 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 `Location` header
  from any response, unresolved and unconstrained: a stray header on a `200` redirected
  it, a relative target was used as given, and `Location: file:///etc/passwd` pointed 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.printXSD` and `printWSDL2` -- the `?xsd=` and `?wsdl2=`
  queries -- looked a requested name up with `getResourceAsStream`, which delegates
  parent-first, so an anonymous caller could read any `META-INF/*.xsd` or `*.wsdl` from
  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 a `URLClassLoader`
  cannot serve this route at all; deployed archives are unaffected.

- **The absolute-`schemaLocation` guard no longer fails open on malformed input.**
  `WSDLToAxisServiceBuilder`'s default schema resolver classified locations with
  `java.net.URI` and ignored `URISyntaxException`. A location `URI` rejects but
  `java.net.URL` accepts -- 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 that `URI` also rejects still resolve.

- **`httpFrontendHostUrl` is documented as a requirement, not a convenience.** Without
  it (or an explicit servlet-transport `port`), the port advertised in generated WSDL
  comes from the first request's `Host` header after startup and is kept for the life of
  the process. See item 14 of `SECURITY.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`), and
  `file:` is refused by the deployment resolvers -- which mattered in one of the four,
  where an absolute `file:` import had been reaching the filesystem. `SECURITY.md` now
  also names what is *not* covered: the build-time codegen factories, the deliberate
  hbm.xml DTD exception, and the `TransformerFactory` instances.

- **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[].url` is relative rather than derived from the request Host.
  `openapi.serverBaseUrl` pins 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
  synthetic `this$0` of 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
                                            
<h2>        Task
</h2>
<ul>
<li>[<a href='https://issues.apache.org/jira/browse/AXIS2-6107'>AXIS2-6107</a>] -         Remove vestigial context externalization code (SafeObjectInputStream and readExternal)
</li>
<li>[<a href='https://issues.apache.org/jira/browse/AXIS2-6108'>AXIS2-6108</a>] -         WS-Addressing decoupled responses are refused by default from 2.0.2
</li>
</ul>
                                                                                                                                                        
