Java: Jakarta SOAP / WSDL client fails to read SOAP Message for logging.

A.E.Veltstra
Javarevisited
Published in
2 min readSep 6, 2023

Solution: Reflection.

The Jakarta SOAP and WSDL client is a relatively new addition to the open-source ecosystem from which Java software engineers can choose. Its parts used to be belong to JEE: Java Enterprise Edition. Much of it still lives in packages first created by Sun Microsystems.

The benefit of Jakarta is its combination of auto-generating Java classes that adhere to the WSDL contract, and its ability to handle all SOAP communication for us.

In a recent project, our tech stack got forced to upgrade to the latest version of Jakarta. You can get it for free from the Maven repository.

Version 3 changed how logging is handled. With version 2, we can set up a client passing in a logging handler, which would then read the SOAP message into a StringWriter, from which we can log to our heart’s content.

With version 3, reading the SOAP message during logging crashes the application. This is likely to get fixed in future updates, but the project doesn’t have time to wait. A solution was needed, stat.

Reflection to the rescue!

A Jakarta SOAPMessage implementation extends the Message class, which has a private packet field with data type Packet. The implementation of its toString() method reveals all its contents without consuming the message, meaning the message still gets handled by the client. Every other publicly available implementation consumes the message.

Unfortunately that packet field is private, and under normal circumstances we would respect that. Given the broken implementation, an exception is warranted. That exception comes in the form of Reflection, which has been an integral part of the JDK. (But even without it, the JRE would have allowed access, because the distinction between private and public fields and methods is enforced at coding time, not at run time.)

With Reflection, we can reference the packet Field from the Message class, and set it to become publicly available. That allows us to call Packet.toString(). Problem solved.

Afterthoughts

We wonder how regular logging is implemented for this version, when handled using common packages like log4j: does it also need to use Reflection? This project avoids using log4j and prefers its own logging implementation. We may never have run into the issue otherwise.

--

--

A.E.Veltstra
Javarevisited

Makes software better. Easier to use, faster to run, cheaper to maintain. Married, has kids, likes making music and climbing rocks. Patreon: @aev_software