Use your existing application, translator, binding process and deployment. You do not need to generate a wizard application, copy its POM or adopt Spring Boot. This guide is for the people maintaining that build; developers then use the Java/Spring/Liberty debugger setup.
The SQLJ plugin uses source maps embedded in the classes actually loaded by the JVM. If your build already embeds matching SQLJ SMAP metadata, retain that process; the supplied tool is an alternative installer, not an additional mandatory stage. Do not install two different mappings into the same class.
The plugin distribution contains an executable wizard/sqlj-debug-tool.jar resource
inside its plugin JAR. It is supplied under MIT, including the license inside the
build JAR. Obtain the plugin ZIP through your approved distribution channel.
An administrator can extract the tool once with Python 3’s standard library:
# Save as extract_sqlj_build_tool.py; run once, outside the application's build.
from pathlib import Path
from io import BytesIO
from zipfile import ZipFile
import sys
archive, destination = map(Path, sys.argv[1:])
found = []
with ZipFile(archive) as distribution:
for name in distribution.namelist():
if not name.endswith('.jar'):
continue
with ZipFile(BytesIO(distribution.read(name))) as plugin:
if 'wizard/sqlj-debug-tool.jar' in plugin.namelist():
found.append(plugin.read('wizard/sqlj-debug-tool.jar'))
if len(found) != 1:
raise SystemExit('Expected exactly one SQLJ debug tool in the plugin ZIP')
# Refuse to overwrite a pinned version accidentally.
destination.parent.mkdir(parents=True, exist_ok=True)
with destination.open('xb') as output:
output.write(found[0])
print(destination)
For example, from the existing application’s root in PowerShell:
py -3 .\extract_sqlj_build_tool.py C:\Downloads\sqlj-lang-1.0.0.zip .\.mvn\sqlj\sqlj-debug-tool.jar
Get-FileHash .\.mvn\sqlj\sqlj-debug-tool.jar -Algorithm SHA256
Substitute the actual approved ZIP name. Commit the tool with the application or store that exact binary in your internal artifact repository, with its hash, plugin distribution version and MIT notice. There is no public Maven coordinate to resolve for this tool. Python is only used for this one-time extraction; it is not needed during the application’s build. IDE installation is not needed on CI. A plugin update does not update pinned application build tools automatically.
The supplied tool runs on JDK 21 or newer, separately from the application’s
compiler/runtime. Keep the existing application release target and server JVM.
If Maven itself runs on an older JDK, point sqlj.debug.java below at a JDK 21
java executable. This does not change the compiler toolchain. Verify your target
class-file format and actual translator output when adopting the tool.
Run these stages per module, with separate source/generated/class directories and a separate manifest for each module:
.sqlj inputs and removes old .java.smap
sidecars from the configured generated-source tree. Run it before translation..java.smap files. For the wizard’s IBM translator the options are
-smap=yes -linemap=no -compile=false. Confirm equivalent options with your
actual translator; do not silently substitute a different vendor tool.-g:lines,vars,source.Both modes take exactly the same four paths, in this order:
java -jar sqlj-debug-tool.jar prepare sourceRoot generatedRoot classesRoot manifest
java -jar sqlj-debug-tool.jar install sourceRoot generatedRoot classesRoot manifest
sourceRoot is the SQLJ source root (packages below it); generatedRoot contains
generated Java and its adjacent .java.smap files; classesRoot is the compiler
output directory. manifest is a build-local file written by prepare and read by
install. Paths may be absolute or relative to the command’s working directory.
Quote each path containing spaces. Missing maps, changed sources and inconsistent
classes fail the command with a nonzero exit code; make that fail the build.
Never run prepare after translation: it intentionally removes sidecars.
Limit each invocation to the module’s translated SQLJ inputs. Prepare recursively
finds .sqlj sources, but does not translate them; extend your existing
translator input list explicitly. It does not verify that every snapshotted input
produced a map. Keep your translator’s own input/output completeness checks.
The installer accepts one SQLJ input and one stratum per map and requires matching
package/SourceFile class metadata. It is not an adapter for arbitrary proprietary
map formats. Keep binding/profile customization unchanged and preserve all SQLJ
runtime/profile resources when packaging.
Merge these fragments into the appropriate existing module; do not replace its POM or add a second compiler/exec plugin declaration. Use an existing approved exec-plugin version if already managed by your organization.
<properties>
<sqlj.debug.java>${java.home}/bin/java</sqlj.debug.java>
<sqlj.debug.tool>${project.basedir}/.mvn/sqlj/sqlj-debug-tool.jar</sqlj.debug.tool>
<sqlj.debug.sources>${project.basedir}/src/main/sqlj</sqlj.debug.sources>
<sqlj.debug.generated>${project.build.directory}/generated-sources/sqlj</sqlj.debug.generated>
<sqlj.debug.manifest>${project.build.directory}/sqlj-debug-inputs.properties</sqlj.debug.manifest>
</properties>
For multiple modules, either supply a pinned JAR to each module or configure
sqlj.debug.tool to the shared approved location explicitly. Do not assume a
module’s project.basedir is the reactor root.
Inside the existing build/plugins:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<debug>true</debug>
<debuglevel>lines,vars,source</debuglevel>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.5.0</version>
<executions>
<execution>
<id>sqlj-debug-prepare</id>
<phase>initialize</phase>
<goals><goal>exec</goal></goals>
<configuration>
<executable>${sqlj.debug.java}</executable>
<workingDirectory>${project.basedir}</workingDirectory>
<arguments>
<argument>-jar</argument><argument>${sqlj.debug.tool}</argument>
<argument>prepare</argument>
<argument>${sqlj.debug.sources}</argument>
<argument>${sqlj.debug.generated}</argument>
<argument>${project.build.outputDirectory}</argument>
<argument>${sqlj.debug.manifest}</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>sqlj-debug-install</id>
<phase>process-classes</phase>
<goals><goal>exec</goal></goals>
<configuration>
<executable>${sqlj.debug.java}</executable>
<workingDirectory>${project.basedir}</workingDirectory>
<arguments>
<argument>-jar</argument><argument>${sqlj.debug.tool}</argument>
<argument>install</argument>
<argument>${sqlj.debug.sources}</argument>
<argument>${sqlj.debug.generated}</argument>
<argument>${project.build.outputDirectory}</argument>
<argument>${sqlj.debug.manifest}</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
This assumes translation runs after initialize (usually generate-sources) and
Java compilation finishes before process-classes. Adapt the phases/order to the
real build, including inherited plugins and active profiles. Register generated
Java with the compiler using the project’s existing mechanism. Running
mvn compile alone does not reach installation; use mvn process-classes for a
local class-directory launch or mvn package / the normal deployment goals.
These fragments intentionally do not configure your translator, database,
credentials, binding or application server.
Run installation after any stage that recompiles/replaces classes and before packaging/signing. Later transformations must preserve source maps and line tables. For Ant, Gradle or scripts, invoke the same two commands at the equivalent points and propagate failures. Keep build-only tools out of the application runtime classpath and WAR/JAR dependencies.
CI must use the same pinned tool and source revision as the developer build. A terminal build must install maps too; IDE hooks alone cannot fix CI artifacts. For ordinary Java/Spring launches, configure SQLJ: Prepare Debug Build to run the appropriate Maven goals. That task runs your build; it does not add these executions to a POM. Put it after other build tasks that would overwrite classes. For Liberty or another remote server, package and deploy the mapped classes, then attach to that JVM; a local process-classes build does not redeploy a server.
Check the resulting class with javap -v: it must contain SourceDebugExtension
and a SQLJ stratum. Also inspect the deployed artifact, not just local target
output. Stop/redeploy/restart as required by the server, then verify a source
breakpoint on an executable SQLJ line. The plugin’s SQLJ: Inspect Debug Session
action can inspect loaded metadata at a paused frame. See the
debugger setup and diagnostics for details.